digitalsee-ai-flow-cli 0.9.15 → 0.9.24-beta

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.
@@ -0,0 +1,413 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CLASSIC_NODE_DESCRIPTORS = exports.LEGACY_HANDLE_NAME_MAP = exports.SWITCH_NODE_PACKAGE_KEY = exports.SWITCH_DEFAULT_BRANCH_HANDLE = void 0;
4
+ exports.normalizeLegacyHandleName = normalizeLegacyHandleName;
5
+ exports.isClassicNodeType = isClassicNodeType;
6
+ exports.resolveClassicNodePorts = resolveClassicNodePorts;
7
+ exports.readSwitchBranches = readSwitchBranches;
8
+ exports.deriveSwitchOutputPorts = deriveSwitchOutputPorts;
9
+ exports.resolveClassicNodeSchema = resolveClassicNodeSchema;
10
+ exports.getAutoConnectRulesForNodeType = getAutoConnectRulesForNodeType;
11
+ exports.applySwitchBranchesToSchema = applySwitchBranchesToSchema;
12
+ exports.listClassicNodeTypes = listClassicNodeTypes;
13
+ exports.SWITCH_DEFAULT_BRANCH_HANDLE = 'default-branch';
14
+ /** NodePackage switch 的 action_key(dip.core.flow.switch) */
15
+ exports.SWITCH_NODE_PACKAGE_KEY = 'dip.core.flow.switch';
16
+ /**
17
+ * 废弃 handle 名迁移表(对齐 RCS useDataLoading REPLACE_HANDLE_MAP):
18
+ * 旧数据的 sourceHandle/targetHandle 可能仍是 chat_model/memory/tools,
19
+ * 读取时统一替换为 ai_model/ai_memory/ai_tool
20
+ */
21
+ exports.LEGACY_HANDLE_NAME_MAP = {
22
+ chat_model: 'ai_model',
23
+ memory: 'ai_memory',
24
+ tools: 'ai_tool',
25
+ };
26
+ /** handle 名规范化:空值返回 undefined,命中废弃名时替换,其余原样返回 */
27
+ function normalizeLegacyHandleName(handle) {
28
+ if (!handle)
29
+ return undefined;
30
+ return exports.LEGACY_HANDLE_NAME_MAP[handle] ?? handle;
31
+ }
32
+ /** Loop / SelfLoop 的 loop → input 自环规则(NodePackage 节点也按 node_type 兜底注入) */
33
+ const LOOP_AUTO_CONNECT = [{ source: 'loop', target: 'input' }];
34
+ const EMPTY_PORTS = [];
35
+ const ACTION_INPUTS = [
36
+ { name: 'input', displayName: '输入', maxConnections: 1 },
37
+ ];
38
+ const ACTION_OUTPUTS = [
39
+ { name: 'output', displayName: '输出', maxConnections: 1 },
40
+ ];
41
+ const TRIGGER_OUTPUTS = [
42
+ { name: 'output', displayName: '输出', maxConnections: 1 },
43
+ ];
44
+ const CONDITION_OUTPUTS = [
45
+ { name: 'true', displayName: 'true', maxConnections: 1 },
46
+ { name: 'false', displayName: 'false', maxConnections: 1 },
47
+ ];
48
+ const LOOP_OUTPUTS = [
49
+ { name: 'done', displayName: 'done', maxConnections: 1 },
50
+ { name: 'loop', displayName: 'loop', maxConnections: 1 },
51
+ ];
52
+ const SWITCH_DEFAULT_OUTPUTS = [
53
+ { name: exports.SWITCH_DEFAULT_BRANCH_HANDLE, displayName: 'default', maxConnections: 1 },
54
+ ];
55
+ /**
56
+ * Agent 底部 slave 桩为 SOURCE(RCS 82b5976 方向翻转):连线从 Agent 出发,
57
+ * 指向 AI 子节点顶部 input 桩。ai_tool 允许多协议(临时兼容,对齐 RCS)
58
+ */
59
+ const AGENT_INPUTS = [{ name: 'input', displayName: '输入' }];
60
+ const AGENT_OUTPUTS = [
61
+ { name: 'output', displayName: '输出', maxConnections: 1 },
62
+ { name: 'ai_model', displayName: 'Chat Model', type: 'AI_LANGUAGE_MODEL', maxConnections: 1 },
63
+ { name: 'ai_memory', displayName: 'Memory', type: 'AI_MEMORY', maxConnections: 1 },
64
+ {
65
+ name: 'ai_tool',
66
+ displayName: 'Tools',
67
+ type: 'AI_TOOL,KNOWLEDGE,MCP_SERVER,BUILTIN_MCP',
68
+ maxConnections: 10,
69
+ },
70
+ ];
71
+ /** BrowserNode(RCS 0f824ad 方向翻转):ai_model slave 桩为连线源,指向 AISubNode 顶部 input 桩 */
72
+ const BROWSER_INPUTS = [{ name: 'input', displayName: '输入' }];
73
+ const BROWSER_OUTPUTS = [
74
+ { name: 'output', displayName: '输出' },
75
+ { name: 'ai_model', displayName: 'Chat Model', type: 'AI_LANGUAGE_MODEL', maxConnections: 1 },
76
+ ];
77
+ /** AI 子节点顶部入桩(RCS 82b5976 方向翻转后为 TARGET):端口名固定 input,协议随类型 */
78
+ const aiSubInput = (protocol, maxConnections = 1) => ({
79
+ name: 'input',
80
+ displayName: '输入',
81
+ type: protocol,
82
+ maxConnections,
83
+ });
84
+ /**
85
+ * MCP 网关系列(RCS 6fc6de5 后):builtin_mcp 顶部入桩(TARGET,BUILTIN_MCP 协议,max 1),
86
+ * 连线源为 Agent ai_tool(多协议含 BUILTIN_MCP)等
87
+ */
88
+ const MCP_BUILTIN_MCP_INPUTS = [
89
+ { name: 'builtin_mcp', displayName: '输入', type: 'BUILTIN_MCP', maxConnections: 1 },
90
+ ];
91
+ /** BuiltinMCP:builtin_mcp 入桩 max 1,output 主出桩 max 10(协议 main) */
92
+ const BUILTIN_MCP_OUTPUTS = [
93
+ { name: 'output', displayName: '输出', maxConnections: 10 },
94
+ ];
95
+ /** MCPTool / MCP_TOOLS_NODE:BUILTIN_MCP 入桩,main 出桩 */
96
+ const MCP_TOOL_INPUTS = [
97
+ { name: 'input', displayName: '输入', type: 'BUILTIN_MCP' },
98
+ ];
99
+ const MCP_TOOL_OUTPUTS = [
100
+ { name: 'output', displayName: '输出', maxConnections: 1 },
101
+ ];
102
+ /** MCP return-variable 等形态:无出桩 */
103
+ const NO_OUTPUT_PROTOCOLS = {
104
+ BUILTIN_MCP: { outputs: EMPTY_PORTS },
105
+ MCP_SERVER: { outputs: EMPTY_PORTS },
106
+ };
107
+ /**
108
+ * classic 静态端口表(唯一事实源,数据对齐 RCS CLASSIC_DESCRIPTORS)。
109
+ */
110
+ exports.CLASSIC_NODE_DESCRIPTORS = {
111
+ StartEventNode: {
112
+ nodeType: 'StartEventNode',
113
+ label: '触发器节点',
114
+ description: '流程触发起点,无输入端口,单输出口',
115
+ inputs: EMPTY_PORTS,
116
+ outputs: TRIGGER_OUTPUTS,
117
+ },
118
+ ActionNode: {
119
+ nodeType: 'ActionNode',
120
+ label: '动作节点',
121
+ description: '常规动作节点;MCP return-variable 协议形态无输出端口',
122
+ inputs: ACTION_INPUTS,
123
+ outputs: ACTION_OUTPUTS,
124
+ byProtocol: NO_OUTPUT_PROTOCOLS,
125
+ },
126
+ ConditionNode: {
127
+ nodeType: 'ConditionNode',
128
+ label: '条件节点',
129
+ description: '条件分支,true/false 双出口',
130
+ inputs: ACTION_INPUTS,
131
+ outputs: CONDITION_OUTPUTS,
132
+ },
133
+ LoopNode: {
134
+ nodeType: 'LoopNode',
135
+ label: '循环节点',
136
+ description: '循环控制,done 出口走完流程,loop 出口配合 input 形成自环',
137
+ inputs: ACTION_INPUTS,
138
+ outputs: LOOP_OUTPUTS,
139
+ autoConnect: LOOP_AUTO_CONNECT,
140
+ },
141
+ SelfLoopNode: {
142
+ nodeType: 'SelfLoopNode',
143
+ label: '自环节点',
144
+ description: '自循环控制,loop → input 自环边为必需结构',
145
+ inputs: ACTION_INPUTS,
146
+ outputs: LOOP_OUTPUTS,
147
+ autoConnect: LOOP_AUTO_CONNECT,
148
+ },
149
+ SwitchNode: {
150
+ nodeType: 'SwitchNode',
151
+ label: '多分支节点',
152
+ description: '多路由分支;输出端口来自 properties.branches[].id(实例派生),default-branch 固定兜底',
153
+ inputs: ACTION_INPUTS,
154
+ outputs: SWITCH_DEFAULT_OUTPUTS,
155
+ },
156
+ AgentNode: {
157
+ nodeType: 'AgentNode',
158
+ label: 'Agent 节点',
159
+ description: 'AI Agent;底部 slave 桩(ai_model/ai_memory/ai_tool)为连线源,指向 AI 子节点顶部 input 桩;ai_tool 支持多协议(AI_TOOL,KNOWLEDGE,MCP_SERVER,BUILTIN_MCP)',
160
+ inputs: AGENT_INPUTS,
161
+ outputs: AGENT_OUTPUTS,
162
+ },
163
+ BrowserNode: {
164
+ nodeType: 'BrowserNode',
165
+ label: '浏览器节点',
166
+ description: 'AI 浏览器操作;ai_model slave 桩为连线源,指向 AISubNode 顶部 input 桩(协议 AI_LANGUAGE_MODEL)',
167
+ inputs: BROWSER_INPUTS,
168
+ outputs: BROWSER_OUTPUTS,
169
+ },
170
+ AISubNode: {
171
+ nodeType: 'AISubNode',
172
+ label: 'AI 配置子节点',
173
+ description: 'AI 配置子节点(模型/记忆/工具);顶部 input 桩接收 Agent slave 桩连线,协议随类型(AI_TOOL 形态 max 10)',
174
+ inputs: [aiSubInput('AI_LANGUAGE_MODEL', 1)],
175
+ outputs: EMPTY_PORTS,
176
+ byProtocol: {
177
+ AI_MEMORY: { inputs: [aiSubInput('AI_MEMORY')] },
178
+ AI_TOOL: { inputs: [aiSubInput('AI_TOOL', 10)] },
179
+ },
180
+ },
181
+ VectorStoreNode: {
182
+ nodeType: 'VectorStoreNode',
183
+ label: '向量存储节点',
184
+ description: '向量存储子节点;protocol=AI_VECTORSTORE 时顶部 input 桩接收 Agent slave 桩连线',
185
+ inputs: EMPTY_PORTS,
186
+ outputs: EMPTY_PORTS,
187
+ byProtocol: {
188
+ // 注意拼写:对齐 RCS NodeProtocol.AI_VECTOR_STORE = 'AI_VECTORSTORE'
189
+ AI_VECTORSTORE: { inputs: [aiSubInput('AI_VECTORSTORE')] },
190
+ },
191
+ },
192
+ MCPServerNode: {
193
+ nodeType: 'MCPServerNode',
194
+ label: 'MCP 服务节点',
195
+ description: '旧 MCP 网关服务;builtin_mcp 入桩(BUILTIN_MCP 协议)max 1,无出桩',
196
+ inputs: MCP_BUILTIN_MCP_INPUTS,
197
+ outputs: EMPTY_PORTS,
198
+ },
199
+ MCP_TRIGGER_NODE: {
200
+ nodeType: 'MCP_TRIGGER_NODE',
201
+ label: 'MCP 网关触发节点',
202
+ description: '旧 MCP 网关触发形态;builtin_mcp 入桩(BUILTIN_MCP 协议)max 1,无出桩',
203
+ inputs: MCP_BUILTIN_MCP_INPUTS,
204
+ outputs: EMPTY_PORTS,
205
+ },
206
+ BuiltinMCPNode: {
207
+ nodeType: 'BuiltinMCPNode',
208
+ label: '内置 MCP 节点',
209
+ description: '内置 MCP 工具节点;builtin_mcp 入桩(BUILTIN_MCP 协议)max 1,output 主出桩 max 10',
210
+ inputs: MCP_BUILTIN_MCP_INPUTS,
211
+ outputs: BUILTIN_MCP_OUTPUTS,
212
+ },
213
+ MCPToolNode: {
214
+ nodeType: 'MCPToolNode',
215
+ label: 'MCP 工具节点',
216
+ description: 'MCP 工具调用;BUILTIN_MCP 入桩,MCP return-variable 形态无出桩',
217
+ inputs: MCP_TOOL_INPUTS,
218
+ outputs: MCP_TOOL_OUTPUTS,
219
+ byProtocol: NO_OUTPUT_PROTOCOLS,
220
+ },
221
+ MCP_TOOLS_NODE: {
222
+ nodeType: 'MCP_TOOLS_NODE',
223
+ label: 'MCP 网关工具列表节点',
224
+ description: 'MCP 网关工具列表形态,端口与 MCPToolNode 一致',
225
+ inputs: MCP_TOOL_INPUTS,
226
+ outputs: MCP_TOOL_OUTPUTS,
227
+ byProtocol: NO_OUTPUT_PROTOCOLS,
228
+ },
229
+ StickyNoteNode: {
230
+ nodeType: 'StickyNoteNode',
231
+ label: '便签节点',
232
+ description: '画布便签,无端口',
233
+ inputs: EMPTY_PORTS,
234
+ outputs: EMPTY_PORTS,
235
+ },
236
+ };
237
+ function toNodeSchemaPort(spec) {
238
+ return {
239
+ name: spec.name,
240
+ display_name: spec.displayName,
241
+ type: spec.type ?? 'main',
242
+ ...(spec.maxConnections !== undefined && spec.maxConnections !== null
243
+ ? { max_connections: spec.maxConnections }
244
+ : {}),
245
+ };
246
+ }
247
+ /** node_type 是否命中内置表 */
248
+ function isClassicNodeType(nodeType) {
249
+ return (Boolean(nodeType) &&
250
+ Object.prototype.hasOwnProperty.call(exports.CLASSIC_NODE_DESCRIPTORS, nodeType));
251
+ }
252
+ /**
253
+ * 按 (node_type, protocol) 解析端口声明。
254
+ * protocol 缺失或未命中 byProtocol 时回退 type 级默认;未知 node_type 返回 null。
255
+ */
256
+ function resolveClassicNodePorts(node) {
257
+ const descriptor = node.node_type ? exports.CLASSIC_NODE_DESCRIPTORS[node.node_type] : undefined;
258
+ if (!descriptor)
259
+ return null;
260
+ const protocol = node.protocol?.trim();
261
+ if (protocol) {
262
+ const override = descriptor.byProtocol?.[protocol];
263
+ if (override) {
264
+ return {
265
+ inputs: override.inputs ?? descriptor.inputs,
266
+ outputs: override.outputs ?? descriptor.outputs,
267
+ };
268
+ }
269
+ }
270
+ return { inputs: descriptor.inputs, outputs: descriptor.outputs };
271
+ }
272
+ /** 探测 + 规范化节点 branches(RCS switchNodePackage 语义:三容器探测 + id 修复) */
273
+ function readSwitchBranches(data) {
274
+ const raw = unwrapSwitchProperties(data);
275
+ const branches = Array.isArray(raw?.branches) ? raw.branches : [];
276
+ const normalized = [];
277
+ const usedIds = new Set([exports.SWITCH_DEFAULT_BRANCH_HANDLE]);
278
+ let migrated = 0;
279
+ for (const item of branches) {
280
+ if (!item || typeof item !== 'object')
281
+ continue;
282
+ const branch = item;
283
+ let id = String(branch.id ?? '');
284
+ const name = String(branch.name ?? '').trim() || `分支 ${normalized.length + 1}`;
285
+ if (!id.startsWith('branch') || id === exports.SWITCH_DEFAULT_BRANCH_HANDLE || usedIds.has(id)) {
286
+ do {
287
+ migrated++;
288
+ id = `branch-migrated-${migrated}`;
289
+ } while (usedIds.has(id));
290
+ }
291
+ usedIds.add(id);
292
+ normalized.push({ id, name });
293
+ }
294
+ return normalized;
295
+ }
296
+ /** 按序探测 config_schema → properties → params,各解包一层 properties/params */
297
+ function unwrapSwitchProperties(data) {
298
+ const candidates = [data.config_schema, data.properties, data.params];
299
+ for (const candidate of candidates) {
300
+ if (!candidate || typeof candidate !== 'object' || Array.isArray(candidate))
301
+ continue;
302
+ const unwrapped = unwrapPropertiesLayer(candidate);
303
+ if (Array.isArray(unwrapped?.branches))
304
+ return unwrapped;
305
+ }
306
+ return undefined;
307
+ }
308
+ function unwrapPropertiesLayer(value) {
309
+ if (Array.isArray(value.branches))
310
+ return value;
311
+ const nested = value.properties;
312
+ if (nested && typeof nested === 'object' && !Array.isArray(nested)) {
313
+ const unwrapped = nested;
314
+ if (Array.isArray(unwrapped.branches))
315
+ return unwrapped;
316
+ }
317
+ const params = value.params;
318
+ if (params && typeof params === 'object' && !Array.isArray(params)) {
319
+ const unwrapped = params;
320
+ if (Array.isArray(unwrapped.branches))
321
+ return unwrapped;
322
+ }
323
+ return value;
324
+ }
325
+ /**
326
+ * branches → 输出端口。classic SwitchNode 用静态模板(main/max1);
327
+ * NodePackage switch 通过 options 传 schema 模板以继承约束。
328
+ * default-branch 固定追加在末尾;branches 为空时仅返回 [defaultPort]。
329
+ */
330
+ function deriveSwitchOutputPorts(branches, options) {
331
+ const template = options?.template ?? {
332
+ name: 'branch-1',
333
+ display_name: '分支',
334
+ type: 'main',
335
+ max_connections: 1,
336
+ };
337
+ const defaultPort = options?.defaultPort ?? {
338
+ name: exports.SWITCH_DEFAULT_BRANCH_HANDLE,
339
+ display_name: 'default',
340
+ type: 'main',
341
+ max_connections: 1,
342
+ };
343
+ return [
344
+ ...branches.map((branch) => ({
345
+ ...template,
346
+ name: branch.id,
347
+ display_name: branch.name,
348
+ })),
349
+ defaultPort,
350
+ ];
351
+ }
352
+ /**
353
+ * 完整解析 classic 节点的内置 schema(含 SwitchNode 实例分支派生)。
354
+ * 未知 node_type 返回 null。
355
+ */
356
+ function resolveClassicNodeSchema(node) {
357
+ const descriptor = node.node_type ? exports.CLASSIC_NODE_DESCRIPTORS[node.node_type] : undefined;
358
+ if (!descriptor)
359
+ return null;
360
+ const ports = resolveClassicNodePorts(node) ?? {
361
+ inputs: descriptor.inputs,
362
+ outputs: descriptor.outputs,
363
+ };
364
+ // Switch 分支端口由 deriveSwitchOutputPorts 产出(已是 NodeSchemaPort),不能再过 toNodeSchemaPort
365
+ const outputs = node.node_type === 'SwitchNode'
366
+ ? deriveSwitchOutputPorts(readSwitchBranches(node))
367
+ : (ports.outputs ?? []).map(toNodeSchemaPort);
368
+ return {
369
+ schemaKey: node.node_type,
370
+ inputs: (ports.inputs ?? []).map(toNodeSchemaPort),
371
+ outputs,
372
+ autoConnect: descriptor.autoConnect ?? [],
373
+ };
374
+ }
375
+ /** Loop/SelfLoop 的 loop→input 兜底(NodePackage 节点也按 node_type 注入,对齐 RCS nodeAutoConnect) */
376
+ function getAutoConnectRulesForNodeType(nodeType) {
377
+ if (!nodeType)
378
+ return [];
379
+ const descriptor = exports.CLASSIC_NODE_DESCRIPTORS[nodeType];
380
+ return descriptor?.autoConnect ?? [];
381
+ }
382
+ /**
383
+ * NodePackage switch schema 应用实例分支(schema.key === 'dip.core.flow.switch' 时,
384
+ * 模板继承 schema 第一个非 default 输出的约束);其余 schema 原样返回。
385
+ */
386
+ function applySwitchBranchesToSchema(schema, node) {
387
+ if (schema.key !== exports.SWITCH_NODE_PACKAGE_KEY)
388
+ return schema;
389
+ const branches = readSwitchBranches(node);
390
+ if (branches.length === 0)
391
+ return schema;
392
+ const schemaOutputs = schema.outputs ?? [];
393
+ const template = schemaOutputs.find((port) => port.name !== exports.SWITCH_DEFAULT_BRANCH_HANDLE) ??
394
+ { name: 'branch-1', display_name: '分支', type: 'main' };
395
+ const defaultPort = schemaOutputs.find((port) => port.name === exports.SWITCH_DEFAULT_BRANCH_HANDLE) ??
396
+ {
397
+ name: exports.SWITCH_DEFAULT_BRANCH_HANDLE,
398
+ display_name: 'Default',
399
+ type: 'main',
400
+ };
401
+ return {
402
+ ...schema,
403
+ outputs: deriveSwitchOutputPorts(branches, { template, defaultPort }),
404
+ };
405
+ }
406
+ /** skills 渲染用:全部内置类型(保持表定义顺序) */
407
+ function listClassicNodeTypes() {
408
+ return Object.values(exports.CLASSIC_NODE_DESCRIPTORS).map((d) => ({
409
+ nodeType: d.nodeType,
410
+ label: d.label,
411
+ }));
412
+ }
413
+ //# sourceMappingURL=classicNodePorts.js.map