@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.
Files changed (158) hide show
  1. package/README.md +126 -0
  2. package/dist/bin/roy.js +127297 -0
  3. package/dist/roy-agent-darwin-arm64/bin/roy.js +127297 -0
  4. package/dist/roy-agent-darwin-x64/bin/roy.js +127297 -0
  5. package/dist/roy-agent-linux-arm64/bin/roy.js +127297 -0
  6. package/dist/roy-agent-linux-x64/bin/roy.js +127297 -0
  7. package/dist/roy-agent-windows-x64/bin/roy.js +127297 -0
  8. package/package.json +91 -0
  9. package/src/bin/roy.ts +12 -0
  10. package/src/cli.ts +101 -0
  11. package/src/commands/act.ts +480 -0
  12. package/src/commands/commands-add.ts +110 -0
  13. package/src/commands/commands-dirs.ts +70 -0
  14. package/src/commands/commands-info.ts +90 -0
  15. package/src/commands/commands-list.ts +161 -0
  16. package/src/commands/commands-remove.ts +147 -0
  17. package/src/commands/commands.ts +55 -0
  18. package/src/commands/config/config-service.test.ts +449 -0
  19. package/src/commands/config/config-service.ts +312 -0
  20. package/src/commands/config/deep-merge.test.ts +168 -0
  21. package/src/commands/config/deep-merge.ts +63 -0
  22. package/src/commands/config/export.ts +97 -0
  23. package/src/commands/config/filter-history-e2e.test.ts +141 -0
  24. package/src/commands/config/import-preserve-refs.test.ts +212 -0
  25. package/src/commands/config/import.ts +119 -0
  26. package/src/commands/config/index.ts +35 -0
  27. package/src/commands/config/list.ts +281 -0
  28. package/src/commands/config/roy-config-e2e.test.ts +297 -0
  29. package/src/commands/config/types.ts +54 -0
  30. package/src/commands/debug/index.ts +38 -0
  31. package/src/commands/debug/log.test.ts +233 -0
  32. package/src/commands/debug/log.ts +123 -0
  33. package/src/commands/debug/span.test.ts +297 -0
  34. package/src/commands/debug/span.ts +211 -0
  35. package/src/commands/debug/trace.test.ts +254 -0
  36. package/src/commands/debug/trace.ts +140 -0
  37. package/src/commands/eventsource/add.ts +133 -0
  38. package/src/commands/eventsource/index.ts +48 -0
  39. package/src/commands/eventsource/list.ts +194 -0
  40. package/src/commands/eventsource/remove.ts +95 -0
  41. package/src/commands/eventsource/start.ts +103 -0
  42. package/src/commands/eventsource/status.ts +185 -0
  43. package/src/commands/eventsource/stop.ts +89 -0
  44. package/src/commands/index.ts +22 -0
  45. package/src/commands/input-handler.test.ts +76 -0
  46. package/src/commands/input-handler.ts +43 -0
  47. package/src/commands/interactive-esc.test.ts +254 -0
  48. package/src/commands/interactive.shutdown.test.ts +122 -0
  49. package/src/commands/interactive.test.ts +221 -0
  50. package/src/commands/interactive.ts +1015 -0
  51. package/src/commands/lsp/check.ts +92 -0
  52. package/src/commands/lsp/index.ts +32 -0
  53. package/src/commands/lsp/install.ts +126 -0
  54. package/src/commands/lsp/list.ts +64 -0
  55. package/src/commands/mcp/index.ts +27 -0
  56. package/src/commands/mcp/list.ts +116 -0
  57. package/src/commands/mcp/reload.ts +70 -0
  58. package/src/commands/mcp/tools.ts +121 -0
  59. package/src/commands/memory/extract-e2e.test.ts +388 -0
  60. package/src/commands/memory/index.ts +11 -0
  61. package/src/commands/memory/memory-simplified.test.ts +58 -0
  62. package/src/commands/memory/memory.ts +25 -0
  63. package/src/commands/memory/organize.ts +300 -0
  64. package/src/commands/memory/recall.test.ts +120 -0
  65. package/src/commands/memory/recall.ts +88 -0
  66. package/src/commands/memory/record-extract-handle-query.test.ts +385 -0
  67. package/src/commands/memory/record-prompt-component.test.ts +343 -0
  68. package/src/commands/memory/record.test.ts +92 -0
  69. package/src/commands/memory/record.ts +332 -0
  70. package/src/commands/plugin.test.ts +292 -0
  71. package/src/commands/plugin.ts +267 -0
  72. package/src/commands/sessions/active.ts +96 -0
  73. package/src/commands/sessions/add-message.ts +96 -0
  74. package/src/commands/sessions/checkpoints.ts +154 -0
  75. package/src/commands/sessions/compact.test.ts +215 -0
  76. package/src/commands/sessions/compact.ts +269 -0
  77. package/src/commands/sessions/delete.ts +236 -0
  78. package/src/commands/sessions/get.ts +165 -0
  79. package/src/commands/sessions/grep.ts +233 -0
  80. package/src/commands/sessions/index.ts +95 -0
  81. package/src/commands/sessions/list.ts +210 -0
  82. package/src/commands/sessions/messages.test.ts +333 -0
  83. package/src/commands/sessions/messages.ts +248 -0
  84. package/src/commands/sessions/mock.ts +194 -0
  85. package/src/commands/sessions/new.ts +82 -0
  86. package/src/commands/sessions/rename.ts +98 -0
  87. package/src/commands/shared/event-handler.ts +213 -0
  88. package/src/commands/shared/event-message-formatter.ts +295 -0
  89. package/src/commands/shared/index.ts +11 -0
  90. package/src/commands/shared/query-executor.test.ts +434 -0
  91. package/src/commands/shared/query-executor.ts +324 -0
  92. package/src/commands/shared/repl-engine.test.ts +354 -0
  93. package/src/commands/shared/session-manager.test.ts +212 -0
  94. package/src/commands/shared/session-manager.ts +114 -0
  95. package/src/commands/skills/get.ts +90 -0
  96. package/src/commands/skills/index.ts +39 -0
  97. package/src/commands/skills/list.ts +129 -0
  98. package/src/commands/skills/reload.ts +59 -0
  99. package/src/commands/skills/search.ts +132 -0
  100. package/src/commands/skills/show-config.ts +93 -0
  101. package/src/commands/tasks/complete.ts +92 -0
  102. package/src/commands/tasks/create.ts +118 -0
  103. package/src/commands/tasks/delete.ts +86 -0
  104. package/src/commands/tasks/get.ts +116 -0
  105. package/src/commands/tasks/index.ts +53 -0
  106. package/src/commands/tasks/list.ts +140 -0
  107. package/src/commands/tasks/operations.ts +120 -0
  108. package/src/commands/tasks/update.ts +122 -0
  109. package/src/commands/tools/exec-tool.ts +128 -0
  110. package/src/commands/tools/get.ts +114 -0
  111. package/src/commands/tools/index.ts +35 -0
  112. package/src/commands/tools/list.ts +107 -0
  113. package/src/commands/tools/shared/index.ts +7 -0
  114. package/src/commands/tools/shared/schema-helper.ts +111 -0
  115. package/src/commands/workflow/commands/add.ts +315 -0
  116. package/src/commands/workflow/commands/get.ts +193 -0
  117. package/src/commands/workflow/commands/list.ts +137 -0
  118. package/src/commands/workflow/commands/nodes.ts +528 -0
  119. package/src/commands/workflow/commands/remove.ts +94 -0
  120. package/src/commands/workflow/commands/run.ts +398 -0
  121. package/src/commands/workflow/commands/status.ts +147 -0
  122. package/src/commands/workflow/commands/stop.ts +91 -0
  123. package/src/commands/workflow/commands/update.ts +130 -0
  124. package/src/commands/workflow/commands/validate.ts +139 -0
  125. package/src/commands/workflow/commands/workflow-cli.test.ts +196 -0
  126. package/src/commands/workflow/index.ts +65 -0
  127. package/src/commands/workflow/renderers.ts +358 -0
  128. package/src/commands/workflow/validators/index.ts +8 -0
  129. package/src/commands/workflow/validators/node-validator-factory.ts +40 -0
  130. package/src/commands/workflow/validators/node-validator.ts +125 -0
  131. package/src/commands/workflow/validators/nodes/agent-node-validator.ts +58 -0
  132. package/src/commands/workflow/validators/nodes/condition-node-validator.ts +34 -0
  133. package/src/commands/workflow/validators/nodes/decorator-node-validator.ts +45 -0
  134. package/src/commands/workflow/validators/nodes/merge-node-validator.ts +46 -0
  135. package/src/commands/workflow/validators/nodes/skill-node-validator.ts +33 -0
  136. package/src/commands/workflow/validators/nodes/tool-node-validator.ts +54 -0
  137. package/src/commands/workflow/validators/nodes/workflow-node-validator.ts +33 -0
  138. package/src/commands/workflow/validators/types.ts +78 -0
  139. package/src/commands/workflow/validators/workflow-validator.test.ts +273 -0
  140. package/src/commands/workflow/validators/workflow-validator.ts +320 -0
  141. package/src/index.ts +19 -0
  142. package/src/plugin/apply.ts +103 -0
  143. package/src/plugin/discover.ts +219 -0
  144. package/src/plugin/index.ts +45 -0
  145. package/src/plugin/registry.ts +272 -0
  146. package/src/plugin/types.ts +165 -0
  147. package/src/services/context-handler.service.test.ts +501 -0
  148. package/src/services/context-handler.service.ts +372 -0
  149. package/src/services/environment.service.commands-prompt.test.ts +167 -0
  150. package/src/services/environment.service.ts +656 -0
  151. package/src/services/output.service.test.ts +92 -0
  152. package/src/services/output.service.ts +122 -0
  153. package/src/services/quiet-mode.service.test.ts +114 -0
  154. package/src/services/quiet-mode.service.ts +81 -0
  155. package/src/services/stream-output.service.test.ts +214 -0
  156. package/src/services/stream-output.service.ts +323 -0
  157. package/src/util/which.test.ts +101 -0
  158. package/src/util/which.ts +55 -0
