@digitalsee-ai/rcs 1.1.0 → 1.1.1

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 (83) hide show
  1. package/dist/components/digitalsee/workflow/Canvas/actionItemToNodeData.d.ts +14 -0
  2. package/dist/components/digitalsee/workflow/Canvas/constants.d.ts +1 -15
  3. package/dist/components/digitalsee/workflow/Canvas/constants.test.d.ts +1 -0
  4. package/dist/components/digitalsee/workflow/Canvas/hooks/classicNodeAddConnection.d.ts +31 -0
  5. package/dist/components/digitalsee/workflow/Canvas/hooks/classicNodeAddConnection.test.d.ts +1 -0
  6. package/dist/components/digitalsee/workflow/Canvas/hooks/createNodeAddHandlerNext.d.ts +1 -16
  7. package/dist/components/digitalsee/workflow/Canvas/hooks/useNodeAddCallback.d.ts +4 -17
  8. package/dist/components/digitalsee/workflow/Canvas/hooks/useWorkflowCanvasState.d.ts +3 -1
  9. package/dist/components/digitalsee/workflow/Handles/CustomHandle.d.ts +3 -0
  10. package/dist/components/digitalsee/workflow/Handles/customHandleConnectable.d.ts +35 -0
  11. package/dist/components/digitalsee/workflow/Handles/customHandleConnectable.test.d.ts +1 -0
  12. package/dist/components/digitalsee/workflow/Nodes/ConditionNode.d.ts +1 -1
  13. package/dist/components/digitalsee/workflow/Nodes/SuperBaseNode.d.ts +6 -1
  14. package/dist/components/digitalsee/workflow/Nodes/SwitchNode.d.ts +1 -1
  15. package/dist/components/digitalsee/workflow/Nodes/classicNodePackageNodes.test.d.ts +1 -0
  16. package/dist/components/digitalsee/workflow/Nodes/classicNodePackagePortLayout.d.ts +23 -0
  17. package/dist/components/digitalsee/workflow/Nodes/classicNodePackagePortLayout.test.d.ts +1 -0
  18. package/dist/components/digitalsee/workflow/Nodes/useClassicNodePackagePorts.d.ts +26 -0
  19. package/dist/components/digitalsee/workflow/Nodes/useClassicNodePackagePorts.test.d.ts +1 -0
  20. package/dist/components/digitalsee/workflow/Panels/ModernNodeSelectorPanel/components/EntryTypeSelector.d.ts +8 -0
  21. package/dist/components/digitalsee/workflow/Panels/ModernNodeSelectorPanel/components/NodeCardList.d.ts +19 -0
  22. package/dist/components/digitalsee/workflow/Panels/ModernNodeSelectorPanel/hooks/useCategories.d.ts +5 -2
  23. package/dist/components/digitalsee/workflow/Panels/ModernNodeSelectorPanel/hooks/useConnectableNodeSelector.d.ts +40 -0
  24. package/dist/components/digitalsee/workflow/Panels/ModernNodeSelectorPanel/hooks/useNavigation.d.ts +4 -2
  25. package/dist/components/digitalsee/workflow/Panels/ModernNodeSelectorPanel/hooks/useNavigation.test.d.ts +1 -0
  26. package/dist/components/digitalsee/workflow/Panels/ModernNodeSelectorPanel/hooks/useNodeActionState.d.ts +30 -0
  27. package/dist/components/digitalsee/workflow/Panels/ModernNodeSelectorPanel/hooks/useNodeSelectorPresentation.d.ts +24 -0
  28. package/dist/components/digitalsee/workflow/Panels/ModernNodeSelectorPanel/types.d.ts +19 -1
  29. package/dist/components/digitalsee/workflow/Panels/ModernNodeSelectorPanel/utils/connectableActionLoader.d.ts +16 -0
  30. package/dist/components/digitalsee/workflow/Panels/ModernNodeSelectorPanel/utils/connectableActionLoader.test.d.ts +1 -0
  31. package/dist/components/digitalsee/workflow/Panels/ModernNodeSelectorPanel/utils/connectableFallback.d.ts +2 -0
  32. package/dist/components/digitalsee/workflow/Panels/ModernNodeSelectorPanel/utils/connectableFallback.test.d.ts +1 -0
  33. package/dist/components/digitalsee/workflow/Panels/ModernNodeSelectorPanel/utils/connectableQuery.d.ts +40 -0
  34. package/dist/components/digitalsee/workflow/Panels/ModernNodeSelectorPanel/utils/connectableQuery.test.d.ts +1 -0
  35. package/dist/components/digitalsee/workflow/Panels/ModernNodeSelectorPanel/utils/connectableResponse.d.ts +35 -0
  36. package/dist/components/digitalsee/workflow/Panels/ModernNodeSelectorPanel/utils/connectableResponse.test.d.ts +1 -0
  37. package/dist/components/digitalsee/workflow/Panels/ModernNodeSelectorPanel/utils/dataTransformers.d.ts +13 -2
  38. package/dist/components/digitalsee/workflow/Panels/ModernNodeSelectorPanel/utils/filterEdgeInsertActions.d.ts +62 -0
  39. package/dist/components/digitalsee/workflow/Panels/ModernNodeSelectorPanel/utils/filterEdgeInsertActions.test.d.ts +1 -0
  40. package/dist/components/digitalsee/workflow/Panels/ModernNodeSelectorPanel/utils/nodeAddContext.d.ts +26 -0
  41. package/dist/components/digitalsee/workflow/Panels/ModernNodeSelectorPanel/utils/nodeAddContext.test.d.ts +1 -0
  42. package/dist/components/digitalsee/workflow/Panels/ModernNodeSelectorPanel/utils/queryParams.d.ts +18 -0
  43. package/dist/components/digitalsee/workflow/Panels/ModernNodeSelectorPanel/utils/queryParams.test.d.ts +1 -0
  44. package/dist/components/digitalsee/workflow/api/connectable.test.d.ts +1 -0
  45. package/dist/components/digitalsee/workflow/api/connectable.types.d.ts +75 -0
  46. package/dist/components/digitalsee/workflow/api/dip.types.d.ts +30 -0
  47. package/dist/components/digitalsee/workflow/api/index.d.ts +6 -1
  48. package/dist/components/digitalsee/workflow/config/defaultCanvasEngineConfig.test.d.ts +1 -0
  49. package/dist/components/digitalsee/workflow/config/defaultNodeSelectorConfig.d.ts +9 -0
  50. package/dist/components/digitalsee/workflow/events/eventBus.d.ts +2 -12
  51. package/dist/components/digitalsee/workflow/hooks/usePanel.d.ts +3 -17
  52. package/dist/components/digitalsee/workflow/store/panelSlice.d.ts +118 -41
  53. package/dist/components/digitalsee/workflow/types/Node.d.ts +1 -1
  54. package/dist/components/digitalsee/workflow/types/NodeAddContext.d.ts +31 -0
  55. package/dist/components/digitalsee/workflow/types/engine.d.ts +15 -0
  56. package/dist/components/digitalsee/workflow/utils/classicNodeActionIdentity.d.ts +7 -0
  57. package/dist/components/digitalsee/workflow/utils/classicNodeActionIdentity.test.d.ts +1 -0
  58. package/dist/components/digitalsee/workflow/utils/classicNodePackageConnection.d.ts +28 -0
  59. package/dist/components/digitalsee/workflow/utils/classicNodePackageConnection.test.d.ts +1 -0
  60. package/dist/components/digitalsee/workflow/utils/classicNodePackageGraphValidation.d.ts +29 -0
  61. package/dist/components/digitalsee/workflow/utils/classicNodePackageGraphValidation.test.d.ts +1 -0
  62. package/dist/components/digitalsee/workflow/utils/compatiblePortSelection.d.ts +79 -0
  63. package/dist/components/digitalsee/workflow/utils/compatiblePortSelection.test.d.ts +1 -0
  64. package/dist/components/digitalsee/workflow/utils/nextNodeSchemaCache.d.ts +8 -0
  65. package/dist/components/digitalsee/workflow/utils/nodeDataFormatter.test.d.ts +1 -0
  66. package/dist/components/digitalsee/workflow/utils/portConnectionValidationMessages.d.ts +48 -0
  67. package/dist/components/digitalsee/workflow/utils/portConnectionValidationMessages.test.d.ts +1 -0
  68. package/dist/components/digitalsee/workflow/utils/portConnectionValidator.d.ts +66 -0
  69. package/dist/components/digitalsee/workflow/utils/portConnectionValidator.test.d.ts +1 -0
  70. package/dist/components/digitalsee/workflow/utils/workflowConnectionValidator.d.ts +20 -0
  71. package/dist/components/digitalsee/workflow/utils/workflowConnectionValidator.test.d.ts +1 -0
  72. package/dist/locales/en-US/link/flow.d.ts +22 -0
  73. package/dist/locales/en-US.d.ts +22 -0
  74. package/dist/locales/zh-CN/link/flow.d.ts +22 -0
  75. package/dist/locales/zh-CN.d.ts +22 -0
  76. package/dist/locales/zh-TW/link/flow.d.ts +22 -0
  77. package/dist/locales/zh-TW.d.ts +22 -0
  78. package/dist/rcs.css +1 -1
  79. package/dist/rcs.es.js +19150 -17210
  80. package/dist/rcs.es.js.map +1 -1
  81. package/dist/rcs.umd.js +59 -59
  82. package/dist/rcs.umd.js.map +1 -1
  83. package/package.json +1 -1
