@ai-setting/roy-agent-cli 1.5.82 → 1.5.85
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/dist/bin/roy-agent.js +534 -18
- package/dist/index.js +534 -18
- package/dist/roy-agent-linux-x64/bin/roy-agent +0 -0
- package/package.json +3 -3
package/dist/bin/roy-agent.js
CHANGED
|
@@ -7320,7 +7320,7 @@ var require_dist = __commonJS((exports) => {
|
|
|
7320
7320
|
var require_package = __commonJS((exports, module) => {
|
|
7321
7321
|
module.exports = {
|
|
7322
7322
|
name: "@ai-setting/roy-agent-cli",
|
|
7323
|
-
version: "1.5.
|
|
7323
|
+
version: "1.5.85",
|
|
7324
7324
|
type: "module",
|
|
7325
7325
|
description: "CLI for roy-agent - Non-interactive command execution",
|
|
7326
7326
|
main: "./dist/index.js",
|
|
@@ -7346,8 +7346,8 @@ var require_package = __commonJS((exports, module) => {
|
|
|
7346
7346
|
typecheck: "npx tsc --noEmit --skipLibCheck"
|
|
7347
7347
|
},
|
|
7348
7348
|
dependencies: {
|
|
7349
|
-
"@ai-setting/roy-agent-coder-harness": "^1.5.
|
|
7350
|
-
"@ai-setting/roy-agent-core": "^1.5.
|
|
7349
|
+
"@ai-setting/roy-agent-coder-harness": "^1.5.50",
|
|
7350
|
+
"@ai-setting/roy-agent-core": "^1.5.83",
|
|
7351
7351
|
"@ai-setting/roy-agent-ontology-harness": "^1.5.47",
|
|
7352
7352
|
chalk: "^5.6.2",
|
|
7353
7353
|
commander: "^14.0.3",
|
|
@@ -9255,8 +9255,16 @@ class InputHandler {
|
|
|
9255
9255
|
buffer = [];
|
|
9256
9256
|
static USER_PROMPT = "❯ ";
|
|
9257
9257
|
static CONTINUATION_PROMPT = "... ";
|
|
9258
|
+
static filterControlChars(input) {
|
|
9259
|
+
if (!input)
|
|
9260
|
+
return "";
|
|
9261
|
+
return input.replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g, "");
|
|
9262
|
+
}
|
|
9258
9263
|
pushLine(line) {
|
|
9259
|
-
|
|
9264
|
+
if (line == null) {
|
|
9265
|
+
return;
|
|
9266
|
+
}
|
|
9267
|
+
this.buffer.push(InputHandler.filterControlChars(line));
|
|
9260
9268
|
}
|
|
9261
9269
|
getBuffer() {
|
|
9262
9270
|
return this.buffer.join(`
|
|
@@ -9341,6 +9349,7 @@ class REPL {
|
|
|
9341
9349
|
isShuttingDown = false;
|
|
9342
9350
|
env = null;
|
|
9343
9351
|
inputHandler;
|
|
9352
|
+
keypressHandler;
|
|
9344
9353
|
constructor(options, env) {
|
|
9345
9354
|
this.options = options;
|
|
9346
9355
|
this.env = env ?? null;
|
|
@@ -9361,6 +9370,17 @@ class REPL {
|
|
|
9361
9370
|
return;
|
|
9362
9371
|
}
|
|
9363
9372
|
this.isShuttingDown = true;
|
|
9373
|
+
if (process.stdin.isTTY) {
|
|
9374
|
+
try {
|
|
9375
|
+
process.stdin.setRawMode?.(false);
|
|
9376
|
+
} catch {}
|
|
9377
|
+
}
|
|
9378
|
+
if (this.keypressHandler) {
|
|
9379
|
+
try {
|
|
9380
|
+
process.stdin.removeListener("keypress", this.keypressHandler);
|
|
9381
|
+
} catch {}
|
|
9382
|
+
this.keypressHandler = undefined;
|
|
9383
|
+
}
|
|
9364
9384
|
this.rl.close();
|
|
9365
9385
|
await this.options.onShutdown();
|
|
9366
9386
|
}
|
|
@@ -9428,7 +9448,9 @@ ${COLORS.system("[没有正在执行的请求]")}`);
|
|
|
9428
9448
|
if (process.stdin.isTTY) {
|
|
9429
9449
|
process.stdin.setRawMode?.(true);
|
|
9430
9450
|
}
|
|
9431
|
-
|
|
9451
|
+
this.keypressHandler = (str, key) => {
|
|
9452
|
+
if (this.isShuttingDown)
|
|
9453
|
+
return;
|
|
9432
9454
|
if (key.meta && key.name === "return") {
|
|
9433
9455
|
readline2.moveCursor(process.stdout, 0, -1);
|
|
9434
9456
|
readline2.clearLine(process.stdout, 0);
|
|
@@ -9438,7 +9460,8 @@ ${COLORS.system("[没有正在执行的请求]")}`);
|
|
|
9438
9460
|
if (key.name === "escape") {
|
|
9439
9461
|
this.handleEscKey();
|
|
9440
9462
|
}
|
|
9441
|
-
}
|
|
9463
|
+
};
|
|
9464
|
+
process.stdin.on("keypress", this.keypressHandler);
|
|
9442
9465
|
return new Promise((resolve) => {
|
|
9443
9466
|
this.rl.on("line", async (line) => {
|
|
9444
9467
|
await this.handleLine(line.trim());
|
|
@@ -9452,6 +9475,9 @@ ${COLORS.system("[没有正在执行的请求]")}`);
|
|
|
9452
9475
|
});
|
|
9453
9476
|
}
|
|
9454
9477
|
async handleLine(line) {
|
|
9478
|
+
if (this.isShuttingDown) {
|
|
9479
|
+
return;
|
|
9480
|
+
}
|
|
9455
9481
|
if (line.startsWith("/") && this.inputHandler.getBuffer() === "") {
|
|
9456
9482
|
await this.handleCommand(line.slice(1));
|
|
9457
9483
|
this.inputHandler.reset();
|
|
@@ -17002,7 +17028,7 @@ var WorkflowListCommand = {
|
|
|
17002
17028
|
describe: "列出所有已注册的 Workflow",
|
|
17003
17029
|
builder: (yargs) => yargs.option("tag", {
|
|
17004
17030
|
alias: "t",
|
|
17005
|
-
describe: "
|
|
17031
|
+
describe: "按标签筛选(可多次 --tag ai --tag cli 表示 AND)",
|
|
17006
17032
|
type: "string"
|
|
17007
17033
|
}).option("task-id", {
|
|
17008
17034
|
alias: "i",
|
|
@@ -17022,6 +17048,27 @@ var WorkflowListCommand = {
|
|
|
17022
17048
|
describe: "分页偏移",
|
|
17023
17049
|
type: "number",
|
|
17024
17050
|
default: 0
|
|
17051
|
+
}).option("page", {
|
|
17052
|
+
describe: "页码(1-based,与 --page-size 配合;与 --offset 互斥)",
|
|
17053
|
+
type: "number",
|
|
17054
|
+
default: 1
|
|
17055
|
+
}).option("page-size", {
|
|
17056
|
+
describe: "每页大小(与 --page 配合;等价于 --limit)",
|
|
17057
|
+
type: "number"
|
|
17058
|
+
}).check((argv) => {
|
|
17059
|
+
if (typeof argv.page === "number" && argv.page < 1) {
|
|
17060
|
+
throw new Error("--page must be >= 1");
|
|
17061
|
+
}
|
|
17062
|
+
if (typeof argv.pageSize === "number" && argv.pageSize < 1) {
|
|
17063
|
+
throw new Error("--page-size must be >= 1");
|
|
17064
|
+
}
|
|
17065
|
+
if (typeof argv.limit === "number" && argv.limit < 1) {
|
|
17066
|
+
throw new Error("--limit must be >= 1");
|
|
17067
|
+
}
|
|
17068
|
+
if (typeof argv.offset === "number" && argv.offset < 0) {
|
|
17069
|
+
throw new Error("--offset must be >= 0");
|
|
17070
|
+
}
|
|
17071
|
+
return true;
|
|
17025
17072
|
}).option("json", {
|
|
17026
17073
|
alias: "j",
|
|
17027
17074
|
describe: "JSON 格式输出",
|
|
@@ -17056,12 +17103,20 @@ var WorkflowListCommand = {
|
|
|
17056
17103
|
output.error('WorkflowService not initialized. Please run "roy-agent workflow init" first.');
|
|
17057
17104
|
process.exit(1);
|
|
17058
17105
|
}
|
|
17106
|
+
const tagsArg = args.tag;
|
|
17107
|
+
const tagsList = Array.isArray(tagsArg) ? tagsArg : tagsArg ? [tagsArg] : [];
|
|
17108
|
+
const pageSize = typeof args.pageSize === "number" ? args.pageSize : typeof args.limit === "number" ? args.limit : 50;
|
|
17109
|
+
const page = typeof args.page === "number" ? args.page : 1;
|
|
17110
|
+
const effectiveOffset = (page - 1) * pageSize;
|
|
17111
|
+
const userOffset = typeof args.offset === "number" ? args.offset : 0;
|
|
17112
|
+
const finalOffset = page > 1 ? effectiveOffset : userOffset;
|
|
17059
17113
|
const tool = createWorkflowListTool(service);
|
|
17060
17114
|
const result = await tool.execute({
|
|
17061
|
-
tag:
|
|
17062
|
-
|
|
17063
|
-
|
|
17064
|
-
|
|
17115
|
+
tag: tagsList.length === 1 ? tagsList[0] : undefined,
|
|
17116
|
+
tags: tagsList.length > 1 ? tagsList : undefined,
|
|
17117
|
+
search: args.search !== undefined && typeof args.search === "string" ? args.search : undefined,
|
|
17118
|
+
limit: pageSize,
|
|
17119
|
+
offset: finalOffset
|
|
17065
17120
|
}, {});
|
|
17066
17121
|
if (!result.success) {
|
|
17067
17122
|
output.error(result.error || "Failed to list workflows");
|
|
@@ -17069,6 +17124,8 @@ var WorkflowListCommand = {
|
|
|
17069
17124
|
}
|
|
17070
17125
|
const data = JSON.parse(result.output);
|
|
17071
17126
|
const workflows = data.workflows || [];
|
|
17127
|
+
const availableTags = data.available_tags || [];
|
|
17128
|
+
const total = typeof data.total === "number" ? data.total : workflows.length;
|
|
17072
17129
|
if (args.json) {
|
|
17073
17130
|
output.json({
|
|
17074
17131
|
workflows: workflows.map((w) => ({
|
|
@@ -17079,7 +17136,12 @@ var WorkflowListCommand = {
|
|
|
17079
17136
|
createdAt: w.created_at,
|
|
17080
17137
|
updatedAt: w.created_at
|
|
17081
17138
|
})),
|
|
17082
|
-
|
|
17139
|
+
available_tags: availableTags,
|
|
17140
|
+
total,
|
|
17141
|
+
count: workflows.length,
|
|
17142
|
+
limit: pageSize,
|
|
17143
|
+
offset: finalOffset,
|
|
17144
|
+
page: page > 1 ? page : Math.floor(finalOffset / pageSize) + 1
|
|
17083
17145
|
});
|
|
17084
17146
|
} else {
|
|
17085
17147
|
const renderWorkflows = workflows.map((w) => ({
|
|
@@ -17094,8 +17156,25 @@ var WorkflowListCommand = {
|
|
|
17094
17156
|
metadata: {}
|
|
17095
17157
|
}));
|
|
17096
17158
|
output.log(renderWorkflowList(renderWorkflows));
|
|
17097
|
-
|
|
17098
|
-
|
|
17159
|
+
if (total > workflows.length) {
|
|
17160
|
+
const start = finalOffset + 1;
|
|
17161
|
+
const end = finalOffset + workflows.length;
|
|
17162
|
+
output.log(chalk61.green(`
|
|
17163
|
+
✅ 显示 ${start}-${end} / 共 ${total} 个 Workflow`));
|
|
17164
|
+
const totalPages = Math.ceil(total / pageSize);
|
|
17165
|
+
const currentPage = Math.floor(finalOffset / pageSize) + 1;
|
|
17166
|
+
if (totalPages > 1) {
|
|
17167
|
+
output.log(chalk61.cyan(`\uD83D\uDCC4 第 ${currentPage} / ${totalPages} 页`));
|
|
17168
|
+
}
|
|
17169
|
+
} else {
|
|
17170
|
+
output.log(chalk61.green(`
|
|
17171
|
+
✅ 共 ${total} 个 Workflow`));
|
|
17172
|
+
}
|
|
17173
|
+
if (availableTags.length > 0) {
|
|
17174
|
+
const tagsLine = availableTags.map((t) => `${t.name}(${t.count})`).join(", ");
|
|
17175
|
+
output.log(chalk61.cyan(`
|
|
17176
|
+
\uD83C\uDFF7️ Available tags: ${tagsLine}`));
|
|
17177
|
+
}
|
|
17099
17178
|
}
|
|
17100
17179
|
} catch (error) {
|
|
17101
17180
|
output.error(`Failed to list workflows: ${error}`);
|
|
@@ -17763,8 +17842,9 @@ var WorkflowAddCommand = {
|
|
|
17763
17842
|
type: "string"
|
|
17764
17843
|
}).option("tags", {
|
|
17765
17844
|
alias: "t",
|
|
17766
|
-
describe: "
|
|
17767
|
-
type: "
|
|
17845
|
+
describe: 'Tags (1-3 required). Select from existing tag pool when possible. Run "roy-agent workflow tag list" first to see available tags. Supports both --tags "a,b,c" and --tags a --tags b --tags c forms.',
|
|
17846
|
+
type: "array",
|
|
17847
|
+
string: true
|
|
17768
17848
|
}).option("task-id", {
|
|
17769
17849
|
alias: "i",
|
|
17770
17850
|
describe: "关联任务 ID",
|
|
@@ -17791,6 +17871,29 @@ var WorkflowAddCommand = {
|
|
|
17791
17871
|
const output = new OutputService;
|
|
17792
17872
|
const envService = new EnvironmentService(output);
|
|
17793
17873
|
try {
|
|
17874
|
+
let parseTags = function(input) {
|
|
17875
|
+
if (input === undefined || input === null)
|
|
17876
|
+
return;
|
|
17877
|
+
const list = [];
|
|
17878
|
+
if (Array.isArray(input)) {
|
|
17879
|
+
for (const item of input) {
|
|
17880
|
+
if (typeof item === "string") {
|
|
17881
|
+
for (const t of item.split(",")) {
|
|
17882
|
+
const trimmed = t.trim();
|
|
17883
|
+
if (trimmed)
|
|
17884
|
+
list.push(trimmed);
|
|
17885
|
+
}
|
|
17886
|
+
}
|
|
17887
|
+
}
|
|
17888
|
+
} else if (typeof input === "string") {
|
|
17889
|
+
for (const t of input.split(",")) {
|
|
17890
|
+
const trimmed = t.trim();
|
|
17891
|
+
if (trimmed)
|
|
17892
|
+
list.push(trimmed);
|
|
17893
|
+
}
|
|
17894
|
+
}
|
|
17895
|
+
return list.length > 0 ? list : undefined;
|
|
17896
|
+
};
|
|
17794
17897
|
await envService.create({ configPath: a.config });
|
|
17795
17898
|
const env = envService.getEnvironment();
|
|
17796
17899
|
if (!env) {
|
|
@@ -17902,7 +18005,19 @@ Agent output:
|
|
|
17902
18005
|
output.error('Usage: roy-agent workflow add --file <path> | --desc "<description>"');
|
|
17903
18006
|
process.exit(1);
|
|
17904
18007
|
}
|
|
17905
|
-
const tags = a.tags
|
|
18008
|
+
const tags = parseTags(a.tags);
|
|
18009
|
+
if (!tags || tags.length === 0) {
|
|
18010
|
+
output.error("❌ --tags is required.");
|
|
18011
|
+
output.error(' Please provide 1-3 tags using --tags "tag1,tag2,tag3"');
|
|
18012
|
+
output.error(' Example: roy-agent workflow add --file my.yaml --tags "ai,ml,etl"');
|
|
18013
|
+
process.exit(1);
|
|
18014
|
+
}
|
|
18015
|
+
if (tags.length > 3) {
|
|
18016
|
+
output.error(`❌ Too many tags: received ${tags.length}, maximum is 3.`);
|
|
18017
|
+
output.error(' Please reduce to 1-3 tags using --tags "tag1,tag2,tag3"');
|
|
18018
|
+
output.error(' Example: roy-agent workflow add --file my.yaml --tags "ai,ml,etl"');
|
|
18019
|
+
process.exit(1);
|
|
18020
|
+
}
|
|
17906
18021
|
const workflow = await service.createWorkflow(definition, {
|
|
17907
18022
|
tags,
|
|
17908
18023
|
taskId: a.taskId,
|
|
@@ -19140,11 +19255,412 @@ Error: ${error.message}`));
|
|
|
19140
19255
|
}
|
|
19141
19256
|
};
|
|
19142
19257
|
|
|
19258
|
+
// src/commands/workflow/commands/search.ts
|
|
19259
|
+
import chalk71 from "chalk";
|
|
19260
|
+
import { wrapFunction as wrapFunction3 } from "@ai-setting/roy-agent-core";
|
|
19261
|
+
var WorkflowSearchCommand = {
|
|
19262
|
+
command: "search",
|
|
19263
|
+
describe: "Search workflows by keyword and/or tags (multiple tags use AND filter). v2: returns available_tags.",
|
|
19264
|
+
builder: (yargs) => yargs.option("keyword", {
|
|
19265
|
+
alias: "k",
|
|
19266
|
+
describe: "Search keyword in name and description",
|
|
19267
|
+
type: "string"
|
|
19268
|
+
}).option("tag", {
|
|
19269
|
+
alias: "t",
|
|
19270
|
+
describe: "Filter by tag (can be specified multiple times for AND filter)",
|
|
19271
|
+
type: "array",
|
|
19272
|
+
string: true
|
|
19273
|
+
}).option("limit", {
|
|
19274
|
+
alias: "l",
|
|
19275
|
+
describe: "Maximum number of results",
|
|
19276
|
+
type: "number",
|
|
19277
|
+
default: 50
|
|
19278
|
+
}).option("offset", {
|
|
19279
|
+
alias: "o",
|
|
19280
|
+
describe: "Pagination offset",
|
|
19281
|
+
type: "number",
|
|
19282
|
+
default: 0
|
|
19283
|
+
}).option("json", {
|
|
19284
|
+
alias: "j",
|
|
19285
|
+
describe: "Output as JSON",
|
|
19286
|
+
type: "boolean",
|
|
19287
|
+
default: false
|
|
19288
|
+
}).option("yaml", {
|
|
19289
|
+
alias: "y",
|
|
19290
|
+
describe: "Output as YAML",
|
|
19291
|
+
type: "boolean",
|
|
19292
|
+
default: false
|
|
19293
|
+
}).option("config", {
|
|
19294
|
+
describe: "Config file path",
|
|
19295
|
+
type: "string"
|
|
19296
|
+
}).check((argv) => {
|
|
19297
|
+
const hasKeyword = typeof argv.keyword === "string" && argv.keyword.length > 0;
|
|
19298
|
+
const hasTags = Array.isArray(argv.tag) && argv.tag.length > 0;
|
|
19299
|
+
if (!hasKeyword && !hasTags) {
|
|
19300
|
+
throw new Error("At least one of --keyword or --tag must be provided");
|
|
19301
|
+
}
|
|
19302
|
+
if (Array.isArray(argv.tag)) {
|
|
19303
|
+
for (const t of argv.tag) {
|
|
19304
|
+
if (typeof t !== "string" || t.length === 0) {
|
|
19305
|
+
throw new Error("Empty tag values are not allowed");
|
|
19306
|
+
}
|
|
19307
|
+
if (t.length > 50) {
|
|
19308
|
+
throw new Error(`Tag "${t}" exceeds 50 characters`);
|
|
19309
|
+
}
|
|
19310
|
+
if (t.includes(",")) {
|
|
19311
|
+
throw new Error(`Tag "${t}" contains comma; pass them as separate --tags`);
|
|
19312
|
+
}
|
|
19313
|
+
}
|
|
19314
|
+
}
|
|
19315
|
+
return true;
|
|
19316
|
+
}),
|
|
19317
|
+
async handler(args) {
|
|
19318
|
+
const a = args;
|
|
19319
|
+
const output = new OutputService;
|
|
19320
|
+
const envService = new EnvironmentService(output);
|
|
19321
|
+
try {
|
|
19322
|
+
await runWorkflowSearch({
|
|
19323
|
+
keyword: a.keyword,
|
|
19324
|
+
tags: a.tag,
|
|
19325
|
+
limit: a.limit,
|
|
19326
|
+
offset: a.offset,
|
|
19327
|
+
asJson: a.json,
|
|
19328
|
+
asYaml: a.yaml,
|
|
19329
|
+
configPath: a.config,
|
|
19330
|
+
output,
|
|
19331
|
+
envService
|
|
19332
|
+
});
|
|
19333
|
+
} catch (error) {
|
|
19334
|
+
output.error(`Failed to search workflows: ${error}`);
|
|
19335
|
+
process.exit(1);
|
|
19336
|
+
} finally {
|
|
19337
|
+
await envService.dispose();
|
|
19338
|
+
}
|
|
19339
|
+
}
|
|
19340
|
+
};
|
|
19341
|
+
var _runWorkflowSearchImpl = async function(opts) {
|
|
19342
|
+
const { keyword, tags, limit, offset, asJson, asYaml, configPath, output, envService } = opts;
|
|
19343
|
+
await envService.create({ configPath });
|
|
19344
|
+
const env = envService.getEnvironment();
|
|
19345
|
+
if (!env) {
|
|
19346
|
+
output.error("Failed to create environment");
|
|
19347
|
+
process.exit(1);
|
|
19348
|
+
}
|
|
19349
|
+
const workflowComponent = env.getComponent("workflow");
|
|
19350
|
+
if (!workflowComponent) {
|
|
19351
|
+
output.error("WorkflowComponent not available");
|
|
19352
|
+
process.exit(1);
|
|
19353
|
+
}
|
|
19354
|
+
const service = workflowComponent.getService();
|
|
19355
|
+
if (!service) {
|
|
19356
|
+
output.error('WorkflowService not initialized. Please run "roy-agent workflow init" first.');
|
|
19357
|
+
process.exit(1);
|
|
19358
|
+
}
|
|
19359
|
+
const useWithTags = typeof service.searchWorkflowsWithTags === "function";
|
|
19360
|
+
const result = useWithTags ? await service.searchWorkflowsWithTags({
|
|
19361
|
+
keyword,
|
|
19362
|
+
tags,
|
|
19363
|
+
limit,
|
|
19364
|
+
offset
|
|
19365
|
+
}) : {
|
|
19366
|
+
workflows: service.searchWorkflows({ keyword, tags, limit, offset }),
|
|
19367
|
+
available_tags: []
|
|
19368
|
+
};
|
|
19369
|
+
const workflows = result.workflows ?? [];
|
|
19370
|
+
const availableTags = result.available_tags ?? [];
|
|
19371
|
+
if (asJson) {
|
|
19372
|
+
output.json({
|
|
19373
|
+
workflows: workflows.map((w) => ({
|
|
19374
|
+
name: w.name,
|
|
19375
|
+
version: w.version,
|
|
19376
|
+
description: w.description,
|
|
19377
|
+
tags: w.tags,
|
|
19378
|
+
createdAt: w.createdAt,
|
|
19379
|
+
updatedAt: w.updatedAt
|
|
19380
|
+
})),
|
|
19381
|
+
available_tags: availableTags,
|
|
19382
|
+
total: workflows.length,
|
|
19383
|
+
keyword,
|
|
19384
|
+
tags
|
|
19385
|
+
});
|
|
19386
|
+
return;
|
|
19387
|
+
}
|
|
19388
|
+
if (asYaml) {
|
|
19389
|
+
const yaml = await Promise.resolve().then(() => __toESM(require_dist(), 1));
|
|
19390
|
+
output.log(yaml.stringify({
|
|
19391
|
+
workflows: workflows.map((w) => ({
|
|
19392
|
+
name: w.name,
|
|
19393
|
+
version: w.version,
|
|
19394
|
+
description: w.description,
|
|
19395
|
+
tags: w.tags
|
|
19396
|
+
})),
|
|
19397
|
+
available_tags: availableTags,
|
|
19398
|
+
total: workflows.length,
|
|
19399
|
+
keyword,
|
|
19400
|
+
tags
|
|
19401
|
+
}));
|
|
19402
|
+
return;
|
|
19403
|
+
}
|
|
19404
|
+
const renderWorkflows = workflows.map((w) => ({
|
|
19405
|
+
id: w.name,
|
|
19406
|
+
name: w.name,
|
|
19407
|
+
version: w.version,
|
|
19408
|
+
description: w.description,
|
|
19409
|
+
tags: w.tags || [],
|
|
19410
|
+
createdAt: w.createdAt ? new Date(w.createdAt) : new Date,
|
|
19411
|
+
updatedAt: w.updatedAt ? new Date(w.updatedAt) : new Date,
|
|
19412
|
+
definition: { nodes: [], config: {}, inputs: {} },
|
|
19413
|
+
metadata: {}
|
|
19414
|
+
}));
|
|
19415
|
+
if (renderWorkflows.length === 0) {
|
|
19416
|
+
output.log(chalk71.yellow("\uD83D\uDD0D No workflows matched the search criteria."));
|
|
19417
|
+
output.log(chalk71.gray(` keyword: ${keyword || "(none)"}`));
|
|
19418
|
+
output.log(chalk71.gray(` tags: ${tags && tags.length > 0 ? tags.join(", ") : "(none)"}`));
|
|
19419
|
+
} else {
|
|
19420
|
+
output.log(chalk71.bold(`\uD83D\uDD0D Search results (${renderWorkflows.length}):`));
|
|
19421
|
+
output.log(renderWorkflowList(renderWorkflows));
|
|
19422
|
+
output.log(chalk71.green(`
|
|
19423
|
+
✅ Found ${renderWorkflows.length} workflow(s)`));
|
|
19424
|
+
}
|
|
19425
|
+
if (availableTags.length > 0) {
|
|
19426
|
+
output.log("");
|
|
19427
|
+
output.log(chalk71.bold("\uD83D\uDCDA Available tags (sorted by usage_count):"));
|
|
19428
|
+
for (const t of availableTags) {
|
|
19429
|
+
const name = t.name ?? t.tag;
|
|
19430
|
+
const count = t.count ?? t.usage_count;
|
|
19431
|
+
output.log(chalk71.gray(` - ${name} (${count})`));
|
|
19432
|
+
}
|
|
19433
|
+
}
|
|
19434
|
+
};
|
|
19435
|
+
var runWorkflowSearch = wrapFunction3(_runWorkflowSearchImpl, "workflow.cli.search", {
|
|
19436
|
+
recordParams: true,
|
|
19437
|
+
recordResult: false,
|
|
19438
|
+
log: false
|
|
19439
|
+
});
|
|
19440
|
+
|
|
19441
|
+
// src/commands/workflow/commands/tag.ts
|
|
19442
|
+
import { wrapFunction as wrapFunction4 } from "@ai-setting/roy-agent-core";
|
|
19443
|
+
import chalk72 from "chalk";
|
|
19444
|
+
var WorkflowTagListCommand = {
|
|
19445
|
+
command: "list",
|
|
19446
|
+
describe: "List all workflow tags from the workflow_tags table (sorted by usage_count DESC by default). Use this BEFORE `workflow add` to discover existing tags and reuse them for semantic consistency.",
|
|
19447
|
+
builder: (yargs) => yargs.option("sort-by", {
|
|
19448
|
+
describe: "Sort field",
|
|
19449
|
+
choices: ["usage_count", "name", "created_at"],
|
|
19450
|
+
default: "usage_count"
|
|
19451
|
+
}).option("order", {
|
|
19452
|
+
describe: "Sort order",
|
|
19453
|
+
choices: ["asc", "desc"],
|
|
19454
|
+
default: "desc"
|
|
19455
|
+
}).option("limit", {
|
|
19456
|
+
describe: "Max number of tags to return",
|
|
19457
|
+
type: "number",
|
|
19458
|
+
default: 100
|
|
19459
|
+
}).option("json", {
|
|
19460
|
+
alias: "j",
|
|
19461
|
+
describe: "Output as JSON",
|
|
19462
|
+
type: "boolean",
|
|
19463
|
+
default: false
|
|
19464
|
+
}).option("config", {
|
|
19465
|
+
describe: "Config file path",
|
|
19466
|
+
type: "string"
|
|
19467
|
+
}),
|
|
19468
|
+
async handler(args) {
|
|
19469
|
+
const a = args;
|
|
19470
|
+
const output = new OutputService;
|
|
19471
|
+
const envService = new EnvironmentService(output);
|
|
19472
|
+
try {
|
|
19473
|
+
await runWorkflowTagList({
|
|
19474
|
+
sortBy: a.sortBy,
|
|
19475
|
+
order: a.order,
|
|
19476
|
+
limit: a.limit,
|
|
19477
|
+
asJson: a.json,
|
|
19478
|
+
configPath: a.config,
|
|
19479
|
+
output,
|
|
19480
|
+
envService
|
|
19481
|
+
});
|
|
19482
|
+
} catch (error) {
|
|
19483
|
+
output.error(`Failed to list workflow tags: ${error}`);
|
|
19484
|
+
process.exit(1);
|
|
19485
|
+
} finally {
|
|
19486
|
+
await envService.dispose();
|
|
19487
|
+
}
|
|
19488
|
+
}
|
|
19489
|
+
};
|
|
19490
|
+
var WorkflowTagGetCommand = {
|
|
19491
|
+
command: "get <name>",
|
|
19492
|
+
describe: "Get details of a single workflow tag (usage_count, created_at, updated_at). Returns error if tag not in the workflow_tags table.",
|
|
19493
|
+
builder: (yargs) => yargs.positional("name", {
|
|
19494
|
+
describe: "Tag name",
|
|
19495
|
+
type: "string"
|
|
19496
|
+
}).option("json", {
|
|
19497
|
+
alias: "j",
|
|
19498
|
+
describe: "Output as JSON",
|
|
19499
|
+
type: "boolean",
|
|
19500
|
+
default: false
|
|
19501
|
+
}).option("config", {
|
|
19502
|
+
describe: "Config file path",
|
|
19503
|
+
type: "string"
|
|
19504
|
+
}).check((argv) => {
|
|
19505
|
+
if (typeof argv.name !== "string" || argv.name.length === 0) {
|
|
19506
|
+
throw new Error("Tag name is required");
|
|
19507
|
+
}
|
|
19508
|
+
if (argv.name.length > 50) {
|
|
19509
|
+
throw new Error(`Tag name exceeds 50 characters`);
|
|
19510
|
+
}
|
|
19511
|
+
return true;
|
|
19512
|
+
}),
|
|
19513
|
+
async handler(args) {
|
|
19514
|
+
const a = args;
|
|
19515
|
+
const output = new OutputService;
|
|
19516
|
+
const envService = new EnvironmentService(output);
|
|
19517
|
+
try {
|
|
19518
|
+
await runWorkflowTagGet({
|
|
19519
|
+
name: a.name,
|
|
19520
|
+
asJson: a.json,
|
|
19521
|
+
configPath: a.config,
|
|
19522
|
+
output,
|
|
19523
|
+
envService
|
|
19524
|
+
});
|
|
19525
|
+
} catch (error) {
|
|
19526
|
+
output.error(`Failed to get tag: ${error}`);
|
|
19527
|
+
process.exit(1);
|
|
19528
|
+
} finally {
|
|
19529
|
+
await envService.dispose();
|
|
19530
|
+
}
|
|
19531
|
+
}
|
|
19532
|
+
};
|
|
19533
|
+
var _runWorkflowTagListImpl = async function(opts) {
|
|
19534
|
+
const { output, envService } = opts;
|
|
19535
|
+
await envService.create({ configPath: opts.configPath });
|
|
19536
|
+
const env = envService.getEnvironment();
|
|
19537
|
+
if (!env) {
|
|
19538
|
+
output.error("Failed to create environment");
|
|
19539
|
+
process.exit(1);
|
|
19540
|
+
}
|
|
19541
|
+
const workflowComponent = env.getComponent("workflow");
|
|
19542
|
+
if (!workflowComponent) {
|
|
19543
|
+
output.error("WorkflowComponent not available");
|
|
19544
|
+
process.exit(1);
|
|
19545
|
+
}
|
|
19546
|
+
const service = workflowComponent.getService();
|
|
19547
|
+
if (!service) {
|
|
19548
|
+
output.error('WorkflowService not initialized. Please run "roy-agent workflow init" first.');
|
|
19549
|
+
process.exit(1);
|
|
19550
|
+
}
|
|
19551
|
+
const result = await callListTags(service, {
|
|
19552
|
+
sortBy: opts.sortBy ?? "usage_count",
|
|
19553
|
+
order: opts.order ?? "desc",
|
|
19554
|
+
limit: opts.limit ?? 100
|
|
19555
|
+
});
|
|
19556
|
+
if (opts.asJson) {
|
|
19557
|
+
output.json({
|
|
19558
|
+
tags: result.tags,
|
|
19559
|
+
total: result.total
|
|
19560
|
+
});
|
|
19561
|
+
return;
|
|
19562
|
+
}
|
|
19563
|
+
if (result.tags.length === 0) {
|
|
19564
|
+
output.log(chalk72.yellow("\uD83C\uDFF7️ No tags in the workflow_tags table yet."));
|
|
19565
|
+
output.log(chalk72.gray(" Tags are created automatically when you run `workflow add --tags <name>`."));
|
|
19566
|
+
return;
|
|
19567
|
+
}
|
|
19568
|
+
output.log(chalk72.bold(`\uD83C\uDFF7️ Workflow tags (${result.total}):`));
|
|
19569
|
+
output.log(chalk72.gray(` ${padRight("NAME", 24)}${padRight("USAGE", 8)}${padRight("CREATED", 22)}`));
|
|
19570
|
+
for (const t of result.tags) {
|
|
19571
|
+
const line = ` ${padRight(t.name, 24)}${padRight(String(t.usage_count), 8)}${padRight(formatDate2(t.created_at), 22)}`;
|
|
19572
|
+
output.log(line);
|
|
19573
|
+
}
|
|
19574
|
+
output.log(chalk72.gray(`
|
|
19575
|
+
\uD83D\uDCA1 Tip: when adding a new workflow, prefer tags from this list to ensure semantic consistency.`));
|
|
19576
|
+
};
|
|
19577
|
+
var _runWorkflowTagGetImpl = async function(opts) {
|
|
19578
|
+
const { output, envService } = opts;
|
|
19579
|
+
await envService.create({ configPath: opts.configPath });
|
|
19580
|
+
const env = envService.getEnvironment();
|
|
19581
|
+
if (!env) {
|
|
19582
|
+
output.error("Failed to create environment");
|
|
19583
|
+
process.exit(1);
|
|
19584
|
+
}
|
|
19585
|
+
const workflowComponent = env.getComponent("workflow");
|
|
19586
|
+
if (!workflowComponent) {
|
|
19587
|
+
output.error("WorkflowComponent not available");
|
|
19588
|
+
process.exit(1);
|
|
19589
|
+
}
|
|
19590
|
+
const service = workflowComponent.getService();
|
|
19591
|
+
if (!service) {
|
|
19592
|
+
output.error('WorkflowService not initialized. Please run "roy-agent workflow init" first.');
|
|
19593
|
+
process.exit(1);
|
|
19594
|
+
}
|
|
19595
|
+
const tag = callGetTag(service, opts.name);
|
|
19596
|
+
if (!tag) {
|
|
19597
|
+
if (opts.asJson) {
|
|
19598
|
+
output.json({ error: "Tag not found", name: opts.name });
|
|
19599
|
+
} else {
|
|
19600
|
+
output.error(`Tag "${opts.name}" not found in the workflow_tags table.`);
|
|
19601
|
+
output.log(chalk72.gray(`Tip: run \`roy-agent workflow tag list\` to see available tags.`));
|
|
19602
|
+
}
|
|
19603
|
+
process.exitCode = 1;
|
|
19604
|
+
return;
|
|
19605
|
+
}
|
|
19606
|
+
if (opts.asJson) {
|
|
19607
|
+
output.json(tag);
|
|
19608
|
+
return;
|
|
19609
|
+
}
|
|
19610
|
+
output.log(chalk72.bold(`\uD83C\uDFF7️ Tag: ${tag.name}`));
|
|
19611
|
+
output.log(chalk72.gray(` usage_count: ${tag.usage_count}`));
|
|
19612
|
+
output.log(chalk72.gray(` created_at: ${tag.created_at}`));
|
|
19613
|
+
output.log(chalk72.gray(` updated_at: ${tag.updated_at}`));
|
|
19614
|
+
};
|
|
19615
|
+
async function callListTags(service, options) {
|
|
19616
|
+
if (typeof service.listTags !== "function") {
|
|
19617
|
+
return { tags: [], total: 0 };
|
|
19618
|
+
}
|
|
19619
|
+
return await service.listTags(options);
|
|
19620
|
+
}
|
|
19621
|
+
function callGetTag(service, name) {
|
|
19622
|
+
if (typeof service.getTag !== "function") {
|
|
19623
|
+
return;
|
|
19624
|
+
}
|
|
19625
|
+
return service.getTag(name);
|
|
19626
|
+
}
|
|
19627
|
+
function padRight(str, width) {
|
|
19628
|
+
if (str.length >= width)
|
|
19629
|
+
return str.slice(0, width - 1) + " ";
|
|
19630
|
+
return str + " ".repeat(width - str.length);
|
|
19631
|
+
}
|
|
19632
|
+
function formatDate2(iso) {
|
|
19633
|
+
try {
|
|
19634
|
+
const d = new Date(iso);
|
|
19635
|
+
if (isNaN(d.getTime()))
|
|
19636
|
+
return iso;
|
|
19637
|
+
return d.toISOString().replace("T", " ").slice(0, 19);
|
|
19638
|
+
} catch {
|
|
19639
|
+
return iso;
|
|
19640
|
+
}
|
|
19641
|
+
}
|
|
19642
|
+
var runWorkflowTagList = wrapFunction4(_runWorkflowTagListImpl, "workflow.cli.tag.list", {
|
|
19643
|
+
recordParams: true,
|
|
19644
|
+
recordResult: false,
|
|
19645
|
+
log: false
|
|
19646
|
+
});
|
|
19647
|
+
var runWorkflowTagGet = wrapFunction4(_runWorkflowTagGetImpl, "workflow.cli.tag.get", {
|
|
19648
|
+
recordParams: true,
|
|
19649
|
+
recordResult: false,
|
|
19650
|
+
log: false
|
|
19651
|
+
});
|
|
19652
|
+
|
|
19143
19653
|
// src/commands/workflow/index.ts
|
|
19654
|
+
var WorkflowTagCommand = {
|
|
19655
|
+
command: "tag",
|
|
19656
|
+
describe: "Manage workflow tags — list and get from the workflow_tags table. Use BEFORE `workflow add` to discover existing tags.",
|
|
19657
|
+
builder: (yargs) => yargs.command(WorkflowTagListCommand).command(WorkflowTagGetCommand).demandCommand(1, "请指定 tag 子命令:list 或 get <name>").help(),
|
|
19658
|
+
handler() {}
|
|
19659
|
+
};
|
|
19144
19660
|
var WorkflowCommand = {
|
|
19145
19661
|
command: "workflow",
|
|
19146
19662
|
describe: "Workflow DAG management and execution - create, run, and monitor workflows",
|
|
19147
|
-
builder: (yargs) => yargs.command(WorkflowListCommand).command(WorkflowAddCommand).command(WorkflowNodesCommand).command(WorkflowValidateCommand).command(WorkflowGetCommand).command(WorkflowUpdateCommand).command(WorkflowRemoveCommand).command(WorkflowRunCommand).command(WorkflowStopCommand).command(WorkflowStatusCommand).demandCommand(1, "请指定子命令:list、add、validate、nodes、get、update、remove、run、stop、status\n\nResume: 使用 `workflow run -s <sessionId>` 恢复暂停的工作流").help(),
|
|
19663
|
+
builder: (yargs) => yargs.command(WorkflowListCommand).command(WorkflowAddCommand).command(WorkflowSearchCommand).command(WorkflowTagCommand).command(WorkflowNodesCommand).command(WorkflowValidateCommand).command(WorkflowGetCommand).command(WorkflowUpdateCommand).command(WorkflowRemoveCommand).command(WorkflowRunCommand).command(WorkflowStopCommand).command(WorkflowStatusCommand).demandCommand(1, "请指定子命令:list、add、search、tag、validate、nodes、get、update、remove、run、stop、status\n\nResume: 使用 `workflow run -s <sessionId>` 恢复暂停的工作流").help(),
|
|
19148
19664
|
handler() {}
|
|
19149
19665
|
};
|
|
19150
19666
|
|
package/dist/index.js
CHANGED
|
@@ -7319,7 +7319,7 @@ var require_dist = __commonJS((exports) => {
|
|
|
7319
7319
|
var require_package = __commonJS((exports, module) => {
|
|
7320
7320
|
module.exports = {
|
|
7321
7321
|
name: "@ai-setting/roy-agent-cli",
|
|
7322
|
-
version: "1.5.
|
|
7322
|
+
version: "1.5.85",
|
|
7323
7323
|
type: "module",
|
|
7324
7324
|
description: "CLI for roy-agent - Non-interactive command execution",
|
|
7325
7325
|
main: "./dist/index.js",
|
|
@@ -7345,8 +7345,8 @@ var require_package = __commonJS((exports, module) => {
|
|
|
7345
7345
|
typecheck: "npx tsc --noEmit --skipLibCheck"
|
|
7346
7346
|
},
|
|
7347
7347
|
dependencies: {
|
|
7348
|
-
"@ai-setting/roy-agent-coder-harness": "^1.5.
|
|
7349
|
-
"@ai-setting/roy-agent-core": "^1.5.
|
|
7348
|
+
"@ai-setting/roy-agent-coder-harness": "^1.5.50",
|
|
7349
|
+
"@ai-setting/roy-agent-core": "^1.5.83",
|
|
7350
7350
|
"@ai-setting/roy-agent-ontology-harness": "^1.5.47",
|
|
7351
7351
|
chalk: "^5.6.2",
|
|
7352
7352
|
commander: "^14.0.3",
|
|
@@ -9254,8 +9254,16 @@ class InputHandler {
|
|
|
9254
9254
|
buffer = [];
|
|
9255
9255
|
static USER_PROMPT = "❯ ";
|
|
9256
9256
|
static CONTINUATION_PROMPT = "... ";
|
|
9257
|
+
static filterControlChars(input) {
|
|
9258
|
+
if (!input)
|
|
9259
|
+
return "";
|
|
9260
|
+
return input.replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g, "");
|
|
9261
|
+
}
|
|
9257
9262
|
pushLine(line) {
|
|
9258
|
-
|
|
9263
|
+
if (line == null) {
|
|
9264
|
+
return;
|
|
9265
|
+
}
|
|
9266
|
+
this.buffer.push(InputHandler.filterControlChars(line));
|
|
9259
9267
|
}
|
|
9260
9268
|
getBuffer() {
|
|
9261
9269
|
return this.buffer.join(`
|
|
@@ -9340,6 +9348,7 @@ class REPL {
|
|
|
9340
9348
|
isShuttingDown = false;
|
|
9341
9349
|
env = null;
|
|
9342
9350
|
inputHandler;
|
|
9351
|
+
keypressHandler;
|
|
9343
9352
|
constructor(options, env) {
|
|
9344
9353
|
this.options = options;
|
|
9345
9354
|
this.env = env ?? null;
|
|
@@ -9360,6 +9369,17 @@ class REPL {
|
|
|
9360
9369
|
return;
|
|
9361
9370
|
}
|
|
9362
9371
|
this.isShuttingDown = true;
|
|
9372
|
+
if (process.stdin.isTTY) {
|
|
9373
|
+
try {
|
|
9374
|
+
process.stdin.setRawMode?.(false);
|
|
9375
|
+
} catch {}
|
|
9376
|
+
}
|
|
9377
|
+
if (this.keypressHandler) {
|
|
9378
|
+
try {
|
|
9379
|
+
process.stdin.removeListener("keypress", this.keypressHandler);
|
|
9380
|
+
} catch {}
|
|
9381
|
+
this.keypressHandler = undefined;
|
|
9382
|
+
}
|
|
9363
9383
|
this.rl.close();
|
|
9364
9384
|
await this.options.onShutdown();
|
|
9365
9385
|
}
|
|
@@ -9427,7 +9447,9 @@ ${COLORS.system("[没有正在执行的请求]")}`);
|
|
|
9427
9447
|
if (process.stdin.isTTY) {
|
|
9428
9448
|
process.stdin.setRawMode?.(true);
|
|
9429
9449
|
}
|
|
9430
|
-
|
|
9450
|
+
this.keypressHandler = (str, key) => {
|
|
9451
|
+
if (this.isShuttingDown)
|
|
9452
|
+
return;
|
|
9431
9453
|
if (key.meta && key.name === "return") {
|
|
9432
9454
|
readline2.moveCursor(process.stdout, 0, -1);
|
|
9433
9455
|
readline2.clearLine(process.stdout, 0);
|
|
@@ -9437,7 +9459,8 @@ ${COLORS.system("[没有正在执行的请求]")}`);
|
|
|
9437
9459
|
if (key.name === "escape") {
|
|
9438
9460
|
this.handleEscKey();
|
|
9439
9461
|
}
|
|
9440
|
-
}
|
|
9462
|
+
};
|
|
9463
|
+
process.stdin.on("keypress", this.keypressHandler);
|
|
9441
9464
|
return new Promise((resolve) => {
|
|
9442
9465
|
this.rl.on("line", async (line) => {
|
|
9443
9466
|
await this.handleLine(line.trim());
|
|
@@ -9451,6 +9474,9 @@ ${COLORS.system("[没有正在执行的请求]")}`);
|
|
|
9451
9474
|
});
|
|
9452
9475
|
}
|
|
9453
9476
|
async handleLine(line) {
|
|
9477
|
+
if (this.isShuttingDown) {
|
|
9478
|
+
return;
|
|
9479
|
+
}
|
|
9454
9480
|
if (line.startsWith("/") && this.inputHandler.getBuffer() === "") {
|
|
9455
9481
|
await this.handleCommand(line.slice(1));
|
|
9456
9482
|
this.inputHandler.reset();
|
|
@@ -17001,7 +17027,7 @@ var WorkflowListCommand = {
|
|
|
17001
17027
|
describe: "列出所有已注册的 Workflow",
|
|
17002
17028
|
builder: (yargs) => yargs.option("tag", {
|
|
17003
17029
|
alias: "t",
|
|
17004
|
-
describe: "
|
|
17030
|
+
describe: "按标签筛选(可多次 --tag ai --tag cli 表示 AND)",
|
|
17005
17031
|
type: "string"
|
|
17006
17032
|
}).option("task-id", {
|
|
17007
17033
|
alias: "i",
|
|
@@ -17021,6 +17047,27 @@ var WorkflowListCommand = {
|
|
|
17021
17047
|
describe: "分页偏移",
|
|
17022
17048
|
type: "number",
|
|
17023
17049
|
default: 0
|
|
17050
|
+
}).option("page", {
|
|
17051
|
+
describe: "页码(1-based,与 --page-size 配合;与 --offset 互斥)",
|
|
17052
|
+
type: "number",
|
|
17053
|
+
default: 1
|
|
17054
|
+
}).option("page-size", {
|
|
17055
|
+
describe: "每页大小(与 --page 配合;等价于 --limit)",
|
|
17056
|
+
type: "number"
|
|
17057
|
+
}).check((argv) => {
|
|
17058
|
+
if (typeof argv.page === "number" && argv.page < 1) {
|
|
17059
|
+
throw new Error("--page must be >= 1");
|
|
17060
|
+
}
|
|
17061
|
+
if (typeof argv.pageSize === "number" && argv.pageSize < 1) {
|
|
17062
|
+
throw new Error("--page-size must be >= 1");
|
|
17063
|
+
}
|
|
17064
|
+
if (typeof argv.limit === "number" && argv.limit < 1) {
|
|
17065
|
+
throw new Error("--limit must be >= 1");
|
|
17066
|
+
}
|
|
17067
|
+
if (typeof argv.offset === "number" && argv.offset < 0) {
|
|
17068
|
+
throw new Error("--offset must be >= 0");
|
|
17069
|
+
}
|
|
17070
|
+
return true;
|
|
17024
17071
|
}).option("json", {
|
|
17025
17072
|
alias: "j",
|
|
17026
17073
|
describe: "JSON 格式输出",
|
|
@@ -17055,12 +17102,20 @@ var WorkflowListCommand = {
|
|
|
17055
17102
|
output.error('WorkflowService not initialized. Please run "roy-agent workflow init" first.');
|
|
17056
17103
|
process.exit(1);
|
|
17057
17104
|
}
|
|
17105
|
+
const tagsArg = args.tag;
|
|
17106
|
+
const tagsList = Array.isArray(tagsArg) ? tagsArg : tagsArg ? [tagsArg] : [];
|
|
17107
|
+
const pageSize = typeof args.pageSize === "number" ? args.pageSize : typeof args.limit === "number" ? args.limit : 50;
|
|
17108
|
+
const page = typeof args.page === "number" ? args.page : 1;
|
|
17109
|
+
const effectiveOffset = (page - 1) * pageSize;
|
|
17110
|
+
const userOffset = typeof args.offset === "number" ? args.offset : 0;
|
|
17111
|
+
const finalOffset = page > 1 ? effectiveOffset : userOffset;
|
|
17058
17112
|
const tool = createWorkflowListTool(service);
|
|
17059
17113
|
const result = await tool.execute({
|
|
17060
|
-
tag:
|
|
17061
|
-
|
|
17062
|
-
|
|
17063
|
-
|
|
17114
|
+
tag: tagsList.length === 1 ? tagsList[0] : undefined,
|
|
17115
|
+
tags: tagsList.length > 1 ? tagsList : undefined,
|
|
17116
|
+
search: args.search !== undefined && typeof args.search === "string" ? args.search : undefined,
|
|
17117
|
+
limit: pageSize,
|
|
17118
|
+
offset: finalOffset
|
|
17064
17119
|
}, {});
|
|
17065
17120
|
if (!result.success) {
|
|
17066
17121
|
output.error(result.error || "Failed to list workflows");
|
|
@@ -17068,6 +17123,8 @@ var WorkflowListCommand = {
|
|
|
17068
17123
|
}
|
|
17069
17124
|
const data = JSON.parse(result.output);
|
|
17070
17125
|
const workflows = data.workflows || [];
|
|
17126
|
+
const availableTags = data.available_tags || [];
|
|
17127
|
+
const total = typeof data.total === "number" ? data.total : workflows.length;
|
|
17071
17128
|
if (args.json) {
|
|
17072
17129
|
output.json({
|
|
17073
17130
|
workflows: workflows.map((w) => ({
|
|
@@ -17078,7 +17135,12 @@ var WorkflowListCommand = {
|
|
|
17078
17135
|
createdAt: w.created_at,
|
|
17079
17136
|
updatedAt: w.created_at
|
|
17080
17137
|
})),
|
|
17081
|
-
|
|
17138
|
+
available_tags: availableTags,
|
|
17139
|
+
total,
|
|
17140
|
+
count: workflows.length,
|
|
17141
|
+
limit: pageSize,
|
|
17142
|
+
offset: finalOffset,
|
|
17143
|
+
page: page > 1 ? page : Math.floor(finalOffset / pageSize) + 1
|
|
17082
17144
|
});
|
|
17083
17145
|
} else {
|
|
17084
17146
|
const renderWorkflows = workflows.map((w) => ({
|
|
@@ -17093,8 +17155,25 @@ var WorkflowListCommand = {
|
|
|
17093
17155
|
metadata: {}
|
|
17094
17156
|
}));
|
|
17095
17157
|
output.log(renderWorkflowList(renderWorkflows));
|
|
17096
|
-
|
|
17097
|
-
|
|
17158
|
+
if (total > workflows.length) {
|
|
17159
|
+
const start = finalOffset + 1;
|
|
17160
|
+
const end = finalOffset + workflows.length;
|
|
17161
|
+
output.log(chalk61.green(`
|
|
17162
|
+
✅ 显示 ${start}-${end} / 共 ${total} 个 Workflow`));
|
|
17163
|
+
const totalPages = Math.ceil(total / pageSize);
|
|
17164
|
+
const currentPage = Math.floor(finalOffset / pageSize) + 1;
|
|
17165
|
+
if (totalPages > 1) {
|
|
17166
|
+
output.log(chalk61.cyan(`\uD83D\uDCC4 第 ${currentPage} / ${totalPages} 页`));
|
|
17167
|
+
}
|
|
17168
|
+
} else {
|
|
17169
|
+
output.log(chalk61.green(`
|
|
17170
|
+
✅ 共 ${total} 个 Workflow`));
|
|
17171
|
+
}
|
|
17172
|
+
if (availableTags.length > 0) {
|
|
17173
|
+
const tagsLine = availableTags.map((t) => `${t.name}(${t.count})`).join(", ");
|
|
17174
|
+
output.log(chalk61.cyan(`
|
|
17175
|
+
\uD83C\uDFF7️ Available tags: ${tagsLine}`));
|
|
17176
|
+
}
|
|
17098
17177
|
}
|
|
17099
17178
|
} catch (error) {
|
|
17100
17179
|
output.error(`Failed to list workflows: ${error}`);
|
|
@@ -17762,8 +17841,9 @@ var WorkflowAddCommand = {
|
|
|
17762
17841
|
type: "string"
|
|
17763
17842
|
}).option("tags", {
|
|
17764
17843
|
alias: "t",
|
|
17765
|
-
describe: "
|
|
17766
|
-
type: "
|
|
17844
|
+
describe: 'Tags (1-3 required). Select from existing tag pool when possible. Run "roy-agent workflow tag list" first to see available tags. Supports both --tags "a,b,c" and --tags a --tags b --tags c forms.',
|
|
17845
|
+
type: "array",
|
|
17846
|
+
string: true
|
|
17767
17847
|
}).option("task-id", {
|
|
17768
17848
|
alias: "i",
|
|
17769
17849
|
describe: "关联任务 ID",
|
|
@@ -17790,6 +17870,29 @@ var WorkflowAddCommand = {
|
|
|
17790
17870
|
const output = new OutputService;
|
|
17791
17871
|
const envService = new EnvironmentService(output);
|
|
17792
17872
|
try {
|
|
17873
|
+
let parseTags = function(input) {
|
|
17874
|
+
if (input === undefined || input === null)
|
|
17875
|
+
return;
|
|
17876
|
+
const list = [];
|
|
17877
|
+
if (Array.isArray(input)) {
|
|
17878
|
+
for (const item of input) {
|
|
17879
|
+
if (typeof item === "string") {
|
|
17880
|
+
for (const t of item.split(",")) {
|
|
17881
|
+
const trimmed = t.trim();
|
|
17882
|
+
if (trimmed)
|
|
17883
|
+
list.push(trimmed);
|
|
17884
|
+
}
|
|
17885
|
+
}
|
|
17886
|
+
}
|
|
17887
|
+
} else if (typeof input === "string") {
|
|
17888
|
+
for (const t of input.split(",")) {
|
|
17889
|
+
const trimmed = t.trim();
|
|
17890
|
+
if (trimmed)
|
|
17891
|
+
list.push(trimmed);
|
|
17892
|
+
}
|
|
17893
|
+
}
|
|
17894
|
+
return list.length > 0 ? list : undefined;
|
|
17895
|
+
};
|
|
17793
17896
|
await envService.create({ configPath: a.config });
|
|
17794
17897
|
const env = envService.getEnvironment();
|
|
17795
17898
|
if (!env) {
|
|
@@ -17901,7 +18004,19 @@ Agent output:
|
|
|
17901
18004
|
output.error('Usage: roy-agent workflow add --file <path> | --desc "<description>"');
|
|
17902
18005
|
process.exit(1);
|
|
17903
18006
|
}
|
|
17904
|
-
const tags = a.tags
|
|
18007
|
+
const tags = parseTags(a.tags);
|
|
18008
|
+
if (!tags || tags.length === 0) {
|
|
18009
|
+
output.error("❌ --tags is required.");
|
|
18010
|
+
output.error(' Please provide 1-3 tags using --tags "tag1,tag2,tag3"');
|
|
18011
|
+
output.error(' Example: roy-agent workflow add --file my.yaml --tags "ai,ml,etl"');
|
|
18012
|
+
process.exit(1);
|
|
18013
|
+
}
|
|
18014
|
+
if (tags.length > 3) {
|
|
18015
|
+
output.error(`❌ Too many tags: received ${tags.length}, maximum is 3.`);
|
|
18016
|
+
output.error(' Please reduce to 1-3 tags using --tags "tag1,tag2,tag3"');
|
|
18017
|
+
output.error(' Example: roy-agent workflow add --file my.yaml --tags "ai,ml,etl"');
|
|
18018
|
+
process.exit(1);
|
|
18019
|
+
}
|
|
17905
18020
|
const workflow = await service.createWorkflow(definition, {
|
|
17906
18021
|
tags,
|
|
17907
18022
|
taskId: a.taskId,
|
|
@@ -19139,11 +19254,412 @@ Error: ${error.message}`));
|
|
|
19139
19254
|
}
|
|
19140
19255
|
};
|
|
19141
19256
|
|
|
19257
|
+
// src/commands/workflow/commands/search.ts
|
|
19258
|
+
import chalk71 from "chalk";
|
|
19259
|
+
import { wrapFunction as wrapFunction3 } from "@ai-setting/roy-agent-core";
|
|
19260
|
+
var WorkflowSearchCommand = {
|
|
19261
|
+
command: "search",
|
|
19262
|
+
describe: "Search workflows by keyword and/or tags (multiple tags use AND filter). v2: returns available_tags.",
|
|
19263
|
+
builder: (yargs) => yargs.option("keyword", {
|
|
19264
|
+
alias: "k",
|
|
19265
|
+
describe: "Search keyword in name and description",
|
|
19266
|
+
type: "string"
|
|
19267
|
+
}).option("tag", {
|
|
19268
|
+
alias: "t",
|
|
19269
|
+
describe: "Filter by tag (can be specified multiple times for AND filter)",
|
|
19270
|
+
type: "array",
|
|
19271
|
+
string: true
|
|
19272
|
+
}).option("limit", {
|
|
19273
|
+
alias: "l",
|
|
19274
|
+
describe: "Maximum number of results",
|
|
19275
|
+
type: "number",
|
|
19276
|
+
default: 50
|
|
19277
|
+
}).option("offset", {
|
|
19278
|
+
alias: "o",
|
|
19279
|
+
describe: "Pagination offset",
|
|
19280
|
+
type: "number",
|
|
19281
|
+
default: 0
|
|
19282
|
+
}).option("json", {
|
|
19283
|
+
alias: "j",
|
|
19284
|
+
describe: "Output as JSON",
|
|
19285
|
+
type: "boolean",
|
|
19286
|
+
default: false
|
|
19287
|
+
}).option("yaml", {
|
|
19288
|
+
alias: "y",
|
|
19289
|
+
describe: "Output as YAML",
|
|
19290
|
+
type: "boolean",
|
|
19291
|
+
default: false
|
|
19292
|
+
}).option("config", {
|
|
19293
|
+
describe: "Config file path",
|
|
19294
|
+
type: "string"
|
|
19295
|
+
}).check((argv) => {
|
|
19296
|
+
const hasKeyword = typeof argv.keyword === "string" && argv.keyword.length > 0;
|
|
19297
|
+
const hasTags = Array.isArray(argv.tag) && argv.tag.length > 0;
|
|
19298
|
+
if (!hasKeyword && !hasTags) {
|
|
19299
|
+
throw new Error("At least one of --keyword or --tag must be provided");
|
|
19300
|
+
}
|
|
19301
|
+
if (Array.isArray(argv.tag)) {
|
|
19302
|
+
for (const t of argv.tag) {
|
|
19303
|
+
if (typeof t !== "string" || t.length === 0) {
|
|
19304
|
+
throw new Error("Empty tag values are not allowed");
|
|
19305
|
+
}
|
|
19306
|
+
if (t.length > 50) {
|
|
19307
|
+
throw new Error(`Tag "${t}" exceeds 50 characters`);
|
|
19308
|
+
}
|
|
19309
|
+
if (t.includes(",")) {
|
|
19310
|
+
throw new Error(`Tag "${t}" contains comma; pass them as separate --tags`);
|
|
19311
|
+
}
|
|
19312
|
+
}
|
|
19313
|
+
}
|
|
19314
|
+
return true;
|
|
19315
|
+
}),
|
|
19316
|
+
async handler(args) {
|
|
19317
|
+
const a = args;
|
|
19318
|
+
const output = new OutputService;
|
|
19319
|
+
const envService = new EnvironmentService(output);
|
|
19320
|
+
try {
|
|
19321
|
+
await runWorkflowSearch({
|
|
19322
|
+
keyword: a.keyword,
|
|
19323
|
+
tags: a.tag,
|
|
19324
|
+
limit: a.limit,
|
|
19325
|
+
offset: a.offset,
|
|
19326
|
+
asJson: a.json,
|
|
19327
|
+
asYaml: a.yaml,
|
|
19328
|
+
configPath: a.config,
|
|
19329
|
+
output,
|
|
19330
|
+
envService
|
|
19331
|
+
});
|
|
19332
|
+
} catch (error) {
|
|
19333
|
+
output.error(`Failed to search workflows: ${error}`);
|
|
19334
|
+
process.exit(1);
|
|
19335
|
+
} finally {
|
|
19336
|
+
await envService.dispose();
|
|
19337
|
+
}
|
|
19338
|
+
}
|
|
19339
|
+
};
|
|
19340
|
+
var _runWorkflowSearchImpl = async function(opts) {
|
|
19341
|
+
const { keyword, tags, limit, offset, asJson, asYaml, configPath, output, envService } = opts;
|
|
19342
|
+
await envService.create({ configPath });
|
|
19343
|
+
const env = envService.getEnvironment();
|
|
19344
|
+
if (!env) {
|
|
19345
|
+
output.error("Failed to create environment");
|
|
19346
|
+
process.exit(1);
|
|
19347
|
+
}
|
|
19348
|
+
const workflowComponent = env.getComponent("workflow");
|
|
19349
|
+
if (!workflowComponent) {
|
|
19350
|
+
output.error("WorkflowComponent not available");
|
|
19351
|
+
process.exit(1);
|
|
19352
|
+
}
|
|
19353
|
+
const service = workflowComponent.getService();
|
|
19354
|
+
if (!service) {
|
|
19355
|
+
output.error('WorkflowService not initialized. Please run "roy-agent workflow init" first.');
|
|
19356
|
+
process.exit(1);
|
|
19357
|
+
}
|
|
19358
|
+
const useWithTags = typeof service.searchWorkflowsWithTags === "function";
|
|
19359
|
+
const result = useWithTags ? await service.searchWorkflowsWithTags({
|
|
19360
|
+
keyword,
|
|
19361
|
+
tags,
|
|
19362
|
+
limit,
|
|
19363
|
+
offset
|
|
19364
|
+
}) : {
|
|
19365
|
+
workflows: service.searchWorkflows({ keyword, tags, limit, offset }),
|
|
19366
|
+
available_tags: []
|
|
19367
|
+
};
|
|
19368
|
+
const workflows = result.workflows ?? [];
|
|
19369
|
+
const availableTags = result.available_tags ?? [];
|
|
19370
|
+
if (asJson) {
|
|
19371
|
+
output.json({
|
|
19372
|
+
workflows: workflows.map((w) => ({
|
|
19373
|
+
name: w.name,
|
|
19374
|
+
version: w.version,
|
|
19375
|
+
description: w.description,
|
|
19376
|
+
tags: w.tags,
|
|
19377
|
+
createdAt: w.createdAt,
|
|
19378
|
+
updatedAt: w.updatedAt
|
|
19379
|
+
})),
|
|
19380
|
+
available_tags: availableTags,
|
|
19381
|
+
total: workflows.length,
|
|
19382
|
+
keyword,
|
|
19383
|
+
tags
|
|
19384
|
+
});
|
|
19385
|
+
return;
|
|
19386
|
+
}
|
|
19387
|
+
if (asYaml) {
|
|
19388
|
+
const yaml = await Promise.resolve().then(() => __toESM(require_dist(), 1));
|
|
19389
|
+
output.log(yaml.stringify({
|
|
19390
|
+
workflows: workflows.map((w) => ({
|
|
19391
|
+
name: w.name,
|
|
19392
|
+
version: w.version,
|
|
19393
|
+
description: w.description,
|
|
19394
|
+
tags: w.tags
|
|
19395
|
+
})),
|
|
19396
|
+
available_tags: availableTags,
|
|
19397
|
+
total: workflows.length,
|
|
19398
|
+
keyword,
|
|
19399
|
+
tags
|
|
19400
|
+
}));
|
|
19401
|
+
return;
|
|
19402
|
+
}
|
|
19403
|
+
const renderWorkflows = workflows.map((w) => ({
|
|
19404
|
+
id: w.name,
|
|
19405
|
+
name: w.name,
|
|
19406
|
+
version: w.version,
|
|
19407
|
+
description: w.description,
|
|
19408
|
+
tags: w.tags || [],
|
|
19409
|
+
createdAt: w.createdAt ? new Date(w.createdAt) : new Date,
|
|
19410
|
+
updatedAt: w.updatedAt ? new Date(w.updatedAt) : new Date,
|
|
19411
|
+
definition: { nodes: [], config: {}, inputs: {} },
|
|
19412
|
+
metadata: {}
|
|
19413
|
+
}));
|
|
19414
|
+
if (renderWorkflows.length === 0) {
|
|
19415
|
+
output.log(chalk71.yellow("\uD83D\uDD0D No workflows matched the search criteria."));
|
|
19416
|
+
output.log(chalk71.gray(` keyword: ${keyword || "(none)"}`));
|
|
19417
|
+
output.log(chalk71.gray(` tags: ${tags && tags.length > 0 ? tags.join(", ") : "(none)"}`));
|
|
19418
|
+
} else {
|
|
19419
|
+
output.log(chalk71.bold(`\uD83D\uDD0D Search results (${renderWorkflows.length}):`));
|
|
19420
|
+
output.log(renderWorkflowList(renderWorkflows));
|
|
19421
|
+
output.log(chalk71.green(`
|
|
19422
|
+
✅ Found ${renderWorkflows.length} workflow(s)`));
|
|
19423
|
+
}
|
|
19424
|
+
if (availableTags.length > 0) {
|
|
19425
|
+
output.log("");
|
|
19426
|
+
output.log(chalk71.bold("\uD83D\uDCDA Available tags (sorted by usage_count):"));
|
|
19427
|
+
for (const t of availableTags) {
|
|
19428
|
+
const name = t.name ?? t.tag;
|
|
19429
|
+
const count = t.count ?? t.usage_count;
|
|
19430
|
+
output.log(chalk71.gray(` - ${name} (${count})`));
|
|
19431
|
+
}
|
|
19432
|
+
}
|
|
19433
|
+
};
|
|
19434
|
+
var runWorkflowSearch = wrapFunction3(_runWorkflowSearchImpl, "workflow.cli.search", {
|
|
19435
|
+
recordParams: true,
|
|
19436
|
+
recordResult: false,
|
|
19437
|
+
log: false
|
|
19438
|
+
});
|
|
19439
|
+
|
|
19440
|
+
// src/commands/workflow/commands/tag.ts
|
|
19441
|
+
import { wrapFunction as wrapFunction4 } from "@ai-setting/roy-agent-core";
|
|
19442
|
+
import chalk72 from "chalk";
|
|
19443
|
+
var WorkflowTagListCommand = {
|
|
19444
|
+
command: "list",
|
|
19445
|
+
describe: "List all workflow tags from the workflow_tags table (sorted by usage_count DESC by default). Use this BEFORE `workflow add` to discover existing tags and reuse them for semantic consistency.",
|
|
19446
|
+
builder: (yargs) => yargs.option("sort-by", {
|
|
19447
|
+
describe: "Sort field",
|
|
19448
|
+
choices: ["usage_count", "name", "created_at"],
|
|
19449
|
+
default: "usage_count"
|
|
19450
|
+
}).option("order", {
|
|
19451
|
+
describe: "Sort order",
|
|
19452
|
+
choices: ["asc", "desc"],
|
|
19453
|
+
default: "desc"
|
|
19454
|
+
}).option("limit", {
|
|
19455
|
+
describe: "Max number of tags to return",
|
|
19456
|
+
type: "number",
|
|
19457
|
+
default: 100
|
|
19458
|
+
}).option("json", {
|
|
19459
|
+
alias: "j",
|
|
19460
|
+
describe: "Output as JSON",
|
|
19461
|
+
type: "boolean",
|
|
19462
|
+
default: false
|
|
19463
|
+
}).option("config", {
|
|
19464
|
+
describe: "Config file path",
|
|
19465
|
+
type: "string"
|
|
19466
|
+
}),
|
|
19467
|
+
async handler(args) {
|
|
19468
|
+
const a = args;
|
|
19469
|
+
const output = new OutputService;
|
|
19470
|
+
const envService = new EnvironmentService(output);
|
|
19471
|
+
try {
|
|
19472
|
+
await runWorkflowTagList({
|
|
19473
|
+
sortBy: a.sortBy,
|
|
19474
|
+
order: a.order,
|
|
19475
|
+
limit: a.limit,
|
|
19476
|
+
asJson: a.json,
|
|
19477
|
+
configPath: a.config,
|
|
19478
|
+
output,
|
|
19479
|
+
envService
|
|
19480
|
+
});
|
|
19481
|
+
} catch (error) {
|
|
19482
|
+
output.error(`Failed to list workflow tags: ${error}`);
|
|
19483
|
+
process.exit(1);
|
|
19484
|
+
} finally {
|
|
19485
|
+
await envService.dispose();
|
|
19486
|
+
}
|
|
19487
|
+
}
|
|
19488
|
+
};
|
|
19489
|
+
var WorkflowTagGetCommand = {
|
|
19490
|
+
command: "get <name>",
|
|
19491
|
+
describe: "Get details of a single workflow tag (usage_count, created_at, updated_at). Returns error if tag not in the workflow_tags table.",
|
|
19492
|
+
builder: (yargs) => yargs.positional("name", {
|
|
19493
|
+
describe: "Tag name",
|
|
19494
|
+
type: "string"
|
|
19495
|
+
}).option("json", {
|
|
19496
|
+
alias: "j",
|
|
19497
|
+
describe: "Output as JSON",
|
|
19498
|
+
type: "boolean",
|
|
19499
|
+
default: false
|
|
19500
|
+
}).option("config", {
|
|
19501
|
+
describe: "Config file path",
|
|
19502
|
+
type: "string"
|
|
19503
|
+
}).check((argv) => {
|
|
19504
|
+
if (typeof argv.name !== "string" || argv.name.length === 0) {
|
|
19505
|
+
throw new Error("Tag name is required");
|
|
19506
|
+
}
|
|
19507
|
+
if (argv.name.length > 50) {
|
|
19508
|
+
throw new Error(`Tag name exceeds 50 characters`);
|
|
19509
|
+
}
|
|
19510
|
+
return true;
|
|
19511
|
+
}),
|
|
19512
|
+
async handler(args) {
|
|
19513
|
+
const a = args;
|
|
19514
|
+
const output = new OutputService;
|
|
19515
|
+
const envService = new EnvironmentService(output);
|
|
19516
|
+
try {
|
|
19517
|
+
await runWorkflowTagGet({
|
|
19518
|
+
name: a.name,
|
|
19519
|
+
asJson: a.json,
|
|
19520
|
+
configPath: a.config,
|
|
19521
|
+
output,
|
|
19522
|
+
envService
|
|
19523
|
+
});
|
|
19524
|
+
} catch (error) {
|
|
19525
|
+
output.error(`Failed to get tag: ${error}`);
|
|
19526
|
+
process.exit(1);
|
|
19527
|
+
} finally {
|
|
19528
|
+
await envService.dispose();
|
|
19529
|
+
}
|
|
19530
|
+
}
|
|
19531
|
+
};
|
|
19532
|
+
var _runWorkflowTagListImpl = async function(opts) {
|
|
19533
|
+
const { output, envService } = opts;
|
|
19534
|
+
await envService.create({ configPath: opts.configPath });
|
|
19535
|
+
const env = envService.getEnvironment();
|
|
19536
|
+
if (!env) {
|
|
19537
|
+
output.error("Failed to create environment");
|
|
19538
|
+
process.exit(1);
|
|
19539
|
+
}
|
|
19540
|
+
const workflowComponent = env.getComponent("workflow");
|
|
19541
|
+
if (!workflowComponent) {
|
|
19542
|
+
output.error("WorkflowComponent not available");
|
|
19543
|
+
process.exit(1);
|
|
19544
|
+
}
|
|
19545
|
+
const service = workflowComponent.getService();
|
|
19546
|
+
if (!service) {
|
|
19547
|
+
output.error('WorkflowService not initialized. Please run "roy-agent workflow init" first.');
|
|
19548
|
+
process.exit(1);
|
|
19549
|
+
}
|
|
19550
|
+
const result = await callListTags(service, {
|
|
19551
|
+
sortBy: opts.sortBy ?? "usage_count",
|
|
19552
|
+
order: opts.order ?? "desc",
|
|
19553
|
+
limit: opts.limit ?? 100
|
|
19554
|
+
});
|
|
19555
|
+
if (opts.asJson) {
|
|
19556
|
+
output.json({
|
|
19557
|
+
tags: result.tags,
|
|
19558
|
+
total: result.total
|
|
19559
|
+
});
|
|
19560
|
+
return;
|
|
19561
|
+
}
|
|
19562
|
+
if (result.tags.length === 0) {
|
|
19563
|
+
output.log(chalk72.yellow("\uD83C\uDFF7️ No tags in the workflow_tags table yet."));
|
|
19564
|
+
output.log(chalk72.gray(" Tags are created automatically when you run `workflow add --tags <name>`."));
|
|
19565
|
+
return;
|
|
19566
|
+
}
|
|
19567
|
+
output.log(chalk72.bold(`\uD83C\uDFF7️ Workflow tags (${result.total}):`));
|
|
19568
|
+
output.log(chalk72.gray(` ${padRight("NAME", 24)}${padRight("USAGE", 8)}${padRight("CREATED", 22)}`));
|
|
19569
|
+
for (const t of result.tags) {
|
|
19570
|
+
const line = ` ${padRight(t.name, 24)}${padRight(String(t.usage_count), 8)}${padRight(formatDate2(t.created_at), 22)}`;
|
|
19571
|
+
output.log(line);
|
|
19572
|
+
}
|
|
19573
|
+
output.log(chalk72.gray(`
|
|
19574
|
+
\uD83D\uDCA1 Tip: when adding a new workflow, prefer tags from this list to ensure semantic consistency.`));
|
|
19575
|
+
};
|
|
19576
|
+
var _runWorkflowTagGetImpl = async function(opts) {
|
|
19577
|
+
const { output, envService } = opts;
|
|
19578
|
+
await envService.create({ configPath: opts.configPath });
|
|
19579
|
+
const env = envService.getEnvironment();
|
|
19580
|
+
if (!env) {
|
|
19581
|
+
output.error("Failed to create environment");
|
|
19582
|
+
process.exit(1);
|
|
19583
|
+
}
|
|
19584
|
+
const workflowComponent = env.getComponent("workflow");
|
|
19585
|
+
if (!workflowComponent) {
|
|
19586
|
+
output.error("WorkflowComponent not available");
|
|
19587
|
+
process.exit(1);
|
|
19588
|
+
}
|
|
19589
|
+
const service = workflowComponent.getService();
|
|
19590
|
+
if (!service) {
|
|
19591
|
+
output.error('WorkflowService not initialized. Please run "roy-agent workflow init" first.');
|
|
19592
|
+
process.exit(1);
|
|
19593
|
+
}
|
|
19594
|
+
const tag = callGetTag(service, opts.name);
|
|
19595
|
+
if (!tag) {
|
|
19596
|
+
if (opts.asJson) {
|
|
19597
|
+
output.json({ error: "Tag not found", name: opts.name });
|
|
19598
|
+
} else {
|
|
19599
|
+
output.error(`Tag "${opts.name}" not found in the workflow_tags table.`);
|
|
19600
|
+
output.log(chalk72.gray(`Tip: run \`roy-agent workflow tag list\` to see available tags.`));
|
|
19601
|
+
}
|
|
19602
|
+
process.exitCode = 1;
|
|
19603
|
+
return;
|
|
19604
|
+
}
|
|
19605
|
+
if (opts.asJson) {
|
|
19606
|
+
output.json(tag);
|
|
19607
|
+
return;
|
|
19608
|
+
}
|
|
19609
|
+
output.log(chalk72.bold(`\uD83C\uDFF7️ Tag: ${tag.name}`));
|
|
19610
|
+
output.log(chalk72.gray(` usage_count: ${tag.usage_count}`));
|
|
19611
|
+
output.log(chalk72.gray(` created_at: ${tag.created_at}`));
|
|
19612
|
+
output.log(chalk72.gray(` updated_at: ${tag.updated_at}`));
|
|
19613
|
+
};
|
|
19614
|
+
async function callListTags(service, options) {
|
|
19615
|
+
if (typeof service.listTags !== "function") {
|
|
19616
|
+
return { tags: [], total: 0 };
|
|
19617
|
+
}
|
|
19618
|
+
return await service.listTags(options);
|
|
19619
|
+
}
|
|
19620
|
+
function callGetTag(service, name) {
|
|
19621
|
+
if (typeof service.getTag !== "function") {
|
|
19622
|
+
return;
|
|
19623
|
+
}
|
|
19624
|
+
return service.getTag(name);
|
|
19625
|
+
}
|
|
19626
|
+
function padRight(str, width) {
|
|
19627
|
+
if (str.length >= width)
|
|
19628
|
+
return str.slice(0, width - 1) + " ";
|
|
19629
|
+
return str + " ".repeat(width - str.length);
|
|
19630
|
+
}
|
|
19631
|
+
function formatDate2(iso) {
|
|
19632
|
+
try {
|
|
19633
|
+
const d = new Date(iso);
|
|
19634
|
+
if (isNaN(d.getTime()))
|
|
19635
|
+
return iso;
|
|
19636
|
+
return d.toISOString().replace("T", " ").slice(0, 19);
|
|
19637
|
+
} catch {
|
|
19638
|
+
return iso;
|
|
19639
|
+
}
|
|
19640
|
+
}
|
|
19641
|
+
var runWorkflowTagList = wrapFunction4(_runWorkflowTagListImpl, "workflow.cli.tag.list", {
|
|
19642
|
+
recordParams: true,
|
|
19643
|
+
recordResult: false,
|
|
19644
|
+
log: false
|
|
19645
|
+
});
|
|
19646
|
+
var runWorkflowTagGet = wrapFunction4(_runWorkflowTagGetImpl, "workflow.cli.tag.get", {
|
|
19647
|
+
recordParams: true,
|
|
19648
|
+
recordResult: false,
|
|
19649
|
+
log: false
|
|
19650
|
+
});
|
|
19651
|
+
|
|
19142
19652
|
// src/commands/workflow/index.ts
|
|
19653
|
+
var WorkflowTagCommand = {
|
|
19654
|
+
command: "tag",
|
|
19655
|
+
describe: "Manage workflow tags — list and get from the workflow_tags table. Use BEFORE `workflow add` to discover existing tags.",
|
|
19656
|
+
builder: (yargs) => yargs.command(WorkflowTagListCommand).command(WorkflowTagGetCommand).demandCommand(1, "请指定 tag 子命令:list 或 get <name>").help(),
|
|
19657
|
+
handler() {}
|
|
19658
|
+
};
|
|
19143
19659
|
var WorkflowCommand = {
|
|
19144
19660
|
command: "workflow",
|
|
19145
19661
|
describe: "Workflow DAG management and execution - create, run, and monitor workflows",
|
|
19146
|
-
builder: (yargs) => yargs.command(WorkflowListCommand).command(WorkflowAddCommand).command(WorkflowNodesCommand).command(WorkflowValidateCommand).command(WorkflowGetCommand).command(WorkflowUpdateCommand).command(WorkflowRemoveCommand).command(WorkflowRunCommand).command(WorkflowStopCommand).command(WorkflowStatusCommand).demandCommand(1, "请指定子命令:list、add、validate、nodes、get、update、remove、run、stop、status\n\nResume: 使用 `workflow run -s <sessionId>` 恢复暂停的工作流").help(),
|
|
19662
|
+
builder: (yargs) => yargs.command(WorkflowListCommand).command(WorkflowAddCommand).command(WorkflowSearchCommand).command(WorkflowTagCommand).command(WorkflowNodesCommand).command(WorkflowValidateCommand).command(WorkflowGetCommand).command(WorkflowUpdateCommand).command(WorkflowRemoveCommand).command(WorkflowRunCommand).command(WorkflowStopCommand).command(WorkflowStatusCommand).demandCommand(1, "请指定子命令:list、add、search、tag、validate、nodes、get、update、remove、run、stop、status\n\nResume: 使用 `workflow run -s <sessionId>` 恢复暂停的工作流").help(),
|
|
19147
19663
|
handler() {}
|
|
19148
19664
|
};
|
|
19149
19665
|
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-setting/roy-agent-cli",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.85",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "CLI for roy-agent - Non-interactive command execution",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -26,8 +26,8 @@
|
|
|
26
26
|
"typecheck": "npx tsc --noEmit --skipLibCheck"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@ai-setting/roy-agent-coder-harness": "^1.5.
|
|
30
|
-
"@ai-setting/roy-agent-core": "^1.5.
|
|
29
|
+
"@ai-setting/roy-agent-coder-harness": "^1.5.50",
|
|
30
|
+
"@ai-setting/roy-agent-core": "^1.5.83",
|
|
31
31
|
"@ai-setting/roy-agent-ontology-harness": "^1.5.47",
|
|
32
32
|
"chalk": "^5.6.2",
|
|
33
33
|
"commander": "^14.0.3",
|