vue-agent-start 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (169) hide show
  1. package/package.json +30 -0
  2. package/pnpm-workspace.yaml +3 -0
  3. package/src/agent-flow/adapter/backend.ts +99 -0
  4. package/src/agent-flow/components/ChatIframePanel.vue +773 -0
  5. package/src/agent-flow/components/DatasetItemCard.vue +313 -0
  6. package/src/agent-flow/components/MemoryWindow.vue +104 -0
  7. package/src/agent-flow/components/PromptEditor.vue +804 -0
  8. package/src/agent-flow/components/PromptEditorTagPanel.vue +460 -0
  9. package/src/agent-flow/components/SvgIcon.vue +32 -0
  10. package/src/agent-flow/components/ToolItemCard.vue +169 -0
  11. package/src/agent-flow/components/VariableCard.vue +161 -0
  12. package/src/agent-flow/components/VariableSelector.vue +162 -0
  13. package/src/agent-flow/components/chat-iframe-types.ts +35 -0
  14. package/src/agent-flow/components/stubs/DatasetChooser.vue +70 -0
  15. package/src/agent-flow/components/stubs/Embedding.vue +22 -0
  16. package/src/agent-flow/components/stubs/ModelSelect.vue +24 -0
  17. package/src/agent-flow/components/stubs/RestfulSelectCard.vue +24 -0
  18. package/src/agent-flow/components/stubs/ToolChooser.vue +96 -0
  19. package/src/agent-flow/components/stubs/TriggersItemCard.vue +126 -0
  20. package/src/agent-flow/components/stubs/VariableModal.vue +115 -0
  21. package/src/agent-flow/index.ts +73 -0
  22. package/src/agent-flow/stores/workflow.ts +72 -0
  23. package/src/agent-flow/utils/langUtils.ts +173 -0
  24. package/src/agent-flow/workflow/Ability.vue +65 -0
  25. package/src/agent-flow/workflow/AuthorizationItem.vue +101 -0
  26. package/src/agent-flow/workflow/ConversationVar.vue +42 -0
  27. package/src/agent-flow/workflow/CustomEdge.vue +94 -0
  28. package/src/agent-flow/workflow/EnvironmentVar.vue +40 -0
  29. package/src/agent-flow/workflow/FlowDesigner.vue +2802 -0
  30. package/src/agent-flow/workflow/Icon.vue +179 -0
  31. package/src/agent-flow/workflow/NodeConfig.vue +509 -0
  32. package/src/agent-flow/workflow/NodeConfigCard.vue +460 -0
  33. package/src/agent-flow/workflow/NodeHandle.vue +147 -0
  34. package/src/agent-flow/workflow/NodeHeaderToolbar.vue +77 -0
  35. package/src/agent-flow/workflow/NodeHoverToolbar.vue +176 -0
  36. package/src/agent-flow/workflow/OutputItemCard.vue +668 -0
  37. package/src/agent-flow/workflow/ParamTableItem.vue +200 -0
  38. package/src/agent-flow/workflow/StructTable.vue +202 -0
  39. package/src/agent-flow/workflow/VarInsertField.vue +517 -0
  40. package/src/agent-flow/workflow/VarSelectField.vue +223 -0
  41. package/src/agent-flow/workflow/VariableSelectorItem.vue +48 -0
  42. package/src/agent-flow/workflow/WfField.vue +206 -0
  43. package/src/agent-flow/workflow/_config-base.css +470 -0
  44. package/src/agent-flow/workflow/composables/useNode.js +55 -0
  45. package/src/agent-flow/workflow/index.vue +53 -0
  46. package/src/agent-flow/workflow/nodeCard/AgentNodeCard.vue +180 -0
  47. package/src/agent-flow/workflow/nodeCard/AnswerNodeCard.vue +65 -0
  48. package/src/agent-flow/workflow/nodeCard/ClassifierCard.vue +152 -0
  49. package/src/agent-flow/workflow/nodeCard/CodeNodeCard.vue +139 -0
  50. package/src/agent-flow/workflow/nodeCard/ConditionNodeCard.vue +323 -0
  51. package/src/agent-flow/workflow/nodeCard/DocumentExtractorCard.vue +83 -0
  52. package/src/agent-flow/workflow/nodeCard/EndNodeCard.vue +123 -0
  53. package/src/agent-flow/workflow/nodeCard/HttpNodeCard.vue +451 -0
  54. package/src/agent-flow/workflow/nodeCard/HumanInputCard.vue +152 -0
  55. package/src/agent-flow/workflow/nodeCard/IterationCard.vue +66 -0
  56. package/src/agent-flow/workflow/nodeCard/KnowledgeRetrievalCard.vue +48 -0
  57. package/src/agent-flow/workflow/nodeCard/LLMNodeCard.vue +206 -0
  58. package/src/agent-flow/workflow/nodeCard/ListOperatorCard.vue +188 -0
  59. package/src/agent-flow/workflow/nodeCard/ParameterExtractorCard.vue +352 -0
  60. package/src/agent-flow/workflow/nodeCard/ServiceApiNodeCard.vue +188 -0
  61. package/src/agent-flow/workflow/nodeCard/StartNodeCard.vue +216 -0
  62. package/src/agent-flow/workflow/nodeCard/VariableAssignerCard.vue +125 -0
  63. package/src/agent-flow/workflow/nodeCard/VariableNodeCard.vue +121 -0
  64. package/src/agent-flow/workflow/nodes/AgentNode.vue +122 -0
  65. package/src/agent-flow/workflow/nodes/AnswerNode.vue +99 -0
  66. package/src/agent-flow/workflow/nodes/ClassifierNode.vue +199 -0
  67. package/src/agent-flow/workflow/nodes/CodeNode.vue +152 -0
  68. package/src/agent-flow/workflow/nodes/ConditionNode.vue +232 -0
  69. package/src/agent-flow/workflow/nodes/DocumentExtractorNode.vue +96 -0
  70. package/src/agent-flow/workflow/nodes/EndNode.vue +119 -0
  71. package/src/agent-flow/workflow/nodes/FileUploadNode.vue +97 -0
  72. package/src/agent-flow/workflow/nodes/HttpNode.vue +204 -0
  73. package/src/agent-flow/workflow/nodes/HumanInputNode.vue +110 -0
  74. package/src/agent-flow/workflow/nodes/IterationNode.vue +98 -0
  75. package/src/agent-flow/workflow/nodes/KnowledgeRetrievalNode.vue +253 -0
  76. package/src/agent-flow/workflow/nodes/LLMNode.vue +134 -0
  77. package/src/agent-flow/workflow/nodes/ListOperatorNode.vue +111 -0
  78. package/src/agent-flow/workflow/nodes/LoopNode.vue +94 -0
  79. package/src/agent-flow/workflow/nodes/ParameterExtractorNode.vue +147 -0
  80. package/src/agent-flow/workflow/nodes/ServiceApiNode.vue +161 -0
  81. package/src/agent-flow/workflow/nodes/StartNode.vue +199 -0
  82. package/src/agent-flow/workflow/nodes/TemplateNode.vue +103 -0
  83. package/src/agent-flow/workflow/nodes/UserInputNode.vue +92 -0
  84. package/src/agent-flow/workflow/nodes/VariableAssignerNode.vue +145 -0
  85. package/src/agent-flow/workflow/nodes/VariableNode.vue +130 -0
  86. package/src/agent-flow/workflow/nodes/_node-base.css +338 -0
  87. package/src/agent-flow/workflow/utils/node_card_form.ts +335 -0
  88. package/src/agent-flow/workflow/utils/node_config.ts +63 -0
  89. package/src/agent-flow/workflow/utils/workflow_utils.ts +151 -0
  90. package/src/agent-studio/adapters/springAgentStart.ts +390 -0
  91. package/src/agent-studio/api/index.ts +1 -0
  92. package/src/agent-studio/api/types.ts +173 -0
  93. package/src/agent-studio/components/AgentApiDocs.vue +500 -0
  94. package/src/agent-studio/components/AgentAppsPage.vue +1601 -0
  95. package/src/agent-studio/components/AgentCardGrid.vue +259 -0
  96. package/src/agent-studio/components/AgentChatPage.vue +553 -0
  97. package/src/agent-studio/components/AgentDebugPanel.vue +350 -0
  98. package/src/agent-studio/components/AgentLogsPanel.vue +391 -0
  99. package/src/agent-studio/components/AgentMonitorPanel.vue +204 -0
  100. package/src/agent-studio/components/AgentOrchestrate.vue +505 -0
  101. package/src/agent-studio/components/AgentPromptEditor.vue +237 -0
  102. package/src/agent-studio/components/AgentStudioShell.vue +227 -0
  103. package/src/agent-studio/components/AgentToolsPanel.vue +394 -0
  104. package/src/agent-studio/components/AgentVariablesPanel.vue +205 -0
  105. package/src/agent-studio/components/ApiKeyManager.vue +251 -0
  106. package/src/agent-studio/components/AppDesignDrawer.vue +3391 -0
  107. package/src/agent-studio/components/CreateAppModal.vue +737 -0
  108. package/src/agent-studio/components/SparkChart.vue +200 -0
  109. package/src/agent-studio/components/VariableEditorModal.vue +499 -0
  110. package/src/agent-studio/composables/useAgentStudio.ts +347 -0
  111. package/src/agent-studio/index.ts +60 -0
  112. package/src/agent-studio/panels/DrawerFlowDesigner.vue +203 -0
  113. package/src/agent-studio/panels/LogAnnotationPanel.vue +490 -0
  114. package/src/agent-studio/panels/MonitorPanel.vue +535 -0
  115. package/src/agent-studio/types.ts +242 -0
  116. package/src/index.ts +155 -0
  117. package/src/knowledge-hub/adapters/springAgentStart.ts +472 -0
  118. package/src/knowledge-hub/components/AddDocumentsWizard.vue +1452 -0
  119. package/src/knowledge-hub/components/CreateDatasetWizard.vue +1723 -0
  120. package/src/knowledge-hub/components/DatasetCardGrid.vue +467 -0
  121. package/src/knowledge-hub/components/DatasetDetailDrawer.vue +888 -0
  122. package/src/knowledge-hub/components/DatasetPicker.vue +65 -0
  123. package/src/knowledge-hub/components/DatasetPickerModal.vue +526 -0
  124. package/src/knowledge-hub/components/DatasetSettingsPanel.vue +908 -0
  125. package/src/knowledge-hub/components/DatasetSidebar.vue +781 -0
  126. package/src/knowledge-hub/components/DocumentChunksView.vue +802 -0
  127. package/src/knowledge-hub/components/DocumentTable.vue +552 -0
  128. package/src/knowledge-hub/components/HitTestingPanel.vue +74 -0
  129. package/src/knowledge-hub/components/KnowledgeApp.vue +66 -0
  130. package/src/knowledge-hub/components/KnowledgeHubApp.vue +504 -0
  131. package/src/knowledge-hub/components/RecallTestingPanelV2.vue +515 -0
  132. package/src/knowledge-hub/components/RetrievalConfigPopover.vue +270 -0
  133. package/src/knowledge-hub/components/RetrievalMethodPicker.vue +547 -0
  134. package/src/knowledge-hub/components/RetrievedList.vue +24 -0
  135. package/src/knowledge-hub/components/internal/KhDialog.vue +195 -0
  136. package/src/knowledge-hub/composables/useKnowledge.ts +89 -0
  137. package/src/knowledge-hub/i18n/index.ts +2 -0
  138. package/src/knowledge-hub/i18n/messages.ts +422 -0
  139. package/src/knowledge-hub/i18n/useKhI18n.ts +107 -0
  140. package/src/knowledge-hub/index.ts +46 -0
  141. package/src/knowledge-hub/styles/index.css +4 -0
  142. package/src/knowledge-hub/styles/tokens.css +138 -0
  143. package/src/knowledge-hub/types/api.ts +213 -0
  144. package/src/knowledge-hub/types/dataset.ts +88 -0
  145. package/src/knowledge-hub/types/document.ts +45 -0
  146. package/src/knowledge-hub/types/index.ts +9 -0
  147. package/src/knowledge-hub/types/retrieval.ts +46 -0
  148. package/src/provider-hub/components/CredentialForm.vue +103 -0
  149. package/src/provider-hub/components/DefaultModelsPanel.vue +270 -0
  150. package/src/provider-hub/components/GroupedModelSelect.vue +445 -0
  151. package/src/provider-hub/components/ModelCardGrid.vue +332 -0
  152. package/src/provider-hub/components/ModelParameterDrawer.vue +739 -0
  153. package/src/provider-hub/components/ModelPickerPopover.vue +1282 -0
  154. package/src/provider-hub/components/ProviderApp.vue +159 -0
  155. package/src/provider-hub/components/ProviderCredentialModal.vue +321 -0
  156. package/src/provider-hub/components/ProviderGallery.vue +131 -0
  157. package/src/provider-hub/components/ProviderHubShell.vue +1992 -0
  158. package/src/provider-hub/components/ProviderIcon.vue +130 -0
  159. package/src/provider-hub/composables/useProviderHub.ts +358 -0
  160. package/src/provider-hub/index.ts +43 -0
  161. package/src/provider-hub/svg/MiniMax.svg +1 -0
  162. package/src/provider-hub/svg/Volcengine.svg +1 -0
  163. package/src/provider-hub/svg/Zhipu.svg +1 -0
  164. package/src/provider-hub/svg/deepseek.svg +1 -0
  165. package/src/provider-hub/svg/moonshot.svg +1 -0
  166. package/src/provider-hub/svg/openai.svg +1 -0
  167. package/src/provider-hub/svg/qwen.svg +1 -0
  168. package/src/provider-hub/svg/siliconflow.svg +1 -0
  169. package/src/provider-hub/types.ts +256 -0
