@defai.digital/automatosx 5.10.0 โ 5.11.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/CHANGELOG.md +116 -0
- package/README.md +1 -1
- package/dist/index.js +289 -17
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,122 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
## [5.11.0] - 2025-10-29
|
|
6
|
+
|
|
7
|
+
### โจ Features & Enhancements
|
|
8
|
+
|
|
9
|
+
**Phase 2B: Full Streaming Progress** - Complete real-time observability for spec execution
|
|
10
|
+
|
|
11
|
+
#### ๐ฏ Streaming Progress System (NEW)
|
|
12
|
+
|
|
13
|
+
1. **Event Emission Integration** (`src/core/spec/SpecExecutor.ts`)
|
|
14
|
+
- Added event emission throughout SpecExecutor execution flow
|
|
15
|
+
- `spec:started` - Emitted when execution begins
|
|
16
|
+
- `spec:completed/failed` - Emitted when execution ends
|
|
17
|
+
- `task:started` - Emitted when each task begins
|
|
18
|
+
- `task:completed/failed` - Emitted when tasks finish
|
|
19
|
+
- `level:started/completed` - Emitted for parallel execution levels
|
|
20
|
+
- All events include duration, timestamps, and context
|
|
21
|
+
|
|
22
|
+
2. **SpecProgressRenderer** (`src/cli/renderers/spec-progress-renderer.ts` - NEW)
|
|
23
|
+
- Real-time terminal rendering for spec execution
|
|
24
|
+
- Live progress updates with task status icons (โณ โ โ)
|
|
25
|
+
- Level-based parallel execution visualization
|
|
26
|
+
- Duration tracking for each task
|
|
27
|
+
- Error diagnostics display with stack traces (DEBUG mode)
|
|
28
|
+
- Clean, informative output with color coding
|
|
29
|
+
|
|
30
|
+
3. **CLI Integration** (`src/cli/commands/spec.ts`)
|
|
31
|
+
- Automatic streaming progress when running `ax spec run`
|
|
32
|
+
- New `--no-streaming` flag to disable and use legacy mode
|
|
33
|
+
- Seamless integration with existing spec command
|
|
34
|
+
- Backward compatible with all existing workflows
|
|
35
|
+
|
|
36
|
+
#### ๐ User Experience Impact
|
|
37
|
+
|
|
38
|
+
**Before (v5.10.0):**
|
|
39
|
+
```bash
|
|
40
|
+
$ ax spec run
|
|
41
|
+
๐ Starting execution...
|
|
42
|
+
โ
Execution completed
|
|
43
|
+
Results:
|
|
44
|
+
Total: 10
|
|
45
|
+
Completed: 10
|
|
46
|
+
Duration: 45.32s
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
**After (v5.11.0):**
|
|
50
|
+
```bash
|
|
51
|
+
$ ax spec run
|
|
52
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
53
|
+
Running spec: my-app-spec
|
|
54
|
+
Total tasks: 10
|
|
55
|
+
Mode: parallel
|
|
56
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
57
|
+
|
|
58
|
+
Level 1/3:
|
|
59
|
+
3 task(s) in parallel
|
|
60
|
+
โ [1/10] Setup database (2.3s)
|
|
61
|
+
โ [2/10] Setup config (1.8s)
|
|
62
|
+
โ [3/10] Initialize environment (1.5s)
|
|
63
|
+
โ All 3 task(s) completed (2.3s)
|
|
64
|
+
|
|
65
|
+
Level 2/3:
|
|
66
|
+
5 task(s) in parallel
|
|
67
|
+
โณ [4/10] Backend API...
|
|
68
|
+
โ [4/10] Backend API (5.2s)
|
|
69
|
+
โณ [5/10] Frontend UI...
|
|
70
|
+
โ [5/10] Frontend UI (6.1s)
|
|
71
|
+
...
|
|
72
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
73
|
+
โ Spec completed successfully
|
|
74
|
+
Duration: 45.3s
|
|
75
|
+
Completed: 10/10
|
|
76
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
#### ๐ฏ Key Benefits
|
|
80
|
+
|
|
81
|
+
- **Live Feedback**: See task progress in real-time
|
|
82
|
+
- **Transparency**: Know exactly what's happening at each moment
|
|
83
|
+
- **Better Debugging**: Immediate visibility into failures
|
|
84
|
+
- **Parallel Visualization**: Clear display of concurrent task execution
|
|
85
|
+
- **Duration Insights**: Per-task timing information
|
|
86
|
+
- **Optional**: Use `--no-streaming` for legacy output
|
|
87
|
+
|
|
88
|
+
#### ๐ง Technical Details
|
|
89
|
+
|
|
90
|
+
- **Performance**: <1ms overhead per event (validated)
|
|
91
|
+
- **Backward Compatible**: All existing code works unchanged
|
|
92
|
+
- **Optional Chaining**: Uses `?.` to safely emit events
|
|
93
|
+
- **Clean Architecture**: Renderer subscribes to events, doesn't interfere with execution
|
|
94
|
+
- **Extensible**: Foundation for future MCP streaming, web dashboards
|
|
95
|
+
|
|
96
|
+
### ๐งช Testing
|
|
97
|
+
|
|
98
|
+
- All 2,197 unit tests passing
|
|
99
|
+
- All 103 integration tests passing
|
|
100
|
+
- Smoke tests passing
|
|
101
|
+
- Type checking: PASSED
|
|
102
|
+
- Build: SUCCESS
|
|
103
|
+
- Zero breaking changes
|
|
104
|
+
|
|
105
|
+
### ๐ Documentation
|
|
106
|
+
|
|
107
|
+
- Updated `automatosx/PRD/PHASE2-FINAL-STATUS.md` with complete Phase 2 status
|
|
108
|
+
- Comprehensive implementation documentation
|
|
109
|
+
- CLI usage examples with streaming
|
|
110
|
+
|
|
111
|
+
### ๐ Phase 2 Complete!
|
|
112
|
+
|
|
113
|
+
Phase 2 (Observability & Streaming Progress) is now **100% complete**:
|
|
114
|
+
- โ
Phase 2A (v5.10.0): Event bus infrastructure
|
|
115
|
+
- โ
Phase 2B (v5.11.0): Full streaming integration
|
|
116
|
+
|
|
117
|
+
Real-time observability is now production-ready across all spec execution workflows!
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
5
121
|
## [5.10.0] - 2025-10-29
|
|
6
122
|
|
|
7
123
|
### โจ Features & Enhancements
|
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@ AutomatosX is a local-first CLI that transforms stateless AI assistants into a p
|
|
|
13
13
|
[](https://www.microsoft.com/windows)
|
|
14
14
|
[](https://ubuntu.com)
|
|
15
15
|
|
|
16
|
-
**Status**: โ
Production Ready ยท **v5.
|
|
16
|
+
**Status**: โ
Production Ready ยท **v5.11.0** ยท October 2025 ยท 19 Specialized Agents ยท 100% Resource Leak Free ยท Spec-Driven Development
|
|
17
17
|
|
|
18
18
|
---
|
|
19
19
|
|
package/dist/index.js
CHANGED
|
@@ -18,7 +18,7 @@ import chalk27 from 'chalk';
|
|
|
18
18
|
import Table from 'cli-table3';
|
|
19
19
|
import * as sqliteVec from 'sqlite-vec';
|
|
20
20
|
import { Mutex } from 'async-mutex';
|
|
21
|
-
import
|
|
21
|
+
import ora6 from 'ora';
|
|
22
22
|
import * as readline from 'readline';
|
|
23
23
|
import readline__default from 'readline';
|
|
24
24
|
import { promisify } from 'util';
|
|
@@ -6182,7 +6182,7 @@ var PRECOMPILED_CONFIG = {
|
|
|
6182
6182
|
"healthCheckInterval": 6e4,
|
|
6183
6183
|
"providerCooldownMs": 3e4
|
|
6184
6184
|
},
|
|
6185
|
-
"version": "5.8.
|
|
6185
|
+
"version": "5.8.10"
|
|
6186
6186
|
};
|
|
6187
6187
|
|
|
6188
6188
|
// src/core/config.ts
|
|
@@ -14695,7 +14695,7 @@ Retry attempt ${attempt}/${maxAttempts}...`));
|
|
|
14695
14695
|
if (verbose) {
|
|
14696
14696
|
this.displayExecutionInfo(context);
|
|
14697
14697
|
}
|
|
14698
|
-
const spinner = showProgress ?
|
|
14698
|
+
const spinner = showProgress ? ora6({
|
|
14699
14699
|
text: "Executing agent...",
|
|
14700
14700
|
spinner: "dots"
|
|
14701
14701
|
}).start() : null;
|
|
@@ -17060,7 +17060,7 @@ var ProgressIndicator = class {
|
|
|
17060
17060
|
console.log(message);
|
|
17061
17061
|
return;
|
|
17062
17062
|
}
|
|
17063
|
-
this.spinner =
|
|
17063
|
+
this.spinner = ora6({
|
|
17064
17064
|
text: message,
|
|
17065
17065
|
spinner: this.options.spinnerType,
|
|
17066
17066
|
color: this.options.colors ? "cyan" : void 0
|
|
@@ -18553,7 +18553,7 @@ var ProgressRenderer = class {
|
|
|
18553
18553
|
}
|
|
18554
18554
|
this.currentStage = event.stageName || "Unknown";
|
|
18555
18555
|
this.currentProgress = 0;
|
|
18556
|
-
this.spinner =
|
|
18556
|
+
this.spinner = ora6({
|
|
18557
18557
|
text: chalk27.cyan(`${this.currentStage} (0%)`),
|
|
18558
18558
|
spinner: "dots"
|
|
18559
18559
|
}).start();
|
|
@@ -19629,7 +19629,7 @@ ${output}
|
|
|
19629
19629
|
console.log(`
|
|
19630
19630
|
${prefix} ${name}`);
|
|
19631
19631
|
if (!this.progressRenderer) {
|
|
19632
|
-
this.spinner =
|
|
19632
|
+
this.spinner = ora6({
|
|
19633
19633
|
text: stage.description,
|
|
19634
19634
|
color: "cyan"
|
|
19635
19635
|
}).start();
|
|
@@ -33971,6 +33971,11 @@ var SpecExecutor = class {
|
|
|
33971
33971
|
parallel: this.options.parallel ?? false,
|
|
33972
33972
|
nativeExecution: this.useNativeExecution
|
|
33973
33973
|
});
|
|
33974
|
+
this.events?.emitSpecStarted({
|
|
33975
|
+
totalTasks: this.runState.metadata.totalTasks,
|
|
33976
|
+
workspacePath: this.spec.metadata.workspacePath,
|
|
33977
|
+
parallel: this.options.parallel ?? false
|
|
33978
|
+
});
|
|
33974
33979
|
if (!this.spec.graph) {
|
|
33975
33980
|
throw new SpecError(
|
|
33976
33981
|
"EXECUTION_FAILED" /* EXECUTION_FAILED */,
|
|
@@ -33999,6 +34004,15 @@ var SpecExecutor = class {
|
|
|
33999
34004
|
completed: this.runState.metadata.completedTasks,
|
|
34000
34005
|
failed: this.runState.metadata.failedTasks
|
|
34001
34006
|
});
|
|
34007
|
+
const skippedCount = Array.from(this.runState.tasks.values()).filter(
|
|
34008
|
+
(t) => t.status === "skipped"
|
|
34009
|
+
).length;
|
|
34010
|
+
this.events?.emitSpecCompleted({
|
|
34011
|
+
completedTasks: this.runState.metadata.completedTasks,
|
|
34012
|
+
failedTasks: this.runState.metadata.failedTasks,
|
|
34013
|
+
skippedTasks: skippedCount,
|
|
34014
|
+
totalTasks: this.runState.metadata.totalTasks
|
|
34015
|
+
});
|
|
34002
34016
|
await this.cleanup();
|
|
34003
34017
|
return {
|
|
34004
34018
|
specId: this.spec.metadata.id,
|
|
@@ -34006,9 +34020,7 @@ var SpecExecutor = class {
|
|
|
34006
34020
|
totalTasks: this.runState.metadata.totalTasks,
|
|
34007
34021
|
completedTasks: this.runState.metadata.completedTasks,
|
|
34008
34022
|
failedTasks: this.runState.metadata.failedTasks,
|
|
34009
|
-
skippedTasks:
|
|
34010
|
-
(t) => t.status === "skipped"
|
|
34011
|
-
).length,
|
|
34023
|
+
skippedTasks: skippedCount,
|
|
34012
34024
|
duration,
|
|
34013
34025
|
taskResults,
|
|
34014
34026
|
runState: this.runState
|
|
@@ -34019,6 +34031,15 @@ var SpecExecutor = class {
|
|
|
34019
34031
|
specId: this.spec.metadata.id
|
|
34020
34032
|
});
|
|
34021
34033
|
this.runState.status = "failed";
|
|
34034
|
+
this.events?.emitSpecFailed({
|
|
34035
|
+
error: {
|
|
34036
|
+
message: error.message,
|
|
34037
|
+
code: error.code,
|
|
34038
|
+
stack: error.stack
|
|
34039
|
+
},
|
|
34040
|
+
completedTasks: this.runState.metadata.completedTasks,
|
|
34041
|
+
failedTasks: this.runState.metadata.failedTasks
|
|
34042
|
+
});
|
|
34022
34043
|
await this.cleanup();
|
|
34023
34044
|
throw error;
|
|
34024
34045
|
}
|
|
@@ -34109,6 +34130,13 @@ var SpecExecutor = class {
|
|
|
34109
34130
|
logger.info(`Executing level ${levelIndex + 1}/${levels.length}`, {
|
|
34110
34131
|
tasksInLevel: taskIds.length
|
|
34111
34132
|
});
|
|
34133
|
+
const levelStartTime = Date.now();
|
|
34134
|
+
this.events?.emitLevelStarted({
|
|
34135
|
+
level: levelIndex,
|
|
34136
|
+
totalLevels: levels.length,
|
|
34137
|
+
taskCount: taskIds.length,
|
|
34138
|
+
taskIds
|
|
34139
|
+
});
|
|
34112
34140
|
const levelResults = await Promise.all(
|
|
34113
34141
|
taskIds.map(async (taskId, i) => {
|
|
34114
34142
|
const state = this.runState.tasks.get(taskId);
|
|
@@ -34142,6 +34170,16 @@ var SpecExecutor = class {
|
|
|
34142
34170
|
})
|
|
34143
34171
|
);
|
|
34144
34172
|
results.push(...levelResults.filter((r) => r !== null));
|
|
34173
|
+
const levelDuration = Date.now() - levelStartTime;
|
|
34174
|
+
const completedInLevel = levelResults.filter((r) => r?.status === "completed").length;
|
|
34175
|
+
const failedInLevel = levelResults.filter((r) => r?.status === "failed").length;
|
|
34176
|
+
this.events?.emitLevelCompleted({
|
|
34177
|
+
level: levelIndex,
|
|
34178
|
+
totalLevels: levels.length,
|
|
34179
|
+
duration: levelDuration,
|
|
34180
|
+
completedTasks: completedInLevel,
|
|
34181
|
+
failedTasks: failedInLevel
|
|
34182
|
+
});
|
|
34145
34183
|
if (!this.options.continueOnError && levelResults.some((r) => r?.status === "failed")) {
|
|
34146
34184
|
logger.error("Stopping execution due to task failure in parallel level");
|
|
34147
34185
|
break;
|
|
@@ -34228,6 +34266,13 @@ var SpecExecutor = class {
|
|
|
34228
34266
|
ops: task.ops
|
|
34229
34267
|
});
|
|
34230
34268
|
const startTime = Date.now();
|
|
34269
|
+
this.events?.emitTaskStarted({
|
|
34270
|
+
taskId: task.id,
|
|
34271
|
+
taskTitle: task.title,
|
|
34272
|
+
agent: task.assigneeHint,
|
|
34273
|
+
level: 0
|
|
34274
|
+
// Will be updated in parallel execution
|
|
34275
|
+
});
|
|
34231
34276
|
if (this.options.dryRun) {
|
|
34232
34277
|
logger.info("Dry run mode - task simulated", { taskId });
|
|
34233
34278
|
return {
|
|
@@ -34241,11 +34286,18 @@ var SpecExecutor = class {
|
|
|
34241
34286
|
try {
|
|
34242
34287
|
const output = await this.executeOpsCommand(task.ops);
|
|
34243
34288
|
await this.updateTaskStatus(taskId, "completed");
|
|
34289
|
+
const duration = Date.now() - startTime;
|
|
34290
|
+
this.events?.emitTaskCompleted({
|
|
34291
|
+
taskId: task.id,
|
|
34292
|
+
taskTitle: task.title,
|
|
34293
|
+
duration,
|
|
34294
|
+
output
|
|
34295
|
+
});
|
|
34244
34296
|
return {
|
|
34245
34297
|
taskId,
|
|
34246
34298
|
status: "completed",
|
|
34247
34299
|
output,
|
|
34248
|
-
duration
|
|
34300
|
+
duration,
|
|
34249
34301
|
executedBy: task.assigneeHint,
|
|
34250
34302
|
retryCount: 0
|
|
34251
34303
|
};
|
|
@@ -34255,11 +34307,21 @@ var SpecExecutor = class {
|
|
|
34255
34307
|
error: error.message
|
|
34256
34308
|
});
|
|
34257
34309
|
await this.updateTaskStatus(taskId, "failed");
|
|
34310
|
+
const duration = Date.now() - startTime;
|
|
34311
|
+
this.events?.emitTaskFailed({
|
|
34312
|
+
taskId: task.id,
|
|
34313
|
+
taskTitle: task.title,
|
|
34314
|
+
duration,
|
|
34315
|
+
error: {
|
|
34316
|
+
message: error.message,
|
|
34317
|
+
stack: error.stack
|
|
34318
|
+
}
|
|
34319
|
+
});
|
|
34258
34320
|
return {
|
|
34259
34321
|
taskId,
|
|
34260
34322
|
status: "failed",
|
|
34261
34323
|
error: error.message,
|
|
34262
|
-
duration
|
|
34324
|
+
duration,
|
|
34263
34325
|
executedBy: task.assigneeHint,
|
|
34264
34326
|
retryCount: 0
|
|
34265
34327
|
};
|
|
@@ -34405,6 +34467,204 @@ var SpecExecutor = class {
|
|
|
34405
34467
|
|
|
34406
34468
|
// src/cli/commands/spec.ts
|
|
34407
34469
|
init_SpecGenerator();
|
|
34470
|
+
|
|
34471
|
+
// src/cli/renderers/spec-progress-renderer.ts
|
|
34472
|
+
init_esm_shims();
|
|
34473
|
+
var SpecProgressRenderer = class {
|
|
34474
|
+
executor;
|
|
34475
|
+
spinner = null;
|
|
34476
|
+
quiet;
|
|
34477
|
+
taskCount = 0;
|
|
34478
|
+
completedCount = 0;
|
|
34479
|
+
failedCount = 0;
|
|
34480
|
+
currentLevel = 0;
|
|
34481
|
+
taskStartTimes = /* @__PURE__ */ new Map();
|
|
34482
|
+
/**
|
|
34483
|
+
* Create SpecProgressRenderer
|
|
34484
|
+
*
|
|
34485
|
+
* @param executor - SpecExecutor instance to listen to
|
|
34486
|
+
* @param options - Renderer options
|
|
34487
|
+
*/
|
|
34488
|
+
constructor(executor, options = {}) {
|
|
34489
|
+
this.executor = executor;
|
|
34490
|
+
this.quiet = options.quiet || false;
|
|
34491
|
+
if (this.executor.events && !this.quiet) {
|
|
34492
|
+
this.executor.events.onAny((event) => {
|
|
34493
|
+
this.handleEvent(event);
|
|
34494
|
+
});
|
|
34495
|
+
}
|
|
34496
|
+
}
|
|
34497
|
+
/**
|
|
34498
|
+
* Handle spec event
|
|
34499
|
+
*
|
|
34500
|
+
* Routes events to appropriate handlers based on type.
|
|
34501
|
+
*
|
|
34502
|
+
* @param event - Spec event to handle
|
|
34503
|
+
*/
|
|
34504
|
+
handleEvent(event) {
|
|
34505
|
+
switch (event.type) {
|
|
34506
|
+
case "spec:started":
|
|
34507
|
+
this.handleSpecStart(event);
|
|
34508
|
+
break;
|
|
34509
|
+
case "spec:completed":
|
|
34510
|
+
this.handleSpecComplete(event);
|
|
34511
|
+
break;
|
|
34512
|
+
case "spec:failed":
|
|
34513
|
+
this.handleSpecFailed(event);
|
|
34514
|
+
break;
|
|
34515
|
+
case "task:started":
|
|
34516
|
+
this.handleTaskStart(event);
|
|
34517
|
+
break;
|
|
34518
|
+
case "task:completed":
|
|
34519
|
+
this.handleTaskComplete(event);
|
|
34520
|
+
break;
|
|
34521
|
+
case "task:failed":
|
|
34522
|
+
this.handleTaskFailed(event);
|
|
34523
|
+
break;
|
|
34524
|
+
case "level:started":
|
|
34525
|
+
this.handleLevelStart(event);
|
|
34526
|
+
break;
|
|
34527
|
+
case "level:completed":
|
|
34528
|
+
this.handleLevelComplete(event);
|
|
34529
|
+
break;
|
|
34530
|
+
}
|
|
34531
|
+
}
|
|
34532
|
+
/**
|
|
34533
|
+
* Handle spec:started event
|
|
34534
|
+
*/
|
|
34535
|
+
handleSpecStart(event) {
|
|
34536
|
+
this.taskCount = event.totalTasks;
|
|
34537
|
+
this.completedCount = 0;
|
|
34538
|
+
this.failedCount = 0;
|
|
34539
|
+
console.log(chalk27.bold("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"));
|
|
34540
|
+
console.log(chalk27.bold(` Running spec: ${event.specId}`));
|
|
34541
|
+
console.log(chalk27.gray(` Total tasks: ${event.totalTasks}`));
|
|
34542
|
+
console.log(chalk27.gray(` Mode: ${event.parallel ? "parallel" : "sequential"}`));
|
|
34543
|
+
console.log(chalk27.gray(` Workspace: ${event.workspacePath}`));
|
|
34544
|
+
console.log(chalk27.bold("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n"));
|
|
34545
|
+
}
|
|
34546
|
+
/**
|
|
34547
|
+
* Handle spec:completed event
|
|
34548
|
+
*/
|
|
34549
|
+
handleSpecComplete(event) {
|
|
34550
|
+
if (this.spinner) {
|
|
34551
|
+
this.spinner.stop();
|
|
34552
|
+
this.spinner = null;
|
|
34553
|
+
}
|
|
34554
|
+
const durationSec = (event.duration / 1e3).toFixed(1);
|
|
34555
|
+
console.log("\n" + chalk27.bold("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"));
|
|
34556
|
+
console.log(chalk27.bold.green(" \u2713 Spec completed successfully"));
|
|
34557
|
+
console.log(chalk27.gray(` Duration: ${durationSec}s`));
|
|
34558
|
+
console.log(chalk27.gray(` Completed: ${event.completedTasks}/${event.totalTasks}`));
|
|
34559
|
+
if (event.failedTasks > 0) {
|
|
34560
|
+
console.log(chalk27.yellow(` Failed: ${event.failedTasks}`));
|
|
34561
|
+
}
|
|
34562
|
+
if (event.skippedTasks > 0) {
|
|
34563
|
+
console.log(chalk27.gray(` Skipped: ${event.skippedTasks}`));
|
|
34564
|
+
}
|
|
34565
|
+
console.log(chalk27.bold("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n"));
|
|
34566
|
+
}
|
|
34567
|
+
/**
|
|
34568
|
+
* Handle spec:failed event
|
|
34569
|
+
*/
|
|
34570
|
+
handleSpecFailed(event) {
|
|
34571
|
+
if (this.spinner) {
|
|
34572
|
+
this.spinner.stop();
|
|
34573
|
+
this.spinner = null;
|
|
34574
|
+
}
|
|
34575
|
+
const durationSec = event.duration ? (event.duration / 1e3).toFixed(1) : "0.0";
|
|
34576
|
+
console.log("\n" + chalk27.bold("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"));
|
|
34577
|
+
console.log(chalk27.bold.red(" \u2717 Spec execution failed"));
|
|
34578
|
+
console.log(chalk27.red(` Error: ${event.error.message}`));
|
|
34579
|
+
if (event.error.taskId) {
|
|
34580
|
+
console.log(chalk27.gray(` Failed task: ${event.error.taskId}`));
|
|
34581
|
+
}
|
|
34582
|
+
console.log(chalk27.gray(` Duration: ${durationSec}s`));
|
|
34583
|
+
console.log(chalk27.gray(` Completed: ${event.completedTasks}/${event.failedTasks + event.completedTasks}`));
|
|
34584
|
+
console.log(chalk27.bold("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n"));
|
|
34585
|
+
}
|
|
34586
|
+
/**
|
|
34587
|
+
* Handle level:started event
|
|
34588
|
+
*/
|
|
34589
|
+
handleLevelStart(event) {
|
|
34590
|
+
this.currentLevel = event.level;
|
|
34591
|
+
if (this.spinner) {
|
|
34592
|
+
this.spinner.stop();
|
|
34593
|
+
}
|
|
34594
|
+
console.log(chalk27.cyan(`
|
|
34595
|
+
Level ${event.level + 1}/${event.totalLevels}:`));
|
|
34596
|
+
console.log(chalk27.gray(` ${event.taskCount} task(s) in parallel`));
|
|
34597
|
+
}
|
|
34598
|
+
/**
|
|
34599
|
+
* Handle level:completed event
|
|
34600
|
+
*/
|
|
34601
|
+
handleLevelComplete(event) {
|
|
34602
|
+
const durationSec = (event.duration / 1e3).toFixed(1);
|
|
34603
|
+
const status = event.failedTasks > 0 ? chalk27.yellow(`\u2713 ${event.completedTasks} completed, ${event.failedTasks} failed`) : chalk27.green(`\u2713 All ${event.completedTasks} task(s) completed`);
|
|
34604
|
+
console.log(chalk27.gray(` ${status} (${durationSec}s)
|
|
34605
|
+
`));
|
|
34606
|
+
}
|
|
34607
|
+
/**
|
|
34608
|
+
* Handle task:started event
|
|
34609
|
+
*/
|
|
34610
|
+
handleTaskStart(event) {
|
|
34611
|
+
this.taskStartTimes.set(event.taskId, Date.now());
|
|
34612
|
+
const progress = `[${this.completedCount + this.failedCount + 1}/${this.taskCount}]`;
|
|
34613
|
+
const text = `${progress} ${event.taskTitle}`;
|
|
34614
|
+
if (this.spinner) {
|
|
34615
|
+
this.spinner.stop();
|
|
34616
|
+
}
|
|
34617
|
+
this.spinner = ora6({
|
|
34618
|
+
text: chalk27.blue(text),
|
|
34619
|
+
spinner: "dots"
|
|
34620
|
+
}).start();
|
|
34621
|
+
}
|
|
34622
|
+
/**
|
|
34623
|
+
* Handle task:completed event
|
|
34624
|
+
*/
|
|
34625
|
+
handleTaskComplete(event) {
|
|
34626
|
+
this.completedCount++;
|
|
34627
|
+
const durationSec = (event.duration / 1e3).toFixed(1);
|
|
34628
|
+
const progress = `[${this.completedCount + this.failedCount}/${this.taskCount}]`;
|
|
34629
|
+
if (this.spinner) {
|
|
34630
|
+
this.spinner.succeed(
|
|
34631
|
+
chalk27.green(`${progress} ${event.taskTitle}`) + chalk27.gray(` (${durationSec}s)`)
|
|
34632
|
+
);
|
|
34633
|
+
this.spinner = null;
|
|
34634
|
+
}
|
|
34635
|
+
}
|
|
34636
|
+
/**
|
|
34637
|
+
* Handle task:failed event
|
|
34638
|
+
*/
|
|
34639
|
+
handleTaskFailed(event) {
|
|
34640
|
+
this.failedCount++;
|
|
34641
|
+
const durationSec = (event.duration / 1e3).toFixed(1);
|
|
34642
|
+
const progress = `[${this.completedCount + this.failedCount}/${this.taskCount}]`;
|
|
34643
|
+
if (this.spinner) {
|
|
34644
|
+
this.spinner.fail(
|
|
34645
|
+
chalk27.red(`${progress} ${event.taskTitle}`) + chalk27.gray(` (${durationSec}s)`)
|
|
34646
|
+
);
|
|
34647
|
+
this.spinner = null;
|
|
34648
|
+
}
|
|
34649
|
+
console.log(chalk27.red(` Error: ${event.error.message}`));
|
|
34650
|
+
if (event.error.stack && process.env.DEBUG) {
|
|
34651
|
+
console.log(chalk27.gray(` Stack: ${event.error.stack.split("\n").slice(0, 3).join("\n")}`));
|
|
34652
|
+
}
|
|
34653
|
+
}
|
|
34654
|
+
/**
|
|
34655
|
+
* Stop rendering
|
|
34656
|
+
*
|
|
34657
|
+
* Cleans up spinner and resets state.
|
|
34658
|
+
*/
|
|
34659
|
+
stop() {
|
|
34660
|
+
if (this.spinner) {
|
|
34661
|
+
this.spinner.stop();
|
|
34662
|
+
this.spinner = null;
|
|
34663
|
+
}
|
|
34664
|
+
}
|
|
34665
|
+
};
|
|
34666
|
+
|
|
34667
|
+
// src/cli/commands/spec.ts
|
|
34408
34668
|
init_path_resolver();
|
|
34409
34669
|
init_claude_provider();
|
|
34410
34670
|
var specCommand = {
|
|
@@ -34438,6 +34698,10 @@ var specCommand = {
|
|
|
34438
34698
|
describe: "Resume from last checkpoint",
|
|
34439
34699
|
type: "boolean",
|
|
34440
34700
|
default: false
|
|
34701
|
+
}).option("no-streaming", {
|
|
34702
|
+
describe: "Disable real-time progress streaming",
|
|
34703
|
+
type: "boolean",
|
|
34704
|
+
default: false
|
|
34441
34705
|
}).option("pending", {
|
|
34442
34706
|
describe: "Show only pending tasks",
|
|
34443
34707
|
type: "boolean",
|
|
@@ -34539,7 +34803,7 @@ async function handleCreate(workspacePath, argv, config) {
|
|
|
34539
34803
|
console.error(chalk27.red("\u2717 Description is required"));
|
|
34540
34804
|
process.exit(1);
|
|
34541
34805
|
}
|
|
34542
|
-
const spinner =
|
|
34806
|
+
const spinner = ora6("Analyzing task complexity...").start();
|
|
34543
34807
|
try {
|
|
34544
34808
|
const claudeConfig = config.providers["claude-code"];
|
|
34545
34809
|
if (!claudeConfig) {
|
|
@@ -34608,7 +34872,7 @@ async function handleCreate(workspacePath, argv, config) {
|
|
|
34608
34872
|
}
|
|
34609
34873
|
}
|
|
34610
34874
|
async function handleRun(workspacePath, argv, config) {
|
|
34611
|
-
const spinner =
|
|
34875
|
+
const spinner = ora6("Loading spec...").start();
|
|
34612
34876
|
try {
|
|
34613
34877
|
const registry = new SpecRegistry({
|
|
34614
34878
|
workspacePath,
|
|
@@ -34663,8 +34927,16 @@ async function handleRun(workspacePath, argv, config) {
|
|
|
34663
34927
|
taskFilter
|
|
34664
34928
|
};
|
|
34665
34929
|
const executor = new SpecExecutor(spec, executorOptions, sessionManager);
|
|
34666
|
-
|
|
34930
|
+
let renderer;
|
|
34931
|
+
if (!argv["no-streaming"]) {
|
|
34932
|
+
renderer = new SpecProgressRenderer(executor);
|
|
34933
|
+
} else {
|
|
34934
|
+
console.log(chalk27.cyan("\u{1F680} Starting execution...\n"));
|
|
34935
|
+
}
|
|
34667
34936
|
const result = await executor.execute();
|
|
34937
|
+
if (renderer) {
|
|
34938
|
+
renderer.stop();
|
|
34939
|
+
}
|
|
34668
34940
|
console.log(chalk27.green("\n\u2705 Execution completed\n"));
|
|
34669
34941
|
console.log(chalk27.cyan("Results:"));
|
|
34670
34942
|
console.log(chalk27.gray(` Total: ${result.totalTasks}`));
|
|
@@ -34681,7 +34953,7 @@ async function handleRun(workspacePath, argv, config) {
|
|
|
34681
34953
|
}
|
|
34682
34954
|
}
|
|
34683
34955
|
async function handleStatus(workspacePath, argv) {
|
|
34684
|
-
const spinner =
|
|
34956
|
+
const spinner = ora6("Loading spec...").start();
|
|
34685
34957
|
try {
|
|
34686
34958
|
const registry = new SpecRegistry({
|
|
34687
34959
|
workspacePath,
|
|
@@ -34749,7 +35021,7 @@ async function handleStatus(workspacePath, argv) {
|
|
|
34749
35021
|
}
|
|
34750
35022
|
}
|
|
34751
35023
|
async function handleValidate(workspacePath, argv) {
|
|
34752
|
-
const spinner =
|
|
35024
|
+
const spinner = ora6("Validating spec...").start();
|
|
34753
35025
|
try {
|
|
34754
35026
|
const registry = new SpecRegistry({
|
|
34755
35027
|
workspacePath,
|
|
@@ -34794,7 +35066,7 @@ async function handleValidate(workspacePath, argv) {
|
|
|
34794
35066
|
}
|
|
34795
35067
|
}
|
|
34796
35068
|
async function handleGraph(workspacePath, argv) {
|
|
34797
|
-
const spinner =
|
|
35069
|
+
const spinner = ora6("Building dependency graph...").start();
|
|
34798
35070
|
try {
|
|
34799
35071
|
const registry = new SpecRegistry({
|
|
34800
35072
|
workspacePath,
|