@agentscope-ai/flow 0.0.3 → 0.0.5

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.
@@ -2,6 +2,8 @@ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" ==
2
2
  function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
3
3
  function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
4
4
  function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
5
+ function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
6
+ function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
5
7
  function _toArray(arr) { return _arrayWithHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableRest(); }
6
8
  function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
7
9
  function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
@@ -15,11 +17,11 @@ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol"
15
17
  function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
16
18
  import $i18n from "../../i18n";
17
19
  import { extractVariables, matchVariableFromVarItem } from "../../utils";
18
- import { Button, getCommonConfig, Input, Select } from '@agentscope-ai/design';
20
+ import { Button, Form, getCommonConfig, Input, Select } from '@agentscope-ai/design';
19
21
  import { SparkClearLine, SparkDeleteLine, SparkEditLine, SparkPlusLine, SparkQuotationLine } from '@agentscope-ai/icons';
20
22
  import { theme, Typography } from 'antd';
21
23
  import classNames from 'classnames';
22
- import React, { memo, useCallback, useMemo } from 'react';
24
+ import React, { memo, useCallback, useEffect, useMemo } from 'react';
23
25
  import FlowIcon from "../flow-icon";
24
26
  import VariableInput, { VariableBaseInput } from "../variable-input";
25
27
  import VariableTreeSelect from "../variable-tree-select";
@@ -236,11 +238,66 @@ export var VALUE_FROM_OPTIONS = [{
236
238
  })),
237
239
  value: 'input'
238
240
  }];
