digitalsee-ai-flow-cli 0.1.9 → 0.2.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.
- package/README.md +349 -66
- package/dist/api/client.d.ts.map +1 -1
- package/dist/api/client.js +93 -17
- package/dist/api/client.js.map +1 -1
- package/dist/api/dip.d.ts.map +1 -0
- package/dist/api/dip.js +14 -0
- package/dist/api/dip.js.map +1 -0
- package/dist/api/flow-log.d.ts.map +1 -0
- package/dist/api/flow-log.js +34 -0
- package/dist/api/flow-log.js.map +1 -0
- package/dist/api/link.d.ts.map +1 -0
- package/dist/api/link.js +42 -0
- package/dist/api/link.js.map +1 -0
- package/dist/api/sync.d.ts.map +1 -0
- package/dist/api/sync.js +42 -0
- package/dist/api/sync.js.map +1 -0
- package/dist/commands/flow/account.d.ts.map +1 -1
- package/dist/commands/flow/account.js +10 -3
- package/dist/commands/flow/account.js.map +1 -1
- package/dist/commands/flow/analyze.d.ts.map +1 -1
- package/dist/commands/flow/analyze.js +40 -3
- package/dist/commands/flow/analyze.js.map +1 -1
- package/dist/commands/flow/create.d.ts.map +1 -1
- package/dist/commands/flow/create.js +33 -2
- package/dist/commands/flow/create.js.map +1 -1
- package/dist/commands/flow/draft.d.ts.map +1 -0
- package/dist/commands/flow/draft.js +173 -0
- package/dist/commands/flow/draft.js.map +1 -0
- package/dist/commands/flow/edge.d.ts.map +1 -1
- package/dist/commands/flow/edge.js +71 -12
- package/dist/commands/flow/edge.js.map +1 -1
- package/dist/commands/flow/helpers.d.ts.map +1 -1
- package/dist/commands/flow/helpers.js +99 -2
- package/dist/commands/flow/helpers.js.map +1 -1
- package/dist/commands/flow/log.d.ts.map +1 -0
- package/dist/commands/flow/log.js +325 -0
- package/dist/commands/flow/log.js.map +1 -0
- package/dist/commands/flow/node.d.ts.map +1 -1
- package/dist/commands/flow/node.js +292 -185
- package/dist/commands/flow/node.js.map +1 -1
- package/dist/commands/flow/test.d.ts.map +1 -1
- package/dist/commands/flow/test.js +58 -18
- package/dist/commands/flow/test.js.map +1 -1
- package/dist/commands/flow/validate.d.ts.map +1 -0
- package/dist/commands/flow/validate.js +85 -0
- package/dist/commands/flow/validate.js.map +1 -0
- package/dist/commands/flow/variables.d.ts.map +1 -1
- package/dist/commands/flow/variables.js +18 -5
- package/dist/commands/flow/variables.js.map +1 -1
- package/dist/commands/flow.d.ts.map +1 -1
- package/dist/commands/flow.js +6 -0
- package/dist/commands/flow.js.map +1 -1
- package/dist/commands/knowledge.d.ts.map +1 -1
- package/dist/commands/knowledge.js +17 -2
- package/dist/commands/knowledge.js.map +1 -1
- package/dist/commands/link/create.d.ts.map +1 -0
- package/dist/commands/link/create.js +38 -0
- package/dist/commands/link/create.js.map +1 -0
- package/dist/commands/link/helpers.d.ts.map +1 -0
- package/dist/commands/link/helpers.js +176 -0
- package/dist/commands/link/helpers.js.map +1 -0
- package/dist/commands/link/list.d.ts.map +1 -0
- package/dist/commands/link/list.js +42 -0
- package/dist/commands/link/list.js.map +1 -0
- package/dist/commands/link/log.d.ts.map +1 -0
- package/dist/commands/link/log.js +208 -0
- package/dist/commands/link/log.js.map +1 -0
- package/dist/commands/link/reset.d.ts.map +1 -0
- package/dist/commands/link/reset.js +23 -0
- package/dist/commands/link/reset.js.map +1 -0
- package/dist/commands/link/templates-cmd.d.ts.map +1 -0
- package/dist/commands/link/templates-cmd.js +26 -0
- package/dist/commands/link/templates-cmd.js.map +1 -0
- package/dist/commands/link/templates.d.ts.map +1 -0
- package/dist/commands/link/templates.js +104 -0
- package/dist/commands/link/templates.js.map +1 -0
- package/dist/commands/link.d.ts.map +1 -0
- package/dist/commands/link.js +17 -0
- package/dist/commands/link.js.map +1 -0
- package/dist/commands/sync/create.d.ts.map +1 -0
- package/dist/commands/sync/create.js +38 -0
- package/dist/commands/sync/create.js.map +1 -0
- package/dist/commands/sync/list.d.ts.map +1 -0
- package/dist/commands/sync/list.js +42 -0
- package/dist/commands/sync/list.js.map +1 -0
- package/dist/commands/sync/log.d.ts.map +1 -0
- package/dist/commands/sync/log.js +207 -0
- package/dist/commands/sync/log.js.map +1 -0
- package/dist/commands/sync/reset.d.ts.map +1 -0
- package/dist/commands/sync/reset.js +23 -0
- package/dist/commands/sync/reset.js.map +1 -0
- package/dist/commands/sync/templates-cmd.d.ts.map +1 -0
- package/dist/commands/sync/templates-cmd.js +26 -0
- package/dist/commands/sync/templates-cmd.js.map +1 -0
- package/dist/commands/sync.d.ts.map +1 -0
- package/dist/commands/sync.js +17 -0
- package/dist/commands/sync.js.map +1 -0
- package/dist/index.js +44 -0
- package/dist/index.js.map +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/common.d.ts.map +1 -0
- package/dist/utils/common.js +14 -0
- package/dist/utils/common.js.map +1 -0
- package/dist/utils/format.d.ts.map +1 -1
- package/dist/utils/format.js +24 -3
- package/dist/utils/format.js.map +1 -1
- package/dist/utils/mask.d.ts.map +1 -0
- package/dist/utils/mask.js +102 -0
- package/dist/utils/mask.js.map +1 -0
- package/dist/utils/output.d.ts.map +1 -1
- package/dist/utils/output.js +132 -27
- package/dist/utils/output.js.map +1 -1
- package/package.json +1 -1
- package/CHANGELOG.md +0 -84
|
@@ -1,40 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
3
|
exports.registerFlowNode = registerFlowNode;
|
|
37
|
-
const fs = __importStar(require("fs"));
|
|
38
4
|
const flow_1 = require("@/api/flow");
|
|
39
5
|
const node_1 = require("@/api/node");
|
|
40
6
|
const flowAnalyzer_1 = require("@/services/flowAnalyzer");
|
|
@@ -46,16 +12,23 @@ function registerFlowNode(flowCmd) {
|
|
|
46
12
|
nodeCmd
|
|
47
13
|
.command('show <nodeId>')
|
|
48
14
|
.description('获取节点详细信息')
|
|
49
|
-
.option('--
|
|
15
|
+
.option('--json', '以 JSON 格式输出')
|
|
50
16
|
.action(async (nodeId, options) => {
|
|
51
17
|
try {
|
|
18
|
+
if (options.json)
|
|
19
|
+
(0, output_1.setJsonMode)(true);
|
|
52
20
|
(0, output_1.printInfo)(`正在获取节点 ${nodeId} 的详情...`);
|
|
53
21
|
const nodeDetail = await (0, node_1.getNodeDetail)(nodeId);
|
|
54
22
|
if (!nodeDetail) {
|
|
55
|
-
(
|
|
23
|
+
if (options.json) {
|
|
24
|
+
(0, output_1.printStructuredResult)({ ok: false, message: `未找到节点 ${nodeId}` });
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
(0, output_1.printError)(`未找到节点 ${nodeId}`);
|
|
28
|
+
}
|
|
56
29
|
return;
|
|
57
30
|
}
|
|
58
|
-
if (options.
|
|
31
|
+
if (options.json) {
|
|
59
32
|
(0, output_1.printJson)(nodeDetail);
|
|
60
33
|
return;
|
|
61
34
|
}
|
|
@@ -118,6 +91,54 @@ function registerFlowNode(flowCmd) {
|
|
|
118
91
|
(0, output_1.printError)(`获取节点信息失败: ${error.message}`);
|
|
119
92
|
}
|
|
120
93
|
});
|
|
94
|
+
nodeCmd
|
|
95
|
+
.command('list')
|
|
96
|
+
.description('列出流中的所有节点')
|
|
97
|
+
.requiredOption('--flow-id <flowId>', '连接流 ID')
|
|
98
|
+
.option('--json', '以 JSON 格式输出')
|
|
99
|
+
.action(async (options) => {
|
|
100
|
+
try {
|
|
101
|
+
if (options.json)
|
|
102
|
+
(0, output_1.setJsonMode)(true);
|
|
103
|
+
const flowId = options.flowId;
|
|
104
|
+
(0, output_1.printInfo)(`获取连接流 ${flowId} 的节点列表...`);
|
|
105
|
+
const flow = await (0, flow_1.getFlowDetail)(flowId);
|
|
106
|
+
const nodes = flow.nodes || [];
|
|
107
|
+
if (options.json) {
|
|
108
|
+
const list = nodes.map((n) => ({
|
|
109
|
+
id: n.n_id || n.id,
|
|
110
|
+
name: n.connector_name || n.action_name || '-',
|
|
111
|
+
type: n.node_type,
|
|
112
|
+
connectorId: n.connector_id,
|
|
113
|
+
actionId: n.action_id,
|
|
114
|
+
status: n.closed === 1 ? 'disabled' : n.status || 'normal',
|
|
115
|
+
position: n.position,
|
|
116
|
+
}));
|
|
117
|
+
(0, output_1.printJson)(list);
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
if (nodes.length === 0) {
|
|
121
|
+
(0, output_1.printInfo)('流中无节点');
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
const headers = ['节点ID', '名称', '类型', '状态'];
|
|
125
|
+
const rows = nodes.map((n) => [
|
|
126
|
+
String(n.n_id || n.id || '-'),
|
|
127
|
+
String(n.connector_name || n.action_name || '-'),
|
|
128
|
+
String(n.node_type || '-'),
|
|
129
|
+
n.closed === 1 ? '已禁用' : String(n.status || '正常'),
|
|
130
|
+
]);
|
|
131
|
+
(0, output_1.printTable)(headers, rows);
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
if (options.json) {
|
|
135
|
+
(0, output_1.printStructuredResult)({ ok: false, message: error.message });
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
(0, output_1.printError)(`获取节点列表失败: ${error.message}`);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
});
|
|
121
142
|
nodeCmd
|
|
122
143
|
.command('create')
|
|
123
144
|
.description('在连接流中创建新节点')
|
|
@@ -132,8 +153,11 @@ function registerFlowNode(flowCmd) {
|
|
|
132
153
|
.option('--data <json>', 'JSON 字符串,格式 {"properties": {...}},用于覆盖节点配置值')
|
|
133
154
|
.option('--position-x <number>', '节点 X 坐标(默认根据已有节点自动计算)')
|
|
134
155
|
.option('--position-y <number>', '节点 Y 坐标(默认根据已有节点自动计算)')
|
|
156
|
+
.option('--json', '以 JSON 格式输出')
|
|
135
157
|
.action(async (options) => {
|
|
136
158
|
try {
|
|
159
|
+
if (options.json)
|
|
160
|
+
(0, output_1.setJsonMode)(true);
|
|
137
161
|
const flowId = options.flowId;
|
|
138
162
|
const connectorId = options.connectorId;
|
|
139
163
|
const actionId = options.actionId;
|
|
@@ -142,7 +166,13 @@ function registerFlowNode(flowCmd) {
|
|
|
142
166
|
const nodes = flow.nodes || [];
|
|
143
167
|
const isFirstNode = nodes.length === 0;
|
|
144
168
|
if (isFirstNode && !options.trigger && options.node_type !== 'StartEventNode') {
|
|
145
|
-
|
|
169
|
+
const msg = '流中尚无节点,建议添加 --trigger 标志创建触发器节点';
|
|
170
|
+
if (options.json) {
|
|
171
|
+
(0, output_1.printStructuredResult)({ ok: false, message: msg });
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
(0, output_1.printWarning)(msg);
|
|
175
|
+
}
|
|
146
176
|
return;
|
|
147
177
|
}
|
|
148
178
|
const defaultPos = (0, helpers_1.calcDefaultPosition)(nodes);
|
|
@@ -157,38 +187,75 @@ function registerFlowNode(flowCmd) {
|
|
|
157
187
|
});
|
|
158
188
|
const action = actions.find((a) => a.id === actionId);
|
|
159
189
|
if (!action) {
|
|
160
|
-
|
|
190
|
+
const msg = `未找到动作 ${actionId}`;
|
|
191
|
+
if (options.json) {
|
|
192
|
+
(0, output_1.printStructuredResult)({ ok: false, message: msg });
|
|
193
|
+
}
|
|
194
|
+
else {
|
|
195
|
+
(0, output_1.printError)(msg);
|
|
196
|
+
}
|
|
161
197
|
return;
|
|
162
198
|
}
|
|
163
199
|
let accountId = options.accountId || null;
|
|
164
200
|
const accountSchemaId = action.config_schema
|
|
165
201
|
?.account_schema_id;
|
|
166
202
|
if (accountSchemaId && !accountId) {
|
|
167
|
-
(0, output_1.printWarning)(`该动作需要配置账号 (account_schema_id: ${accountSchemaId})`);
|
|
168
203
|
try {
|
|
169
204
|
const accounts = await (0, node_1.getAccountInstances)(connectorId, accountSchemaId);
|
|
170
|
-
if (accounts.length
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
205
|
+
if (accounts.length === 1) {
|
|
206
|
+
accountId = accounts[0].id;
|
|
207
|
+
(0, output_1.printInfo)(`自动选择账号: ${accounts[0].name || accountId}`);
|
|
208
|
+
}
|
|
209
|
+
else if (accounts.length > 1) {
|
|
210
|
+
if (options.json) {
|
|
211
|
+
(0, output_1.printStructuredResult)({
|
|
212
|
+
ok: false,
|
|
213
|
+
message: `该动作需要配置账号 (account_schema_id: ${accountSchemaId}),请通过 --account-id 指定`,
|
|
214
|
+
availableAccounts: accounts.map((a) => ({
|
|
215
|
+
id: a.id,
|
|
216
|
+
name: a.name,
|
|
217
|
+
auth_type: a.auth_type,
|
|
218
|
+
})),
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
else {
|
|
222
|
+
(0, output_1.printError)(`该动作需要配置账号 (account_schema_id: ${accountSchemaId}),可用账号:`);
|
|
223
|
+
const headers = ['ID', '名称', '认证类型'];
|
|
224
|
+
const rows = accounts.map((a) => {
|
|
225
|
+
const acc = a;
|
|
226
|
+
return [
|
|
227
|
+
String(acc.id || '-'),
|
|
228
|
+
String(acc.name || '-'),
|
|
229
|
+
String(acc.auth_type || '-'),
|
|
230
|
+
];
|
|
231
|
+
});
|
|
232
|
+
(0, output_1.printTable)(headers, rows);
|
|
233
|
+
(0, output_1.printError)('请通过 --account-id <id> 指定账号实例 ID');
|
|
234
|
+
}
|
|
235
|
+
process.exitCode = 1;
|
|
236
|
+
return;
|
|
182
237
|
}
|
|
183
238
|
else {
|
|
184
|
-
|
|
239
|
+
const msg = '未找到可用账号实例,请先创建账号';
|
|
240
|
+
if (options.json) {
|
|
241
|
+
(0, output_1.printStructuredResult)({ ok: false, message: msg });
|
|
242
|
+
}
|
|
243
|
+
else {
|
|
244
|
+
(0, output_1.printError)(msg);
|
|
245
|
+
}
|
|
246
|
+
return;
|
|
185
247
|
}
|
|
186
248
|
}
|
|
187
249
|
catch {
|
|
188
|
-
|
|
250
|
+
const msg = '获取账号实例失败,请通过 --account-id <id> 指定账号实例 ID';
|
|
251
|
+
if (options.json) {
|
|
252
|
+
(0, output_1.printStructuredResult)({ ok: false, message: msg });
|
|
253
|
+
}
|
|
254
|
+
else {
|
|
255
|
+
(0, output_1.printError)(msg);
|
|
256
|
+
}
|
|
257
|
+
return;
|
|
189
258
|
}
|
|
190
|
-
(0, output_1.printError)('请通过 --account-id <id> 指定账号实例 ID');
|
|
191
|
-
return;
|
|
192
259
|
}
|
|
193
260
|
let configSchema = action.config_schema || {};
|
|
194
261
|
const overrideValues = (0, helpers_1.resolveDataOption)(options, helpers_1.NODE_CREATE_DATA_SCHEMA);
|
|
@@ -200,9 +267,14 @@ function registerFlowNode(flowCmd) {
|
|
|
200
267
|
const config = (0, format_1.deepMerge)({ properties: action.config_schema }, overrideValues ?? {});
|
|
201
268
|
const defaultNodeType = trigger ? 'StartEventNode' : 'ActionNode';
|
|
202
269
|
const node_type = options.nodeType || action.action_type || defaultNodeType;
|
|
203
|
-
//此处逻辑仅因为服务端数据 trigger中的 nodeType 不正确
|
|
204
270
|
if (isFirstNode && node_type !== 'StartEventNode') {
|
|
205
|
-
|
|
271
|
+
const msg = '首个节点 nodeType 应该是 StartEventNode';
|
|
272
|
+
if (options.json) {
|
|
273
|
+
(0, output_1.printStructuredResult)({ ok: false, message: msg });
|
|
274
|
+
}
|
|
275
|
+
else {
|
|
276
|
+
(0, output_1.printError)(msg);
|
|
277
|
+
}
|
|
206
278
|
return;
|
|
207
279
|
}
|
|
208
280
|
const payload = {
|
|
@@ -218,73 +290,75 @@ function registerFlowNode(flowCmd) {
|
|
|
218
290
|
if (accountId) {
|
|
219
291
|
payload.account_id = accountId;
|
|
220
292
|
}
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
}
|
|
227
|
-
try {
|
|
228
|
-
payload.error_handler = JSON.parse(fs.readFileSync(ehPath, 'utf-8'));
|
|
229
|
-
}
|
|
230
|
-
catch {
|
|
231
|
-
(0, output_1.printError)(`错误处理 JSON 文件格式无效: ${ehPath}`);
|
|
232
|
-
return;
|
|
233
|
-
}
|
|
234
|
-
}
|
|
293
|
+
const eh = (0, helpers_1.resolveErrorHandlerFile)(options.errorHandlerFile, !!options.json);
|
|
294
|
+
if (eh === undefined)
|
|
295
|
+
return;
|
|
296
|
+
if (eh)
|
|
297
|
+
payload.error_handler = eh;
|
|
235
298
|
if (configSchema) {
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
(0, output_1.printWarning)(`节点配置值校验发现 ${validationErrors.length} 个问题:`);
|
|
239
|
-
for (const err of validationErrors) {
|
|
240
|
-
const ruleLabel = err.rule === 'required' ? '必填' : '类型';
|
|
241
|
-
(0, output_1.printWarning)(` [${ruleLabel}] ${err.message}`);
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
const specialErrors = (0, format_1.validateSpecialNodeType)(node_type, payload);
|
|
246
|
-
if (specialErrors.length > 0) {
|
|
247
|
-
(0, output_1.printWarning)(`特殊节点参数校验发现 ${specialErrors.length} 个问题:`);
|
|
248
|
-
for (const err of specialErrors) {
|
|
249
|
-
const ruleLabel = err.rule === 'required' ? '必填' : '类型';
|
|
250
|
-
(0, output_1.printWarning)(` [${ruleLabel}] ${err.message}`);
|
|
251
|
-
}
|
|
299
|
+
if ((0, helpers_1.checkPropertyValidation)((0, format_1.validateNodePropertyValues)(configSchema), !!options.json))
|
|
300
|
+
return;
|
|
252
301
|
}
|
|
302
|
+
if ((0, helpers_1.checkSpecialNodeValidation)((0, format_1.validateSpecialNodeType)(node_type, payload, configSchema), !!options.json))
|
|
303
|
+
return;
|
|
253
304
|
(0, output_1.printInfo)('正在创建节点...');
|
|
254
305
|
const result = await (0, node_1.createNode)(payload);
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
pairs.push(['账号 ID', accountId]);
|
|
306
|
+
const resultObj = result;
|
|
307
|
+
if (options.json) {
|
|
308
|
+
(0, output_1.printStructuredResult)({
|
|
309
|
+
ok: true,
|
|
310
|
+
id: String(resultObj.id || ''),
|
|
311
|
+
message: '节点创建成功',
|
|
312
|
+
nodeType: String(payload.node_type),
|
|
313
|
+
actionName: action.name,
|
|
314
|
+
connectorId: action.connector_id,
|
|
315
|
+
trigger,
|
|
316
|
+
position: { x: posX, y: posY },
|
|
317
|
+
});
|
|
268
318
|
}
|
|
269
|
-
|
|
270
|
-
|
|
319
|
+
else {
|
|
320
|
+
(0, output_1.printSuccess)('节点创建成功');
|
|
321
|
+
const nPayload = payload;
|
|
322
|
+
const nPos = nPayload.position;
|
|
323
|
+
const pairs = [
|
|
324
|
+
['节点 ID', String(resultObj.id || '-')],
|
|
325
|
+
['动作名称', action.name],
|
|
326
|
+
['连接器', action.connector_id],
|
|
327
|
+
['节点类型', String(nPayload.node_type)],
|
|
328
|
+
['触发器', trigger ? '是' : '否'],
|
|
329
|
+
['位置', `(${nPos.x}, ${nPos.y})`],
|
|
330
|
+
];
|
|
331
|
+
if (accountId) {
|
|
332
|
+
pairs.push(['账号 ID', accountId]);
|
|
333
|
+
}
|
|
334
|
+
if (options.errorHandlerFile) {
|
|
335
|
+
pairs.push(['错误处理', options.errorHandlerFile]);
|
|
336
|
+
}
|
|
337
|
+
if (options.dataFile)
|
|
338
|
+
pairs.push(['配置文件', options.dataFile]);
|
|
339
|
+
else if (options.data)
|
|
340
|
+
pairs.push(['配置数据', '--data']);
|
|
341
|
+
(0, output_1.printKeyValue)(pairs);
|
|
271
342
|
}
|
|
272
|
-
if (options.dataFile)
|
|
273
|
-
pairs.push(['配置文件', options.dataFile]);
|
|
274
|
-
else if (options.data)
|
|
275
|
-
pairs.push(['配置数据', '--data']);
|
|
276
|
-
(0, output_1.printKeyValue)(pairs);
|
|
277
343
|
}
|
|
278
344
|
catch (error) {
|
|
279
|
-
(
|
|
345
|
+
if (options.json) {
|
|
346
|
+
(0, output_1.printStructuredResult)({ ok: false, message: error.message });
|
|
347
|
+
}
|
|
348
|
+
else {
|
|
349
|
+
(0, output_1.printError)(`创建节点失败: ${error.message}`);
|
|
350
|
+
}
|
|
280
351
|
}
|
|
281
352
|
});
|
|
282
353
|
nodeCmd
|
|
283
354
|
.command('update <nodeId>')
|
|
284
355
|
.description('更新连接流中的节点配置')
|
|
285
356
|
.requiredOption('--flow-id <flowId>', '连接流 ID')
|
|
286
|
-
.option('--
|
|
287
|
-
.option('--
|
|
357
|
+
.option('--patch <json>', 'JSON 字符串,格式 {"properties": {...}},用于 patch 更新节点配置值')
|
|
358
|
+
.option('--patch-file <path>', 'JSON 文件路径,格式 {"properties": {...}},用于 patch 更新节点配置值')
|
|
359
|
+
.option('--data <json>', '(deprecated) 使用 --patch 代替')
|
|
360
|
+
.option('--data-file <path>', '(deprecated) 使用 --patch-file 代替')
|
|
361
|
+
.option('--validate-vars', '校验 patch 中的变量引用合法性', false)
|
|
288
362
|
.option('--position-x <number>', '节点 X 坐标')
|
|
289
363
|
.option('--position-y <number>', '节点 Y 坐标')
|
|
290
364
|
.option('--note <text>', '节点备注')
|
|
@@ -292,16 +366,31 @@ function registerFlowNode(flowCmd) {
|
|
|
292
366
|
.option('--action-id <actionId>', '更换动作 ID')
|
|
293
367
|
.option('--account-id <id>', '更换账号实例 ID')
|
|
294
368
|
.option('--error-handler-file <path>', '错误处理配置 JSON 文件')
|
|
369
|
+
.option('--json', '以 JSON 格式输出')
|
|
295
370
|
.action(async (nodeId, options) => {
|
|
296
371
|
try {
|
|
372
|
+
if (options.json)
|
|
373
|
+
(0, output_1.setJsonMode)(true);
|
|
297
374
|
const flowId = options.flowId;
|
|
375
|
+
if (options.patch || options.patchFile) {
|
|
376
|
+
options.data = options.patch;
|
|
377
|
+
options.dataFile = options.patchFile;
|
|
378
|
+
}
|
|
379
|
+
else if (options.data || options.dataFile) {
|
|
380
|
+
(0, output_1.printWarning)('--data/--data-file 已废弃,请使用 --patch/--patch-file');
|
|
381
|
+
}
|
|
298
382
|
(0, output_1.printInfo)(`正在获取节点 ${nodeId} 的详情...`);
|
|
299
383
|
const nodeDetail = await (0, node_1.getNodeDetail)(nodeId);
|
|
300
384
|
if (!nodeDetail) {
|
|
301
|
-
|
|
385
|
+
const msg = `未找到节点 ${nodeId}`;
|
|
386
|
+
if (options.json) {
|
|
387
|
+
(0, output_1.printStructuredResult)({ ok: false, message: msg });
|
|
388
|
+
}
|
|
389
|
+
else {
|
|
390
|
+
(0, output_1.printError)(msg);
|
|
391
|
+
}
|
|
302
392
|
return;
|
|
303
393
|
}
|
|
304
|
-
// 以 nodeDetail 为基准初始化 updateData
|
|
305
394
|
const nd = nodeDetail;
|
|
306
395
|
let updateData = {
|
|
307
396
|
flow_id: flowId,
|
|
@@ -321,7 +410,10 @@ function registerFlowNode(flowCmd) {
|
|
|
321
410
|
if (configValues) {
|
|
322
411
|
updateData = (0, format_1.deepMerge)(updateData, configValues);
|
|
323
412
|
}
|
|
324
|
-
|
|
413
|
+
if (options.validateVars && configValues) {
|
|
414
|
+
if (await (0, helpers_1.validateVariableRefs)(configValues, flowId, nodeId, !!options.json))
|
|
415
|
+
return;
|
|
416
|
+
}
|
|
325
417
|
if (options.positionX !== undefined || options.positionY !== undefined) {
|
|
326
418
|
const udPos = updateData.position;
|
|
327
419
|
updateData.position = {
|
|
@@ -337,103 +429,118 @@ function registerFlowNode(flowCmd) {
|
|
|
337
429
|
updateData.action_id = options.actionId;
|
|
338
430
|
if (options.accountId)
|
|
339
431
|
updateData.account_id = options.accountId;
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
432
|
+
const eh = (0, helpers_1.resolveErrorHandlerFile)(options.errorHandlerFile, !!options.json);
|
|
433
|
+
if (eh === undefined)
|
|
434
|
+
return;
|
|
435
|
+
if (eh)
|
|
436
|
+
updateData.error_handler = eh;
|
|
437
|
+
if (Object.keys(updateData).length === 0) {
|
|
438
|
+
const msg = '未指定任何更新参数';
|
|
439
|
+
if (options.json) {
|
|
440
|
+
(0, output_1.printStructuredResult)({ ok: false, message: msg });
|
|
345
441
|
}
|
|
346
|
-
|
|
347
|
-
|
|
442
|
+
else {
|
|
443
|
+
(0, output_1.printWarning)(msg);
|
|
348
444
|
}
|
|
349
|
-
catch {
|
|
350
|
-
(0, output_1.printError)(`错误处理 JSON 文件格式无效: ${ehPath}`);
|
|
351
|
-
return;
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
if (Object.keys(updateData).length === 0) {
|
|
355
|
-
(0, output_1.printWarning)('未指定任何更新参数');
|
|
356
445
|
return;
|
|
357
446
|
}
|
|
358
|
-
// 校验 properties 中各字段值与 page_control 类型匹配
|
|
359
447
|
if (updateData.properties) {
|
|
360
|
-
|
|
361
|
-
if (validationErrors.length > 0) {
|
|
362
|
-
(0, output_1.printWarning)(`节点配置值校验发现 ${validationErrors.length} 个问题:`);
|
|
363
|
-
for (const err of validationErrors) {
|
|
364
|
-
const ruleLabel = err.rule === 'required' ? '必填' : '类型';
|
|
365
|
-
(0, output_1.printWarning)(` [${ruleLabel}] ${err.message}`);
|
|
366
|
-
}
|
|
448
|
+
if ((0, helpers_1.checkPropertyValidation)((0, format_1.validateNodePropertyValues)(updateData.properties), !!options.json))
|
|
367
449
|
return;
|
|
368
|
-
}
|
|
369
450
|
}
|
|
370
|
-
|
|
371
|
-
if (specialErrors.length > 0) {
|
|
372
|
-
(0, output_1.printWarning)(`特殊节点参数校验发现 ${specialErrors.length} 个问题:`);
|
|
373
|
-
for (const err of specialErrors) {
|
|
374
|
-
const ruleLabel = err.rule === 'required' ? '必填' : '类型';
|
|
375
|
-
(0, output_1.printWarning)(` [${ruleLabel}] ${err.message}`);
|
|
376
|
-
}
|
|
451
|
+
if ((0, helpers_1.checkSpecialNodeValidation)((0, format_1.validateSpecialNodeType)(String(nd.node_type), updateData, nd.config_schema), !!options.json))
|
|
377
452
|
return;
|
|
378
|
-
}
|
|
379
453
|
(0, output_1.printInfo)('正在更新节点...');
|
|
380
454
|
await (0, node_1.updateNode)(nodeId, updateData);
|
|
381
|
-
(
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
455
|
+
if (options.json) {
|
|
456
|
+
const result = {
|
|
457
|
+
ok: true,
|
|
458
|
+
id: nodeId,
|
|
459
|
+
message: '节点更新成功',
|
|
460
|
+
};
|
|
461
|
+
if (updateData.position) {
|
|
462
|
+
const udPos = updateData.position;
|
|
463
|
+
result.position = { x: udPos.x, y: udPos.y };
|
|
464
|
+
}
|
|
465
|
+
if (options.note !== undefined)
|
|
466
|
+
result.note = options.note;
|
|
467
|
+
if (options.connectorId)
|
|
468
|
+
result.connectorId = options.connectorId;
|
|
469
|
+
if (options.actionId)
|
|
470
|
+
result.actionId = options.actionId;
|
|
471
|
+
if (options.accountId)
|
|
472
|
+
result.accountId = options.accountId;
|
|
473
|
+
(0, output_1.printStructuredResult)(result);
|
|
474
|
+
}
|
|
475
|
+
else {
|
|
476
|
+
(0, output_1.printSuccess)('节点更新成功');
|
|
477
|
+
const pairs = [['节点 ID', nodeId]];
|
|
478
|
+
if (options.dataFile)
|
|
479
|
+
pairs.push(['配置文件', options.dataFile]);
|
|
480
|
+
else if (options.data)
|
|
481
|
+
pairs.push(['配置数据', '--data']);
|
|
482
|
+
if (updateData.position) {
|
|
483
|
+
const udPos = updateData.position;
|
|
484
|
+
pairs.push(['位置', `(${udPos.x}, ${udPos.y})`]);
|
|
485
|
+
}
|
|
486
|
+
if (options.note !== undefined)
|
|
487
|
+
pairs.push(['备注', options.note]);
|
|
488
|
+
if (options.connectorId)
|
|
489
|
+
pairs.push(['连接器', options.connectorId]);
|
|
490
|
+
if (options.actionId)
|
|
491
|
+
pairs.push(['动作', options.actionId]);
|
|
492
|
+
if (options.accountId)
|
|
493
|
+
pairs.push(['账号 ID', options.accountId]);
|
|
494
|
+
if (options.errorHandlerFile)
|
|
495
|
+
pairs.push(['错误处理', options.errorHandlerFile]);
|
|
496
|
+
(0, output_1.printKeyValue)(pairs);
|
|
390
497
|
}
|
|
391
|
-
if (options.note !== undefined)
|
|
392
|
-
pairs.push(['备注', options.note]);
|
|
393
|
-
if (options.connectorId)
|
|
394
|
-
pairs.push(['连接器', options.connectorId]);
|
|
395
|
-
if (options.actionId)
|
|
396
|
-
pairs.push(['动作', options.actionId]);
|
|
397
|
-
if (options.accountId)
|
|
398
|
-
pairs.push(['账号 ID', options.accountId]);
|
|
399
|
-
if (options.errorHandlerFile)
|
|
400
|
-
pairs.push(['错误处理', options.errorHandlerFile]);
|
|
401
|
-
(0, output_1.printKeyValue)(pairs);
|
|
402
498
|
}
|
|
403
499
|
catch (error) {
|
|
404
|
-
(
|
|
500
|
+
if (options.json) {
|
|
501
|
+
(0, output_1.printStructuredResult)({ ok: false, message: error.message });
|
|
502
|
+
}
|
|
503
|
+
else {
|
|
504
|
+
(0, output_1.printError)(`更新节点失败: ${error.message}`);
|
|
505
|
+
}
|
|
405
506
|
}
|
|
406
507
|
});
|
|
407
508
|
nodeCmd
|
|
408
509
|
.command('delete <nodeId>')
|
|
409
510
|
.description('删除连接流中的节点')
|
|
410
511
|
.requiredOption('--flow-id <flowId>', '连接流 ID')
|
|
411
|
-
.option('--
|
|
512
|
+
.option('--yes', '跳过确认,直接删除')
|
|
513
|
+
.option('--json', '以 JSON 格式输出')
|
|
412
514
|
.action(async (nodeId, options) => {
|
|
413
515
|
try {
|
|
414
|
-
if (
|
|
415
|
-
(0, output_1.
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
});
|
|
426
|
-
if (answer.toLowerCase() !== 'y') {
|
|
427
|
-
(0, output_1.printInfo)('已取消删除');
|
|
428
|
-
return;
|
|
429
|
-
}
|
|
516
|
+
if (options.json)
|
|
517
|
+
(0, output_1.setJsonMode)(true);
|
|
518
|
+
if (!options.yes) {
|
|
519
|
+
const msg = {
|
|
520
|
+
ok: false,
|
|
521
|
+
message: `确认删除节点 ${nodeId}?`,
|
|
522
|
+
suggestion: `使用 --yes 标志直接删除: ai-flow flow node delete ${nodeId} --flow-id ${options.flowId} --yes`,
|
|
523
|
+
};
|
|
524
|
+
(0, output_1.printStructuredResult)(msg);
|
|
525
|
+
process.exitCode = 1;
|
|
526
|
+
return;
|
|
430
527
|
}
|
|
431
528
|
(0, output_1.printInfo)(`正在删除节点 ${nodeId}...`);
|
|
432
529
|
await (0, node_1.deleteNode)(nodeId);
|
|
433
|
-
(
|
|
530
|
+
if (options.json) {
|
|
531
|
+
(0, output_1.printStructuredResult)({ ok: true, id: nodeId, message: `节点 ${nodeId} 已删除` });
|
|
532
|
+
}
|
|
533
|
+
else {
|
|
534
|
+
(0, output_1.printSuccess)(`节点 ${nodeId} 已删除`);
|
|
535
|
+
}
|
|
434
536
|
}
|
|
435
537
|
catch (error) {
|
|
436
|
-
(
|
|
538
|
+
if (options.json) {
|
|
539
|
+
(0, output_1.printStructuredResult)({ ok: false, message: error.message });
|
|
540
|
+
}
|
|
541
|
+
else {
|
|
542
|
+
(0, output_1.printError)(`删除节点失败: ${error.message}`);
|
|
543
|
+
}
|
|
437
544
|
}
|
|
438
545
|
});
|
|
439
546
|
}
|