@digitalsee-ai/rcs 2.0.4-beta9 → 2.0.4-rc3

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.
@@ -8,15 +8,10 @@ import { useWorkflow } from '../../hooks/useWorkflow';
8
8
  import { useAppDispatch } from '../../store';
9
9
  import { CanvasAPI, EdgeConfig as EngineEdgeConfig } from '../../types/engine';
10
10
  import { FlowDraftPayload } from '../../types/flowVersion';
11
+ import { TriggerNodeInfo } from '../../utils/triggerNode';
11
12
  import { Connection, Edge, EdgeChange, Node, NodeChange, useEdgesState, useNodesState, useReactFlow, useStoreApi } from '@xyflow/react';
12
13
  import { default as React } from 'react';
13
- /** 当前画布 trigger 节点信息;一个画布最多一个 trigger,记录它即可推导画布级状态。 */
14
- export interface TriggerNodeInfo {
15
- /** trigger 节点 id */
16
- id: string;
17
- /** 是否为 MCP Server 触发画布(trigger 节点的 action_key 指向 MCP Server) */
18
- isMcpServer: boolean;
19
- }
14
+ export type { TriggerNodeInfo } from '../../utils/triggerNode';
20
15
  export interface WorkflowCanvasStateResult {
21
16
  nodes: Node[];
22
17
  edges: Edge[];
@@ -0,0 +1,26 @@
1
+ import { ViewPlugin } from '@codemirror/view';
2
+ /** {{变量}} 高亮的 class 名,便于调试定位与外部样式覆盖 */
3
+ export declare const VARIABLE_HIGHLIGHT_CLASS = "workflow-code-variable";
4
+ /**
5
+ * 匹配带路径的节点变量 {{N节点ID.字段}}、全局变量 {{global.x}} 以及内置变量
6
+ * {{sys_tenant_id}} / {{response}},不把任意 {{...}} 当作变量。
7
+ */
8
+ export declare const buildVariableRegExp: () => RegExp;
9
+ /**
10
+ * 变量在编辑器中的展示文本:隐藏 {{global. 与 {{N节点ID. 前缀,只保留字段路径。
11
+ * 例如 {{global.userName}} -> {{userName}},{{ N1.profile.name }} -> {{profile.name}}。
12
+ */
13
+ export declare const buildVariableDisplayText: (raw: string) => string;
14
+ /**
15
+ * 给 CodeMirror 加 {{变量}} 高亮,并把变量块声明成原子区间。
16
+ *
17
+ * 结构与 JavascriptTagEditorField 的 placeholdersPlugin 保持一致:
18
+ * - 展示:用 replace 装饰把变量渲染成 {{字段路径}},隐藏 global. / N节点ID. 前缀,
19
+ * 不改变文档内容,复制、悬停提示与提交时仍是完整变量;
20
+ * - 原子区间:光标无法停在块中间(点击/方向键都落到块边界),选区端点也不会切进块内,
21
+ * 因此鼠标框选、双击与 Backspace/Delete 都是整块选中、整块删除。
22
+ *
23
+ * 做成工厂函数(同 placeholdersPlugin)是为了让每个编辑器实例持有独立的
24
+ * MatchDecorator 与正则实例,避免正则 lastIndex 在多实例间共享。
25
+ */
26
+ export declare const variableHighlightPlugin: () => ViewPlugin<any, undefined>;
@@ -1,3 +1,4 @@
1
1
  import { ViewPlugin } from '@codemirror/view';
2
2
  import { PlaceholderThemesType } from '../interface';
3
+ export declare const buildPlaceholderRegExp: () => RegExp;
3
4
  export declare const placeholdersPlugin: (themes: PlaceholderThemesType, mode?: string) => ViewPlugin<any, undefined>;
@@ -15,6 +15,7 @@ interface TextFieldProps extends IFieldSuperProps {
15
15
  lang?: CodeEditorLanguage;
16
16
  onFocus?: () => void;
17
17
  onBlur?: () => void;
18
+ required?: boolean;
18
19
  }
19
20
  export declare const TextField: (props: TextFieldProps) => import("react/jsx-runtime").JSX.Element;
20
21
  export {};
@@ -0,0 +1,30 @@
1
+ import { DynamicFormField } from '../../../dynamic-form/types/form-schema';
2
+ import { DynamicFormFields, NodeStatus, NodeType } from '../enums/node';
3
+ export declare const AI_FLOW_ACCEPTANCE_MANIFEST_VERSION = "1.0.0";
4
+ export declare const AI_FLOW_ACCEPTANCE_COVERAGE_VERSION = "2026.07.23-local";
5
+ export type AcceptanceSurface = {
6
+ id: string;
7
+ title: string;
8
+ source: string[];
9
+ uxEntry: string;
10
+ storyId: string;
11
+ tests: string[];
12
+ states: string[];
13
+ };
14
+ /**
15
+ * 当前本地验收口径的源码功能分母。
16
+ *
17
+ * 数量来自实际运行时枚举与 DynamicForm 注册类型,不以文档手写数量代替。
18
+ */
19
+ export declare const AI_FLOW_SOURCE_DENOMINATORS: {
20
+ readonly runtimeNodes: NodeType[];
21
+ readonly nodeStatuses: NodeStatus[];
22
+ readonly classicFields: DynamicFormFields[];
23
+ readonly nodeSchemaFields: DynamicFormField[];
24
+ };
25
+ /**
26
+ * 源码功能、UX 入口、Story 与自动化证据的版本化对应关系。
27
+ *
28
+ * 每一项至少提供一个真实本地页面入口、一个 Storybook 入口和一组测试证据。
29
+ */
30
+ export declare const AI_FLOW_ACCEPTANCE_SURFACES: AcceptanceSurface[];
@@ -0,0 +1,34 @@
1
+ export type CoverageGroup = {
2
+ key: string;
3
+ title: string;
4
+ description: string;
5
+ items: string[];
6
+ source: string;
7
+ };
8
+ export declare const AI_FLOW_COVERAGE_GROUPS: CoverageGroup[];
9
+ export declare const AI_FLOW_EXPECTED_COUNTS: {
10
+ readonly nodes: number;
11
+ readonly statuses: number;
12
+ readonly nodeSchemaFields: number;
13
+ readonly registeredNodeSchemaFields: number;
14
+ readonly classicFields: number;
15
+ };
16
+ export declare const AI_FLOW_COMPONENT_AREAS: readonly [{
17
+ readonly name: "画布骨架";
18
+ readonly components: readonly ["顶部栏", "保存/上线", "网格背景", "缩放控制", "MiniMap", "快速操作", "加载与错误态"];
19
+ }, {
20
+ readonly name: "节点与连线";
21
+ readonly components: readonly ["18 种节点注册", "9 种状态", "主端口", "AI 子端口", "分支端口", "连线操作"];
22
+ }, {
23
+ readonly name: "节点选择";
24
+ readonly components: readonly ["搜索", "分类筛选", "连接器卡片", "动作展开", "空态", "加载态"];
25
+ }, {
26
+ readonly name: "配置工作区";
27
+ readonly components: readonly ["变量树", "参数配置", "设置/错误处理", "节点测试", "账号与凭据", "在线 IDE", "执行管控", "模板设置"];
28
+ }, {
29
+ readonly name: "配置字段";
30
+ readonly components: readonly ["32 种 NodeSchema 字段", "19 种 Classic 字段", "条件显示", "校验", "动态选项", "变量插入"];
31
+ }, {
32
+ readonly name: "运行与调试";
33
+ readonly components: readonly ["节点测试", "忽略调试", "结果查看", "全流程检查", "调试面板", "成功/失败反馈"];
34
+ }];
@@ -1,5 +1,12 @@
1
1
  import { Node } from '@xyflow/react';
2
- type TriggerCandidate = Pick<Node, 'type'> & Partial<Pick<Node, 'data'>>;
2
+ type TriggerCandidate = Pick<Node, 'type' | 'id'> & Partial<Pick<Node, 'data'>>;
3
+ /** 当前画布 trigger 节点信息;一个画布最多一个 trigger,记录它即可推导画布级状态。 */
4
+ export interface TriggerNodeInfo {
5
+ /** trigger 节点 id */
6
+ id: string;
7
+ /** 是否为 MCP Server 触发画布(trigger 节点的 action_key 指向 MCP Server) */
8
+ isMcpServer: boolean;
9
+ }
3
10
  /**
4
11
  * 判断节点是否为 Trigger 节点。
5
12
  *
@@ -10,4 +17,11 @@ type TriggerCandidate = Pick<Node, 'type'> & Partial<Pick<Node, 'data'>>;
10
17
  * 一个画布最多只有一个 trigger 节点,因此画布级推导只需记录该节点信息即可。
11
18
  */
12
19
  export declare const isTriggerNode: (node?: TriggerCandidate | null) => boolean;
20
+ /**
21
+ * 从节点列表解析画布级 trigger 信息。
22
+ *
23
+ * 一个画布最多只有一个 trigger,因此找到第一个即可;`null` 表示当前画布没有 trigger。
24
+ * 抽成纯函数便于覆盖“新增/删除 trigger 后画布状态”的回归用例。
25
+ */
26
+ export declare const findTriggerNodeInfo: (nodes: readonly TriggerCandidate[]) => TriggerNodeInfo | null;
13
27
  export {};
@@ -56,6 +56,8 @@ export interface ValueModeWrapperProps {
56
56
  onFocus?: () => void;
57
57
  /** 失去焦点时的回调 */
58
58
  onBlur?: () => void;
59
+ /** 用户通过输入控件改值时的回调(外部程序化写值不会触发) */
60
+ onUserEdit?: (value: string) => void;
59
61
  /** 自定义渲染普通模式的组件 */
60
62
  renderNormalMode?: (props: {
61
63
  value?: string;
@@ -84,6 +86,8 @@ export interface ValueModeWrapperProps {
84
86
  * 代码编辑器语言(json / javascript)
85
87
  */
86
88
  lang?: CodeEditorLanguage;
89
+ /** 是否必填 */
90
+ required?: boolean;
87
91
  }
88
92
  export declare const ValueModeWrapper: React.FC<ValueModeWrapperProps>;
89
93
  export default ValueModeWrapper;
@@ -66,6 +66,8 @@ export interface FieldComponentProps<T extends FieldDef = FieldDef, K = unknown>
66
66
  onChange?: (value: unknown) => void;
67
67
  /** 字段 ID(由 Form.Item 注入) */
68
68
  id?: string;
69
+ /** 是否必填 */
70
+ required?: boolean;
69
71
  }
70
72
  /**
71
73
  * 字段组件元数据
@@ -0,0 +1,167 @@
1
+ import { jsx as e, jsxs as l } from "react/jsx-runtime";
2
+ import { D as N, V as $, f as S, a as D, v as F, R as M, g as V, j as R, b as W, s as B } from "./index-C5Zcv_fc.mjs";
3
+ import { useEventEmitter as G, useSize as L } from "ahooks";
4
+ import { FormattedMessage as f } from "react-intl";
5
+ import { CloseCircleFilled as A, CheckCircleFilled as P } from "@ant-design/icons";
6
+ import { Button as k } from "antd";
7
+ import { useRef as y, useMemo as T, useCallback as g, useEffect as z } from "react";
8
+ import { createPortal as H } from "react-dom";
9
+ const K = "_ideWrapper_sfar6_1", O = {
10
+ ideWrapper: K
11
+ }, U = (n) => {
12
+ const { nodeId: i, onInsert: o, open: d } = n, a = G();
13
+ return a.useSubscription((c) => {
14
+ c.type === "insert" && o(c.expression);
15
+ }), /* @__PURE__ */ e(N.Provider, { value: { event$: a }, children: /* @__PURE__ */ e("div", { className: O.ideWrapper, children: /* @__PURE__ */ e($, { nodeId: i, onInsert: o, open: d }) }) });
16
+ }, q = "_siderContainer_fhkbn_1", J = {
17
+ siderContainer: q
18
+ };
19
+ function Q(n) {
20
+ return /* @__PURE__ */ e("div", { className: J.siderContainer, children: /* @__PURE__ */ e(U, { open: n.open, nodeId: n.nodeId, onInsert: n.onInsert }) });
21
+ }
22
+ const X = {
23
+ javascript: "link.flow.code_editor_language_javascript",
24
+ json: "link.flow.code_editor_language_json"
25
+ };
26
+ function Y({ language: n = "javascript" }) {
27
+ return /* @__PURE__ */ l("h2", { id: "workflow-online-ide-title", className: "workflow-online-ide-title", children: [
28
+ /* @__PURE__ */ e(f, { id: "link.flow.code_editor" }),
29
+ " (",
30
+ /* @__PURE__ */ e(f, { id: X[n] }),
31
+ ")"
32
+ ] });
33
+ }
34
+ function Z(n) {
35
+ return /* @__PURE__ */ l("div", { className: "workflow-online-ide-toolbar", children: [
36
+ /* @__PURE__ */ e(k, { size: "small", onClick: n.onCancel, icon: /* @__PURE__ */ e(A, {}), children: /* @__PURE__ */ e(f, { id: "app.common.word.cancel" }) }),
37
+ /* @__PURE__ */ e(k, { type: "primary", size: "small", onClick: n.onFinish, icon: /* @__PURE__ */ e(P, {}), children: /* @__PURE__ */ e(f, { id: "app.common.word.finish" }) })
38
+ ] });
39
+ }
40
+ const ee = [{ trigger: "log", content: "console.log('$1');$2", desc: "输出日志" }, { trigger: "imp", content: "import $1 from '$2';$3" }, { trigger: "loop", content: `for (let $1=0; i< $2.length;i++) {
41
+
42
+ }`, desc: "循环操作" }], ne = {
43
+ snippets: ee
44
+ }, oe = "_modalContainer_1ajlo_5", ie = "_editorContainer_1ajlo_16", te = "_sider_1ajlo_25", re = "_main_1ajlo_34", ae = "_header_1ajlo_40", se = "_editor_1ajlo_16", s = {
45
+ modalContainer: oe,
46
+ editorContainer: ie,
47
+ sider: te,
48
+ main: re,
49
+ header: ae,
50
+ editor: se
51
+ }, le = (n) => n === "javascript" ? [R()] : [W()], de = (n) => {
52
+ const i = n.matchBefore(/[\w$]*/);
53
+ return !i || i.from === i.to && !n.explicit ? null : {
54
+ from: i.from,
55
+ options: ne.snippets.map(
56
+ (o) => B(o.content, {
57
+ label: o.trigger,
58
+ detail: o.desc
59
+ })
60
+ )
61
+ };
62
+ };
63
+ function _e(n) {
64
+ var j;
65
+ const {
66
+ initialValue: i = "",
67
+ language: o = "javascript",
68
+ nodeId: d,
69
+ onCancel: a,
70
+ onChange: c,
71
+ onFinish: v,
72
+ open: m,
73
+ showVariableSidebar: E = !0
74
+ } = n, p = y(null), _ = y(null), u = L(_), x = T(
75
+ () => [
76
+ ...le(o),
77
+ ...o === "javascript" ? [D({ override: [de] })] : [],
78
+ F(),
79
+ S
80
+ ],
81
+ [o]
82
+ ), I = g((r) => {
83
+ var b;
84
+ const t = (b = p.current) == null ? void 0 : b.view;
85
+ if (!t)
86
+ return;
87
+ const h = t.state.selection.main;
88
+ t.dispatch({
89
+ changes: {
90
+ from: h.from,
91
+ to: h.to,
92
+ insert: r
93
+ },
94
+ selection: {
95
+ anchor: h.from + r.length
96
+ }
97
+ }), t.focus();
98
+ }, []), w = g(
99
+ () => {
100
+ var r, t;
101
+ return ((t = (r = p.current) == null ? void 0 : r.view) == null ? void 0 : t.state.doc.toString()) ?? i;
102
+ },
103
+ [i]
104
+ ), C = g(() => {
105
+ v(w());
106
+ }, [w, v]);
107
+ return z(() => {
108
+ if (!m)
109
+ return;
110
+ const r = (t) => {
111
+ t.key === "Escape" && (t.preventDefault(), a());
112
+ };
113
+ return window.addEventListener("keydown", r), () => window.removeEventListener("keydown", r);
114
+ }, [a, m]), H(
115
+ /* @__PURE__ */ e(
116
+ "div",
117
+ {
118
+ className: s.modalContainer,
119
+ ref: _,
120
+ style: { display: m ? "flex" : "none" },
121
+ role: "dialog",
122
+ "aria-modal": "true",
123
+ "aria-labelledby": "workflow-online-ide-title",
124
+ children: /* @__PURE__ */ l("div", { className: s.editorContainer, id: "javascript-code-editor", children: [
125
+ E ? /* @__PURE__ */ e("div", { className: s.sider, style: { maxWidth: "20%", padding: 0 }, children: /* @__PURE__ */ e(
126
+ Q,
127
+ {
128
+ onCancel: a,
129
+ onFinish: C,
130
+ editor: (j = p.current) == null ? void 0 : j.view,
131
+ nodeId: d ?? "",
132
+ open: !!m,
133
+ onInsert: I
134
+ }
135
+ ) }) : null,
136
+ /* @__PURE__ */ l("div", { className: s.main, children: [
137
+ /* @__PURE__ */ l("div", { className: s.header, children: [
138
+ /* @__PURE__ */ e(Y, { language: o }),
139
+ /* @__PURE__ */ e(Z, { onCancel: a, onFinish: C })
140
+ ] }),
141
+ /* @__PURE__ */ e("div", { className: s.editor, children: /* @__PURE__ */ e(
142
+ M,
143
+ {
144
+ ref: p,
145
+ value: i,
146
+ height: `${Math.max(((u == null ? void 0 : u.height) ?? 0) - 40, 0)}px`,
147
+ theme: V,
148
+ extensions: x,
149
+ onChange: c,
150
+ basicSetup: {
151
+ lineNumbers: !0,
152
+ foldGutter: !1
153
+ }
154
+ },
155
+ d
156
+ ) })
157
+ ] })
158
+ ] })
159
+ }
160
+ ),
161
+ document.body
162
+ );
163
+ }
164
+ export {
165
+ _e as default
166
+ };
167
+ //# sourceMappingURL=index-Bk0YRxdv.mjs.map