@@ -0,0 +1,528 @@
1
+ /**
2
+ * @fileoverview Workflow Nodes Command
3
+ *
4
+ * List all built-in node types with their input/output descriptions
5
+ */
6
+
7
+ import { CommandModule } from 'yargs';
8
+ import chalk from 'chalk';
9
+
10
+ export interface WorkflowNodesOptions {
11
+ type?: string;
12
+ }
13
+
14
+ /**
15
+ * Node type definition
16
+ */
17
+ export interface NodeDefinition {
18
+ name: string;
19
+ type: string;
20
+ description: string;
21
+ inputs: Array<{
22
+ name: string;
23
+ type: string;
24
+ required: boolean;
25
+ description: string;
26
+ }>;
27
+ output: string;
28
+ example?: string;
29
+ }
30
+
31
+ /**
32
+ * Common parameters supported by all node types
33
+ */
34
+ const COMMON_PARAMS = [
35
+ {
36
+ name: 'depends_on',
37
+ type: 'string[]',
38
+ required: false,
39
+ description: 'List of node IDs that must complete before this node runs',
40
+ },
41
+ {
42
+ name: 'timeout',
43
+ type: 'number',
44
+ required: false,
45
+ description: 'Execution timeout in milliseconds (default: 30000)',
46
+ },
47
+ {
48
+ name: 'retry',
49
+ type: 'object',
50
+ required: false,
51
+ description: 'Retry config: {max_attempts, backoff: "fixed"|"exponential", initial_delay}',
52
+ },
53
+ ];
54
+
55
+ /**
56
+ * Built-in node type definitions
57
+ */
58
+ export const BUILT_IN_NODES: NodeDefinition[] = [
59
+ // =========================================================================
60
+ // Tool Node
61
+ // =========================================================================
62
+ {
63
+ name: 'ToolNode',
64
+ type: 'tool',
65
+ description:
66
+ 'Execute a registered tool. Tools are atomic operations that perform specific tasks like bash, file operations, or API calls. Supports template resolution for input values.',
67
+ inputs: [
68
+ {
69
+ name: 'tool / toolName',
70
+ type: 'string',
71
+ required: true,
72
+ description: 'Name of the registered tool to execute (e.g., bash, read-file, web-search)',
73
+ },
74
+ {
75
+ name: 'input / args',
76
+ type: 'object',
77
+ required: false,
78
+ description: 'Key-value pairs passed to the tool (use input or args key). Supports template strings like {{nodes.nodeId.output}}',
79
+ },
80
+ {
81
+ name: 'command',
82
+ type: 'string',
83
+ required: false,
84
+ description: 'Single command string (for bash tool with {command: "..."} signature). Supports templates.',
85
+ },
86
+ {
87
+ name: 'message',
88
+ type: 'string',
89
+ required: false,
90
+ description: 'Single message string (for echo tool with {message: "..."} signature). Supports templates.',
91
+ },
92
+ ],
93
+ output: '{output: any, error?: Error, durationMs: number}',
94
+ example: `# Example 1: Execute bash command
95
+ nodes:
96
+ run-tests:
97
+ type: tool
98
+ config:
99
+ tool: bash
100
+ input:
101
+ command: "npm test"
102
+
103
+ # Example 2: Read file with template reference
104
+ nodes:
105
+ read-config:
106
+ type: tool
107
+ config:
108
+ tool: read-file
109
+ input:
110
+ path: "{{input.configPath}}"
111
+
112
+ # Example 3: Web search
113
+ nodes:
114
+ search:
115
+ type: tool
116
+ config:
117
+ tool: web-search
118
+ input:
119
+ query: "AI news"
120
+ numResults: 5`,
121
+ },
122
+
123
+ // =========================================================================
124
+ // Skill Node
125
+ // =========================================================================
126
+ {
127
+ name: 'SkillNode',
128
+ type: 'skill',
129
+ description:
130
+ 'Invoke a skill processor. Skills are higher-level operations that combine multiple tools and logic for complex tasks. Supports template resolution for input values.',
131
+ inputs: [
132
+ {
133
+ name: 'skill',
134
+ type: 'string',
135
+ required: true,
136
+ description: 'Name of the registered skill to invoke',
137
+ },
138
+ {
139
+ name: 'input',
140
+ type: 'object',
141
+ required: false,
142
+ description: 'Input parameters for the skill. Supports template strings like {{nodes.nodeId.output}}',
143
+ },
144
+ ],
145
+ output: '{output: any, error?: Error, durationMs: number}',
146
+ example: `# Example: Summarize text
147
+ nodes:
148
+ summarize:
149
+ type: skill
150
+ config:
151
+ skill: text-summarizer
152
+ input:
153
+ content: "{{nodes.fetch.output}}"
154
+ maxLength: 200
155
+
156
+ # Example: Code review
157
+ nodes:
158
+ review:
159
+ type: skill
160
+ config:
161
+ skill: code-reviewer
162
+ input:
163
+ code: "{{input.code}}"
164
+ language: "{{input.language}}"`,
165
+ },
166
+
167
+ // =========================================================================
168
+ // Agent Node
169
+ // =========================================================================
170
+ {
171
+ name: 'AgentNode',
172
+ type: 'agent',
173
+ description:
174
+ 'Run an AI agent with reasoning loop. Agents use LLM to reason, plan, and use tools for complex tasks. Supports workflow history for multi-agent collaboration. Prompt templates support {{input.key}} and {{nodes.nodeId.output}} interpolation.',
175
+ inputs: [
176
+ {
177
+ name: 'agent_type',
178
+ type: 'string',
179
+ required: true,
180
+ description: 'Agent type (e.g., general, research, coder, critic). Auto-registers if not found.',
181
+ },
182
+ {
183
+ name: 'prompt',
184
+ type: 'string',
185
+ required: true,
186
+ description: 'Prompt template (supports {{input.key}} and {{nodes.nodeId.output}} interpolation)',
187
+ },
188
+ {
189
+ name: 'options',
190
+ type: 'object',
191
+ required: false,
192
+ description: 'Execution options: {timeout?: number, model?: string}',
193
+ },
194
+ {
195
+ name: 'system_prompt / systemPrompt',
196
+ type: 'string',
197
+ required: false,
198
+ description: 'Custom system prompt for this agent (auto-generated if not provided)',
199
+ },
200
+ ],
201
+ output: '{result: any, metadata: {tokens?: number, duration?: number}, workflowHistory: [...]}',
202
+ example: `# Example: Research agent
203
+ nodes:
204
+ analyze:
205
+ type: agent
206
+ config:
207
+ agent_type: research
208
+ prompt: |
209
+ Based on the data: {{nodes.fetch.output}}
210
+ Please analyze and provide insights.
211
+ options:
212
+ timeout: 60000
213
+ model: "minimax"
214
+
215
+ # Example: Multi-agent with history
216
+ nodes:
217
+ planner:
218
+ type: agent
219
+ config:
220
+ agent_type: general
221
+ prompt: "Plan the implementation for {{input.task}}"
222
+
223
+ executor:
224
+ type: agent
225
+ config:
226
+ agent_type: coder
227
+ prompt: "Implement the plan: {{nodes.planner.output}}"
228
+ depends_on:
229
+ - planner`,
230
+ },
231
+
232
+ // =========================================================================
233
+ // Workflow Node (Sub-workflow)
234
+ // =========================================================================
235
+ {
236
+ name: 'WorkflowNode',
237
+ type: 'workflow',
238
+ description:
239
+ 'Execute a nested/sub workflow. Allows creating complex workflows by combining simpler ones. Supports template resolution for input values.',
240
+ inputs: [
241
+ {
242
+ name: 'workflow_name',
243
+ type: 'string',
244
+ required: true,
245
+ description: 'Name of the sub-workflow to execute',
246
+ },
247
+ {
248
+ name: 'input',
249
+ type: 'object',
250
+ required: false,
251
+ description: 'Input parameters for the sub-workflow. Supports template strings like {{nodes.nodeId.output}}',
252
+ },
253
+ {
254
+ name: 'wait_complete',
255
+ type: 'boolean',
256
+ required: false,
257
+ description: 'Whether to wait for sub-workflow completion (default: true)',
258
+ },
259
+ ],
260
+ output: '{success: boolean, output?: any, error?: string, duration: number}',
261
+ example: `# Example: Execute sub-workflow
262
+ nodes:
263
+ data-process:
264
+ type: workflow
265
+ config:
266
+ workflow_name: data-processor
267
+ input:
268
+ data: "{{nodes.fetch.output}}"
269
+
270
+ # Example: Sequential workflows
271
+ nodes:
272
+ step1:
273
+ type: workflow
274
+ config:
275
+ workflow_name: preprocessing
276
+ input:
277
+ raw: "{{input.data}}"
278
+
279
+ step2:
280
+ type: workflow
281
+ config:
282
+ workflow_name: analysis
283
+ input:
284
+ cleaned: "{{nodes.step1.output}}"
285
+ depends_on:
286
+ - step1`,
287
+ },
288
+
289
+ // =========================================================================
290
+ // Condition Node
291
+ // =========================================================================
292
+ {
293
+ name: 'ConditionNode',
294
+ type: 'condition',
295
+ description:
296
+ 'Evaluate a condition and decide workflow path. Supports boolean values, template expressions, and references to previous node outputs. Default to true if no condition specified.',
297
+ inputs: [
298
+ {
299
+ name: 'condition',
300
+ type: 'string | boolean',
301
+ required: false,
302
+ description: 'Condition to evaluate: boolean value, template {{nodeId.output.success}}, or template {{input.key}}. Defaults to true if not specified.',
303
+ },
304
+ ],
305
+ output: '{success: boolean, condition: resolved_value}',
306
+ example: `# Example: Check test results
307
+ nodes:
308
+ run-tests:
309
+ type: tool
310
+ config:
311
+ tool: bash
312
+ input:
313
+ command: "npm test"
314
+
315
+ check-result:
316
+ type: condition
317
+ config:
318
+ condition: "{{run-tests.output.success}}"
319
+ depends_on:
320
+ - run-tests
321
+
322
+ # Example: Check input value
323
+ nodes:
324
+ validate:
325
+ type: condition
326
+ config:
327
+ condition: "{{input.validate}}"
328
+ depends_on: []`,
329
+ },
330
+
331
+ // =========================================================================
332
+ // Merge Node
333
+ // =========================================================================
334
+ {
335
+ name: 'MergeNode',
336
+ type: 'merge',
337
+ description:
338
+ 'Collect and merge outputs from multiple dependency nodes. Supports strategies: collect (default), first, last, merge.',
339
+ inputs: [
340
+ {
341
+ name: 'strategy',
342
+ type: 'string',
343
+ required: false,
344
+ description: 'Merge strategy: collect (default, returns map), first (returns first output), last (returns last output), merge (deep merge objects)',
345
+ },
346
+ ],
347
+ output: '{strategy: string, results: any, count: number}',
348
+ example: `# Example: Collect parallel results
349
+ nodes:
350
+ parallel-fetch:
351
+ type: merge
352
+ config:
353
+ strategy: collect
354
+ depends_on:
355
+ - fetch-user
356
+ - fetch-orders
357
+ - fetch-preferences
358
+
359
+ # Example: Get first successful result
360
+ nodes:
361
+ first-success:
362
+ type: merge
363
+ config:
364
+ strategy: first
365
+ depends_on:
366
+ - primary-source
367
+ - backup-source
368
+
369
+ # Example: Merge objects
370
+ nodes:
371
+ merge-data:
372
+ type: merge
373
+ config:
374
+ strategy: merge
375
+ depends_on:
376
+ - metadata
377
+ - content
378
+ - analytics`,
379
+ },
380
+
381
+ // =========================================================================
382
+ // Decorator Node
383
+ // =========================================================================
384
+ {
385
+ name: 'DecoratorNode',
386
+ type: 'decorator',
387
+ description:
388
+ 'Execute a class method decorated with @Workflow or @NodeAs. Supports retry logic and timeout. Automatically extracts output from decorated methods.',
389
+ inputs: [
390
+ {
391
+ name: '_methodName',
392
+ type: 'string',
393
+ required: true,
394
+ description: 'Name of the decorated method to execute',
395
+ },
396
+ {
397
+ name: '_instance',
398
+ type: 'object',
399
+ required: true,
400
+ description: 'Class instance containing the decorated method',
401
+ },
402
+ {
403
+ name: 'retry',
404
+ type: 'object',
405
+ required: false,
406
+ description: 'Retry config: {max_attempts: number, backoff: "fixed"|"exponential", initial_delay: number}',
407
+ },
408
+ ],
409
+ output: '{success: boolean, output?: any, error?: string, duration: number, metadata: {methodName: string}}',
410
+ example: `# Example: Execute decorated method
411
+ nodes:
412
+ process-data:
413
+ type: decorator
414
+ config:
415
+ _methodName: "processData"
416
+ _instance: "{{input.workflowInstance}}"
417
+ timeout: 30000
418
+ retry:
419
+ max_attempts: 3
420
+ backoff: exponential
421
+ initial_delay: 1000
422
+ depends_on:
423
+ - fetch-data`,
424
+ },
425
+ ];
426
+
427
+ /**
428
+ * Render node types table
429
+ */
430
+ function renderNodeTypesTable(nodes: NodeDefinition[]): string {
431
+ const lines: string[] = [];
432
+
433
+ lines.push(chalk.bold('\n📦 Built-in Node Types\n'));
434
+ lines.push('┌────────────┬────────────────────┬─────────────────────────────────────────────────────────────┐');
435
+ lines.push('│ Type │ Name │ Description │');
436
+ lines.push('├────────────┼────────────────────┼─────────────────────────────────────────────────────────────┤');
437
+
438
+ for (const node of nodes) {
439
+ const type = node.type.padEnd(10);
440
+ const name = node.name.padEnd(18);
441
+ const desc = node.description.substring(0, 59).padEnd(59);
442
+ lines.push(`│ ${type} │ ${name} │ ${desc} │`);
443
+ }
444
+
445
+ lines.push('└────────────┴────────────────────┴─────────────────────────────────────────────────────────────┘');
446
+
447
+ return lines.join('\n');
448
+ }
449
+
450
+ /**
451
+ * Render detailed node information
452
+ */
453
+ function renderNodeDetail(node: NodeDefinition): string {
454
+ const lines: string[] = [];
455
+
456
+ lines.push(chalk.bold(`\n[${node.type}] ${node.name}`));
457
+ lines.push(chalk.dim('─'.repeat(60)) + '\n');
458
+
459
+ lines.push(chalk.bold('Description:'));
460
+ lines.push(` ${node.description}\n`);
461
+
462
+ lines.push(chalk.bold('Configuration:'));
463
+ lines.push(' type: "' + node.type + '"');
464
+ lines.push(' config:');
465
+
466
+ for (const input of node.inputs) {
467
+ const required = input.required ? chalk.red('*') : ' ';
468
+ lines.push(` ${input.name} (${input.type})${required}`);
469
+ lines.push(` ${input.description}`);
470
+ }
471
+
472
+ lines.push(`\n${chalk.bold('Output:')} ${node.output}`);
473
+
474
+ if (node.example) {
475
+ lines.push(chalk.bold('\nExample:'));
476
+ lines.push(chalk.gray('```yaml'));
477
+ lines.push(node.example);
478
+ lines.push(chalk.gray('```'));
479
+ }
480
+
481
+ return lines.join('\n');
482
+ }
483
+
484
+ /**
485
+ * WorkflowNodesCommand - List built-in node types
486
+ */
487
+ export const WorkflowNodesCommand: CommandModule<object, WorkflowNodesOptions> = {
488
+ command: 'nodes [type]',
489
+ describe: '列出所有内置节点类型及其配置说明',
490
+
491
+ builder: (yargs) =>
492
+ yargs.positional('type', {
493
+ describe: '节点类型 (tool/skill/agent/workflow/condition/merge/decorator/end)',
494
+ type: 'string',
495
+ }),
496
+
497
+ async handler(args) {
498
+ const nodeType = (args as any).type?.toLowerCase();
499
+
500
+ // List all node types
501
+ if (!nodeType) {
502
+ console.log(renderNodeTypesTable(BUILT_IN_NODES));
503
+ console.log(
504
+ chalk.gray('\nUse ') +
505
+ chalk.cyan('roy workflow nodes <type>') +
506
+ chalk.gray(' for detailed information')
507
+ );
508
+ console.log(
509
+ chalk.gray('Available types: ') +
510
+ chalk.yellow(BUILT_IN_NODES.map((n) => n.type).join(', '))
511
+ );
512
+ return;
513
+ }
514
+
515
+ // Show specific node type
516
+ const node = BUILT_IN_NODES.find((n) => n.type === nodeType);
517
+ if (!node) {
518
+ console.log(chalk.red(`\n❌ Unknown node type: ${nodeType}`));
519
+ console.log(
520
+ chalk.gray('Available types: ') +
521
+ chalk.yellow(BUILT_IN_NODES.map((n) => n.type).join(', '))
522
+ );
523
+ process.exit(1);
524
+ }
525
+
526
+ console.log(renderNodeDetail(node));
527
+ },
528
+ };
@@ -0,0 +1,94 @@
1
+ /**
2
+ * @fileoverview Workflow Remove Command
3
+ *
4
+ * Delete a workflow
5
+ */
6
+
7
+ import { CommandModule } from 'yargs';
8
+ import { EnvironmentService } from '../../../services/environment.service';
9
+ import { OutputService } from '../../../services/output.service';
10
+ import { renderWorkflowDeleted } from '../renderers';
11
+ import chalk from 'chalk';
12
+ import type { WorkflowService } from '@ai-setting/roy-agent-core/env/workflow/service';
13
+
14
+ export interface WorkflowRemoveOptions {
15
+ name: string;
16
+ force?: boolean;
17
+ config?: string;
18
+ }
19
+
20
+ /**
21
+ * WorkflowRemoveCommand - Delete a workflow
22
+ */
23
+ export const WorkflowRemoveCommand: CommandModule<object, WorkflowRemoveOptions> = {
24
+ command: 'remove <name>',
25
+ describe: '删除 Workflow',
26
+
27
+ builder: (yargs) =>
28
+ yargs
29
+ .positional('name', {
30
+ describe: 'Workflow 名称',
31
+ type: 'string',
32
+ demandOption: true,
33
+ })
34
+ .option('force', {
35
+ alias: 'f',
36
+ describe: '强制删除(不确认)',
37
+ type: 'boolean',
38
+ default: false,
39
+ })
40
+ .option('config', {
41
+ describe: '配置文件路径',
42
+ type: 'string',
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 workflowComponent = env.getComponent('workflow') as any;
57
+
58
+ if (!workflowComponent) {
59
+ output.error('WorkflowComponent not available');
60
+ process.exit(1);
61
+ }
62
+
63
+ const service = workflowComponent.getService() as WorkflowService;
64
+
65
+ // Check if workflow exists
66
+ const existing = service.getWorkflow(args.name);
67
+ if (!existing) {
68
+ output.error(`Workflow not found: ${args.name}`);
69
+ process.exit(1);
70
+ }
71
+
72
+ // Confirm deletion if not forced
73
+ if (!args.force) {
74
+ output.log(chalk.yellow(`Are you sure you want to delete workflow '${args.name}'?`));
75
+ output.log(chalk.gray('Use --force to skip confirmation'));
76
+ process.exit(1);
77
+ }
78
+
79
+ // Delete workflow
80
+ const deleted = await service.deleteWorkflow(args.name);
81
+ if (!deleted) {
82
+ output.error(`Failed to delete workflow: ${args.name}`);
83
+ process.exit(1);
84
+ }
85
+
86
+ output.log(renderWorkflowDeleted(args.name));
87
+ } catch (error) {
88
+ output.error(`Failed to delete workflow: ${error}`);
89
+ process.exit(1);
90
+ } finally {
91
+ await envService.dispose();
92
+ }
93
+ },
94
+ };