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.
- package/README.md +3 -0
- package/dist/api/client.js +36 -10
- package/dist/api/flowVersion.js +45 -0
- package/dist/api/knowledge.js +58 -17
- package/dist/api/node.js +76 -38
- package/dist/commands/flow/edge.js +71 -12
- package/dist/commands/flow/list.js +2 -1
- package/dist/commands/flow/node.js +147 -45
- package/dist/commands/flow/offline.js +37 -10
- package/dist/commands/flow/online.js +4 -4
- package/dist/commands/flow/publish.js +122 -17
- package/dist/commands/flow/validate.js +12 -0
- package/dist/commands/flow/version.js +303 -0
- package/dist/commands/flow.js +2 -0
- package/dist/commands/knowledge.js +101 -27
- package/dist/services/classicNodePorts.js +413 -0
- package/dist/services/portValidator.js +304 -0
- package/dist/services/skillGenerator.js +215 -29
- package/dist/utils/connectable.js +221 -0
- package/dist/utils/nodePackage.js +23 -1
- package/dist/utils/nodeSchemaCache.js +87 -0
- package/package.json +1 -1
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.formatPublishTime = formatPublishTime;
|
|
4
|
+
exports.parseVersionNo = parseVersionNo;
|
|
5
|
+
exports.resolveVersionId = resolveVersionId;
|
|
6
|
+
exports.registerFlowVersion = registerFlowVersion;
|
|
7
|
+
const flowVersion_1 = require("@/api/flowVersion");
|
|
8
|
+
const exit_code_1 = require("@/constants/exit-code");
|
|
9
|
+
const output_1 = require("@/utils/output");
|
|
10
|
+
/** 格式化发布时间:YYYY-MM-DD HH:mm(对齐 IAM-Console formatPublishTime) */
|
|
11
|
+
function formatPublishTime(value) {
|
|
12
|
+
if (!value)
|
|
13
|
+
return '-';
|
|
14
|
+
const normalized = value.includes('T') ? value.replace('T', ' ') : value;
|
|
15
|
+
return normalized.length >= 16 ? normalized.slice(0, 16) : normalized;
|
|
16
|
+
}
|
|
17
|
+
/** 解析 vN / N 形式的版本号(version_no 为小整数);雪花 ID 或其他形式返回 null */
|
|
18
|
+
function parseVersionNo(ref) {
|
|
19
|
+
const trimmed = ref.trim();
|
|
20
|
+
if (/^\d{10,}$/.test(trimmed))
|
|
21
|
+
return null;
|
|
22
|
+
const match = /^v?(\d{1,9})$/i.exec(trimmed);
|
|
23
|
+
return match ? Number(match[1]) : null;
|
|
24
|
+
}
|
|
25
|
+
function listAvailableVersions(versions) {
|
|
26
|
+
const listed = versions
|
|
27
|
+
.map((v) => `v${v.version_no}(${v.id})`)
|
|
28
|
+
.slice(0, 20)
|
|
29
|
+
.join('、');
|
|
30
|
+
return listed || '该连接流暂无已发布版本';
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* 将 <versionFlowId> 参数(雪花 ID 或 vN / N)解析为版本 ID。
|
|
34
|
+
* vN / N 形式通过 getFlowVersions 查找对应 id,找不到时报错并列出可用版本。
|
|
35
|
+
*/
|
|
36
|
+
async function resolveVersionId(flowId, ref) {
|
|
37
|
+
const trimmed = ref.trim();
|
|
38
|
+
const versionNo = parseVersionNo(trimmed);
|
|
39
|
+
if (versionNo === null)
|
|
40
|
+
return trimmed;
|
|
41
|
+
const page = await (0, flowVersion_1.getFlowVersions)(flowId, { page: 1, size: 100 });
|
|
42
|
+
const matched = (page.items || []).find((v) => v.version_no === versionNo);
|
|
43
|
+
if (matched)
|
|
44
|
+
return matched.id;
|
|
45
|
+
throw new Error(`未找到版本 v${versionNo}。可用版本: ${listAvailableVersions(page.items || [])}`);
|
|
46
|
+
}
|
|
47
|
+
function versionLabel(v) {
|
|
48
|
+
return v.effective ? `v${v.version_no} (生效中)` : `v${v.version_no}`;
|
|
49
|
+
}
|
|
50
|
+
function registerFlowVersion(flowCmd) {
|
|
51
|
+
const versionCmd = flowCmd
|
|
52
|
+
.command('version')
|
|
53
|
+
.description('连接流版本管理(状态/历史/详情/回滚/载入草稿/删除)');
|
|
54
|
+
versionCmd
|
|
55
|
+
.command('status <flowId>')
|
|
56
|
+
.description('查看草稿与线上生效版本状态')
|
|
57
|
+
.option('--json', '以 JSON 格式输出')
|
|
58
|
+
.action(async (flowId, options) => {
|
|
59
|
+
try {
|
|
60
|
+
if (options.json)
|
|
61
|
+
(0, output_1.setJsonMode)(true);
|
|
62
|
+
const status = await (0, flowVersion_1.getFlowVersionStatus)(flowId);
|
|
63
|
+
if (options.json) {
|
|
64
|
+
(0, output_1.printStructuredResult)({ ok: true, data: status });
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
(0, output_1.printHeader)(`连接流版本状态: ${flowId}`);
|
|
68
|
+
(0, output_1.printKeyValue)([
|
|
69
|
+
['是否已发布', status.published ? '是' : '否(从未发布)'],
|
|
70
|
+
[
|
|
71
|
+
'生效版本',
|
|
72
|
+
status.published && status.effective_version_no != null
|
|
73
|
+
? `v${status.effective_version_no}`
|
|
74
|
+
: '-',
|
|
75
|
+
],
|
|
76
|
+
['当前草稿版本', `v${status.draft_version_no}`],
|
|
77
|
+
]);
|
|
78
|
+
if (!status.published) {
|
|
79
|
+
(0, output_1.printInfo)('该连接流从未发布过版本');
|
|
80
|
+
}
|
|
81
|
+
else if (status.has_unpublished_changes) {
|
|
82
|
+
(0, output_1.printWarning)('草稿有未发布修改');
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
(0, output_1.printSuccess)('草稿与生效版本一致,无未发布修改');
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
if (options.json) {
|
|
90
|
+
(0, output_1.printStructuredResult)({ ok: false, message: error.message });
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
(0, output_1.printError)(`查询版本状态失败: ${error.message}`);
|
|
94
|
+
}
|
|
95
|
+
process.exitCode = exit_code_1.ExitCode.FAILURE;
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
versionCmd
|
|
99
|
+
.command('list <flowId>')
|
|
100
|
+
.description('查看发布版本历史')
|
|
101
|
+
.option('--page <page>', '页码(默认 1)', '1')
|
|
102
|
+
.option('--size <size>', '每页数量(默认 20)', '20')
|
|
103
|
+
.option('--json', '以 JSON 格式输出')
|
|
104
|
+
.action(async (flowId, options) => {
|
|
105
|
+
try {
|
|
106
|
+
if (options.json)
|
|
107
|
+
(0, output_1.setJsonMode)(true);
|
|
108
|
+
const page = Math.max(1, parseInt(options.page || '1', 10) || 1);
|
|
109
|
+
const size = Math.max(1, parseInt(options.size || '20', 10) || 20);
|
|
110
|
+
const result = await (0, flowVersion_1.getFlowVersions)(flowId, { page, size });
|
|
111
|
+
if (options.json) {
|
|
112
|
+
(0, output_1.printStructuredResult)({
|
|
113
|
+
ok: true,
|
|
114
|
+
data: result.items || [],
|
|
115
|
+
total: result.total ?? (result.items || []).length,
|
|
116
|
+
});
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
(0, output_1.printHeader)(`发布版本历史: ${flowId}(第 ${page} 页,共 ${result.total ?? 0} 个)`);
|
|
120
|
+
(0, output_1.printTable)(['版本', '命名', '备注', '发布人', '发布时间'], (result.items || []).map((v) => [
|
|
121
|
+
versionLabel(v),
|
|
122
|
+
v.version_name || '-',
|
|
123
|
+
v.remark || '-',
|
|
124
|
+
v.publish_by || '-',
|
|
125
|
+
formatPublishTime(v.publish_time),
|
|
126
|
+
]));
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
if (options.json) {
|
|
130
|
+
(0, output_1.printStructuredResult)({ ok: false, message: error.message });
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
(0, output_1.printError)(`查询版本历史失败: ${error.message}`);
|
|
134
|
+
}
|
|
135
|
+
process.exitCode = exit_code_1.ExitCode.FAILURE;
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
versionCmd
|
|
139
|
+
.command('detail <flowId> <versionFlowId>')
|
|
140
|
+
.description('查看历史版本详情(versionFlowId 支持版本 ID 或 vN / N)')
|
|
141
|
+
.option('--json', '以 JSON 格式输出')
|
|
142
|
+
.action(async (flowId, versionFlowId, options) => {
|
|
143
|
+
try {
|
|
144
|
+
if (options.json)
|
|
145
|
+
(0, output_1.setJsonMode)(true);
|
|
146
|
+
const versionId = await resolveVersionId(flowId, versionFlowId);
|
|
147
|
+
const detail = await (0, flowVersion_1.getFlowVersionDetail)(flowId, versionId);
|
|
148
|
+
if (options.json) {
|
|
149
|
+
(0, output_1.printStructuredResult)({
|
|
150
|
+
ok: true,
|
|
151
|
+
data: detail.version,
|
|
152
|
+
flow: detail.flow,
|
|
153
|
+
});
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
const v = detail.version;
|
|
157
|
+
(0, output_1.printHeader)(`版本详情: v${v.version_no}`);
|
|
158
|
+
(0, output_1.printKeyValue)([
|
|
159
|
+
['版本', versionLabel(v)],
|
|
160
|
+
['命名', v.version_name || '-'],
|
|
161
|
+
['备注', v.remark || '-'],
|
|
162
|
+
['发布人', v.publish_by || '-'],
|
|
163
|
+
['发布时间', formatPublishTime(v.publish_time)],
|
|
164
|
+
['版本 ID', v.id],
|
|
165
|
+
]);
|
|
166
|
+
if (detail.flow && Object.keys(detail.flow).length > 0) {
|
|
167
|
+
(0, output_1.printInfo)('Flow 配置:');
|
|
168
|
+
(0, output_1.printJson)(detail.flow);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
catch (error) {
|
|
172
|
+
if (options.json) {
|
|
173
|
+
(0, output_1.printStructuredResult)({ ok: false, message: error.message });
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
(0, output_1.printError)(`查询版本详情失败: ${error.message}`);
|
|
177
|
+
}
|
|
178
|
+
process.exitCode = exit_code_1.ExitCode.FAILURE;
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
versionCmd
|
|
182
|
+
.command('rollback <flowId> <versionFlowId>')
|
|
183
|
+
.description('回滚到历史版本(回滚成功即隐式发布,线上生效版本立即切换)')
|
|
184
|
+
.option('--force', '跳过确认提示')
|
|
185
|
+
.option('--json', '以 JSON 格式输出')
|
|
186
|
+
.action(async (flowId, versionFlowId, options) => {
|
|
187
|
+
try {
|
|
188
|
+
if (options.json)
|
|
189
|
+
(0, output_1.setJsonMode)(true);
|
|
190
|
+
const versionId = await resolveVersionId(flowId, versionFlowId);
|
|
191
|
+
if (!options.force && !options.json) {
|
|
192
|
+
(0, output_1.printWarning)(`确认回滚到 ${versionFlowId}?回滚成功即隐式发布,线上生效版本立即切换`);
|
|
193
|
+
(0, output_1.printInfo)('如需确认回滚,请使用 --force 参数');
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
if (options.json) {
|
|
197
|
+
const version = await (0, flowVersion_1.rollbackFlowVersion)(flowId, versionId);
|
|
198
|
+
(0, output_1.printStructuredResult)({
|
|
199
|
+
ok: true,
|
|
200
|
+
id: flowId,
|
|
201
|
+
version_id: version.id,
|
|
202
|
+
version_no: version.version_no,
|
|
203
|
+
message: `已回滚到 v${version.version_no},线上生效版本已切换`,
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
(0, output_1.printInfo)(`正在回滚到 ${versionFlowId}...(回滚成功即隐式发布,线上生效版本立即切换)`);
|
|
208
|
+
const version = await (0, flowVersion_1.rollbackFlowVersion)(flowId, versionId);
|
|
209
|
+
(0, output_1.printSuccess)(`已回滚到 v${version.version_no},线上生效版本已切换`);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
catch (error) {
|
|
213
|
+
if (options.json) {
|
|
214
|
+
(0, output_1.printStructuredResult)({ ok: false, message: error.message });
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
217
|
+
(0, output_1.printError)(`回滚版本失败: ${error.message}`);
|
|
218
|
+
}
|
|
219
|
+
process.exitCode = exit_code_1.ExitCode.FAILURE;
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
versionCmd
|
|
223
|
+
.command('load-draft <flowId> <versionFlowId>')
|
|
224
|
+
.description('用历史版本覆盖唯一草稿(当前草稿未发布修改会被覆盖)')
|
|
225
|
+
.option('--force', '跳过确认提示')
|
|
226
|
+
.option('--json', '以 JSON 格式输出')
|
|
227
|
+
.action(async (flowId, versionFlowId, options) => {
|
|
228
|
+
try {
|
|
229
|
+
if (options.json)
|
|
230
|
+
(0, output_1.setJsonMode)(true);
|
|
231
|
+
const versionId = await resolveVersionId(flowId, versionFlowId);
|
|
232
|
+
if (!options.force && !options.json) {
|
|
233
|
+
(0, output_1.printWarning)(`确认用 ${versionFlowId} 覆盖当前草稿?当前草稿未发布修改会被覆盖`);
|
|
234
|
+
(0, output_1.printInfo)('如需确认覆盖,请使用 --force 参数');
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
if (options.json) {
|
|
238
|
+
await (0, flowVersion_1.loadFlowVersionAsDraft)(flowId, versionId);
|
|
239
|
+
(0, output_1.printStructuredResult)({
|
|
240
|
+
ok: true,
|
|
241
|
+
id: flowId,
|
|
242
|
+
version_id: versionId,
|
|
243
|
+
message: '已用历史版本覆盖草稿',
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
(0, output_1.printInfo)(`正在用 ${versionFlowId} 覆盖草稿...(当前草稿未发布修改会被覆盖)`);
|
|
248
|
+
await (0, flowVersion_1.loadFlowVersionAsDraft)(flowId, versionId);
|
|
249
|
+
(0, output_1.printSuccess)('已用历史版本覆盖草稿');
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
catch (error) {
|
|
253
|
+
if (options.json) {
|
|
254
|
+
(0, output_1.printStructuredResult)({ ok: false, message: error.message });
|
|
255
|
+
}
|
|
256
|
+
else {
|
|
257
|
+
(0, output_1.printError)(`载入草稿失败: ${error.message}`);
|
|
258
|
+
}
|
|
259
|
+
process.exitCode = exit_code_1.ExitCode.FAILURE;
|
|
260
|
+
}
|
|
261
|
+
});
|
|
262
|
+
versionCmd
|
|
263
|
+
.command('delete <flowId> <versionFlowId>')
|
|
264
|
+
.description('删除发布版本(生效版本不可删除)')
|
|
265
|
+
.option('--force', '跳过确认提示')
|
|
266
|
+
.option('--json', '以 JSON 格式输出')
|
|
267
|
+
.action(async (flowId, versionFlowId, options) => {
|
|
268
|
+
try {
|
|
269
|
+
if (options.json)
|
|
270
|
+
(0, output_1.setJsonMode)(true);
|
|
271
|
+
const versionId = await resolveVersionId(flowId, versionFlowId);
|
|
272
|
+
if (!options.force && !options.json) {
|
|
273
|
+
(0, output_1.printWarning)(`确认删除版本 ${versionFlowId}?删除后不可恢复`);
|
|
274
|
+
(0, output_1.printInfo)('如需确认删除,请使用 --force 参数');
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
if (options.json) {
|
|
278
|
+
await (0, flowVersion_1.deleteFlowVersion)(flowId, versionId);
|
|
279
|
+
(0, output_1.printStructuredResult)({
|
|
280
|
+
ok: true,
|
|
281
|
+
id: flowId,
|
|
282
|
+
version_id: versionId,
|
|
283
|
+
message: '版本删除成功',
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
else {
|
|
287
|
+
(0, output_1.printInfo)(`正在删除版本 ${versionFlowId}...`);
|
|
288
|
+
await (0, flowVersion_1.deleteFlowVersion)(flowId, versionId);
|
|
289
|
+
(0, output_1.printSuccess)('版本删除成功');
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
catch (error) {
|
|
293
|
+
if (options.json) {
|
|
294
|
+
(0, output_1.printStructuredResult)({ ok: false, message: error.message });
|
|
295
|
+
}
|
|
296
|
+
else {
|
|
297
|
+
(0, output_1.printError)(`删除版本失败: ${error.message}`);
|
|
298
|
+
}
|
|
299
|
+
process.exitCode = exit_code_1.ExitCode.FAILURE;
|
|
300
|
+
}
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
//# sourceMappingURL=version.js.map
|
package/dist/commands/flow.js
CHANGED
|
@@ -21,6 +21,7 @@ const copy_1 = require("@/commands/flow/copy");
|
|
|
21
21
|
const export_1 = require("@/commands/flow/export");
|
|
22
22
|
const import_1 = require("@/commands/flow/import");
|
|
23
23
|
const delete_1 = require("@/commands/flow/delete");
|
|
24
|
+
const version_1 = require("@/commands/flow/version");
|
|
24
25
|
function registerFlowCommand(program) {
|
|
25
26
|
const flowCmd = program.command('flow').description('连接流操作');
|
|
26
27
|
(0, create_1.registerFlowCreate)(flowCmd);
|
|
@@ -43,5 +44,6 @@ function registerFlowCommand(program) {
|
|
|
43
44
|
(0, export_1.registerFlowExport)(flowCmd);
|
|
44
45
|
(0, import_1.registerFlowImport)(flowCmd);
|
|
45
46
|
(0, delete_1.registerFlowDelete)(flowCmd);
|
|
47
|
+
(0, version_1.registerFlowVersion)(flowCmd);
|
|
46
48
|
}
|
|
47
49
|
//# sourceMappingURL=flow.js.map
|
|
@@ -5,7 +5,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.registerKnowledgeCommand = registerKnowledgeCommand;
|
|
7
7
|
const knowledge_1 = require("@/api/knowledge");
|
|
8
|
-
const
|
|
8
|
+
const nodePackage_1 = require("@/utils/nodePackage");
|
|
9
|
+
const exit_code_1 = require("@/constants/exit-code");
|
|
9
10
|
const skillGenerator_1 = require("@/services/skillGenerator");
|
|
10
11
|
const output_1 = require("@/utils/output");
|
|
11
12
|
const format_1 = require("@/utils/format");
|
|
@@ -16,7 +17,7 @@ function registerKnowledgeCommand(program) {
|
|
|
16
17
|
knowledgeCmd
|
|
17
18
|
.command('categories')
|
|
18
19
|
.description('列出所有节点分类')
|
|
19
|
-
.option('--type [type]', 'normal
|
|
20
|
+
.option('--type [type]', '使用场景 scene 值(目前仅 mcp,mfa,sync,normal 有效,mcp 对应 MCP Server 画布;mfa 对应MFA画布; sync 对应 集成/同步流; 默认 normal 常规自动化)', 'normal')
|
|
20
21
|
.option('--trigger', '仅 Trigger 分类')
|
|
21
22
|
.option('--json', '以 JSON 格式输出')
|
|
22
23
|
.action(async (options) => {
|
|
@@ -24,6 +25,7 @@ function registerKnowledgeCommand(program) {
|
|
|
24
25
|
if (options.json)
|
|
25
26
|
(0, output_1.setJsonMode)(true);
|
|
26
27
|
const categories = await (0, knowledge_1.getNodeCategories)({
|
|
28
|
+
mode: 'independent',
|
|
27
29
|
trigger: options.trigger,
|
|
28
30
|
scene: options.type,
|
|
29
31
|
});
|
|
@@ -36,15 +38,8 @@ function registerKnowledgeCommand(program) {
|
|
|
36
38
|
const key = String(cat.name || '');
|
|
37
39
|
const label = String(cat.label || cat.name || key);
|
|
38
40
|
const desc = String(cat.desc || '');
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
if (children && Array.isArray(children) && children.length > 0) {
|
|
42
|
-
for (const child of children) {
|
|
43
|
-
const childKey = String(child.name || '');
|
|
44
|
-
const childLabel = String(child.label || childKey);
|
|
45
|
-
console.log(` ${chalk_1.default.gray('└─')} ${chalk_1.default.dim(childKey)} ${chalk_1.default.dim(childLabel)}`);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
41
|
+
const searchTag = cat.search_action ? chalk_1.default.magenta(' [search_action]') : '';
|
|
42
|
+
console.log(` ${chalk_1.default.cyan(key.padEnd(20))} ${chalk_1.default.white(label)} ${chalk_1.default.gray(desc)}${searchTag}`);
|
|
48
43
|
}
|
|
49
44
|
}
|
|
50
45
|
catch (error) {
|
|
@@ -54,12 +49,13 @@ function registerKnowledgeCommand(program) {
|
|
|
54
49
|
else {
|
|
55
50
|
(0, output_1.printError)(`获取分类失败: ${error.message}`);
|
|
56
51
|
}
|
|
52
|
+
process.exitCode = exit_code_1.ExitCode.FAILURE;
|
|
57
53
|
}
|
|
58
54
|
});
|
|
59
55
|
knowledgeCmd
|
|
60
56
|
.command('nodes [category]')
|
|
61
57
|
.description('搜索节点,展示匹配的 connector 及 actions(含 nodeType)')
|
|
62
|
-
.option('--name <name>', '
|
|
58
|
+
.option('--name <name>', '按关键字搜索动作(search_action 分类下必须提供,此时按 keyword 搜动作而非按分类过滤)')
|
|
63
59
|
.option('--trigger', '仅触发器')
|
|
64
60
|
.option('--page <number>', '页码', '1')
|
|
65
61
|
.option('--size <number>', '每页数量', '50')
|
|
@@ -69,10 +65,37 @@ function registerKnowledgeCommand(program) {
|
|
|
69
65
|
try {
|
|
70
66
|
if (opts.json)
|
|
71
67
|
(0, output_1.setJsonMode)(true);
|
|
68
|
+
const keyword = opts.name;
|
|
69
|
+
const trigger = opts.trigger || false;
|
|
70
|
+
// search_action=true 的分类:语义是"选中该分类时按 keyword 直接搜动作而非按
|
|
71
|
+
// category_name 过滤"(参考 rcs types.ts search_action 注释)。
|
|
72
|
+
// 仅当给了 category 时才需要探测其 search_action 标记。
|
|
73
|
+
let categoryIsSearchAction = false;
|
|
74
|
+
if (category) {
|
|
75
|
+
try {
|
|
76
|
+
const categories = await (0, knowledge_1.getNodeCategories)({
|
|
77
|
+
mode: 'independent',
|
|
78
|
+
trigger,
|
|
79
|
+
scene: 'normal',
|
|
80
|
+
});
|
|
81
|
+
const matched = categories.find((cat) => cat.name === category);
|
|
82
|
+
categoryIsSearchAction = matched?.search_action === true;
|
|
83
|
+
if (categoryIsSearchAction && !keyword) {
|
|
84
|
+
throw new Error(`分类 "${category}" 是 search_action 分类,需提供 --name <keyword> 按关键字搜索动作`);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
if (error instanceof Error && error.message.includes('search_action'))
|
|
89
|
+
throw error;
|
|
90
|
+
// 分类探测失败不阻塞主流程,回退按 category_name 查询
|
|
91
|
+
}
|
|
92
|
+
}
|
|
72
93
|
const result = await (0, knowledge_1.searchNodesByCategory)({
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
94
|
+
mode: 'independent',
|
|
95
|
+
scene: 'normal',
|
|
96
|
+
categoryName: categoryIsSearchAction ? undefined : category,
|
|
97
|
+
keyword,
|
|
98
|
+
trigger,
|
|
76
99
|
page: Number(opts.page),
|
|
77
100
|
size: Number(opts.size),
|
|
78
101
|
});
|
|
@@ -81,7 +104,7 @@ function registerKnowledgeCommand(program) {
|
|
|
81
104
|
return;
|
|
82
105
|
}
|
|
83
106
|
const items = result.items || [];
|
|
84
|
-
(0, output_1.printHeader)(`节点列表${category ? ` [${category}]` : ''} (共 ${result.total} 个)`);
|
|
107
|
+
(0, output_1.printHeader)(`节点列表${category ? ` [${category}]` : ''}${keyword ? ` (keyword: ${keyword})` : ''} (共 ${result.total} 个)`);
|
|
85
108
|
for (const item of items) {
|
|
86
109
|
const c = item.connector;
|
|
87
110
|
console.log(`\n${chalk_1.default.bold.blue('▸')} ${chalk_1.default.bold.white(c.name)} ${chalk_1.default.gray(`(${c.id})`)}`);
|
|
@@ -94,13 +117,24 @@ function registerKnowledgeCommand(program) {
|
|
|
94
117
|
}
|
|
95
118
|
(0, output_1.printKeyValue)(pairs, ' ');
|
|
96
119
|
let actions = item.matched_actions || [];
|
|
97
|
-
if (
|
|
120
|
+
if (keyword) {
|
|
121
|
+
// connectable 接口按 link_id + keyword 重查取 matched_actions,
|
|
122
|
+
// linkId 限定后为 exact match(对齐 rcs loadConnectableNodeActions)
|
|
98
123
|
try {
|
|
99
|
-
|
|
124
|
+
const refetch = await (0, knowledge_1.searchNodesByCategory)({
|
|
125
|
+
mode: 'independent',
|
|
126
|
+
scene: 'normal',
|
|
100
127
|
linkId: c.id,
|
|
101
|
-
|
|
102
|
-
trigger
|
|
128
|
+
keyword,
|
|
129
|
+
trigger,
|
|
130
|
+
page: 1,
|
|
131
|
+
size: Number(opts.size),
|
|
103
132
|
});
|
|
133
|
+
const exact = refetch.items.find((candidate) => candidate.connector.id === c.id) ??
|
|
134
|
+
refetch.items[0];
|
|
135
|
+
if (exact?.matched_actions && exact.matched_actions.length > 0) {
|
|
136
|
+
actions = exact.matched_actions;
|
|
137
|
+
}
|
|
104
138
|
}
|
|
105
139
|
catch {
|
|
106
140
|
// fallback to matched_actions
|
|
@@ -112,7 +146,11 @@ function registerKnowledgeCommand(program) {
|
|
|
112
146
|
const action = a;
|
|
113
147
|
const triggerTag = action.is_trigger ? chalk_1.default.yellow(' [trigger]') : '';
|
|
114
148
|
const nodeType = action.action_type || '-';
|
|
115
|
-
|
|
149
|
+
// NodePackage 持久身份是 action_key@action_ver,可直接喂给 flow node add --action-id
|
|
150
|
+
const identity = action.node_schema
|
|
151
|
+
? `${action.action_key || action.id} version: ${action.node_schema?.version}`
|
|
152
|
+
: String(action.action_key || action.id);
|
|
153
|
+
console.log(` ${chalk_1.default.cyan(identity)} ${action.name} ${chalk_1.default.gray('nodeType:')} ${chalk_1.default.green(String(nodeType))}${triggerTag} ${chalk_1.default.gray('nodeId:')} ${action.id} ${chalk_1.default.gray('connectorId:')} ${action.connector_id}`);
|
|
116
154
|
}
|
|
117
155
|
}
|
|
118
156
|
}
|
|
@@ -121,7 +159,13 @@ function registerKnowledgeCommand(program) {
|
|
|
121
159
|
}
|
|
122
160
|
}
|
|
123
161
|
catch (error) {
|
|
124
|
-
(
|
|
162
|
+
if (opts.json) {
|
|
163
|
+
(0, output_1.printStructuredResult)({ ok: false, message: error.message });
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
(0, output_1.printError)(`获取节点失败: ${error.message}`);
|
|
167
|
+
}
|
|
168
|
+
process.exitCode = exit_code_1.ExitCode.FAILURE;
|
|
125
169
|
}
|
|
126
170
|
});
|
|
127
171
|
knowledgeCmd
|
|
@@ -133,10 +177,28 @@ function registerKnowledgeCommand(program) {
|
|
|
133
177
|
try {
|
|
134
178
|
if (options.json)
|
|
135
179
|
(0, output_1.setJsonMode)(true);
|
|
136
|
-
|
|
180
|
+
// 本版本统一走 connectable API;服务端不支持时直接报错并给出降级建议,不再回退旧接口
|
|
181
|
+
const supported = await (0, nodePackage_1.checkAndCacheNodePackageSupport)();
|
|
182
|
+
if (!supported) {
|
|
183
|
+
const msg = `目标 baseUrl 不支持 NodePackage。${nodePackage_1.NODE_PACKAGE_DOWNGRADE_HINT}`;
|
|
184
|
+
process.exitCode = exit_code_1.ExitCode.FAILURE;
|
|
185
|
+
if (options.json) {
|
|
186
|
+
(0, output_1.printStructuredResult)({ ok: false, message: msg });
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
(0, output_1.printError)(msg);
|
|
190
|
+
}
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
// connectable 接口按 link_id + trigger 查询,取 matched_actions
|
|
194
|
+
const result = await (0, knowledge_1.searchNodesByCategory)({
|
|
195
|
+
mode: 'independent',
|
|
196
|
+
scene: 'normal',
|
|
137
197
|
linkId,
|
|
138
|
-
trigger: options.trigger,
|
|
198
|
+
trigger: options.trigger || false,
|
|
139
199
|
});
|
|
200
|
+
const exact = result.items.find((candidate) => candidate.connector.id === linkId) ?? result.items[0];
|
|
201
|
+
const actions = (exact?.matched_actions ?? []) || [];
|
|
140
202
|
if (options.json) {
|
|
141
203
|
const enriched = actions.map((a) => ({
|
|
142
204
|
...a,
|
|
@@ -147,9 +209,14 @@ function registerKnowledgeCommand(program) {
|
|
|
147
209
|
}
|
|
148
210
|
(0, output_1.printHeader)(`连接器动作 (共 ${actions.length} 个) — Link: ${linkId}`);
|
|
149
211
|
for (const action of actions) {
|
|
150
|
-
|
|
212
|
+
// NodePackage 持久身份是 action_key@action_ver,可直接喂给 flow node create --action-id
|
|
213
|
+
const actionVer = action.action_ver ?? action.node_schema?.version;
|
|
214
|
+
const identity = actionVer
|
|
215
|
+
? `${action.action_key}@${actionVer}`
|
|
216
|
+
: String(action.action_key || action.id);
|
|
217
|
+
console.log(`\n${chalk_1.default.bold.blue('▸')} ${chalk_1.default.bold.white(action.name)} ${chalk_1.default.gray(`[${identity}]`)}`);
|
|
151
218
|
const pairs = [
|
|
152
|
-
['ID',
|
|
219
|
+
['ID', identity],
|
|
153
220
|
['描述', action.description || '(无)'],
|
|
154
221
|
['Trigger', action.is_trigger ? '是' : '否'],
|
|
155
222
|
['nodeType', action.action_type || '-'],
|
|
@@ -194,7 +261,13 @@ function registerKnowledgeCommand(program) {
|
|
|
194
261
|
}
|
|
195
262
|
}
|
|
196
263
|
catch (error) {
|
|
197
|
-
(
|
|
264
|
+
if (options.json) {
|
|
265
|
+
(0, output_1.printStructuredResult)({ ok: false, message: error.message });
|
|
266
|
+
}
|
|
267
|
+
else {
|
|
268
|
+
(0, output_1.printError)(`获取动作失败: ${error.message}`);
|
|
269
|
+
}
|
|
270
|
+
process.exitCode = exit_code_1.ExitCode.FAILURE;
|
|
198
271
|
}
|
|
199
272
|
});
|
|
200
273
|
knowledgeCmd
|
|
@@ -257,6 +330,7 @@ function registerKnowledgeCommand(program) {
|
|
|
257
330
|
else {
|
|
258
331
|
(0, output_1.printError)(`生成失败: ${error.message}`);
|
|
259
332
|
}
|
|
333
|
+
process.exitCode = exit_code_1.ExitCode.FAILURE;
|
|
260
334
|
}
|
|
261
335
|
});
|
|
262
336
|
}
|