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,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
@@ -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 node_1 = require("@/api/node");
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|mcp', '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
- console.log(` ${chalk_1.default.cyan(key.padEnd(20))} ${chalk_1.default.white(label)} ${chalk_1.default.gray(desc)}`);
40
- const children = cat.next;
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
- category_name: category,
74
- keyword: opts.name,
75
- trigger: opts.trigger || false,
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 (opts.name) {
120
+ if (keyword) {
121
+ // connectable 接口按 link_id + keyword 重查取 matched_actions,
122
+ // linkId 限定后为 exact match(对齐 rcs loadConnectableNodeActions)
98
123
  try {
99
- actions = await (0, node_1.getActions)({
124
+ const refetch = await (0, knowledge_1.searchNodesByCategory)({
125
+ mode: 'independent',
126
+ scene: 'normal',
100
127
  linkId: c.id,
101
- name: opts.name,
102
- trigger: opts.trigger || false,
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
- console.log(` ${chalk_1.default.cyan(String(action.action_key || action.id))} ${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}`);
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
- (0, output_1.printError)(`获取节点失败: ${error.message}`);
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
- const actions = await (0, node_1.getActions)({
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
- console.log(`\n${chalk_1.default.bold.blue('▸')} ${chalk_1.default.bold.white(action.name)} ${chalk_1.default.gray(`[${action.action_key}]`)}`);
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', action.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
- (0, output_1.printError)(`获取动作失败: ${error.message}`);
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
  }