@fractary/faber-cli 1.5.46 ā 1.5.47
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/commands/init.d.ts.map +1 -1
- package/dist/commands/plan/index.js +31 -14
- package/dist/commands/spec/index.d.ts.map +1 -1
- package/dist/commands/workflow/index.d.ts +17 -0
- package/dist/commands/workflow/index.d.ts.map +1 -1
- package/dist/commands/workflow/index.js +174 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/package.json +1 -1
- package/schemas/plan.schema.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAcpC,wBAAgB,iBAAiB,IAAI,OAAO,CA0J3C"}
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/fractary-faber-init.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAcpC,wBAAgB,iBAAiB,IAAI,OAAO,CA0J3C"}
|
|
@@ -24,7 +24,7 @@ export function createPlanCommand() {
|
|
|
24
24
|
.option('--work-label <labels>', 'Comma-separated label filters (e.g., "workflow:etl,status:approved")')
|
|
25
25
|
.option('--workflow <name>', 'Override workflow (default: read from issue "workflow:*" label)')
|
|
26
26
|
.option('--autonomy <level>', 'Override autonomy level (guarded|autonomous)')
|
|
27
|
-
.option('--
|
|
27
|
+
.option('--worktree', 'Create a git worktree for this workflow (overrides config)')
|
|
28
28
|
.option('--no-branch', 'Skip branch creation')
|
|
29
29
|
.option('--skip-confirm', 'Skip confirmation prompt (use with caution)')
|
|
30
30
|
.option('--output <format>', 'Output format: text|json|yaml', 'text')
|
|
@@ -186,7 +186,7 @@ async function executePlanCommand(options) {
|
|
|
186
186
|
const issuesWithWorkflows = await assignWorkflows(issues, availableWorkflows, options, outputFormat);
|
|
187
187
|
// Step 3: Show confirmation prompt
|
|
188
188
|
if (!options.skipConfirm) {
|
|
189
|
-
const confirmed = await showConfirmationPrompt(issuesWithWorkflows, config, outputFormat);
|
|
189
|
+
const confirmed = await showConfirmationPrompt(issuesWithWorkflows, config, options, outputFormat);
|
|
190
190
|
if (!confirmed) {
|
|
191
191
|
if (outputFormat === 'text') {
|
|
192
192
|
console.log(chalk.yellow('\nā Planning cancelled'));
|
|
@@ -306,24 +306,40 @@ async function assignWorkflows(issues, availableWorkflows, options, outputFormat
|
|
|
306
306
|
/**
|
|
307
307
|
* Show confirmation prompt before planning
|
|
308
308
|
*/
|
|
309
|
-
async function showConfirmationPrompt(issues, config, outputFormat) {
|
|
309
|
+
async function showConfirmationPrompt(issues, config, options, outputFormat) {
|
|
310
310
|
if (outputFormat !== 'text') {
|
|
311
311
|
return true; // Skip in JSON mode
|
|
312
312
|
}
|
|
313
|
+
const createWorktree = shouldCreateWorktree(options, config);
|
|
313
314
|
console.log(chalk.cyan('\nš Will plan workflows for the following issues:\n'));
|
|
314
315
|
for (const issue of issues) {
|
|
315
316
|
const { organization, project } = getRepoInfoFromConfig(config);
|
|
316
317
|
const branch = `feature/${issue.number}`;
|
|
317
|
-
const worktree = `~/.claude-worktrees/${organization}-${project}-${issue.number}`;
|
|
318
318
|
console.log(chalk.bold(`#${issue.number}: ${issue.title}`));
|
|
319
319
|
console.log(chalk.gray(` Workflow: ${issue.workflow}`));
|
|
320
320
|
console.log(chalk.gray(` Branch: ${branch}`));
|
|
321
|
-
|
|
321
|
+
if (createWorktree) {
|
|
322
|
+
const worktree = `~/.claude-worktrees/${organization}-${project}-${issue.number}`;
|
|
323
|
+
console.log(chalk.gray(` Worktree: ${worktree}`));
|
|
324
|
+
}
|
|
322
325
|
console.log();
|
|
323
326
|
}
|
|
324
327
|
const response = await prompt('Proceed? [Y/n]: ');
|
|
325
328
|
return !response || response.toLowerCase() === 'y' || response.toLowerCase() === 'yes';
|
|
326
329
|
}
|
|
330
|
+
/**
|
|
331
|
+
* Determine whether to create a worktree based on CLI flag and config
|
|
332
|
+
*/
|
|
333
|
+
function shouldCreateWorktree(options, config) {
|
|
334
|
+
// Explicit CLI flag always wins
|
|
335
|
+
if (options.worktree === true)
|
|
336
|
+
return true;
|
|
337
|
+
// Config setting is the default authority
|
|
338
|
+
if (config.worktree?.enabled === true)
|
|
339
|
+
return true;
|
|
340
|
+
// Default: no worktree
|
|
341
|
+
return false;
|
|
342
|
+
}
|
|
327
343
|
/**
|
|
328
344
|
* Plan a single issue
|
|
329
345
|
*/
|
|
@@ -331,6 +347,7 @@ async function planSingleIssue(issue, config, repoClient, anthropicClient, optio
|
|
|
331
347
|
const { organization, project } = getRepoInfoFromConfig(config);
|
|
332
348
|
const branch = `feature/${issue.number}`;
|
|
333
349
|
const worktree = `~/.claude-worktrees/${organization}-${project}-${issue.number}`;
|
|
350
|
+
const createWorktree = shouldCreateWorktree(options, config);
|
|
334
351
|
// Create branch without checking it out (so it won't conflict with worktree creation)
|
|
335
352
|
if (!options.noBranch) {
|
|
336
353
|
if (outputFormat === 'text') {
|
|
@@ -348,9 +365,9 @@ async function planSingleIssue(issue, config, repoClient, anthropicClient, optio
|
|
|
348
365
|
// Branch might already exist, that's ok
|
|
349
366
|
}
|
|
350
367
|
}
|
|
351
|
-
// Create worktree
|
|
352
|
-
let worktreePath = worktree;
|
|
353
|
-
if (
|
|
368
|
+
// Create worktree (only when explicitly opted in via flag or config)
|
|
369
|
+
let worktreePath = createWorktree ? worktree : process.cwd();
|
|
370
|
+
if (createWorktree) {
|
|
354
371
|
if (outputFormat === 'text') {
|
|
355
372
|
console.log(chalk.gray(` ā Creating worktree: ${worktree}...`));
|
|
356
373
|
process.stdout.write(''); // Force flush
|
|
@@ -393,8 +410,8 @@ async function planSingleIssue(issue, config, repoClient, anthropicClient, optio
|
|
|
393
410
|
// Non-fatal: if cleanup fails, workflow-run will handle conflict detection
|
|
394
411
|
}
|
|
395
412
|
}
|
|
396
|
-
// Check for existing plan
|
|
397
|
-
if (!options.forceNew
|
|
413
|
+
// Check for existing plan (skip if found, unless --force-new)
|
|
414
|
+
if (!options.forceNew) {
|
|
398
415
|
const runsDir = path.join(worktreePath, '.fractary', 'faber', 'runs');
|
|
399
416
|
try {
|
|
400
417
|
const entries = await fs.readdir(runsDir);
|
|
@@ -434,8 +451,8 @@ async function planSingleIssue(issue, config, repoClient, anthropicClient, optio
|
|
|
434
451
|
plan.autonomy = options.autonomy;
|
|
435
452
|
}
|
|
436
453
|
const planId = plan.id;
|
|
437
|
-
// Write plan to worktree
|
|
438
|
-
|
|
454
|
+
// Write plan to worktree (or project root when no worktree)
|
|
455
|
+
{
|
|
439
456
|
// Validate plan ID format (prevent path traversal via malicious plan IDs)
|
|
440
457
|
validatePlanId(planId);
|
|
441
458
|
const runDir = getRunDir(planId, worktreePath);
|
|
@@ -544,7 +561,7 @@ function generatePlanComment(plan, workflow, worktreePath, planId, issueNumber)
|
|
|
544
561
|
comment += `cd ${worktreePath}\n`;
|
|
545
562
|
comment += `claude\n`;
|
|
546
563
|
comment += `# Then in Claude Code:\n`;
|
|
547
|
-
comment += `/fractary-faber
|
|
564
|
+
comment += `/fractary-faber-workflow-run ${issueNumber}\n`;
|
|
548
565
|
comment += `\`\`\`\n`;
|
|
549
566
|
return comment;
|
|
550
567
|
}
|
|
@@ -575,7 +592,7 @@ function outputTextSummary(results) {
|
|
|
575
592
|
console.log();
|
|
576
593
|
console.log(chalk.cyan(' To execute:'));
|
|
577
594
|
console.log(chalk.gray(` cd ${result.worktree} && claude`));
|
|
578
|
-
console.log(chalk.gray(` /fractary-faber
|
|
595
|
+
console.log(chalk.gray(` /fractary-faber-workflow-run ${result.issue.number}`));
|
|
579
596
|
console.log();
|
|
580
597
|
});
|
|
581
598
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/spec/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,OAAO,CAc3C"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/fractary-faber-spec/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,OAAO,CAc3C"}
|
|
@@ -40,6 +40,19 @@ export declare function createWorkflowUpdateCommand(): Command;
|
|
|
40
40
|
* Create the workflow-inspect command
|
|
41
41
|
*/
|
|
42
42
|
export declare function createWorkflowInspectCommand(): Command;
|
|
43
|
+
/**
|
|
44
|
+
* Create the workflow-resolve command.
|
|
45
|
+
*
|
|
46
|
+
* Resolves a workflow with full inheritance chain merging via WorkflowResolver.
|
|
47
|
+
* Unlike workflow-inspect (which only looks in project-local registry),
|
|
48
|
+
* workflow-resolve also searches bundled plugin defaults ā making it the
|
|
49
|
+
* CLI equivalent of merge-workflows.sh and the correct tool for agents and
|
|
50
|
+
* skills that need a fully-merged workflow definition.
|
|
51
|
+
*
|
|
52
|
+
* Works identically in Claude Code and pi installs: WorkflowResolver uses
|
|
53
|
+
* __dirname to locate bundled workflows without any environment configuration.
|
|
54
|
+
*/
|
|
55
|
+
export declare function createWorkflowResolveCommand(): Command;
|
|
43
56
|
/**
|
|
44
57
|
* Create the workflow-debug command
|
|
45
58
|
*/
|
|
@@ -52,4 +65,8 @@ export declare function createBatchPlanCommand(): Command;
|
|
|
52
65
|
* Create the workflow-batch-run command
|
|
53
66
|
*/
|
|
54
67
|
export declare function createBatchRunCommand(): Command;
|
|
68
|
+
/**
|
|
69
|
+
* Create the workflow-execute command (multi-model CLI-native execution)
|
|
70
|
+
*/
|
|
71
|
+
export declare function createWorkflowExecuteCommand(): Command;
|
|
55
72
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/workflow/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/workflow/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAgBpC;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CAsJ1C;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,OAAO,CAiF7C;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,OAAO,CAyB7C;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,OAAO,CAoB5C;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,OAAO,CA2B9C;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,OAAO,CA8B9C;AAED;;GAEG;AACH,wBAAgB,2BAA2B,IAAI,OAAO,CAoCrD;AAED;;GAEG;AACH,wBAAgB,2BAA2B,IAAI,OAAO,CA4BrD;AAED;;GAEG;AACH,wBAAgB,4BAA4B,IAAI,OAAO,CA0CtD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,4BAA4B,IAAI,OAAO,CAkDtD;AAED;;GAEG;AACH,wBAAgB,0BAA0B,IAAI,OAAO,CAkDpD;AAED;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,OAAO,CAehD;AAED;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,OAAO,CAgB/C;AAgYD;;GAEG;AACH,wBAAgB,4BAA4B,IAAI,OAAO,CAuHtD"}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { Command } from 'commander';
|
|
7
7
|
import chalk from 'chalk';
|
|
8
|
-
import { FaberWorkflow, StateManager, createWorkflow, updateWorkflow, inspectWorkflow, debugWorkflow, } from '@fractary/faber';
|
|
8
|
+
import { FaberWorkflow, StateManager, createWorkflow, updateWorkflow, inspectWorkflow, debugWorkflow, WorkflowResolver, ExecutorRegistry, WorkflowExecutor, } from '@fractary/faber';
|
|
9
9
|
import { parsePositiveInteger } from '../../utils/validation.js';
|
|
10
10
|
/**
|
|
11
11
|
* Create the workflow-run command
|
|
@@ -477,6 +477,67 @@ export function createWorkflowInspectCommand() {
|
|
|
477
477
|
}
|
|
478
478
|
});
|
|
479
479
|
}
|
|
480
|
+
/**
|
|
481
|
+
* Create the workflow-resolve command.
|
|
482
|
+
*
|
|
483
|
+
* Resolves a workflow with full inheritance chain merging via WorkflowResolver.
|
|
484
|
+
* Unlike workflow-inspect (which only looks in project-local registry),
|
|
485
|
+
* workflow-resolve also searches bundled plugin defaults ā making it the
|
|
486
|
+
* CLI equivalent of merge-workflows.sh and the correct tool for agents and
|
|
487
|
+
* skills that need a fully-merged workflow definition.
|
|
488
|
+
*
|
|
489
|
+
* Works identically in Claude Code and pi installs: WorkflowResolver uses
|
|
490
|
+
* __dirname to locate bundled workflows without any environment configuration.
|
|
491
|
+
*/
|
|
492
|
+
export function createWorkflowResolveCommand() {
|
|
493
|
+
return new Command('workflow-resolve')
|
|
494
|
+
.description('Resolve a workflow with full inheritance chain merging (includes bundled plugin defaults)')
|
|
495
|
+
.argument('<id>', 'Workflow ID to resolve (e.g. "core", "default", "project:my-workflow")')
|
|
496
|
+
.option('--project-root <path>', 'Project root directory (default: cwd)')
|
|
497
|
+
.option('--json', 'Output as JSON')
|
|
498
|
+
.action(async (id, options) => {
|
|
499
|
+
try {
|
|
500
|
+
const resolver = new WorkflowResolver({
|
|
501
|
+
projectRoot: options.projectRoot,
|
|
502
|
+
});
|
|
503
|
+
const workflow = await resolver.resolveWorkflow(id);
|
|
504
|
+
if (options.json) {
|
|
505
|
+
console.log(JSON.stringify({ status: 'success', workflow }, null, 2));
|
|
506
|
+
}
|
|
507
|
+
else {
|
|
508
|
+
console.log(chalk.bold(`Workflow: ${workflow.id}`));
|
|
509
|
+
if (workflow.description) {
|
|
510
|
+
console.log(` Description: ${workflow.description}`);
|
|
511
|
+
}
|
|
512
|
+
console.log(` Inheritance chain: ${workflow.inheritance_chain.join(' ā ')}`);
|
|
513
|
+
if (workflow.skipped_steps?.length) {
|
|
514
|
+
console.log(` Skipped steps: ${workflow.skipped_steps.join(', ')}`);
|
|
515
|
+
}
|
|
516
|
+
console.log();
|
|
517
|
+
for (const [phase, def] of Object.entries(workflow.phases)) {
|
|
518
|
+
const steps = def.steps ?? [];
|
|
519
|
+
const enabled = def.enabled !== false;
|
|
520
|
+
console.log(chalk.cyan(` ${phase}`), enabled ? '' : chalk.gray('(disabled)'), chalk.gray(`${steps.length} steps`));
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
catch (error) {
|
|
525
|
+
if (options.json) {
|
|
526
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
527
|
+
const paths = error.searchedPaths;
|
|
528
|
+
console.error(JSON.stringify({
|
|
529
|
+
status: 'failure',
|
|
530
|
+
message: msg,
|
|
531
|
+
errors: paths ? [`Searched: ${paths.join(', ')}`] : [msg],
|
|
532
|
+
}));
|
|
533
|
+
}
|
|
534
|
+
else {
|
|
535
|
+
console.error(chalk.red(`Error: ${error instanceof Error ? error.message : String(error)}`));
|
|
536
|
+
}
|
|
537
|
+
process.exit(1);
|
|
538
|
+
}
|
|
539
|
+
});
|
|
540
|
+
}
|
|
480
541
|
/**
|
|
481
542
|
* Create the workflow-debug command
|
|
482
543
|
*/
|
|
@@ -708,7 +769,7 @@ async function executeBatchPlanCommand(options) {
|
|
|
708
769
|
console.log(chalk.white(` fractary-faber workflow-batch-run --batch ${batchId} --autonomous`));
|
|
709
770
|
console.log('');
|
|
710
771
|
console.log(chalk.cyan('Or in Claude Code:'));
|
|
711
|
-
console.log(chalk.white(` /fractary-faber
|
|
772
|
+
console.log(chalk.white(` /fractary-faber-workflow-batch-run --batch ${batchId} --autonomous`));
|
|
712
773
|
}
|
|
713
774
|
}
|
|
714
775
|
async function executeBatchRunCommand(options) {
|
|
@@ -872,6 +933,117 @@ async function executeBatchRunCommand(options) {
|
|
|
872
933
|
process.exit(1);
|
|
873
934
|
}
|
|
874
935
|
}
|
|
936
|
+
/**
|
|
937
|
+
* Create the workflow-execute command (multi-model CLI-native execution)
|
|
938
|
+
*/
|
|
939
|
+
export function createWorkflowExecuteCommand() {
|
|
940
|
+
return new Command('workflow-execute')
|
|
941
|
+
.description('Execute a workflow using the multi-model executor framework (CLI-native, no Claude Code required)')
|
|
942
|
+
.argument('<plan-path>', 'Path to plan.json file')
|
|
943
|
+
.option('--model <model>', 'Default model for steps without an explicit executor (default: claude-sonnet-4-6-20250514)')
|
|
944
|
+
.option('--phase <phases>', 'Execute only specified phase(s) ā comma-separated')
|
|
945
|
+
.option('--step <step-id>', 'Execute only a specific step')
|
|
946
|
+
.option('--json', 'Output as JSON')
|
|
947
|
+
.action(async (planPath, options) => {
|
|
948
|
+
try {
|
|
949
|
+
const fs = await import('fs/promises');
|
|
950
|
+
const path = await import('path');
|
|
951
|
+
// Load plan
|
|
952
|
+
const resolvedPath = path.resolve(planPath);
|
|
953
|
+
const planContent = await fs.readFile(resolvedPath, 'utf-8');
|
|
954
|
+
const plan = JSON.parse(planContent);
|
|
955
|
+
if (!plan.workflow?.phases) {
|
|
956
|
+
throw new Error('Invalid plan: missing workflow.phases');
|
|
957
|
+
}
|
|
958
|
+
// Create executor registry with defaults
|
|
959
|
+
const registry = ExecutorRegistry.createDefault();
|
|
960
|
+
// Override default model if specified
|
|
961
|
+
const workflowExecutor = plan.workflow.executor || (options.model ? {
|
|
962
|
+
provider: 'claude',
|
|
963
|
+
model: options.model,
|
|
964
|
+
} : undefined);
|
|
965
|
+
// Create workflow executor
|
|
966
|
+
const executor = new WorkflowExecutor(registry);
|
|
967
|
+
// Parse options
|
|
968
|
+
const phasesToRun = options.phase?.split(',').map((p) => p.trim()) ?? null;
|
|
969
|
+
// Extract work ID from plan
|
|
970
|
+
const workId = plan.source?.work_id || plan.items?.[0]?.work_id || 'unknown';
|
|
971
|
+
const issue = plan.items?.[0]?.issue;
|
|
972
|
+
if (!options.json) {
|
|
973
|
+
console.log(chalk.blue.bold('FABER Multi-Model Workflow Execution'));
|
|
974
|
+
console.log(chalk.gray('ā'.repeat(50)));
|
|
975
|
+
console.log(chalk.gray(`Plan: ${resolvedPath}`));
|
|
976
|
+
console.log(chalk.gray(`Work ID: ${workId}`));
|
|
977
|
+
console.log(chalk.gray(`Workflow: ${plan.workflow.id}`));
|
|
978
|
+
if (workflowExecutor) {
|
|
979
|
+
console.log(chalk.gray(`Default executor: ${workflowExecutor.provider}${workflowExecutor.model ? ` (${workflowExecutor.model})` : ''}`));
|
|
980
|
+
}
|
|
981
|
+
console.log('');
|
|
982
|
+
}
|
|
983
|
+
// Execute
|
|
984
|
+
const result = await executor.execute({
|
|
985
|
+
phases: plan.workflow.phases,
|
|
986
|
+
executor: workflowExecutor,
|
|
987
|
+
phase_executors: plan.workflow.phase_executors,
|
|
988
|
+
result_handling: plan.workflow.result_handling,
|
|
989
|
+
}, {
|
|
990
|
+
workId,
|
|
991
|
+
issue: issue ? { number: issue.number, title: issue.title, body: '' } : undefined,
|
|
992
|
+
workingDirectory: path.dirname(resolvedPath),
|
|
993
|
+
phasesToRun: phasesToRun || undefined,
|
|
994
|
+
stepToRun: options.step || null,
|
|
995
|
+
onPhaseStart: (phase) => {
|
|
996
|
+
if (!options.json) {
|
|
997
|
+
console.log(chalk.cyan(`\nā Phase: ${phase.toUpperCase()}`));
|
|
998
|
+
}
|
|
999
|
+
},
|
|
1000
|
+
onStepStart: (phase, step, index, total) => {
|
|
1001
|
+
if (!options.json) {
|
|
1002
|
+
const executor = step.executor;
|
|
1003
|
+
const providerTag = executor
|
|
1004
|
+
? chalk.magenta(`[${executor.provider}${executor.model ? `:${executor.model}` : ''}]`)
|
|
1005
|
+
: chalk.gray('[default]');
|
|
1006
|
+
console.log(chalk.gray(` [${index + 1}/${total}] ${step.name} ${providerTag}`));
|
|
1007
|
+
}
|
|
1008
|
+
},
|
|
1009
|
+
onStepComplete: (_phase, step, stepResult) => {
|
|
1010
|
+
if (!options.json) {
|
|
1011
|
+
const icon = stepResult.status === 'success' ? chalk.green('ā') :
|
|
1012
|
+
stepResult.status === 'warning' ? chalk.yellow('ā ') :
|
|
1013
|
+
chalk.red('ā');
|
|
1014
|
+
console.log(` ${icon} ${step.id} (${stepResult.metadata.duration_ms}ms)`);
|
|
1015
|
+
if (stepResult.metadata.tokens_used) {
|
|
1016
|
+
console.log(chalk.gray(` tokens: ${stepResult.metadata.tokens_used.input}ā${stepResult.metadata.tokens_used.output}`));
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
},
|
|
1020
|
+
onPhaseComplete: (phase, status) => {
|
|
1021
|
+
if (!options.json) {
|
|
1022
|
+
const icon = status === 'completed' ? chalk.green('ā') :
|
|
1023
|
+
status === 'skipped' ? chalk.gray('ā') :
|
|
1024
|
+
chalk.red('ā');
|
|
1025
|
+
console.log(` ${icon} Phase ${phase} ${status}`);
|
|
1026
|
+
}
|
|
1027
|
+
},
|
|
1028
|
+
});
|
|
1029
|
+
if (options.json) {
|
|
1030
|
+
console.log(JSON.stringify({ status: 'success', data: result }, null, 2));
|
|
1031
|
+
}
|
|
1032
|
+
else {
|
|
1033
|
+
console.log(chalk.gray('\n' + 'ā'.repeat(50)));
|
|
1034
|
+
const statusIcon = result.status === 'completed' ? chalk.green('ā') : chalk.red('ā');
|
|
1035
|
+
console.log(`${statusIcon} Workflow ${result.status} (${result.duration_ms}ms)`);
|
|
1036
|
+
console.log(chalk.gray(` Steps: ${result.steps_completed}/${result.steps_total}`));
|
|
1037
|
+
}
|
|
1038
|
+
if (result.status === 'failed') {
|
|
1039
|
+
process.exit(1);
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1042
|
+
catch (error) {
|
|
1043
|
+
handleWorkflowError(error, options);
|
|
1044
|
+
}
|
|
1045
|
+
});
|
|
1046
|
+
}
|
|
875
1047
|
// Helper functions
|
|
876
1048
|
function getStateColor(state) {
|
|
877
1049
|
switch (state) {
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;GAKG;AAMH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAqBpC;;GAEG;AACH,wBAAgB,cAAc,IAAI,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;GAKG;AAMH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAqBpC;;GAEG;AACH,wBAAgB,cAAc,IAAI,OAAO,CA0DxC"}
|
package/dist/index.js
CHANGED
|
@@ -10,7 +10,7 @@ import dotenv from 'dotenv';
|
|
|
10
10
|
dotenv.config();
|
|
11
11
|
import { Command } from 'commander';
|
|
12
12
|
import chalk from 'chalk';
|
|
13
|
-
import { createRunCommand, createStatusCommand, createResumeCommand, createPauseCommand, createRecoverCommand, createCleanupCommand, createWorkflowCreateCommand, createWorkflowUpdateCommand, createWorkflowInspectCommand, createWorkflowDebugCommand, createBatchPlanCommand, createBatchRunCommand } from './commands/workflow/index.js';
|
|
13
|
+
import { createRunCommand, createStatusCommand, createResumeCommand, createPauseCommand, createRecoverCommand, createCleanupCommand, createWorkflowCreateCommand, createWorkflowUpdateCommand, createWorkflowInspectCommand, createWorkflowResolveCommand, createWorkflowDebugCommand, createBatchPlanCommand, createBatchRunCommand, createWorkflowExecuteCommand } from './commands/workflow/index.js';
|
|
14
14
|
import { createSessionLoadCommand, createSessionSaveCommand } from './commands/session.js';
|
|
15
15
|
import { createWorkCommand } from './commands/work/index.js';
|
|
16
16
|
import { createRepoCommand } from './commands/repo/index.js';
|
|
@@ -51,10 +51,12 @@ export function createFaberCLI() {
|
|
|
51
51
|
program.addCommand(createCleanupCommand()); // workflow-cleanup
|
|
52
52
|
program.addCommand(createWorkflowCreateCommand()); // workflow-create
|
|
53
53
|
program.addCommand(createWorkflowUpdateCommand()); // workflow-update
|
|
54
|
-
program.addCommand(createWorkflowInspectCommand()); // workflow-inspect
|
|
54
|
+
program.addCommand(createWorkflowInspectCommand()); // workflow-inspect (project-local registry)
|
|
55
|
+
program.addCommand(createWorkflowResolveCommand()); // workflow-resolve (full inheritance + bundled defaults)
|
|
55
56
|
program.addCommand(createWorkflowDebugCommand()); // workflow-debug
|
|
56
57
|
program.addCommand(createBatchPlanCommand()); // workflow-batch-plan
|
|
57
58
|
program.addCommand(createBatchRunCommand()); // workflow-batch-run
|
|
59
|
+
program.addCommand(createWorkflowExecuteCommand()); // workflow-execute (multi-model CLI-native)
|
|
58
60
|
program.addCommand(createSessionLoadCommand()); // session-load
|
|
59
61
|
program.addCommand(createSessionSaveCommand()); // session-save
|
|
60
62
|
// Subcommand trees
|
package/package.json
CHANGED
package/schemas/plan.schema.json
CHANGED
|
@@ -91,7 +91,7 @@
|
|
|
91
91
|
"properties": {
|
|
92
92
|
"id": {
|
|
93
93
|
"type": "string",
|
|
94
|
-
"description": "Workflow identifier (e.g., fractary-faber
|
|
94
|
+
"description": "Workflow identifier (e.g., fractary-faber-default, dataset-create)"
|
|
95
95
|
},
|
|
96
96
|
"resolved_at": {
|
|
97
97
|
"type": "string",
|