@@ -18,6 +18,7 @@ export interface CanvasEngineConfig {
18
18
  flowId: string;
19
19
  engineMode?: EngineMode;
20
20
  canvas: CanvasCoreConfig;
21
+ nodeSelector: NodeSelectorConfig;
21
22
  nodeTypes: NodeTypesRegistryConfig;
22
23
  edgeRules: EdgeRulesConfig;
23
24
  toolbar: ToolbarConfig;
@@ -25,6 +26,20 @@ export interface CanvasEngineConfig {
25
26
  httpClient?: HttpClient;
26
27
  history?: HistoryNavigator;
27
28
  }
29
+ /**
30
+ * NodePackage 可连线候选能力配置。
31
+ *
32
+ * 默认关闭,由 CLASSIC/ACM 宿主显式启用,便于在接口联调异常时快速回退旧候选链路。
33
+ */
34
+ export interface NodeSelectorConnectableConfig {
35
+ enabled: boolean;
36
+ scene: string;
37
+ fallbackToLegacy: boolean;
38
+ debug: boolean;
39
+ }
40
+ export interface NodeSelectorConfig {
41
+ connectable: NodeSelectorConnectableConfig;
42
+ }
28
43
  type NativeReactFLowProps = ComponentProps<typeof ReactFlow>;
29
44
  export interface RegisterComponents {
30
45
  form: {
@@ -0,0 +1,7 @@
1
+ import { ActionItem } from '../Panels/ModernNodeSelectorPanel/types';
2
+ /**
3
+ * 解析 CLASSIC create-node API 使用的原始 Long action_id。
4
+ *
5
+ * NodePackage 的 UI key 通常是 actionKey,而后端 action id 可能为 0/负数;两者不可混用。
6
+ */
7
+ export declare function resolveClassicCreateActionId(action: Pick<ActionItem, 'id' | 'backendActionId' | 'action_id'>): string;
@@ -0,0 +1,28 @@
1
+ import { DipNodeSchema } from '../api/dip';
2
+ import { PortConnectionEdge, PortConnectionValidationCode } from './portConnectionValidator';
3
+ import { Node } from '@xyflow/react';
4
+ export type ClassicNodePackageConnectionCode = PortConnectionValidationCode | 'NOT_APPLICABLE' | 'SCHEMA_NOT_READY';
5
+ export interface ClassicNodePackageConnectionResult {
6
+ applicable: boolean;
7
+ valid: boolean;
8
+ code: ClassicNodePackageConnectionCode;
9
+ reason: string;
10
+ missingSchemaNodeIds?: string[];
11
+ }
12
+ export interface ValidateClassicNodePackageConnectionInput {
13
+ sourceNode?: Node | null;
14
+ targetNode?: Node | null;
15
+ sourceHandle?: string | null;
16
+ targetHandle?: string | null;
17
+ edges?: readonly PortConnectionEdge[];
18
+ }
19
+ /** 同步解析节点内联或已预加载的 CLASSIC nodepackage Schema。 */
20
+ export declare function resolveClassicNodePackageSchema(node?: Node | null): DipNodeSchema | null;
21
+ export declare function isClassicNodePackageNode(node?: Node | null): boolean;
22
+ /**
23
+ * 校验两个 CLASSIC nodepackage 节点之间的端口连接。
24
+ *
25
+ * 混合 legacy/nodepackage 连接保留前端当前精确 handle 名称,并按后端虚拟端口契约
26
+ * 将 legacy 端口能力类型统一映射为 main。
27
+ */
28
+ export declare function validateClassicNodePackageConnection({ sourceNode, targetNode, sourceHandle, targetHandle, edges, }: ValidateClassicNodePackageConnectionInput): ClassicNodePackageConnectionResult;
@@ -0,0 +1,29 @@
1
+ import { PortConnectionValidationCode } from './portConnectionValidator';
2
+ import { Edge, Node } from '@xyflow/react';
3
+ export type ClassicNodePackageGraphIssueCode = PortConnectionValidationCode | 'REQUIRED_INPUT_MISSING' | 'SCHEMA_NOT_READY';
4
+ export interface ClassicNodePackageGraphIssue {
5
+ code: ClassicNodePackageGraphIssueCode;
6
+ reason: string;
7
+ blocking: boolean;
8
+ nodeId?: string;
9
+ portName?: string;
10
+ edgeId?: string;
11
+ sourceNodeId?: string;
12
+ targetNodeId?: string;
13
+ }
14
+ export interface ClassicNodePackageGraphValidationResult {
15
+ valid: boolean;
16
+ issues: ClassicNodePackageGraphIssue[];
17
+ blockingIssues: ClassicNodePackageGraphIssue[];
18
+ missingSchemaNodeIds: string[];
19
+ }
20
+ interface ValidateClassicNodePackageGraphInput {
21
+ nodes: readonly Node[];
22
+ edges: readonly Edge[];
23
+ }
24
+ /**
25
+ * 保存前检查当前已知的 CLASSIC nodepackage 端口约束。
26
+ * Schema 尚未加载属于非阻塞 warning,最终交给 ACM 后端兜底;已知非法端口则阻止保存。
27
+ */
28
+ export declare function validateClassicNodePackageGraph({ nodes, edges, }: ValidateClassicNodePackageGraphInput): ClassicNodePackageGraphValidationResult;
29
+ export {};
@@ -0,0 +1,79 @@
1
+ import { DipNodeSchema } from '../api/dip.types';
2
+ import { PortConnectionEdge, PortConnectionNode, PortConnectionValidationCode } from './portConnectionValidator';
3
+ type SourceNodeSchema = Pick<DipNodeSchema, 'outputs'>;
4
+ type TargetNodeSchema = Pick<DipNodeSchema, 'inputs'>;
5
+ type InsertedNodeSchema = Pick<DipNodeSchema, 'inputs' | 'outputs'>;
6
+ export type CompatiblePortSelectionCode = 'COMPATIBLE_PORT_PAIR_FOUND' | 'SOURCE_PORTS_EMPTY' | 'TARGET_PORTS_EMPTY' | 'SOURCE_HANDLE_NOT_FOUND' | 'TARGET_HANDLE_NOT_FOUND' | 'NO_COMPATIBLE_PORT_PAIR';
7
+ /** 自动选端口的结构化结果;compatibleCount 大于 1 时调用方可记录歧义日志。 */
8
+ export interface CompatiblePortSelectionResult {
9
+ valid: boolean;
10
+ code: CompatiblePortSelectionCode;
11
+ reason: string;
12
+ sourceHandle: string | null;
13
+ targetHandle: string | null;
14
+ compatibleCount: number;
15
+ /** 未找到组合时记录首个候选的底层校验码,便于 UI 映射文案。 */
16
+ validationCode: PortConnectionValidationCode | null;
17
+ }
18
+ export interface SelectCompatiblePortPairInput {
19
+ sourceNode: PortConnectionNode;
20
+ targetNode: PortConnectionNode;
21
+ sourceSchema: SourceNodeSchema;
22
+ targetSchema: TargetNodeSchema;
23
+ edges?: readonly PortConnectionEdge[];
24
+ /** 已存在的源 handle;缺失时按 sourceSchema.outputs 顺序枚举。 */
25
+ sourceHandle?: string | null;
26
+ /** 已存在的目标 handle;缺失时按 targetSchema.inputs 顺序枚举。 */
27
+ targetHandle?: string | null;
28
+ }
29
+ export interface SelectSourceToNewCompatiblePortInput {
30
+ sourceNode: PortConnectionNode;
31
+ newNode: PortConnectionNode;
32
+ sourceSchema: SourceNodeSchema;
33
+ newNodeSchema: TargetNodeSchema;
34
+ sourceHandle: string | null | undefined;
35
+ edges?: readonly PortConnectionEdge[];
36
+ }
37
+ export interface SelectNewToTargetCompatiblePortInput {
38
+ newNode: PortConnectionNode;
39
+ targetNode: PortConnectionNode;
40
+ newNodeSchema: SourceNodeSchema;
41
+ targetSchema: TargetNodeSchema;
42
+ targetHandle: string | null | undefined;
43
+ edges?: readonly PortConnectionEdge[];
44
+ }
45
+ export type EdgeInsertPortSelectionCode = 'EDGE_INSERT_PORTS_FOUND' | 'SOURCE_TO_NEW_INCOMPATIBLE' | 'NEW_TO_TARGET_INCOMPATIBLE';
46
+ export interface EdgeInsertPortSelectionResult {
47
+ valid: boolean;
48
+ code: EdgeInsertPortSelectionCode;
49
+ reason: string;
50
+ /** 两段可选组合数的乘积。 */
51
+ compatibleCount: number;
52
+ sourceToNew: CompatiblePortSelectionResult;
53
+ newToTarget: CompatiblePortSelectionResult | null;
54
+ }
55
+ export interface SelectCompatiblePortsForEdgeInsertInput {
56
+ sourceNode: PortConnectionNode;
57
+ newNode: PortConnectionNode;
58
+ targetNode: PortConnectionNode;
59
+ sourceSchema: SourceNodeSchema;
60
+ newNodeSchema: InsertedNodeSchema;
61
+ targetSchema: TargetNodeSchema;
62
+ sourceHandle: string | null | undefined;
63
+ targetHandle: string | null | undefined;
64
+ edges?: readonly PortConnectionEdge[];
65
+ /** 插边成功后会替换的旧边;校验连接数时必须先排除。 */
66
+ replacedEdgeId?: string;
67
+ }
68
+ /**
69
+ * 按 source outputs → target inputs 的 Schema 顺序枚举所有组合。
70
+ * 会继续扫描首个成功组合之后的候选,以便返回准确的 compatibleCount。
71
+ */
72
+ export declare const selectCompatiblePortPair: ({ sourceNode, targetNode, sourceSchema, targetSchema, sourceHandle, targetHandle, edges, }: SelectCompatiblePortPairInput) => CompatiblePortSelectionResult;
73
+ /** 从已有输出端口增加新节点:仅枚举新节点 inputs。 */
74
+ export declare const selectSourceToNewCompatiblePort: ({ sourceNode, newNode, sourceSchema, newNodeSchema, sourceHandle, edges, }: SelectSourceToNewCompatiblePortInput) => CompatiblePortSelectionResult;
75
+ /** 从已有输入端口增加前置节点:仅枚举新节点 outputs。 */
76
+ export declare const selectNewToTargetCompatiblePort: ({ newNode, targetNode, newNodeSchema, targetSchema, targetHandle, edges, }: SelectNewToTargetCompatiblePortInput) => CompatiblePortSelectionResult;
77
+ /** 插边时同时选择 source→new 与 new→target 两段端口。 */
78
+ export declare const selectCompatiblePortsForEdgeInsert: ({ sourceNode, newNode, targetNode, sourceSchema, newNodeSchema, targetSchema, sourceHandle, targetHandle, edges, replacedEdgeId, }: SelectCompatiblePortsForEdgeInsertInput) => EdgeInsertPortSelectionResult;
79
+ export {};
@@ -2,5 +2,13 @@ import { DipNodeSchema } from '../api/dip';
2
2
  export declare function clearNextNodeSchemaCache(): void;
3
3
  export declare function setCachedNextNodeSchema(nodeKey: string, nodeVersion: number | undefined, schema: DipNodeSchema): void;
4
4
  export declare function setCachedClassicNextNodeSchema(nodeKey: string, nodeVersion: number | undefined, schema: DipNodeSchema): void;
5
+ /**
6
+ * 同步读取已预加载的 CLASSIC nodepackage Schema,不触发网络请求。
7
+ *
8
+ * 手动拖线发生在 ReactFlow 的同步校验阶段,无法等待异步 Schema 请求;
9
+ * 因此画布加载/选择器转换阶段会先预热缓存,再由这里读取。缺失版本时与
10
+ * `getCachedClassicNextNodeSchema` 保持一致,按 ACM 版本 1 兜底。
11
+ */
12
+ export declare function peekCachedClassicNextNodeSchema(nodeKey: string, nodeVersion?: number): DipNodeSchema | null;
5
13
  export declare function getCachedClassicNextNodeSchema(nodeKey: string, nodeVersion?: number): Promise<DipNodeSchema | null>;
6
14
  export declare function getCachedNextNodeSchema(nodeKey: string, nodeVersion?: number): Promise<DipNodeSchema | null>;
@@ -0,0 +1,48 @@
1
+ import { PortConnectionValidationResult } from './portConnectionValidator';
2
+ import { TranslateFn } from '../../../../locales';
3
+ /** 供选择器、自动连线和已有边检查复用的 connectable 界面文案。 */
4
+ export declare const CONNECTABLE_UI_MESSAGE_IDS: {
5
+ readonly categoryUnavailable: "link.flow.connectable.category_unavailable";
6
+ readonly connectorUnavailable: "link.flow.connectable.connector_unavailable";
7
+ readonly actionUnavailable: "link.flow.connectable.action_unavailable";
8
+ readonly loadFailed: "link.flow.connectable.load_failed";
9
+ readonly noCompatibleNodes: "link.flow.connectable.no_compatible_nodes";
10
+ readonly noCompatibleInput: "link.flow.connectable.no_compatible_input";
11
+ readonly noCompatibleOutput: "link.flow.connectable.no_compatible_output";
12
+ readonly noBidirectionalCompatiblePort: "link.flow.connectable.no_bidirectional_compatible_port";
13
+ readonly schemaUnavailable: "link.flow.connectable.schema_unavailable";
14
+ readonly existingEdgeInvalid: "link.flow.connectable.existing_edge_invalid";
15
+ };
16
+ /**
17
+ * 端口校验错误码与 RCS 内置文案的唯一映射。
18
+ *
19
+ * 使用 `satisfies` 保证校验器新增 code 时这里会产生类型错误,避免界面静默回退成中文
20
+ * `reason`。`reason` 仍保留给未知后端规则或版本不一致场景作运行时兜底。
21
+ */
22
+ export declare const PORT_CONNECTION_VALIDATION_MESSAGE_IDS: {
23
+ readonly SOURCE_NODE_NOT_FOUND: "link.flow.connectable.validation.source_node_not_found";
24
+ readonly TARGET_NODE_NOT_FOUND: "link.flow.connectable.validation.target_node_not_found";
25
+ readonly SOURCE_PORT_NOT_FOUND: "link.flow.connectable.validation.source_port_not_found";
26
+ readonly TARGET_PORT_NOT_FOUND: "link.flow.connectable.validation.target_port_not_found";
27
+ readonly PORT_TYPE_MISMATCH: "link.flow.connectable.validation.port_type_mismatch";
28
+ readonly SOURCE_NODE_NOT_ALLOWED: "link.flow.connectable.validation.source_node_not_allowed";
29
+ readonly TARGET_NODE_NOT_ALLOWED: "link.flow.connectable.validation.target_node_not_allowed";
30
+ readonly SOURCE_NODE_DENIED: "link.flow.connectable.validation.source_node_denied";
31
+ readonly TARGET_NODE_DENIED: "link.flow.connectable.validation.target_node_denied";
32
+ readonly SOURCE_MAX_CONNECTIONS_REACHED: "link.flow.connectable.validation.source_max_connections_reached";
33
+ readonly TARGET_MAX_CONNECTIONS_REACHED: "link.flow.connectable.validation.target_max_connections_reached";
34
+ readonly SELF_CONNECTION_NOT_ALLOWED: "link.flow.connectable.validation.self_connection_not_allowed";
35
+ };
36
+ /**
37
+ * 将端口连接校验结果转为当前 locale 的用户文案。
38
+ *
39
+ * @example
40
+ * ```ts
41
+ * const intl = useIntl();
42
+ * const text = formatPortConnectionValidationMessage(
43
+ * validationResult,
44
+ * (id, values) => intl.formatMessage({ id }, values),
45
+ * );
46
+ * ```
47
+ */
48
+ export declare const formatPortConnectionValidationMessage: (result: PortConnectionValidationResult, translate: TranslateFn) => string;
@@ -0,0 +1,66 @@
1
+ import { DipPortSchema } from '../api/dip.types';
2
+ export declare const DEFAULT_PORT_CONNECTION_TYPE = "main";
3
+ /** 已完成运行时默认值归一化的端口 Schema。 */
4
+ export interface NormalizedDipPortSchema extends DipPortSchema {
5
+ type: string;
6
+ }
7
+ /**
8
+ * 校验器所需的最小节点结构,可直接接收 ReactFlow Node。
9
+ *
10
+ * 节点 schema key 必须放在 data.action_key/actionKey/nodeKey/node_key 中;
11
+ * ReactFlow 的 node.type 只是渲染类型,不能作为连接白名单身份。
12
+ */
13
+ export interface PortConnectionNode {
14
+ id: string;
15
+ data?: Record<string, unknown> | null;
16
+ }
17
+ /** 校验器所需的最小边结构,可直接接收 ReactFlow Edge。 */
18
+ export interface PortConnectionEdge {
19
+ id?: string;
20
+ source: string;
21
+ target: string;
22
+ sourceHandle?: string | null;
23
+ targetHandle?: string | null;
24
+ }
25
+ export interface PortConnectionValidationOptions {
26
+ /**
27
+ * 显式兼容旧 CLASSIC handle:source `output`、target `input` 映射到 Schema `main`。
28
+ * nodepackage 节点必须保持默认 false,避免把真实的 `input/output/main` 端口混为一谈。
29
+ */
30
+ allowLegacyMainHandleAliases?: boolean;
31
+ }
32
+ export interface ValidatePortConnectionInput {
33
+ sourceNode?: PortConnectionNode | null;
34
+ targetNode?: PortConnectionNode | null;
35
+ sourceHandle?: string | null;
36
+ targetHandle?: string | null;
37
+ /** 源节点的 output Schema 列表。 */
38
+ sourcePorts?: readonly DipPortSchema[] | null;
39
+ /** 目标节点的 input Schema 列表。 */
40
+ targetPorts?: readonly DipPortSchema[] | null;
41
+ /** 当前画布已有边;新建边本身不应提前加入此列表。 */
42
+ edges?: readonly PortConnectionEdge[] | null;
43
+ options?: PortConnectionValidationOptions;
44
+ }
45
+ export type PortConnectionValidationCode = 'VALID' | 'SOURCE_NODE_NOT_FOUND' | 'TARGET_NODE_NOT_FOUND' | 'SOURCE_PORT_NOT_FOUND' | 'TARGET_PORT_NOT_FOUND' | 'PORT_TYPE_MISMATCH' | 'SOURCE_NODE_NOT_ALLOWED' | 'TARGET_NODE_NOT_ALLOWED' | 'SOURCE_NODE_DENIED' | 'TARGET_NODE_DENIED' | 'SOURCE_MAX_CONNECTIONS_REACHED' | 'TARGET_MAX_CONNECTIONS_REACHED' | 'SELF_CONNECTION_NOT_ALLOWED';
46
+ export interface PortConnectionValidationResult {
47
+ valid: boolean;
48
+ code: PortConnectionValidationCode;
49
+ /** 可直接用于调试的中文兜底原因;界面层应优先按 code 映射 i18n 文案。 */
50
+ reason: string;
51
+ sourcePort: NormalizedDipPortSchema | null;
52
+ targetPort: NormalizedDipPortSchema | null;
53
+ }
54
+ /**
55
+ * 将端口运行时默认值和 ACM SNAKE_CASE 响应统一为内部 camelCase,不修改原始对象。
56
+ */
57
+ export declare const normalizePortSchema: (port: DipPortSchema) => NormalizedDipPortSchema;
58
+ /** 从 ReactFlow 节点 data 中解析用于黑白名单判断的 NodePackage schema key。 */
59
+ export declare const getPortConnectionNodeIdentity: (node?: PortConnectionNode | null) => string | null;
60
+ /**
61
+ * 按 NodePackage PortSchema 校验一条准备创建的连接。
62
+ *
63
+ * 本函数拒绝直接自连,但不校验多节点环路、MCP 等画布专项规则;调用方应按
64
+ * “通用图结构规则 → Schema 规则 → 专项规则”的顺序组合。
65
+ */
66
+ export declare const validatePortConnection: ({ sourceNode, targetNode, sourceHandle, targetHandle, sourcePorts, targetPorts, edges, options, }: ValidatePortConnectionInput) => PortConnectionValidationResult;
@@ -0,0 +1,20 @@
1
+ import { EngineMode } from '../enums/workflow';
2
+ import { EdgeConfig, EdgeRulesConfig, NodeSelectorConnectableConfig } from '../types/engine';
3
+ import { Edge, IsValidConnection, Node } from '@xyflow/react';
4
+ interface ValidateWorkflowConnectionInput {
5
+ edge: EdgeConfig;
6
+ nodes: Node[];
7
+ edges: Edge[];
8
+ engineMode?: EngineMode;
9
+ connectable?: Pick<NodeSelectorConnectableConfig, 'enabled' | 'debug'>;
10
+ validators?: EdgeRulesConfig['validators'];
11
+ nativeIsValidConnection?: IsValidConnection;
12
+ }
13
+ /**
14
+ * 校验一条准备创建的画布连接。
15
+ *
16
+ * 手动拖线与程序化新增都传入各自的节点/边快照,从而复用 NodePackage、MCP、
17
+ * 宿主 edgeRules 和 ReactFlow native validator。边中插入可由调用方先从快照移除旧边。
18
+ */
19
+ export declare function validateWorkflowConnection({ edge, nodes, edges, engineMode, connectable, validators, nativeIsValidConnection, }: ValidateWorkflowConnectionInput): boolean;
20
+ export {};
@@ -145,6 +145,28 @@ declare const _default: {
145
145
  'link.flow.force_online_confirm': string;
146
146
  'link.flow.offline_success': string;
147
147
  'link.flow.operation_title': string;
148
+ 'link.flow.connectable.category_unavailable': string;
149
+ 'link.flow.connectable.connector_unavailable': string;
150
+ 'link.flow.connectable.action_unavailable': string;
151
+ 'link.flow.connectable.load_failed': string;
152
+ 'link.flow.connectable.no_compatible_nodes': string;
153
+ 'link.flow.connectable.no_compatible_input': string;
154
+ 'link.flow.connectable.no_compatible_output': string;
155
+ 'link.flow.connectable.no_bidirectional_compatible_port': string;
156
+ 'link.flow.connectable.schema_unavailable': string;
157
+ 'link.flow.connectable.existing_edge_invalid': string;
158
+ 'link.flow.connectable.validation.source_node_not_found': string;
159
+ 'link.flow.connectable.validation.target_node_not_found': string;
160
+ 'link.flow.connectable.validation.source_port_not_found': string;
161
+ 'link.flow.connectable.validation.target_port_not_found': string;
162
+ 'link.flow.connectable.validation.port_type_mismatch': string;
163
+ 'link.flow.connectable.validation.source_node_not_allowed': string;
164
+ 'link.flow.connectable.validation.target_node_not_allowed': string;
165
+ 'link.flow.connectable.validation.source_node_denied': string;
166
+ 'link.flow.connectable.validation.target_node_denied': string;
167
+ 'link.flow.connectable.validation.source_max_connections_reached': string;
168
+ 'link.flow.connectable.validation.target_max_connections_reached': string;
169
+ 'link.flow.connectable.validation.self_connection_not_allowed': string;
148
170
  'link.flow.switch.condition_one': string;
149
171
  'link.flow.switch.condition_two': string;
150
172
  'link.flow.switch.condition_n': string;
@@ -145,6 +145,28 @@ declare const _default: {
145
145
  'link.flow.force_online_confirm': string;
146
146
  'link.flow.offline_success': string;
147
147
  'link.flow.operation_title': string;
148
+ 'link.flow.connectable.category_unavailable': string;
149
+ 'link.flow.connectable.connector_unavailable': string;
150
+ 'link.flow.connectable.action_unavailable': string;
151
+ 'link.flow.connectable.load_failed': string;
152
+ 'link.flow.connectable.no_compatible_nodes': string;
153
+ 'link.flow.connectable.no_compatible_input': string;
154
+ 'link.flow.connectable.no_compatible_output': string;
155
+ 'link.flow.connectable.no_bidirectional_compatible_port': string;
156
+ 'link.flow.connectable.schema_unavailable': string;
157
+ 'link.flow.connectable.existing_edge_invalid': string;
158
+ 'link.flow.connectable.validation.source_node_not_found': string;
159
+ 'link.flow.connectable.validation.target_node_not_found': string;
160
+ 'link.flow.connectable.validation.source_port_not_found': string;
161
+ 'link.flow.connectable.validation.target_port_not_found': string;
162
+ 'link.flow.connectable.validation.port_type_mismatch': string;
163
+ 'link.flow.connectable.validation.source_node_not_allowed': string;
164
+ 'link.flow.connectable.validation.target_node_not_allowed': string;
165
+ 'link.flow.connectable.validation.source_node_denied': string;
166
+ 'link.flow.connectable.validation.target_node_denied': string;
167
+ 'link.flow.connectable.validation.source_max_connections_reached': string;
168
+ 'link.flow.connectable.validation.target_max_connections_reached': string;
169
+ 'link.flow.connectable.validation.self_connection_not_allowed': string;
148
170
  'link.flow.switch.condition_one': string;
149
171
  'link.flow.switch.condition_two': string;
150
172
  'link.flow.switch.condition_n': string;
@@ -145,6 +145,28 @@ declare const _default: {
145
145
  'link.flow.force_online_confirm': string;
146
146
  'link.flow.offline_success': string;
147
147
  'link.flow.operation_title': string;
148
+ 'link.flow.connectable.category_unavailable': string;
149
+ 'link.flow.connectable.connector_unavailable': string;
150
+ 'link.flow.connectable.action_unavailable': string;
151
+ 'link.flow.connectable.load_failed': string;
152
+ 'link.flow.connectable.no_compatible_nodes': string;
153
+ 'link.flow.connectable.no_compatible_input': string;
154
+ 'link.flow.connectable.no_compatible_output': string;
155
+ 'link.flow.connectable.no_bidirectional_compatible_port': string;
156
+ 'link.flow.connectable.schema_unavailable': string;
157
+ 'link.flow.connectable.existing_edge_invalid': string;
158
+ 'link.flow.connectable.validation.source_node_not_found': string;
159
+ 'link.flow.connectable.validation.target_node_not_found': string;
160
+ 'link.flow.connectable.validation.source_port_not_found': string;
161
+ 'link.flow.connectable.validation.target_port_not_found': string;
162
+ 'link.flow.connectable.validation.port_type_mismatch': string;
163
+ 'link.flow.connectable.validation.source_node_not_allowed': string;
164
+ 'link.flow.connectable.validation.target_node_not_allowed': string;
165
+ 'link.flow.connectable.validation.source_node_denied': string;
166
+ 'link.flow.connectable.validation.target_node_denied': string;
167
+ 'link.flow.connectable.validation.source_max_connections_reached': string;
168
+ 'link.flow.connectable.validation.target_max_connections_reached': string;
169
+ 'link.flow.connectable.validation.self_connection_not_allowed': string;
148
170
  'link.flow.switch.condition_one': string;
149
171
  'link.flow.switch.condition_two': string;
150
172
  'link.flow.switch.condition_n': string;
@@ -145,6 +145,28 @@ declare const _default: {
145
145
  'link.flow.force_online_confirm': string;
146
146
  'link.flow.offline_success': string;
147
147
  'link.flow.operation_title': string;
148
+ 'link.flow.connectable.category_unavailable': string;
149
+ 'link.flow.connectable.connector_unavailable': string;
150
+ 'link.flow.connectable.action_unavailable': string;
151
+ 'link.flow.connectable.load_failed': string;
152
+ 'link.flow.connectable.no_compatible_nodes': string;
153
+ 'link.flow.connectable.no_compatible_input': string;
154
+ 'link.flow.connectable.no_compatible_output': string;
155
+ 'link.flow.connectable.no_bidirectional_compatible_port': string;
156
+ 'link.flow.connectable.schema_unavailable': string;
157
+ 'link.flow.connectable.existing_edge_invalid': string;
158
+ 'link.flow.connectable.validation.source_node_not_found': string;
159
+ 'link.flow.connectable.validation.target_node_not_found': string;
160
+ 'link.flow.connectable.validation.source_port_not_found': string;
161
+ 'link.flow.connectable.validation.target_port_not_found': string;
162
+ 'link.flow.connectable.validation.port_type_mismatch': string;
163
+ 'link.flow.connectable.validation.source_node_not_allowed': string;
164
+ 'link.flow.connectable.validation.target_node_not_allowed': string;
165
+ 'link.flow.connectable.validation.source_node_denied': string;
166
+ 'link.flow.connectable.validation.target_node_denied': string;
167
+ 'link.flow.connectable.validation.source_max_connections_reached': string;
168
+ 'link.flow.connectable.validation.target_max_connections_reached': string;
169
+ 'link.flow.connectable.validation.self_connection_not_allowed': string;
148
170
  'link.flow.switch.condition_one': string;
149
171
  'link.flow.switch.condition_two': string;
150
172
  'link.flow.switch.condition_n': string;
@@ -144,6 +144,28 @@ declare const _default: {
144
144
  'link.flow.force_online_confirm': string;
145
145
  'link.flow.offline_success': string;
146
146
  'link.flow.operation_title': string;
147
+ 'link.flow.connectable.category_unavailable': string;
148
+ 'link.flow.connectable.connector_unavailable': string;
149
+ 'link.flow.connectable.action_unavailable': string;
150
+ 'link.flow.connectable.load_failed': string;
151
+ 'link.flow.connectable.no_compatible_nodes': string;
152
+ 'link.flow.connectable.no_compatible_input': string;
153
+ 'link.flow.connectable.no_compatible_output': string;
154
+ 'link.flow.connectable.no_bidirectional_compatible_port': string;
155
+ 'link.flow.connectable.schema_unavailable': string;
156
+ 'link.flow.connectable.existing_edge_invalid': string;
157
+ 'link.flow.connectable.validation.source_node_not_found': string;
158
+ 'link.flow.connectable.validation.target_node_not_found': string;
159
+ 'link.flow.connectable.validation.source_port_not_found': string;
160
+ 'link.flow.connectable.validation.target_port_not_found': string;
161
+ 'link.flow.connectable.validation.port_type_mismatch': string;
162
+ 'link.flow.connectable.validation.source_node_not_allowed': string;
163
+ 'link.flow.connectable.validation.target_node_not_allowed': string;
164
+ 'link.flow.connectable.validation.source_node_denied': string;
165
+ 'link.flow.connectable.validation.target_node_denied': string;
166
+ 'link.flow.connectable.validation.source_max_connections_reached': string;
167
+ 'link.flow.connectable.validation.target_max_connections_reached': string;
168
+ 'link.flow.connectable.validation.self_connection_not_allowed': string;
147
169
  'link.flow.switch.condition_one': string;
148
170
  'link.flow.switch.condition_two': string;
149
171
  'link.flow.switch.condition_n': string;
@@ -144,6 +144,28 @@ declare const _default: {
144
144
  'link.flow.force_online_confirm': string;
145
145
  'link.flow.offline_success': string;
146
146
  'link.flow.operation_title': string;
147
+ 'link.flow.connectable.category_unavailable': string;
148
+ 'link.flow.connectable.connector_unavailable': string;
149
+ 'link.flow.connectable.action_unavailable': string;
150
+ 'link.flow.connectable.load_failed': string;
151
+ 'link.flow.connectable.no_compatible_nodes': string;
152
+ 'link.flow.connectable.no_compatible_input': string;
153
+ 'link.flow.connectable.no_compatible_output': string;
154
+ 'link.flow.connectable.no_bidirectional_compatible_port': string;
155
+ 'link.flow.connectable.schema_unavailable': string;
156
+ 'link.flow.connectable.existing_edge_invalid': string;
157
+ 'link.flow.connectable.validation.source_node_not_found': string;
158
+ 'link.flow.connectable.validation.target_node_not_found': string;
159
+ 'link.flow.connectable.validation.source_port_not_found': string;
160
+ 'link.flow.connectable.validation.target_port_not_found': string;
161
+ 'link.flow.connectable.validation.port_type_mismatch': string;
162
+ 'link.flow.connectable.validation.source_node_not_allowed': string;
163
+ 'link.flow.connectable.validation.target_node_not_allowed': string;
164
+ 'link.flow.connectable.validation.source_node_denied': string;
165
+ 'link.flow.connectable.validation.target_node_denied': string;
166
+ 'link.flow.connectable.validation.source_max_connections_reached': string;
167
+ 'link.flow.connectable.validation.target_max_connections_reached': string;
168
+ 'link.flow.connectable.validation.self_connection_not_allowed': string;
147
169
  'link.flow.switch.condition_one': string;
148
170
  'link.flow.switch.condition_two': string;
149
171
  'link.flow.switch.condition_n': string;