@ai-setting/roy-agent-cli 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +126 -0
- package/dist/bin/roy.js +127297 -0
- package/dist/roy-agent-darwin-arm64/bin/roy.js +127297 -0
- package/dist/roy-agent-darwin-x64/bin/roy.js +127297 -0
- package/dist/roy-agent-linux-arm64/bin/roy.js +127297 -0
- package/dist/roy-agent-linux-x64/bin/roy.js +127297 -0
- package/dist/roy-agent-windows-x64/bin/roy.js +127297 -0
- package/package.json +91 -0
- package/src/bin/roy.ts +12 -0
- package/src/cli.ts +101 -0
- package/src/commands/act.ts +480 -0
- package/src/commands/commands-add.ts +110 -0
- package/src/commands/commands-dirs.ts +70 -0
- package/src/commands/commands-info.ts +90 -0
- package/src/commands/commands-list.ts +161 -0
- package/src/commands/commands-remove.ts +147 -0
- package/src/commands/commands.ts +55 -0
- package/src/commands/config/config-service.test.ts +449 -0
- package/src/commands/config/config-service.ts +312 -0
- package/src/commands/config/deep-merge.test.ts +168 -0
- package/src/commands/config/deep-merge.ts +63 -0
- package/src/commands/config/export.ts +97 -0
- package/src/commands/config/filter-history-e2e.test.ts +141 -0
- package/src/commands/config/import-preserve-refs.test.ts +212 -0
- package/src/commands/config/import.ts +119 -0
- package/src/commands/config/index.ts +35 -0
- package/src/commands/config/list.ts +281 -0
- package/src/commands/config/roy-config-e2e.test.ts +297 -0
- package/src/commands/config/types.ts +54 -0
- package/src/commands/debug/index.ts +38 -0
- package/src/commands/debug/log.test.ts +233 -0
- package/src/commands/debug/log.ts +123 -0
- package/src/commands/debug/span.test.ts +297 -0
- package/src/commands/debug/span.ts +211 -0
- package/src/commands/debug/trace.test.ts +254 -0
- package/src/commands/debug/trace.ts +140 -0
- package/src/commands/eventsource/add.ts +133 -0
- package/src/commands/eventsource/index.ts +48 -0
- package/src/commands/eventsource/list.ts +194 -0
- package/src/commands/eventsource/remove.ts +95 -0
- package/src/commands/eventsource/start.ts +103 -0
- package/src/commands/eventsource/status.ts +185 -0
- package/src/commands/eventsource/stop.ts +89 -0
- package/src/commands/index.ts +22 -0
- package/src/commands/input-handler.test.ts +76 -0
- package/src/commands/input-handler.ts +43 -0
- package/src/commands/interactive-esc.test.ts +254 -0
- package/src/commands/interactive.shutdown.test.ts +122 -0
- package/src/commands/interactive.test.ts +221 -0
- package/src/commands/interactive.ts +1015 -0
- package/src/commands/lsp/check.ts +92 -0
- package/src/commands/lsp/index.ts +32 -0
- package/src/commands/lsp/install.ts +126 -0
- package/src/commands/lsp/list.ts +64 -0
- package/src/commands/mcp/index.ts +27 -0
- package/src/commands/mcp/list.ts +116 -0
- package/src/commands/mcp/reload.ts +70 -0
- package/src/commands/mcp/tools.ts +121 -0
- package/src/commands/memory/extract-e2e.test.ts +388 -0
- package/src/commands/memory/index.ts +11 -0
- package/src/commands/memory/memory-simplified.test.ts +58 -0
- package/src/commands/memory/memory.ts +25 -0
- package/src/commands/memory/organize.ts +300 -0
- package/src/commands/memory/recall.test.ts +120 -0
- package/src/commands/memory/recall.ts +88 -0
- package/src/commands/memory/record-extract-handle-query.test.ts +385 -0
- package/src/commands/memory/record-prompt-component.test.ts +343 -0
- package/src/commands/memory/record.test.ts +92 -0
- package/src/commands/memory/record.ts +332 -0
- package/src/commands/plugin.test.ts +292 -0
- package/src/commands/plugin.ts +267 -0
- package/src/commands/sessions/active.ts +96 -0
- package/src/commands/sessions/add-message.ts +96 -0
- package/src/commands/sessions/checkpoints.ts +154 -0
- package/src/commands/sessions/compact.test.ts +215 -0
- package/src/commands/sessions/compact.ts +269 -0
- package/src/commands/sessions/delete.ts +236 -0
- package/src/commands/sessions/get.ts +165 -0
- package/src/commands/sessions/grep.ts +233 -0
- package/src/commands/sessions/index.ts +95 -0
- package/src/commands/sessions/list.ts +210 -0
- package/src/commands/sessions/messages.test.ts +333 -0
- package/src/commands/sessions/messages.ts +248 -0
- package/src/commands/sessions/mock.ts +194 -0
- package/src/commands/sessions/new.ts +82 -0
- package/src/commands/sessions/rename.ts +98 -0
- package/src/commands/shared/event-handler.ts +213 -0
- package/src/commands/shared/event-message-formatter.ts +295 -0
- package/src/commands/shared/index.ts +11 -0
- package/src/commands/shared/query-executor.test.ts +434 -0
- package/src/commands/shared/query-executor.ts +324 -0
- package/src/commands/shared/repl-engine.test.ts +354 -0
- package/src/commands/shared/session-manager.test.ts +212 -0
- package/src/commands/shared/session-manager.ts +114 -0
- package/src/commands/skills/get.ts +90 -0
- package/src/commands/skills/index.ts +39 -0
- package/src/commands/skills/list.ts +129 -0
- package/src/commands/skills/reload.ts +59 -0
- package/src/commands/skills/search.ts +132 -0
- package/src/commands/skills/show-config.ts +93 -0
- package/src/commands/tasks/complete.ts +92 -0
- package/src/commands/tasks/create.ts +118 -0
- package/src/commands/tasks/delete.ts +86 -0
- package/src/commands/tasks/get.ts +116 -0
- package/src/commands/tasks/index.ts +53 -0
- package/src/commands/tasks/list.ts +140 -0
- package/src/commands/tasks/operations.ts +120 -0
- package/src/commands/tasks/update.ts +122 -0
- package/src/commands/tools/exec-tool.ts +128 -0
- package/src/commands/tools/get.ts +114 -0
- package/src/commands/tools/index.ts +35 -0
- package/src/commands/tools/list.ts +107 -0
- package/src/commands/tools/shared/index.ts +7 -0
- package/src/commands/tools/shared/schema-helper.ts +111 -0
- package/src/commands/workflow/commands/add.ts +315 -0
- package/src/commands/workflow/commands/get.ts +193 -0
- package/src/commands/workflow/commands/list.ts +137 -0
- package/src/commands/workflow/commands/nodes.ts +528 -0
- package/src/commands/workflow/commands/remove.ts +94 -0
- package/src/commands/workflow/commands/run.ts +398 -0
- package/src/commands/workflow/commands/status.ts +147 -0
- package/src/commands/workflow/commands/stop.ts +91 -0
- package/src/commands/workflow/commands/update.ts +130 -0
- package/src/commands/workflow/commands/validate.ts +139 -0
- package/src/commands/workflow/commands/workflow-cli.test.ts +196 -0
- package/src/commands/workflow/index.ts +65 -0
- package/src/commands/workflow/renderers.ts +358 -0
- package/src/commands/workflow/validators/index.ts +8 -0
- package/src/commands/workflow/validators/node-validator-factory.ts +40 -0
- package/src/commands/workflow/validators/node-validator.ts +125 -0
- package/src/commands/workflow/validators/nodes/agent-node-validator.ts +58 -0
- package/src/commands/workflow/validators/nodes/condition-node-validator.ts +34 -0
- package/src/commands/workflow/validators/nodes/decorator-node-validator.ts +45 -0
- package/src/commands/workflow/validators/nodes/merge-node-validator.ts +46 -0
- package/src/commands/workflow/validators/nodes/skill-node-validator.ts +33 -0
- package/src/commands/workflow/validators/nodes/tool-node-validator.ts +54 -0
- package/src/commands/workflow/validators/nodes/workflow-node-validator.ts +33 -0
- package/src/commands/workflow/validators/types.ts +78 -0
- package/src/commands/workflow/validators/workflow-validator.test.ts +273 -0
- package/src/commands/workflow/validators/workflow-validator.ts +320 -0
- package/src/index.ts +19 -0
- package/src/plugin/apply.ts +103 -0
- package/src/plugin/discover.ts +219 -0
- package/src/plugin/index.ts +45 -0
- package/src/plugin/registry.ts +272 -0
- package/src/plugin/types.ts +165 -0
- package/src/services/context-handler.service.test.ts +501 -0
- package/src/services/context-handler.service.ts +372 -0
- package/src/services/environment.service.commands-prompt.test.ts +167 -0
- package/src/services/environment.service.ts +656 -0
- package/src/services/output.service.test.ts +92 -0
- package/src/services/output.service.ts +122 -0
- package/src/services/quiet-mode.service.test.ts +114 -0
- package/src/services/quiet-mode.service.ts +81 -0
- package/src/services/stream-output.service.test.ts +214 -0
- package/src/services/stream-output.service.ts +323 -0
- package/src/util/which.test.ts +101 -0
- package/src/util/which.ts +55 -0
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Skills Search Command
|
|
3
|
+
*
|
|
4
|
+
* 命令:roy skills search <term>
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { CommandModule } from "yargs";
|
|
8
|
+
import { EnvironmentService } from "../../services/environment.service";
|
|
9
|
+
import { OutputService } from "../../services/output.service";
|
|
10
|
+
import chalk from "chalk";
|
|
11
|
+
import type { SkillComponent, SkillListItem } from "@ai-setting/roy-agent-core";
|
|
12
|
+
|
|
13
|
+
interface SearchOptions {
|
|
14
|
+
term: string;
|
|
15
|
+
json?: boolean;
|
|
16
|
+
quiet?: boolean;
|
|
17
|
+
config?: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const SearchCommand: CommandModule<object, SearchOptions> = {
|
|
21
|
+
command: "search <term>",
|
|
22
|
+
aliases: ["find"],
|
|
23
|
+
describe: "搜索技能(按名称或描述)",
|
|
24
|
+
|
|
25
|
+
builder: (yargs) =>
|
|
26
|
+
yargs
|
|
27
|
+
.positional("term", {
|
|
28
|
+
type: "string",
|
|
29
|
+
demandOption: true,
|
|
30
|
+
description: "搜索关键词",
|
|
31
|
+
})
|
|
32
|
+
.option("json", {
|
|
33
|
+
alias: "j",
|
|
34
|
+
type: "boolean",
|
|
35
|
+
default: false,
|
|
36
|
+
description: "JSON 输出",
|
|
37
|
+
})
|
|
38
|
+
.option("quiet", {
|
|
39
|
+
alias: "q",
|
|
40
|
+
type: "boolean",
|
|
41
|
+
default: false,
|
|
42
|
+
description: "简洁输出",
|
|
43
|
+
}),
|
|
44
|
+
|
|
45
|
+
async handler(args) {
|
|
46
|
+
const output = new OutputService();
|
|
47
|
+
const envService = new EnvironmentService(output);
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
await envService.create({ configPath: args.config });
|
|
51
|
+
const env = envService.getEnvironment();
|
|
52
|
+
if (!env) {
|
|
53
|
+
output.error("Failed to create environment");
|
|
54
|
+
process.exit(1);
|
|
55
|
+
}
|
|
56
|
+
const skillComponent = env.getComponent("skill") as SkillComponent | undefined;
|
|
57
|
+
|
|
58
|
+
if (!skillComponent) {
|
|
59
|
+
output.error("SkillComponent not available");
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const allSkills = skillComponent.getSkillList() as SkillListItem[];
|
|
64
|
+
const term = args.term.toLowerCase();
|
|
65
|
+
|
|
66
|
+
// 搜索匹配(name 或 description 包含 term)
|
|
67
|
+
const results = allSkills.filter((s: SkillListItem) =>
|
|
68
|
+
s.name.toLowerCase().includes(term) ||
|
|
69
|
+
s.description.toLowerCase().includes(term)
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
if (results.length === 0) {
|
|
73
|
+
output.log(chalk.yellow(`No skills found matching: ${args.term}`));
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (args.json) {
|
|
78
|
+
output.json({
|
|
79
|
+
results: results.map((s: SkillListItem) => ({
|
|
80
|
+
name: s.name,
|
|
81
|
+
description: s.description,
|
|
82
|
+
source: s.source,
|
|
83
|
+
matchedIn: s.name.toLowerCase().includes(term) ? "name" : "description",
|
|
84
|
+
})),
|
|
85
|
+
count: results.length,
|
|
86
|
+
term: args.term,
|
|
87
|
+
});
|
|
88
|
+
} else if (args.quiet) {
|
|
89
|
+
results.forEach((s: SkillListItem) => output.log(s.name));
|
|
90
|
+
} else {
|
|
91
|
+
output.log(chalk.bold(`Search results for "${args.term}":`));
|
|
92
|
+
output.log("");
|
|
93
|
+
|
|
94
|
+
const header = [
|
|
95
|
+
chalk.bold("Name"),
|
|
96
|
+
chalk.bold("Description"),
|
|
97
|
+
chalk.bold("Match"),
|
|
98
|
+
].join(" | ");
|
|
99
|
+
|
|
100
|
+
const rows = results.map((s: SkillListItem) => {
|
|
101
|
+
const matchedIn = s.name.toLowerCase().includes(term) ? "name" : "description";
|
|
102
|
+
const matchColor = matchedIn === "name" ? chalk.green : chalk.blue;
|
|
103
|
+
|
|
104
|
+
const desc = s.description.length > 40
|
|
105
|
+
? s.description.slice(0, 37) + "..."
|
|
106
|
+
: s.description;
|
|
107
|
+
|
|
108
|
+
return [
|
|
109
|
+
chalk.cyan(s.name),
|
|
110
|
+
desc,
|
|
111
|
+
matchColor(`[${matchedIn}]`),
|
|
112
|
+
].join(" | ");
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
output.log([
|
|
116
|
+
`┌─ Skills ${"─".repeat(55)}┐`,
|
|
117
|
+
`│${header}│`,
|
|
118
|
+
"├" + "─".repeat(header.length + 2) + "┤",
|
|
119
|
+
...rows.map(r => `│${r}│`),
|
|
120
|
+
"└" + "─".repeat(header.length + 2) + "┘",
|
|
121
|
+
"",
|
|
122
|
+
chalk.gray(`${results.length} matching skill(s) found.`),
|
|
123
|
+
].join("\n"));
|
|
124
|
+
}
|
|
125
|
+
} catch (error) {
|
|
126
|
+
output.error(`Failed to search skills: ${error}`);
|
|
127
|
+
process.exit(1);
|
|
128
|
+
} finally {
|
|
129
|
+
await envService.dispose();
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
};
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Skills Show Config Command
|
|
3
|
+
*
|
|
4
|
+
* 命令:roy skills show-config
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { CommandModule } from "yargs";
|
|
8
|
+
import { EnvironmentService } from "../../services/environment.service";
|
|
9
|
+
import { OutputService } from "../../services/output.service";
|
|
10
|
+
import chalk from "chalk";
|
|
11
|
+
import type { SkillComponent, SkillConfig } from "@ai-setting/roy-agent-core";
|
|
12
|
+
|
|
13
|
+
interface ShowConfigOptions {
|
|
14
|
+
config?: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const ShowConfigCommand: CommandModule<object, ShowConfigOptions> = {
|
|
18
|
+
command: "show-config",
|
|
19
|
+
aliases: ["config"],
|
|
20
|
+
describe: "显示技能配置信息",
|
|
21
|
+
|
|
22
|
+
builder: (yargs) =>
|
|
23
|
+
yargs
|
|
24
|
+
.option("config", {
|
|
25
|
+
type: "string",
|
|
26
|
+
description: "配置文件路径",
|
|
27
|
+
}),
|
|
28
|
+
|
|
29
|
+
async handler(args) {
|
|
30
|
+
const output = new OutputService();
|
|
31
|
+
const envService = new EnvironmentService(output);
|
|
32
|
+
|
|
33
|
+
try {
|
|
34
|
+
await envService.create({ configPath: args.config });
|
|
35
|
+
const env = envService.getEnvironment();
|
|
36
|
+
if (!env) {
|
|
37
|
+
output.error("Failed to create environment");
|
|
38
|
+
process.exit(1);
|
|
39
|
+
}
|
|
40
|
+
const skillComponent = env.getComponent("skill") as SkillComponent | undefined;
|
|
41
|
+
|
|
42
|
+
if (!skillComponent) {
|
|
43
|
+
output.error("SkillComponent not available");
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// SkillComponent 当前使用默认配置,还没有从配置系统读取
|
|
48
|
+
// 这里展示的是默认配置路径
|
|
49
|
+
const defaultConfig = skillComponent.getConfig?.();
|
|
50
|
+
|
|
51
|
+
output.log(chalk.bold.cyan("# Skills Configuration\n"));
|
|
52
|
+
|
|
53
|
+
// 扫描路径
|
|
54
|
+
output.log(chalk.bold("## Scan Paths\n"));
|
|
55
|
+
|
|
56
|
+
const paths = [
|
|
57
|
+
{ type: "user", desc: "用户路径", path: "~/.config/roy-agent/skills/" },
|
|
58
|
+
{ type: "project", desc: "项目路径", path: ".roy/skills/" },
|
|
59
|
+
];
|
|
60
|
+
|
|
61
|
+
for (const p of paths) {
|
|
62
|
+
const typeColor = p.type === "project" ? chalk.green : chalk.blue;
|
|
63
|
+
output.log(` ${typeColor("[ " + p.type + " ]")} ${chalk.gray(p.desc)}`);
|
|
64
|
+
output.log(` ${chalk.cyan(p.path)}\n`);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// 扫描规则
|
|
68
|
+
output.log(chalk.bold("## Scan Rules\n"));
|
|
69
|
+
output.log(` ${chalk.gray("Pattern:")} ${chalk.cyan("**/SKILL.md")}`);
|
|
70
|
+
output.log(` ${chalk.gray("Recursive:")} ${chalk.green("true")}`);
|
|
71
|
+
output.log(` ${chalk.gray("Ignore:")} ${chalk.cyan("**/node_modules/**")}\n`);
|
|
72
|
+
|
|
73
|
+
// 优先级说明
|
|
74
|
+
output.log(chalk.bold("## Priority (High to Low)\n"));
|
|
75
|
+
output.log(` ${chalk.green("1. project")} - 项目路径(最高优先级)`);
|
|
76
|
+
output.log(` ${chalk.blue("2. user")} - 用户路径`);
|
|
77
|
+
output.log(` ${chalk.gray("3. built-in")} - 内置路径(预留)\n`);
|
|
78
|
+
|
|
79
|
+
// 使用提示
|
|
80
|
+
output.log(chalk.bold("## Usage\n"));
|
|
81
|
+
output.log(` ${chalk.cyan("roy skills list")} ${chalk.gray("- 列出所有技能")}`);
|
|
82
|
+
output.log(` ${chalk.cyan("roy skills get <name>")} ${chalk.gray("- 获取技能内容")}`);
|
|
83
|
+
output.log(` ${chalk.cyan("roy skills search <term>")} ${chalk.gray("- 搜索技能")}`);
|
|
84
|
+
output.log(` ${chalk.cyan("roy skills reload")} ${chalk.gray("- 重新扫描技能")}`);
|
|
85
|
+
|
|
86
|
+
} catch (error) {
|
|
87
|
+
output.error(`Failed to show config: ${error}`);
|
|
88
|
+
process.exit(1);
|
|
89
|
+
} finally {
|
|
90
|
+
await envService.dispose();
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
};
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Tasks Complete Command
|
|
3
|
+
*
|
|
4
|
+
* 命令:roy tasks complete <task-id>
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { CommandModule } from "yargs";
|
|
8
|
+
import { EnvironmentService } from "../../services/environment.service";
|
|
9
|
+
import { OutputService } from "../../services/output.service";
|
|
10
|
+
import chalk from "chalk";
|
|
11
|
+
import type {
|
|
12
|
+
SessionComponent,
|
|
13
|
+
TaskComponent,
|
|
14
|
+
Task,
|
|
15
|
+
} from "@ai-setting/roy-agent-core";
|
|
16
|
+
|
|
17
|
+
interface CompleteOptions {
|
|
18
|
+
id: number;
|
|
19
|
+
json?: boolean;
|
|
20
|
+
config?: string;
|
|
21
|
+
plugin?: string[];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export const CompleteCommand: CommandModule<object, CompleteOptions> = {
|
|
25
|
+
command: "complete <id>",
|
|
26
|
+
aliases: ["done", "finish"],
|
|
27
|
+
describe: "完成任务",
|
|
28
|
+
|
|
29
|
+
builder: (yargs) =>
|
|
30
|
+
yargs
|
|
31
|
+
.positional("id", {
|
|
32
|
+
type: "number",
|
|
33
|
+
describe: "任务 ID",
|
|
34
|
+
demandOption: true,
|
|
35
|
+
})
|
|
36
|
+
.option("json", { alias: "j", type: "boolean", default: false, description: "JSON 输出" })
|
|
37
|
+
.option("plugin", {
|
|
38
|
+
alias: "p",
|
|
39
|
+
type: "string",
|
|
40
|
+
array: true,
|
|
41
|
+
description: "Enable plugin (e.g., --plugin task-tag)",
|
|
42
|
+
}),
|
|
43
|
+
|
|
44
|
+
async handler(args) {
|
|
45
|
+
const output = new OutputService();
|
|
46
|
+
const envService = new EnvironmentService(output);
|
|
47
|
+
|
|
48
|
+
try {
|
|
49
|
+
// 传递 plugin 选项到 EnvironmentService
|
|
50
|
+
await envService.create({
|
|
51
|
+
configPath: args.config,
|
|
52
|
+
plugins: args.plugin,
|
|
53
|
+
});
|
|
54
|
+
const env = envService.getEnvironment();
|
|
55
|
+
if (!env) {
|
|
56
|
+
output.error("Failed to create environment");
|
|
57
|
+
process.exit(1);
|
|
58
|
+
}
|
|
59
|
+
const sessionComponent = env.getComponent("session") as SessionComponent | undefined;
|
|
60
|
+
const taskComponent = env.getComponent("task") as TaskComponent | undefined;
|
|
61
|
+
|
|
62
|
+
if (!taskComponent) {
|
|
63
|
+
output.error("TaskComponent not available");
|
|
64
|
+
process.exit(1);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Get current session ID
|
|
68
|
+
const currentSessionId = sessionComponent?.getActiveSessionId() || "cli";
|
|
69
|
+
|
|
70
|
+
const task: Task | undefined = await taskComponent.completeTask(args.id, currentSessionId);
|
|
71
|
+
|
|
72
|
+
if (!task) {
|
|
73
|
+
output.error(`Task not found: ${args.id}`);
|
|
74
|
+
process.exit(1);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (args.json) {
|
|
78
|
+
output.json(task);
|
|
79
|
+
} else {
|
|
80
|
+
output.log(chalk.green(`\n✓ Task completed: #${task.id}`));
|
|
81
|
+
output.log(` Title: ${task.title}`);
|
|
82
|
+
output.log(` Progress: ${task.progress}%`);
|
|
83
|
+
output.log(` Completed at: ${task.updatedAt}`);
|
|
84
|
+
}
|
|
85
|
+
} catch (error) {
|
|
86
|
+
output.error(`Failed to complete task: ${error}`);
|
|
87
|
+
process.exit(1);
|
|
88
|
+
} finally {
|
|
89
|
+
await envService.dispose();
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
};
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Tasks Create Command
|
|
3
|
+
*
|
|
4
|
+
* 命令:roy tasks create <title>
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { CommandModule } from "yargs";
|
|
8
|
+
import { EnvironmentService } from "../../services/environment.service";
|
|
9
|
+
import { OutputService } from "../../services/output.service";
|
|
10
|
+
import chalk from "chalk";
|
|
11
|
+
import type {
|
|
12
|
+
SessionComponent,
|
|
13
|
+
TaskComponent,
|
|
14
|
+
Task,
|
|
15
|
+
CreateTaskOptions,
|
|
16
|
+
TaskPriority,
|
|
17
|
+
} from "@ai-setting/roy-agent-core";
|
|
18
|
+
|
|
19
|
+
interface CreateOptions {
|
|
20
|
+
title: string;
|
|
21
|
+
description?: string;
|
|
22
|
+
priority?: string;
|
|
23
|
+
goals?: string;
|
|
24
|
+
due?: string;
|
|
25
|
+
tags?: string;
|
|
26
|
+
json?: boolean;
|
|
27
|
+
config?: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export const CreateCommand: CommandModule<object, CreateOptions> = {
|
|
31
|
+
command: "create <title>",
|
|
32
|
+
aliases: ["add", "new"],
|
|
33
|
+
describe: "创建新任务",
|
|
34
|
+
|
|
35
|
+
builder: (yargs) =>
|
|
36
|
+
yargs
|
|
37
|
+
.positional("title", {
|
|
38
|
+
type: "string",
|
|
39
|
+
describe: "任务标题",
|
|
40
|
+
demandOption: true,
|
|
41
|
+
})
|
|
42
|
+
.option("description", {
|
|
43
|
+
alias: "d",
|
|
44
|
+
type: "string",
|
|
45
|
+
description: "任务描述",
|
|
46
|
+
})
|
|
47
|
+
.option("priority", {
|
|
48
|
+
alias: "p",
|
|
49
|
+
type: "string",
|
|
50
|
+
choices: ["low", "medium", "high"],
|
|
51
|
+
default: "medium",
|
|
52
|
+
description: "优先级",
|
|
53
|
+
})
|
|
54
|
+
.option("goals", {
|
|
55
|
+
alias: "g",
|
|
56
|
+
type: "string",
|
|
57
|
+
description: "目标和预期产出",
|
|
58
|
+
})
|
|
59
|
+
.option("due", {
|
|
60
|
+
type: "string",
|
|
61
|
+
description: "截止日期 (ISO 格式)",
|
|
62
|
+
})
|
|
63
|
+
.option("tags", {
|
|
64
|
+
type: "string",
|
|
65
|
+
description: "标签 (逗号分隔)",
|
|
66
|
+
})
|
|
67
|
+
.option("json", { alias: "j", type: "boolean", default: false, description: "JSON 输出" }),
|
|
68
|
+
|
|
69
|
+
async handler(args) {
|
|
70
|
+
const output = new OutputService();
|
|
71
|
+
const envService = new EnvironmentService(output);
|
|
72
|
+
|
|
73
|
+
try {
|
|
74
|
+
await envService.create({ configPath: args.config });
|
|
75
|
+
const env = envService.getEnvironment();
|
|
76
|
+
if (!env) {
|
|
77
|
+
output.error("Failed to create environment");
|
|
78
|
+
process.exit(1);
|
|
79
|
+
}
|
|
80
|
+
const sessionComponent = env.getComponent("session") as SessionComponent | undefined;
|
|
81
|
+
const taskComponent = env.getComponent("task") as TaskComponent | undefined;
|
|
82
|
+
|
|
83
|
+
if (!taskComponent) {
|
|
84
|
+
output.error("TaskComponent not available");
|
|
85
|
+
process.exit(1);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Get current session ID
|
|
89
|
+
const currentSessionId = sessionComponent?.getActiveSessionId() || "cli";
|
|
90
|
+
|
|
91
|
+
const createOptions: CreateTaskOptions = {
|
|
92
|
+
title: args.title,
|
|
93
|
+
description: args.description,
|
|
94
|
+
priority: args.priority as TaskPriority,
|
|
95
|
+
goals_and_expected_deliverables: args.goals,
|
|
96
|
+
due_date: args.due,
|
|
97
|
+
tags: args.tags ? args.tags.split(",").map(t => t.trim()) : undefined,
|
|
98
|
+
sessionId: currentSessionId,
|
|
99
|
+
};
|
|
100
|
+
const task: Task = await taskComponent.createTask(createOptions);
|
|
101
|
+
|
|
102
|
+
if (args.json) {
|
|
103
|
+
output.json(task);
|
|
104
|
+
} else {
|
|
105
|
+
output.log(chalk.green(`\n✓ Task created: #${task.id}`));
|
|
106
|
+
output.log(` Title: ${task.title}`);
|
|
107
|
+
output.log(` Status: ${task.status}`);
|
|
108
|
+
output.log(` Priority: ${task.priority}`);
|
|
109
|
+
output.log(` Created at: ${task.createdAt}`);
|
|
110
|
+
}
|
|
111
|
+
} catch (error) {
|
|
112
|
+
output.error(`Failed to create task: ${error}`);
|
|
113
|
+
process.exit(1);
|
|
114
|
+
} finally {
|
|
115
|
+
await envService.dispose();
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
};
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Tasks Delete Command
|
|
3
|
+
*
|
|
4
|
+
* 命令:roy tasks delete <task-id>
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { CommandModule } from "yargs";
|
|
8
|
+
import { EnvironmentService } from "../../services/environment.service";
|
|
9
|
+
import { OutputService } from "../../services/output.service";
|
|
10
|
+
import chalk from "chalk";
|
|
11
|
+
import type { TaskComponent, Task } from "@ai-setting/roy-agent-core";
|
|
12
|
+
|
|
13
|
+
interface DeleteOptions {
|
|
14
|
+
id: number;
|
|
15
|
+
force?: boolean;
|
|
16
|
+
config?: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const DeleteCommand: CommandModule<object, DeleteOptions> = {
|
|
20
|
+
command: "delete <id>",
|
|
21
|
+
aliases: ["remove", "rm", "del"],
|
|
22
|
+
describe: "删除任务",
|
|
23
|
+
|
|
24
|
+
builder: (yargs) =>
|
|
25
|
+
yargs
|
|
26
|
+
.positional("id", {
|
|
27
|
+
type: "number",
|
|
28
|
+
describe: "任务 ID",
|
|
29
|
+
demandOption: true,
|
|
30
|
+
})
|
|
31
|
+
.option("force", {
|
|
32
|
+
alias: "f",
|
|
33
|
+
type: "boolean",
|
|
34
|
+
default: false,
|
|
35
|
+
description: "强制删除,不确认"
|
|
36
|
+
}),
|
|
37
|
+
|
|
38
|
+
async handler(args) {
|
|
39
|
+
const output = new OutputService();
|
|
40
|
+
const envService = new EnvironmentService(output);
|
|
41
|
+
|
|
42
|
+
try {
|
|
43
|
+
await envService.create({ configPath: args.config });
|
|
44
|
+
const env = envService.getEnvironment();
|
|
45
|
+
if (!env) {
|
|
46
|
+
output.error("Failed to create environment");
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
49
|
+
const taskComponent = env.getComponent("task") as TaskComponent | undefined;
|
|
50
|
+
|
|
51
|
+
if (!taskComponent) {
|
|
52
|
+
output.error("TaskComponent not available");
|
|
53
|
+
process.exit(1);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Check if task exists
|
|
57
|
+
const task: Task | undefined = await taskComponent.getTask(args.id);
|
|
58
|
+
if (!task) {
|
|
59
|
+
output.error(`Task not found: ${args.id}`);
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (!args.force) {
|
|
64
|
+
output.log(chalk.yellow(`Are you sure you want to delete task #${args.id}?`));
|
|
65
|
+
output.log(chalk.yellow(` Title: ${task.title}`));
|
|
66
|
+
output.log(chalk.yellow(` Status: ${task.status}`));
|
|
67
|
+
output.log(chalk.yellow(`\nUse --force to skip this confirmation`));
|
|
68
|
+
process.exit(1);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const deleted = await taskComponent.deleteTask(args.id);
|
|
72
|
+
|
|
73
|
+
if (deleted) {
|
|
74
|
+
output.log(chalk.green(`\n✓ Task deleted: #${args.id}`));
|
|
75
|
+
} else {
|
|
76
|
+
output.error(`Failed to delete task: ${args.id}`);
|
|
77
|
+
process.exit(1);
|
|
78
|
+
}
|
|
79
|
+
} catch (error) {
|
|
80
|
+
output.error(`Failed to delete task: ${error}`);
|
|
81
|
+
process.exit(1);
|
|
82
|
+
} finally {
|
|
83
|
+
await envService.dispose();
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
};
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Tasks Get Command
|
|
3
|
+
*
|
|
4
|
+
* 命令:roy tasks get <task-id>
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { CommandModule } from "yargs";
|
|
8
|
+
import { EnvironmentService } from "../../services/environment.service";
|
|
9
|
+
import { OutputService } from "../../services/output.service";
|
|
10
|
+
import chalk from "chalk";
|
|
11
|
+
import type {
|
|
12
|
+
TaskComponent,
|
|
13
|
+
Task,
|
|
14
|
+
TaskOperation,
|
|
15
|
+
} from "@ai-setting/roy-agent-core";
|
|
16
|
+
|
|
17
|
+
interface GetOptions {
|
|
18
|
+
id: number;
|
|
19
|
+
operations?: boolean;
|
|
20
|
+
json?: boolean;
|
|
21
|
+
config?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export const GetCommand: CommandModule<object, GetOptions> = {
|
|
25
|
+
command: "get <id>",
|
|
26
|
+
aliases: ["show"],
|
|
27
|
+
describe: "获取任务详情",
|
|
28
|
+
|
|
29
|
+
builder: (yargs) =>
|
|
30
|
+
yargs
|
|
31
|
+
.positional("id", {
|
|
32
|
+
type: "number",
|
|
33
|
+
describe: "任务 ID",
|
|
34
|
+
demandOption: true,
|
|
35
|
+
})
|
|
36
|
+
.option("operations", {
|
|
37
|
+
alias: "o",
|
|
38
|
+
type: "boolean",
|
|
39
|
+
default: false,
|
|
40
|
+
description: "包含操作记录",
|
|
41
|
+
})
|
|
42
|
+
.option("json", { alias: "j", type: "boolean", default: false, description: "JSON 输出" }),
|
|
43
|
+
|
|
44
|
+
async handler(args) {
|
|
45
|
+
const output = new OutputService();
|
|
46
|
+
const envService = new EnvironmentService(output);
|
|
47
|
+
|
|
48
|
+
try {
|
|
49
|
+
await envService.create({ configPath: args.config });
|
|
50
|
+
const env = envService.getEnvironment();
|
|
51
|
+
if (!env) {
|
|
52
|
+
output.error("Failed to create environment");
|
|
53
|
+
process.exit(1);
|
|
54
|
+
}
|
|
55
|
+
const taskComponent = env.getComponent("task") as TaskComponent | undefined;
|
|
56
|
+
|
|
57
|
+
if (!taskComponent) {
|
|
58
|
+
output.error("TaskComponent not available");
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (args.operations) {
|
|
63
|
+
const result = await taskComponent.getTaskWithOperations(args.id);
|
|
64
|
+
if (!result) {
|
|
65
|
+
output.error(`Task not found: ${args.id}`);
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (args.json) {
|
|
70
|
+
output.json(result);
|
|
71
|
+
} else {
|
|
72
|
+
output.log(chalk.bold(`\nTask #${result.task.id}: ${result.task.title}\n`));
|
|
73
|
+
output.log(`Status: ${chalk.blue(result.task.status)} | Priority: ${result.task.priority} | Progress: ${result.task.progress}%`);
|
|
74
|
+
output.log(`Created: ${result.task.createdAt} | Updated: ${result.task.updatedAt}`);
|
|
75
|
+
if (result.task.current_status) {
|
|
76
|
+
output.log(`\nCurrent Status: ${result.task.current_status}`);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
output.log(chalk.bold(`\nOperations (${result.operations.length}):\n`));
|
|
80
|
+
result.operations.forEach((op: TaskOperation, i: number) => {
|
|
81
|
+
output.log(` ${i + 1}. [${op.actionType}] ${op.actionTitle}`);
|
|
82
|
+
output.log(` Session: ${op.sessionId} | Time: ${op.timestamp}`);
|
|
83
|
+
if (op.actionDescription) {
|
|
84
|
+
output.log(` ${op.actionDescription}`);
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
} else {
|
|
89
|
+
const task: Task | undefined = await taskComponent.getTask(args.id);
|
|
90
|
+
if (!task) {
|
|
91
|
+
output.error(`Task not found: ${args.id}`);
|
|
92
|
+
process.exit(1);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (args.json) {
|
|
96
|
+
output.json(task);
|
|
97
|
+
} else {
|
|
98
|
+
output.log(chalk.bold(`\nTask #${task.id}: ${task.title}\n`));
|
|
99
|
+
output.log(`Status: ${chalk.blue(task.status)} | Priority: ${task.priority} | Progress: ${task.progress}%`);
|
|
100
|
+
output.log(`Created: ${task.createdAt} | Updated: ${task.updatedAt}`);
|
|
101
|
+
if (task.current_status) {
|
|
102
|
+
output.log(`\nCurrent Status: ${task.current_status}`);
|
|
103
|
+
}
|
|
104
|
+
if (task.description) {
|
|
105
|
+
output.log(`\nDescription: ${task.description}`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
} catch (error) {
|
|
110
|
+
output.error(`Failed to get task: ${error}`);
|
|
111
|
+
process.exit(1);
|
|
112
|
+
} finally {
|
|
113
|
+
await envService.dispose();
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Tasks Command Entry
|
|
3
|
+
*
|
|
4
|
+
* 命令入口:roy tasks [action]
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { CommandModule } from "yargs";
|
|
8
|
+
import { ListCommand } from "./list";
|
|
9
|
+
import { GetCommand } from "./get";
|
|
10
|
+
import { CreateCommand } from "./create";
|
|
11
|
+
import { UpdateCommand } from "./update";
|
|
12
|
+
import { DeleteCommand } from "./delete";
|
|
13
|
+
import { CompleteCommand } from "./complete";
|
|
14
|
+
import { OperationsCommand } from "./operations";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Tasks Command
|
|
18
|
+
*
|
|
19
|
+
* 任务管理命令,提供以下子命令:
|
|
20
|
+
* - list: 列出所有任务
|
|
21
|
+
* - get: 获取任务详情
|
|
22
|
+
* - create: 创建任务
|
|
23
|
+
* - update: 更新任务
|
|
24
|
+
* - delete: 删除任务
|
|
25
|
+
* - complete: 完成任务
|
|
26
|
+
* - operations: 操作记录管理
|
|
27
|
+
*/
|
|
28
|
+
export const TasksCommand: CommandModule = {
|
|
29
|
+
command: "tasks",
|
|
30
|
+
describe: "任务管理 - 创建、追踪、管理任务",
|
|
31
|
+
builder: (yargs) =>
|
|
32
|
+
yargs
|
|
33
|
+
// 传递全局 plugin 选项到子命令
|
|
34
|
+
.option("plugin", {
|
|
35
|
+
alias: "p",
|
|
36
|
+
type: "string",
|
|
37
|
+
array: true,
|
|
38
|
+
description: "Enable plugin (e.g., --plugin task-tag)",
|
|
39
|
+
global: false, // 不再是 global,避免重复
|
|
40
|
+
})
|
|
41
|
+
.command(ListCommand)
|
|
42
|
+
.command(GetCommand)
|
|
43
|
+
.command(CreateCommand)
|
|
44
|
+
.command(UpdateCommand)
|
|
45
|
+
.command(DeleteCommand)
|
|
46
|
+
.command(CompleteCommand)
|
|
47
|
+
.command(OperationsCommand)
|
|
48
|
+
.demandCommand()
|
|
49
|
+
.help(),
|
|
50
|
+
handler: () => {
|
|
51
|
+
console.log("Use 'roy tasks --help' for usage information");
|
|
52
|
+
},
|
|
53
|
+
};
|