@@ -0,0 +1,216 @@
1
+ <script setup lang="ts">
2
+ import { h, ref } from 'vue';
3
+
4
+ import {
5
+ DeleteOutlined,
6
+ EditOutlined,
7
+ PlusOutlined,
8
+ UserSwitchOutlined,
9
+ } from '@ant-design/icons-vue';
10
+
11
+ import TriggersItemCard from '@/components/stubs/TriggersItemCard.vue';
12
+ import VariableModal from '@/components/stubs/VariableModal.vue';
13
+ import WfField from '@/workflow/WfField.vue';
14
+
15
+ defineProps<{ nodeId?: string }>();
16
+
17
+ const formState: any = defineModel();
18
+
19
+ const variableModalRef = ref();
20
+
21
+ // 直接把 item 作为参数交给 showModal,同一次同步调用里就把表单初值写进
22
+ // 弹窗内部的 form;再也不通过 :main-data prop 中转,避免 prop 需要下一
23
+ // 个 tick 才刷新导致的"第一次点开表单是空的 / 是上次的"那种时序 bug。
24
+ function toEditVariable(item?: any) {
25
+ variableModalRef.value?.showModal?.(item ?? {});
26
+ }
27
+
28
+ function removeVariable(index: number) {
29
+ formState.value.variables.splice(index, 1);
30
+ }
31
+
32
+ const variableFormSubmit = (data: any) => {
33
+ if (!Array.isArray(formState.value.variables)) formState.value.variables = [];
34
+ const items = formState.value.variables;
35
+ if (data.id) {
36
+ const index = items.findIndex((it: any) => it.id === data.id);
37
+ if (index === -1) items.push(data);
38
+ else items[index] = { ...data };
39
+ } else {
40
+ data.id = Date.now();
41
+ items.push(data);
42
+ }
43
+ };
44
+ </script>
45
+
46
+ <template>
47
+ <VariableModal
48
+ ref="variableModalRef"
49
+ @form-submit="variableFormSubmit"
50
+ />
51
+
52
+ <div v-if="formState.mode === 'WORKFLOW'" class="wf-config-section">
53
+ <WfField title="触发器">
54
+ <template #tooltip>
55
+ 定义工作流被外部(HTTP / 定时 / 事件)触发的方式。
56
+ </template>
57
+ <TriggersItemCard v-model="formState" />
58
+ </WfField>
59
+ </div>
60
+
61
+ <div class="wf-config-section">
62
+ <WfField title="输入变量">
63
+ <template #tooltip>
64
+ 这里定义的变量会在整个流程中可用,通过 <code v-pre>{{#sys.xxx#}}</code> 或 <code>/</code> 引用。
65
+ </template>
66
+ <template #operations>
67
+ <a-button
68
+ :icon="h(PlusOutlined)"
69
+ size="small"
70
+ type="primary"
71
+ @click="toEditVariable({})"
72
+ />
73
+ </template>
74
+
75
+ <div
76
+ v-if="!formState.variables || formState.variables.length === 0"
77
+ class="start-empty"
78
+ >
79
+ 尚未配置输入变量,点击右上角 + 添加
80
+ </div>
81
+
82
+ <div class="start-var-list">
83
+ <div
84
+ v-for="(item, index) in formState.variables"
85
+ :key="item.id ?? index"
86
+ class="start-var-item"
87
+ >
88
+ <div class="start-var-left">
89
+ <UserSwitchOutlined class="start-var-icon" />
90
+ <div>
91
+ <div class="start-var-label">{{ item.label || item.name }}</div>
92
+ <div class="start-var-sub">{{ item.name }}</div>
93
+ </div>
94
+ </div>
95
+ <div class="start-var-right">
96
+ <a-tag>{{ item.type }}</a-tag>
97
+ <a-tag v-if="item.required" color="orange">必填</a-tag>
98
+ <a-button
99
+ :icon="h(EditOutlined)"
100
+ size="small"
101
+ type="text"
102
+ @click="toEditVariable(item)"
103
+ />
104
+ <a-button
105
+ :icon="h(DeleteOutlined)"
106
+ size="small"
107
+ type="text"
108
+ danger
109
+ @click="removeVariable(index)"
110
+ />
111
+ </div>
112
+ </div>
113
+ </div>
114
+ </WfField>
115
+ </div>
116
+
117
+ <div class="wf-config-section">
118
+ <WfField title="系统变量" foldable default-fold>
119
+ <template #tooltip>
120
+ 运行时由引擎注入的只读变量,通过 <code v-pre>{{#sys.xxx#}}</code> 引用。
121
+ </template>
122
+ <div class="start-var-list">
123
+ <div
124
+ v-for="(item, index) in formState.sysVariables"
125
+ :key="index"
126
+ class="start-var-item start-var-item-readonly"
127
+ >
128
+ <div class="start-var-left">
129
+ <div class="start-var-sys">sys</div>
130
+ <div class="start-var-label">{{ item.name }}</div>
131
+ </div>
132
+ <a-tag>{{ item.type }}</a-tag>
133
+ </div>
134
+ </div>
135
+ </WfField>
136
+ </div>
137
+ </template>
138
+
139
+ <style scoped>
140
+ .start-empty {
141
+ padding: 12px;
142
+ text-align: center;
143
+ font-size: 12px;
144
+ color: #9ca3af;
145
+ background: #f9fafb;
146
+ border: 1px dashed #e5e7eb;
147
+ border-radius: 6px;
148
+ }
149
+
150
+ .start-var-list {
151
+ display: flex;
152
+ flex-direction: column;
153
+ gap: 6px;
154
+ }
155
+
156
+ .start-var-item {
157
+ display: flex;
158
+ align-items: center;
159
+ justify-content: space-between;
160
+ padding: 6px 10px;
161
+ background: #f9fafb;
162
+ border: 1px solid #f0f0f0;
163
+ border-radius: 6px;
164
+ transition: background 0.15s;
165
+ }
166
+
167
+ .start-var-item:hover {
168
+ background: #f3f4f6;
169
+ }
170
+
171
+ .start-var-item-readonly {
172
+ background: #ffffff;
173
+ }
174
+
175
+ .start-var-left {
176
+ display: flex;
177
+ align-items: center;
178
+ gap: 8px;
179
+ }
180
+
181
+ .start-var-right {
182
+ display: flex;
183
+ align-items: center;
184
+ gap: 4px;
185
+ }
186
+
187
+ .start-var-icon {
188
+ font-size: 16px;
189
+ color: #6366f1;
190
+ }
191
+
192
+ .start-var-label {
193
+ font-size: 12px;
194
+ font-weight: 500;
195
+ color: #1f2937;
196
+ }
197
+
198
+ .start-var-sub {
199
+ font-size: 11px;
200
+ color: #9ca3af;
201
+ font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
202
+ }
203
+
204
+ .start-var-sys {
205
+ display: inline-flex;
206
+ align-items: center;
207
+ justify-content: center;
208
+ width: 24px;
209
+ height: 20px;
210
+ font-size: 10px;
211
+ font-weight: 600;
212
+ color: #ffffff;
213
+ background: #6b7280;
214
+ border-radius: 4px;
215
+ }
216
+ </style>
@@ -0,0 +1,125 @@
1
+ <script setup lang="ts">
2
+ import { h } from 'vue';
3
+
4
+ import { DeleteOutlined, PlusOutlined } from '@ant-design/icons-vue';
5
+
6
+ import VariableSelector from '@/components/VariableSelector.vue';
7
+ import WfField from '@/workflow/WfField.vue';
8
+
9
+ defineProps<{ nodeId?: string }>();
10
+
11
+ const formState: any = defineModel();
12
+
13
+ const WRITE_MODES = [
14
+ { value: 'overwrite', label: '覆盖' },
15
+ { value: 'append', label: '追加' },
16
+ { value: 'clear', label: '清空' },
17
+ ];
18
+
19
+ const addAssignment = () => {
20
+ if (!Array.isArray(formState.value.assignments)) formState.value.assignments = [];
21
+ formState.value.assignments.push({
22
+ target: '',
23
+ source: [],
24
+ writeMode: 'overwrite',
25
+ });
26
+ };
27
+
28
+ const removeAssignment = (index: number) => {
29
+ formState.value.assignments.splice(index, 1);
30
+ };
31
+ </script>
32
+
33
+ <template>
34
+ <div class="wf-config-section">
35
+ <WfField title="赋值项">
36
+ <template #tooltip>
37
+ 为每一项指定目标变量、来源变量、写入模式。
38
+ </template>
39
+ <template #operations>
40
+ <a-button
41
+ :icon="h(PlusOutlined)"
42
+ size="small"
43
+ type="primary"
44
+ @click="addAssignment"
45
+ />
46
+ </template>
47
+
48
+ <div
49
+ v-if="!formState.assignments || formState.assignments.length === 0"
50
+ class="assigner-empty"
51
+ >
52
+ 点击右上角 + 添加赋值项
53
+ </div>
54
+
55
+ <div class="assigner-list">
56
+ <div
57
+ v-for="(a, index) in formState.assignments"
58
+ :key="index"
59
+ class="assigner-item"
60
+ >
61
+ <div class="assigner-row-1">
62
+ <a-input
63
+ v-model:value="a.target"
64
+ placeholder="目标变量(如 sys.foo)"
65
+ size="small"
66
+ style="flex: 1"
67
+ />
68
+ <a-select
69
+ v-model:value="a.writeMode"
70
+ :options="WRITE_MODES"
71
+ size="small"
72
+ style="width: 80px"
73
+ />
74
+ <a-button
75
+ :icon="h(DeleteOutlined)"
76
+ size="small"
77
+ type="text"
78
+ danger
79
+ @click="removeAssignment(index)"
80
+ />
81
+ </div>
82
+ <VariableSelector
83
+ v-if="a.writeMode !== 'clear'"
84
+ v-model="a.source"
85
+ :node-id="nodeId"
86
+ placeholder="来源变量"
87
+ />
88
+ </div>
89
+ </div>
90
+ </WfField>
91
+ </div>
92
+ </template>
93
+
94
+ <style scoped>
95
+ .assigner-empty {
96
+ padding: 12px;
97
+ text-align: center;
98
+ font-size: 12px;
99
+ color: #9ca3af;
100
+ background: #f9fafb;
101
+ border: 1px dashed #e5e7eb;
102
+ border-radius: 6px;
103
+ }
104
+
105
+ .assigner-list {
106
+ display: flex;
107
+ flex-direction: column;
108
+ gap: 8px;
109
+ }
110
+
111
+ .assigner-item {
112
+ display: flex;
113
+ flex-direction: column;
114
+ gap: 6px;
115
+ padding: 8px;
116
+ background: #f9fafb;
117
+ border-radius: 6px;
118
+ }
119
+
120
+ .assigner-row-1 {
121
+ display: flex;
122
+ align-items: center;
123
+ gap: 6px;
124
+ }
125
+ </style>
@@ -0,0 +1,121 @@
1
+ <script setup lang="ts">
2
+ import { h } from 'vue';
3
+
4
+ import { DeleteOutlined, PlusOutlined } from '@ant-design/icons-vue';
5
+
6
+ import VariableSelector from '@/components/VariableSelector.vue';
7
+ import WfField from '@/workflow/WfField.vue';
8
+
9
+ defineProps<{ nodeId?: string }>();
10
+
11
+ const formState: any = defineModel();
12
+
13
+ const addItem = () => {
14
+ if (!formState.value.output) formState.value.output = [{ children: [] }];
15
+ if (!Array.isArray(formState.value.output[0].children)) {
16
+ formState.value.output[0].children = [];
17
+ }
18
+ formState.value.output[0].children.push({
19
+ type: 'string',
20
+ name: '',
21
+ label: '',
22
+ value: '',
23
+ description: '',
24
+ variableSelector: [],
25
+ });
26
+ };
27
+
28
+ const removeItem = (index: number) => {
29
+ formState.value.output[0].children.splice(index, 1);
30
+ };
31
+
32
+ const onNameChange = (it: any) => {
33
+ it.label = it.name;
34
+ };
35
+ </script>
36
+
37
+ <template>
38
+ <div class="wf-config-section">
39
+ <WfField title="聚合变量" required>
40
+ <template #tooltip>
41
+ 把多个上游变量映射到本节点的输出字段,供下游统一引用。
42
+ </template>
43
+ <template #operations>
44
+ <a-button
45
+ :icon="h(PlusOutlined)"
46
+ size="small"
47
+ type="primary"
48
+ @click="addItem"
49
+ />
50
+ </template>
51
+
52
+ <div
53
+ v-if="
54
+ !formState.output ||
55
+ !formState.output[0]?.children ||
56
+ formState.output[0].children.length === 0
57
+ "
58
+ class="var-empty"
59
+ >
60
+ 点击右上角 + 添加聚合项
61
+ </div>
62
+
63
+ <div class="var-list">
64
+ <div
65
+ v-for="(it, index) in formState.output[0]?.children"
66
+ :key="index"
67
+ class="var-item"
68
+ >
69
+ <a-input
70
+ v-model:value="it.name"
71
+ placeholder="字段名"
72
+ size="small"
73
+ style="width: 120px"
74
+ @change="onNameChange(it)"
75
+ />
76
+ <VariableSelector
77
+ v-model="it.variableSelector"
78
+ :node-id="nodeId"
79
+ placeholder="选择上游变量"
80
+ style="flex: 1"
81
+ />
82
+ <a-button
83
+ :icon="h(DeleteOutlined)"
84
+ size="small"
85
+ type="text"
86
+ danger
87
+ @click="removeItem(index)"
88
+ />
89
+ </div>
90
+ </div>
91
+ </WfField>
92
+ </div>
93
+ </template>
94
+
95
+ <style scoped>
96
+ .var-empty {
97
+ padding: 12px;
98
+ text-align: center;
99
+ font-size: 12px;
100
+ color: #9ca3af;
101
+ background: #f9fafb;
102
+ border: 1px dashed #e5e7eb;
103
+ border-radius: 6px;
104
+ }
105
+
106
+ .var-list {
107
+ display: flex;
108
+ flex-direction: column;
109
+ gap: 6px;
110
+ }
111
+
112
+ .var-item {
113
+ display: flex;
114
+ align-items: center;
115
+ gap: 6px;
116
+ padding: 6px 8px;
117
+ background: #f9fafb;
118
+ border: 1px solid #f0f0f0;
119
+ border-radius: 6px;
120
+ }
121
+ </style>
@@ -0,0 +1,122 @@
1
+ <script setup>
2
+ import { ref } from 'vue';
3
+
4
+ import Icon from '../Icon.vue';
5
+ import NodeHandle from '../NodeHandle.vue';
6
+ import NodeHoverToolbar from '../NodeHoverToolbar.vue';
7
+
8
+ const props = defineProps({
9
+ id: String,
10
+ data: {
11
+ type: Object,
12
+ default: () => ({
13
+ label: 'Agent',
14
+ description: '智能体节点',
15
+ config: {
16
+ model: 'gpt-3.5-turbo',
17
+ temperature: 0.7,
18
+ max_tokens: 1000,
19
+ prompt: '',
20
+ },
21
+ }),
22
+ },
23
+ });
24
+
25
+ const emit = defineEmits(['duplicate', 'delete', 'connection-plus-click']);
26
+
27
+ const isRunning = ref(false);
28
+ const showMetrics = ref(true);
29
+ const isHovered = ref(false);
30
+
31
+ const onMouseEnter = () => (isHovered.value = true);
32
+ const onMouseLeave = () => (isHovered.value = false);
33
+ const duplicateNode = () => emit('duplicate', props.id);
34
+ const deleteNode = () => emit('delete', props.id);
35
+ const onConnectionPlusClick = (event, nodeId, handleId) => {
36
+ emit('connection-plus-click', event, nodeId, handleId);
37
+ };
38
+
39
+ const truncateText = (text, maxLength) => {
40
+ if (!text) return '';
41
+ return text.length > maxLength
42
+ ? `${text.slice(0, Math.max(0, maxLength))}...`
43
+ : text;
44
+ };
45
+ </script>
46
+
47
+ <template>
48
+ <div
49
+ class="wf-node agent-node"
50
+ @mouseenter="onMouseEnter"
51
+ @mouseleave="onMouseLeave"
52
+ >
53
+ <NodeHoverToolbar
54
+ v-if="isHovered"
55
+ node-type="agent"
56
+ @duplicate="duplicateNode"
57
+ @delete="deleteNode"
58
+ />
59
+
60
+ <div class="wf-node-header">
61
+ <div class="wf-node-icon">
62
+ <Icon name="agent" />
63
+ </div>
64
+ <div class="wf-node-info">
65
+ <div class="wf-node-title">{{ data.label }}</div>
66
+ <div class="wf-node-subtitle">
67
+ <div>{{ data.model?.provider }}</div>
68
+ <div>{{ data.model?.modelName || 'GPT-3.5-turbo' }}</div>
69
+ </div>
70
+ </div>
71
+ <div v-if="isRunning" class="wf-node-status">
72
+ <div class="wf-node-status-indicator wf-is-running"></div>
73
+ </div>
74
+ </div>
75
+
76
+ <div class="wf-node-content">
77
+ <div class="wf-node-description">{{ data.description }}</div>
78
+ <div v-if="data.config?.prompt" class="wf-node-config-preview">
79
+ <div class="wf-node-config-label">提示词预览</div>
80
+ <div class="wf-node-config-value">
81
+ {{ truncateText(data.config.prompt, 50) }}
82
+ </div>
83
+ </div>
84
+ </div>
85
+
86
+ <div v-if="showMetrics" class="wf-node-metrics">
87
+ <div class="wf-node-metric">
88
+ <span class="wf-node-metric-label">温度</span>
89
+ <span class="wf-node-metric-value">{{ data.config?.temperature ?? 0.7 }}</span>
90
+ </div>
91
+ <div class="wf-node-metric">
92
+ <span class="wf-node-metric-label">最大令牌</span>
93
+ <span class="wf-node-metric-value">{{ data.config?.max_tokens ?? 1000 }}</span>
94
+ </div>
95
+ </div>
96
+
97
+ <NodeHandle
98
+ :id="id"
99
+ type="target"
100
+ position="Left"
101
+ class-name="flow-node-handle-left"
102
+ :style="{ background: '#8b5cf6', border: '2px solid #ffffff' }"
103
+ />
104
+
105
+ <NodeHandle
106
+ :id="id"
107
+ type="source"
108
+ position="Right"
109
+ :is-hovered="isHovered"
110
+ class-name="flow-node-handle-right"
111
+ :style="{ background: '#8b5cf6', border: '2px solid #ffffff' }"
112
+ @connection-plus-click="onConnectionPlusClick"
113
+ />
114
+ </div>
115
+ </template>
116
+
117
+ <style scoped>
118
+ .agent-node {
119
+ --wf-accent: #8b5cf6;
120
+ --wf-accent-hover: #7c3aed;
121
+ }
122
+ </style>
@@ -0,0 +1,99 @@
1
+ <script setup lang="ts">
2
+ import { ref } from 'vue';
3
+
4
+ import workflow_utils from '@/workflow/utils/workflow_utils';
5
+
6
+ import Icon from '../Icon.vue';
7
+ import NodeHandle from '../NodeHandle.vue';
8
+ import NodeHoverToolbar from '../NodeHoverToolbar.vue';
9
+
10
+ const props = defineProps({
11
+ id: String,
12
+ data: {
13
+ type: Object,
14
+ default: () => ({
15
+ label: '直接回复',
16
+ description: '直接回复节点',
17
+ config: { text: '' },
18
+ }),
19
+ },
20
+ });
21
+
22
+ const emit = defineEmits(['duplicate', 'delete']);
23
+ const isHovered = ref(false);
24
+
25
+ const onMouseEnter = () => (isHovered.value = true);
26
+ const onMouseLeave = () => (isHovered.value = false);
27
+ const duplicateNode = () => emit('duplicate', props.id);
28
+ const deleteNode = () => emit('delete', props.id);
29
+
30
+ const getAnswerTexts = (answer: string) => {
31
+ const label: string[] = [];
32
+ const list = workflow_utils.splitExpressions(answer);
33
+ for (const it of list) {
34
+ if (it.startsWith('{{#')) label.push(it);
35
+ }
36
+ return label;
37
+ };
38
+
39
+ const getAnswerTextLabel = (str: string) => {
40
+ const list = str.replaceAll(/\{\{#(.*?)#\}\}/g, '$1').split('.');
41
+ return workflow_utils.getVariableLabel(list);
42
+ };
43
+ </script>
44
+
45
+ <template>
46
+ <div
47
+ class="wf-node answer-node"
48
+ @mouseenter="onMouseEnter"
49
+ @mouseleave="onMouseLeave"
50
+ >
51
+ <NodeHoverToolbar
52
+ v-if="isHovered"
53
+ node-type="answer"
54
+ @duplicate="duplicateNode"
55
+ @delete="deleteNode"
56
+ />
57
+
58
+ <div class="wf-node-header">
59
+ <div class="wf-node-icon">
60
+ <Icon name="answer" />
61
+ </div>
62
+ <div class="wf-node-info">
63
+ <div class="wf-node-title">{{ data.label }}</div>
64
+ <div class="wf-node-subtitle">直接回复用户</div>
65
+ </div>
66
+ </div>
67
+
68
+ <div class="wf-node-content">
69
+ <div class="wf-node-description">{{ data.description }}</div>
70
+ <div v-if="data.answer" class="wf-node-preview">
71
+ <div class="wf-node-preview-list">
72
+ <template v-for="text in getAnswerTexts(data.answer)" :key="text">
73
+ <div v-if="text.startsWith('{{#')">{{ getAnswerTextLabel(text) }}</div>
74
+ <div v-else>{{ text }}</div>
75
+ </template>
76
+ </div>
77
+ </div>
78
+ <div v-else class="wf-node-empty">
79
+ <span class="wf-node-empty-text">尚未配置回复内容</span>
80
+ </div>
81
+ </div>
82
+
83
+ <NodeHandle
84
+ :id="id"
85
+ type="target"
86
+ position="Left"
87
+ :is-hovered="isHovered"
88
+ class-name="flow-node-handle-left"
89
+ :style="{ background: '#f97316', border: '2px solid #ffffff' }"
90
+ />
91
+ </div>
92
+ </template>
93
+
94
+ <style scoped>
95
+ .answer-node {
96
+ --wf-accent: #f97316;
97
+ --wf-accent-hover: #ea580c;
98
+ }
99
+ </style>