241
+
242
+ /**
243
+ * 创建变量名验证规则
244
+ * @param allValues 所有变量的值数组,用于检查重复
245
+ * @param currentIndex 当前编辑的变量索引
246
+ */
247
+ var createVariableNameRules = function createVariableNameRules(allValues, currentIndex) {
248
+ return [{
249
+ validator: function validator(_, value) {
250
+ if (!value || value.trim() === '') {
251
+ return Promise.resolve();
252
+ }
253
+
254
+ // 检查是否以数字开头
255
+ if (/^\d/.test(value)) {
256
+ return Promise.reject(new Error($i18n.get({
257
+ id: 'spark-flow.components.CustomInputsControl.index.variableNameCannotStartWithNumber',
258
+ dm: '变量名不能以数字开头'
259
+ })));
260
+ }
261
+
262
+ // 检查是否包含非法字符
263
+ if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(value)) {
264
+ return Promise.reject(new Error($i18n.get({
265
+ id: 'spark-flow.components.CustomInputsControl.index.variableNameOnlyAllowLettersNumbersUnderscores',
266
+ dm: '变量名只能包含字母、数字和下划线'
267
+ })));
268
+ }
269
+
270
+ // 检查是否重复
271
+ var isDuplicate = allValues.some(function (item, index) {
272
+ return index !== currentIndex && item.key === value && item.key !== '';
273
+ });
274
+ if (isDuplicate) {
275
+ return Promise.reject(new Error($i18n.get({
276
+ id: 'spark-flow.components.CustomInputsControl.index.variableNameDuplicate',
277
+ dm: '变量名不能重复'
278
+ })));
279
+ }
280
+ return Promise.resolve();
281
+ }
282
+ }];
283
+ };
239
284
  export default /*#__PURE__*/memo(function CustomInputsControl(props) {
240
285
  var _props$value = props.value,
241
286
  value = _props$value === void 0 ? [] : _props$value;
242
287
  var _theme$useToken = theme.useToken(),
243
288
  token = _theme$useToken.token;
289
+ var _Form$useForm = Form.useForm(),
290
+ _Form$useForm2 = _slicedToArray(_Form$useForm, 1),
291
+ form = _Form$useForm2[0];
292
+
293
+ // 同步 value 到 form
294
+ useEffect(function () {
295
+ var formValues = {};
296
+ value.forEach(function (item, index) {
297
+ formValues["var_".concat(index)] = item.key;
298
+ });
299
+ form.setFieldsValue(formValues);
300
+ }, [value, form]);
244
301
  var changeRowValue = useCallback(function (ind, payload) {
245
302
  var newVal = value.map(function (item, index) {
246
303
  if (index === ind) {
@@ -267,7 +324,10 @@ export default /*#__PURE__*/memo(function CustomInputsControl(props) {
267
324
  }, [props.onChange, value]);
268
325
  var _getCommonConfig = getCommonConfig(),
269
326
  antPrefix = _getCommonConfig.antPrefix;
270
- return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
327
+ return /*#__PURE__*/React.createElement(Form, {
328
+ form: form,
329
+ component: false
330
+ }, /*#__PURE__*/React.createElement("div", {
271
331
  className: "spark-flow-inputs-form-label flex gap-[8px]"
272
332
  }, /*#__PURE__*/React.createElement("div", {
273
333
  style: {
@@ -290,12 +350,16 @@ export default /*#__PURE__*/memo(function CustomInputsControl(props) {
290
350
  return /*#__PURE__*/React.createElement("div", {
291
351
  key: index,
292
352
  className: "spark-flow-inputs-form-item flex gap-[8px] items-stretch w-full"
293
- }, /*#__PURE__*/React.createElement(Input, {
353
+ }, /*#__PURE__*/React.createElement(Form.Item, {
354
+ name: "var_".concat(index),
294
355
  style: {
295
- width: props.disabledValueFrom ? 146 : 84
356
+ width: props.disabledValueFrom ? 146 : 84,
357
+ marginBottom: 0,
358
+ flexShrink: 0
296
359
  },
297
- className: "flex-shrink-0",
298
- value: item.key,
360
+ validateTrigger: ['onChange', 'onBlur'],
361
+ rules: createVariableNameRules(value, index)
362
+ }, /*#__PURE__*/React.createElement(Input, {
299
363
  placeholder: $i18n.get({
300
364
  id: 'spark-flow.components.CustomInputsControl.index.enterVariableName',
301
365
  dm: '请输入变量名'
@@ -312,7 +376,7 @@ export default /*#__PURE__*/memo(function CustomInputsControl(props) {
312
376
  color: token.colorError
313
377
  }
314
378
  }, "*") : null
315
- }), !props.disabledValueFrom && /*#__PURE__*/React.createElement(Select, {
379
+ })), !props.disabledValueFrom && /*#__PURE__*/React.createElement(Select, {
316
380
  style: {
317
381
  width: 60
318
382
  },
@@ -6,8 +6,6 @@
6
6
  }
7
7
  }
8
8
  .spark-flow-variable-from-select {
9
- height: auto !important;
10
-
11
9
  .@{ant-prefix}-select-selection-item {
12
10
  height: 30px;
13
11
  }
@@ -74,27 +74,27 @@ var NodeResultPanel = function NodeResultPanel(props) {
74
74
  _useState2 = _slicedToArray(_useState, 2),
75
75
  expand = _useState2[0],
76
76
  setExpand = _useState2[1];
77
- var isBatch = props.data.isBatch && !!props.data.batches;
77
+ var batch = props.data.batch && !!props.data.batches;
78
78
  var _useState3 = useState(1),
79
79
  _useState4 = _slicedToArray(_useState3, 2),
80
80
  batchIndex = _useState4[0],
81
81
  setBatchIndex = _useState4[1];
82
82
  var inputContent = useMemo(function () {
83
- if (isBatch) {
83
+ if (batch) {
84
84
  var _props$data$batches;
85
85
  return (_props$data$batches = props.data.batches[batchIndex - 1]) === null || _props$data$batches === void 0 ? void 0 : _props$data$batches.input;
86
86
  }
87
87
  return props.data.input;
88
88
  }, [props.data, batchIndex]);
89
89
  var outputContent = useMemo(function () {
90
- if (isBatch) {
90
+ if (batch) {
91
91
  var _props$data$batches2;
92
92
  return (_props$data$batches2 = props.data.batches[batchIndex - 1]) === null || _props$data$batches2 === void 0 ? void 0 : _props$data$batches2.output;
93
93
  }
94
94
  return props.data.output;
95
95
  }, [props.data, batchIndex]);
96
96
  var errorInfoContent = useMemo(function () {
97
- if (isBatch) {
97
+ if (batch) {
98
98
  var _props$data$batches3;
99
99
  return (_props$data$batches3 = props.data.batches[batchIndex - 1]) === null || _props$data$batches3 === void 0 ? void 0 : _props$data$batches3.errorInfo;
100
100
  }
@@ -123,7 +123,7 @@ var NodeResultPanel = function NodeResultPanel(props) {
123
123
  className: "spark-flow-node-result-time"
124
124
  }, props.data.nodeExecTime)), props.data.nodeStatus !== 'skip' && /*#__PURE__*/React.createElement(SparkUpLine, {
125
125
  className: "text-base spark-flow-node-result-expand-icon"
126
- })), expand && isBatch && /*#__PURE__*/React.createElement(Pagination, {
126
+ })), expand && batch && /*#__PURE__*/React.createElement(Pagination, {
127
127
  current: batchIndex,
128
128
  total: props.data.batches.length,
129
129
  pageSize: 1,
@@ -62,10 +62,6 @@ var createCompletionSource = function createCompletionSource(inputParams) {
62
62
  console.log('IME composing, blocking autocomplete');
63
63
  return null;
64
64
  }
65
-
66
- // 恢复原来的匹配逻辑:匹配任意单词字符
67
- var word = context.matchBefore(/\w*/);
68
- if (!word) return null;
69
65
  var completions = _toConsumableArray(inputParams.map(function (param) {
70
66
  return {
71
67
  label: "params.".concat(param.key),
@@ -73,6 +69,20 @@ var createCompletionSource = function createCompletionSource(inputParams) {
73
69
  info: "Params parameter: ".concat(param.key, " (").concat(param.type, ")")
74
70
  };
75
71
  }));
72
+
73
+ // 检查是否是 / 触发的补全
74
+ var slashMatch = context.matchBefore(/\/\w*/);
75
+ if (slashMatch) {
76
+ return {
77
+ from: slashMatch.from + 1,
78
+ // 从 / 后面开始替换,保留 /
79
+ options: completions
80
+ };
81
+ }
82
+
83
+ // 正常的单词补全:使用 \w+ 确保至少有一个字符,避免特殊字符触发
84
+ var word = context.matchBefore(/\w+/);
85
+ if (!word) return null;
76
86
  return {
77
87
  from: word.from,
78
88
  options: completions
@@ -120,7 +120,7 @@ export interface IWorkFlowTaskResultItem {
120
120
  parentNodeId?: string;
121
121
  }
122
122
  export interface IWorkFlowNodeResultItem {
123
- isBatch: boolean;
123
+ batch: boolean;
124
124
  retry?: {
125
125
  happened: boolean;
126
126
  retryTimes: number;
@@ -133,7 +133,7 @@ export interface IWorkFlowNodeResultItem {
133
133
  totalTokens: number;
134
134
  }[];
135
135
  batches: IWorkFlowNodeResultItem[];
136
- isMultiBranch: boolean;
136
+ multiBranch: boolean;
137
137
  multiBranchResults?: {
138
138
  conditionId: string;
139
139
  targetIds: string[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentscope-ai/flow",
3
- "version": "0.0.3",
3
+ "version": "0.0.5",
4
4
  "description": "A powerful and flexible flow canvas rendering engine designed for AI applications. Provides comprehensive workflow visualization and interaction capabilities for platforms like Bailian and AgentScope, enabling seamless creation and management of complex AI agent workflows with an intuitive drag-and-drop interface.",
5
5
  "module": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
package/README.zh-CN.md DELETED
@@ -1,67 +0,0 @@
1
- # Spark Flow
2
- ## 项目介绍
3
- Spark Flow是供给主包`packages/main`的画布编辑基础业务组件,主要技术栈包含React、React Flow、Antd、zustand等。
4
-
5
- ### 主要功能
6
- + 节点检查清单列表;
7
- + 节点管理器;
8
- + 画布执行状态管理;
9
- + 支持回退、撤销;
10
- + 支持全生命周期快速定制业务节点;
11
- + 支持复杂节点交互;
12
-
13
- ### 项目主要结构
14
- ```plain
15
- spark-flow/
16
- ├── docs/
17
- ├── public/ # 静态资源文件
18
- ├── src/
19
- │ ├── components/ # 基础组件
20
- │ ├── constant/ # 可视化工作流编辑器
21
- │ ├── demos/ # 国际化支持
22
- │ ├── flow/ # 画布组件主入口
23
- │ ├── hooks/ # 画布类操作工具库
24
- │ ├── i18n/ # 国际化
25
- │ ├── store/ # 全局状态管理
26
- │ ├── types/ # 类型定义
27
- | ├── utils/ # 函数工具库
28
- | ├── index.less/ # less变量定义
29
- | └── index.ts/ # 项目主入口文件
30
- └── package.json # 项目配置
31
- ```
32
-
33
- #### 节点结构
34
- ```plain
35
- [业务节点名]
36
- ├── node # 画布节点渲染
37
- ├── panel # 节点配置面板
38
- └── schema # 节点Schema协议配置
39
- ```
40
-
41
- #### 自定义
42
- + 通过覆盖 `packages/spark-flow/src/index.less` 中的 `@ant-prefix` 可以修改样式文件中的自定义类名和 CSS 变量名前缀;
43
- + 同时需要在项目中通过 `ConfigProvider` 设置自定义类名和 CSS 变量名前缀:
44
- ```
45
- import { ConfigProvider } from '@agentscope-ai/design';
46
-
47
- <ConfigProvider prefix="efm" prefixCls="efm_ant>
48
- ...
49
- </ConfigProvider>
50
- ```
51
-
52
- ## 如何开发
53
- ### 快速启动
54
- ```shell
55
- npm run re-install && cd packages/spark-flow && npm start
56
- ```
57
-
58
- + **安装依赖** 在根目录执行`npm run re-install`
59
- + **运行** cd`packages/spark-flow`且执行`npm start`
60
-
61
- ### 开发
62
- > [!NOTE]
63
- > **注意:** 前提是你完成了快速启动的 **安装依赖** 操作
64
-
65
- + 开发完之后根目录下执行`npm run fresh:flow`能够快速清除主包`packages/main`的依赖;
66
- + 进入主包`packages/main`执行`npm start`
67
- + 进行测试 & 验证;