@litmers/cursorflow-orchestrator 0.2.3 → 0.2.5
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 +14 -0
- package/README.md +7 -11
- package/dist/cli/complete.d.ts +7 -0
- package/dist/cli/complete.js +304 -0
- package/dist/cli/complete.js.map +1 -0
- package/dist/cli/logs.js +51 -61
- package/dist/cli/logs.js.map +1 -1
- package/dist/cli/monitor.js +56 -44
- package/dist/cli/monitor.js.map +1 -1
- package/dist/cli/resume.js +2 -2
- package/dist/cli/resume.js.map +1 -1
- package/dist/core/git-lifecycle-manager.js +2 -2
- package/dist/core/git-lifecycle-manager.js.map +1 -1
- package/dist/core/git-pipeline-coordinator.js +25 -25
- package/dist/core/git-pipeline-coordinator.js.map +1 -1
- package/dist/core/orchestrator.js +8 -7
- package/dist/core/orchestrator.js.map +1 -1
- package/dist/core/runner/pipeline.js +3 -3
- package/dist/core/runner/pipeline.js.map +1 -1
- package/dist/hooks/data-accessor.js +2 -2
- package/dist/hooks/data-accessor.js.map +1 -1
- package/dist/services/logging/buffer.d.ts +1 -2
- package/dist/services/logging/buffer.js +22 -63
- package/dist/services/logging/buffer.js.map +1 -1
- package/dist/services/logging/formatter.d.ts +4 -0
- package/dist/services/logging/formatter.js +201 -33
- package/dist/services/logging/formatter.js.map +1 -1
- package/dist/services/logging/paths.d.ts +0 -3
- package/dist/services/logging/paths.js +0 -3
- package/dist/services/logging/paths.js.map +1 -1
- package/dist/types/config.d.ts +1 -9
- package/dist/types/logging.d.ts +1 -1
- package/dist/utils/config.js +2 -6
- package/dist/utils/config.js.map +1 -1
- package/dist/utils/enhanced-logger.d.ts +17 -37
- package/dist/utils/enhanced-logger.js +237 -267
- package/dist/utils/enhanced-logger.js.map +1 -1
- package/dist/utils/logger.js +17 -4
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils/repro-thinking-logs.js +4 -4
- package/dist/utils/repro-thinking-logs.js.map +1 -1
- package/package.json +2 -2
- package/scripts/monitor-lanes.sh +5 -5
- package/scripts/stream-logs.sh +1 -1
- package/scripts/test-log-parser.ts +8 -42
- package/src/cli/complete.ts +305 -0
- package/src/cli/logs.ts +46 -60
- package/src/cli/monitor.ts +64 -46
- package/src/cli/resume.ts +1 -1
- package/src/core/git-lifecycle-manager.ts +2 -2
- package/src/core/git-pipeline-coordinator.ts +25 -25
- package/src/core/orchestrator.ts +7 -7
- package/src/core/runner/pipeline.ts +3 -3
- package/src/hooks/data-accessor.ts +2 -2
- package/src/services/logging/buffer.ts +20 -68
- package/src/services/logging/formatter.ts +199 -32
- package/src/services/logging/paths.ts +0 -3
- package/src/types/config.ts +1 -13
- package/src/types/logging.ts +2 -0
- package/src/utils/config.ts +2 -6
- package/src/utils/enhanced-logger.ts +239 -290
- package/src/utils/logger.ts +18 -3
- package/src/utils/repro-thinking-logs.ts +4 -4
- package/dist/utils/log-formatter.d.ts +0 -26
- package/dist/utils/log-formatter.js +0 -274
- package/dist/utils/log-formatter.js.map +0 -1
- package/src/utils/log-formatter.ts +0 -287
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,20 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.2.4] - 2025-12-28
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- **Logging**: Introduced tool-specific labels (READ, EDIT, SHLL, etc.) and emojis for better visibility.
|
|
12
|
+
- **Logging**: Added path simplification (absolute path to relative `./`) in tool execution logs.
|
|
13
|
+
|
|
14
|
+
### Improved
|
|
15
|
+
- **Logging**: Enhanced log color consistency by dimming unimportant system and info logs.
|
|
16
|
+
- **Logging**: Improved multi-line thinking message formatting with proper indentation.
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
- **Logging**: Fixed box alignment issues for USER and SYS messages by accurately calculating terminal visual width for emojis.
|
|
20
|
+
- **Logging**: Filtered out redundant or empty agent events from readable logs.
|
|
21
|
+
|
|
8
22
|
## [0.1.37] - 2025-12-26
|
|
9
23
|
|
|
10
24
|
### Fixed
|
package/README.md
CHANGED
|
@@ -313,13 +313,11 @@ Logs use the format `[{n}-{t}-{lanename}]`:
|
|
|
313
313
|
Example: `[1-2-backend]` = Lane 1, Task 2, lane "backend"
|
|
314
314
|
|
|
315
315
|
### Features
|
|
316
|
-
- **ANSI Stripping**:
|
|
317
|
-
- **Timestamps**: Automatic timestamps on each line (ISO
|
|
316
|
+
- **ANSI Stripping**: Logs content without terminal escape codes
|
|
317
|
+
- **Timestamps**: Automatic timestamps on each line (ISO format)
|
|
318
318
|
- **Log Rotation**: Automatic rotation when files exceed size limits
|
|
319
|
-
- **
|
|
320
|
-
- `terminal.
|
|
321
|
-
- `terminal-raw.log` - Raw logs with ANSI codes
|
|
322
|
-
- `terminal.jsonl` - Structured JSON for programmatic access
|
|
319
|
+
- **Unified Format**:
|
|
320
|
+
- `terminal.jsonl` - Structured JSON for programmatic access and human-readable display via `cursorflow logs` or `monitor`.
|
|
323
321
|
|
|
324
322
|
### Usage
|
|
325
323
|
|
|
@@ -327,7 +325,7 @@ Example: `[1-2-backend]` = Lane 1, Task 2, lane "backend"
|
|
|
327
325
|
# View logs summary for latest run
|
|
328
326
|
cursorflow logs
|
|
329
327
|
|
|
330
|
-
# View specific lane logs
|
|
328
|
+
# View specific lane logs (automatically formatted from JSONL)
|
|
331
329
|
cursorflow logs --lane api-setup
|
|
332
330
|
|
|
333
331
|
# View ALL lanes merged (unified timeline)
|
|
@@ -377,12 +375,10 @@ module.exports = {
|
|
|
377
375
|
// ... other config ...
|
|
378
376
|
enhancedLogging: {
|
|
379
377
|
enabled: true, // Enable enhanced logging
|
|
380
|
-
stripAnsi: true, // Strip ANSI codes
|
|
381
|
-
addTimestamps: true, // Add timestamps to each line
|
|
378
|
+
stripAnsi: true, // Strip ANSI codes
|
|
382
379
|
maxFileSize: 52428800, // 50MB max before rotation
|
|
383
380
|
maxFiles: 5, // Keep 5 rotated files
|
|
384
|
-
|
|
385
|
-
writeJsonLog: true, // Generate JSON logs
|
|
381
|
+
writeJsonLog: true, // Generate JSON logs (main format)
|
|
386
382
|
timestampFormat: 'iso', // 'iso' | 'relative' | 'short'
|
|
387
383
|
},
|
|
388
384
|
};
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* CursorFlow 'complete' command
|
|
4
|
+
*
|
|
5
|
+
* Consolidates all lanes of a flow into a single branch and cleans up.
|
|
6
|
+
*/
|
|
7
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
8
|
+
if (k2 === undefined) k2 = k;
|
|
9
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
10
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
11
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
12
|
+
}
|
|
13
|
+
Object.defineProperty(o, k2, desc);
|
|
14
|
+
}) : (function(o, m, k, k2) {
|
|
15
|
+
if (k2 === undefined) k2 = k;
|
|
16
|
+
o[k2] = m[k];
|
|
17
|
+
}));
|
|
18
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
19
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
20
|
+
}) : function(o, v) {
|
|
21
|
+
o["default"] = v;
|
|
22
|
+
});
|
|
23
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
24
|
+
var ownKeys = function(o) {
|
|
25
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
26
|
+
var ar = [];
|
|
27
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
28
|
+
return ar;
|
|
29
|
+
};
|
|
30
|
+
return ownKeys(o);
|
|
31
|
+
};
|
|
32
|
+
return function (mod) {
|
|
33
|
+
if (mod && mod.__esModule) return mod;
|
|
34
|
+
var result = {};
|
|
35
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
36
|
+
__setModuleDefault(result, mod);
|
|
37
|
+
return result;
|
|
38
|
+
};
|
|
39
|
+
})();
|
|
40
|
+
const fs = __importStar(require("fs"));
|
|
41
|
+
const path = __importStar(require("path"));
|
|
42
|
+
const logger = __importStar(require("../utils/logger"));
|
|
43
|
+
const git = __importStar(require("../utils/git"));
|
|
44
|
+
const config_1 = require("../utils/config");
|
|
45
|
+
const path_1 = require("../utils/path");
|
|
46
|
+
const run_service_1 = require("../utils/run-service");
|
|
47
|
+
const flow_1 = require("../utils/flow");
|
|
48
|
+
const process_1 = require("../services/process");
|
|
49
|
+
function printHelp() {
|
|
50
|
+
console.log(`
|
|
51
|
+
\x1b[1mcursorflow complete\x1b[0m - Flow 통합 및 마무리
|
|
52
|
+
|
|
53
|
+
\x1b[1m사용법:\x1b[0m
|
|
54
|
+
cursorflow complete <flow-dir> [options]
|
|
55
|
+
|
|
56
|
+
\x1b[1m설명:\x1b[0m
|
|
57
|
+
모든 레인의 작업이 완료된 후, 각 레인의 브랜치들을 하나의 통합 브랜치로 병합합니다.
|
|
58
|
+
병합이 성공하면 임시로 사용된 레인 브랜치들과 워크트리들을 삭제합니다.
|
|
59
|
+
|
|
60
|
+
\x1b[33m참고:\x1b[0m Flow가 성공적으로 완료되면 자동으로 통합됩니다.
|
|
61
|
+
이 명령어는 자동 통합이 실패했을 때 수동으로 복구하거나,
|
|
62
|
+
특정 옵션으로 통합하고 싶을 때 사용합니다.
|
|
63
|
+
|
|
64
|
+
\x1b[1m옵션:\x1b[0m
|
|
65
|
+
--branch <name> 통합 브랜치 이름 지정 (기본값: feature/<FlowName>-integrated)
|
|
66
|
+
--force 완료되지 않은 레인이 있어도 강제로 진행
|
|
67
|
+
--dry-run 실제로 병합하거나 삭제하지 않고 계획만 출력
|
|
68
|
+
--no-cleanup 병합 후 브랜치 및 워크트리를 삭제하지 않음
|
|
69
|
+
--help, -h 도움말 출력
|
|
70
|
+
|
|
71
|
+
\x1b[1m예시:\x1b[0m
|
|
72
|
+
# 자동 통합 실패 후 수동 복구
|
|
73
|
+
cursorflow complete ShopFeature
|
|
74
|
+
|
|
75
|
+
# 특정 브랜치 이름으로 통합
|
|
76
|
+
cursorflow complete ShopFeature --branch feat/shop-v1
|
|
77
|
+
|
|
78
|
+
# 정리 없이 통합만 수행
|
|
79
|
+
cursorflow complete ShopFeature --no-cleanup
|
|
80
|
+
`);
|
|
81
|
+
}
|
|
82
|
+
function parseArgs(args) {
|
|
83
|
+
const branchIdx = args.indexOf('--branch');
|
|
84
|
+
return {
|
|
85
|
+
flowDir: args.find(a => !a.startsWith('--')),
|
|
86
|
+
targetBranch: branchIdx >= 0 ? args[branchIdx + 1] : undefined,
|
|
87
|
+
force: args.includes('--force'),
|
|
88
|
+
help: args.includes('--help') || args.includes('-h'),
|
|
89
|
+
dryRun: args.includes('--dry-run'),
|
|
90
|
+
noCleanup: args.includes('--no-cleanup'),
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
async function complete(args) {
|
|
94
|
+
const options = parseArgs(args);
|
|
95
|
+
if (options.help) {
|
|
96
|
+
printHelp();
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
const config = (0, config_1.loadConfig)();
|
|
100
|
+
git.setVerboseGit(config.verboseGit || false);
|
|
101
|
+
const repoRoot = git.getRepoRoot();
|
|
102
|
+
const logsDir = (0, config_1.getLogsDir)(config);
|
|
103
|
+
const runService = (0, run_service_1.createRunService)(config.projectRoot);
|
|
104
|
+
// 1. Find Flow Directory
|
|
105
|
+
let flowDir = '';
|
|
106
|
+
if (!options.flowDir) {
|
|
107
|
+
flowDir = (0, flow_1.findLatestFlowOrTask)(config) || '';
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
const flowsDir = (0, path_1.safeJoin)(config.projectRoot, config.flowsDir);
|
|
111
|
+
flowDir = (0, flow_1.findFlowDir)(flowsDir, options.flowDir) || path.resolve(options.flowDir);
|
|
112
|
+
}
|
|
113
|
+
if (!flowDir || !fs.existsSync(flowDir)) {
|
|
114
|
+
throw new Error(`Flow 디렉토리를 찾을 수 없습니다: ${options.flowDir || 'latest'}`);
|
|
115
|
+
}
|
|
116
|
+
logger.section(`🏁 Completing Flow: ${path.basename(flowDir)}`);
|
|
117
|
+
// 2. Find Latest Run
|
|
118
|
+
const runs = runService.listRuns().filter(run => {
|
|
119
|
+
// Check if this run belongs to the target flowDir
|
|
120
|
+
// We look at the first lane's state to check tasksFile
|
|
121
|
+
if (run.lanes.length === 0)
|
|
122
|
+
return false;
|
|
123
|
+
const laneDir = (0, path_1.safeJoin)(run.path, 'lanes', run.lanes[0].name);
|
|
124
|
+
const statePath = (0, path_1.safeJoin)(laneDir, 'state.json');
|
|
125
|
+
if (!fs.existsSync(statePath))
|
|
126
|
+
return false;
|
|
127
|
+
try {
|
|
128
|
+
const state = JSON.parse(fs.readFileSync(statePath, 'utf8'));
|
|
129
|
+
return state.tasksFile && path.resolve(path.dirname(state.tasksFile)) === path.resolve(flowDir);
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
if (runs.length === 0) {
|
|
136
|
+
throw new Error(`이 Flow에 대한 실행 기록(Run)을 찾을 수 없습니다.`);
|
|
137
|
+
}
|
|
138
|
+
const latestRun = runs[0];
|
|
139
|
+
logger.info(`Run ID: ${latestRun.id}`);
|
|
140
|
+
// 3. Verify Status
|
|
141
|
+
const summary = (0, process_1.getFlowSummary)(latestRun.path);
|
|
142
|
+
logger.info(`Status: ${summary.completed}/${summary.total} lanes completed`);
|
|
143
|
+
if (summary.completed < summary.total && !options.force) {
|
|
144
|
+
logger.error(`모든 레인이 완료되지 않았습니다 (${summary.completed}/${summary.total}).`);
|
|
145
|
+
logger.info('완료되지 않은 레인:');
|
|
146
|
+
const statuses = (0, process_1.getAllLaneProcessStatuses)(latestRun.path);
|
|
147
|
+
for (const s of statuses) {
|
|
148
|
+
if (s.actualStatus !== 'completed') {
|
|
149
|
+
logger.info(` - ${s.laneName}: ${s.actualStatus}`);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
logger.info('\n강제로 통합하려면 --force 옵션을 사용하세요.');
|
|
153
|
+
process.exit(1);
|
|
154
|
+
}
|
|
155
|
+
// 4. Determine Target Branch Name
|
|
156
|
+
const flowName = path.basename(flowDir).replace(/^\d+_/, '');
|
|
157
|
+
const targetBranch = options.targetBranch || `feature/${flowName}-integrated`;
|
|
158
|
+
// 5. Get Base Branch from flow.meta.json
|
|
159
|
+
let baseBranch = 'main';
|
|
160
|
+
const metaPath = (0, path_1.safeJoin)(flowDir, 'flow.meta.json');
|
|
161
|
+
if (fs.existsSync(metaPath)) {
|
|
162
|
+
try {
|
|
163
|
+
const meta = JSON.parse(fs.readFileSync(metaPath, 'utf8'));
|
|
164
|
+
baseBranch = meta.baseBranch || 'main';
|
|
165
|
+
}
|
|
166
|
+
catch (e) {
|
|
167
|
+
logger.warn(`flow.meta.json 읽기 실패, 기본값 main 사용: ${e}`);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
logger.info(`Target Branch: ${targetBranch}`);
|
|
171
|
+
logger.info(`Base Branch: ${baseBranch}`);
|
|
172
|
+
const laneBranches = latestRun.lanes
|
|
173
|
+
.filter(l => l.pipelineBranch)
|
|
174
|
+
.map(l => l.pipelineBranch);
|
|
175
|
+
if (laneBranches.length === 0) {
|
|
176
|
+
throw new Error(`통합할 브랜치가 없습니다.`);
|
|
177
|
+
}
|
|
178
|
+
logger.info(`Lanes to merge: ${laneBranches.length}`);
|
|
179
|
+
for (const b of laneBranches) {
|
|
180
|
+
logger.info(` - ${b}`);
|
|
181
|
+
}
|
|
182
|
+
if (options.dryRun) {
|
|
183
|
+
logger.section('🧪 Dry Run: No changes will be made');
|
|
184
|
+
logger.info(`Would create branch '${targetBranch}' from '${baseBranch}'`);
|
|
185
|
+
for (const b of laneBranches) {
|
|
186
|
+
logger.info(`Would merge '${b}' into '${targetBranch}'`);
|
|
187
|
+
}
|
|
188
|
+
if (!options.noCleanup) {
|
|
189
|
+
logger.info(`Would delete ${laneBranches.length} lane branches and ${latestRun.worktrees.length} worktrees`);
|
|
190
|
+
}
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
// 6. Perform Merges
|
|
194
|
+
try {
|
|
195
|
+
// Ensure we are on a clean state in the main repo
|
|
196
|
+
const currentBranch = git.getCurrentBranch(repoRoot);
|
|
197
|
+
if (git.hasUncommittedChanges(repoRoot)) {
|
|
198
|
+
throw new Error('메인 저장소에 커밋되지 않은 변경사항이 있습니다. 커밋하거나 스태시한 후 다시 시도하세요.');
|
|
199
|
+
}
|
|
200
|
+
// Checkout base branch and create target branch
|
|
201
|
+
logger.info(`Creating target branch '${targetBranch}' from '${baseBranch}'...`);
|
|
202
|
+
git.runGit(['checkout', baseBranch], { cwd: repoRoot });
|
|
203
|
+
git.runGit(['checkout', '-B', targetBranch], { cwd: repoRoot });
|
|
204
|
+
// Merge each lane branch
|
|
205
|
+
for (const branch of laneBranches) {
|
|
206
|
+
logger.info(`Merging ${branch}...`);
|
|
207
|
+
// Fetch remote branch if needed
|
|
208
|
+
if (!git.branchExists(branch, { cwd: repoRoot })) {
|
|
209
|
+
logger.info(` Fetching ${branch} from remote...`);
|
|
210
|
+
try {
|
|
211
|
+
git.runGit(['fetch', 'origin', branch], { cwd: repoRoot });
|
|
212
|
+
}
|
|
213
|
+
catch (e) {
|
|
214
|
+
logger.warn(` Failed to fetch ${branch}: ${e}`);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
const branchRef = git.branchExists(branch, { cwd: repoRoot }) ? branch : `origin/${branch}`;
|
|
218
|
+
const mergeResult = git.safeMerge(branchRef, {
|
|
219
|
+
cwd: repoRoot,
|
|
220
|
+
noFf: true,
|
|
221
|
+
message: `chore: merge lane ${branch} into flow integration`,
|
|
222
|
+
abortOnConflict: false, // We'll handle it below
|
|
223
|
+
});
|
|
224
|
+
if (!mergeResult.success) {
|
|
225
|
+
if (mergeResult.conflict) {
|
|
226
|
+
logger.error(`❌ '${branch}' 병합 중 충돌이 발생했습니다.`);
|
|
227
|
+
logger.error(`충돌 파일: ${mergeResult.conflictingFiles.join(', ')}`);
|
|
228
|
+
logger.info('\n충돌을 해결한 후 다시 시도하거나, 수동으로 마무리하세요.');
|
|
229
|
+
// Don't abort here, let the user see the state or suggest cleanup
|
|
230
|
+
throw new Error('Merge conflict occurred during integration.');
|
|
231
|
+
}
|
|
232
|
+
else {
|
|
233
|
+
throw new Error(`병합 실패 (${branch}): ${mergeResult.error}`);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
logger.success(`✓ Merged ${branch}`);
|
|
237
|
+
}
|
|
238
|
+
// 7. Push final branch
|
|
239
|
+
logger.info(`Pushing '${targetBranch}' to remote...`);
|
|
240
|
+
git.push(targetBranch, { cwd: repoRoot, setUpstream: true });
|
|
241
|
+
logger.success(`✓ Pushed ${targetBranch}`);
|
|
242
|
+
// 8. Cleanup
|
|
243
|
+
if (!options.noCleanup) {
|
|
244
|
+
logger.section('🧹 Cleaning Up');
|
|
245
|
+
// Delete local and remote lane branches
|
|
246
|
+
for (const branch of laneBranches) {
|
|
247
|
+
logger.info(`Deleting branch: ${branch}`);
|
|
248
|
+
try {
|
|
249
|
+
git.deleteBranch(branch, { cwd: repoRoot, force: true });
|
|
250
|
+
// Try deleting remote branch too
|
|
251
|
+
try {
|
|
252
|
+
git.deleteBranch(branch, { cwd: repoRoot, remote: true });
|
|
253
|
+
}
|
|
254
|
+
catch {
|
|
255
|
+
// Might not exist on remote or no permission
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
catch (e) {
|
|
259
|
+
logger.warn(` Failed to delete branch ${branch}: ${e}`);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
// Remove worktrees
|
|
263
|
+
for (const wtPath of latestRun.worktrees) {
|
|
264
|
+
if (fs.existsSync(wtPath)) {
|
|
265
|
+
logger.info(`Removing worktree: ${wtPath}`);
|
|
266
|
+
try {
|
|
267
|
+
git.removeWorktree(wtPath, { cwd: repoRoot, force: true });
|
|
268
|
+
if (fs.existsSync(wtPath)) {
|
|
269
|
+
fs.rmSync(wtPath, { recursive: true, force: true });
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
catch (e) {
|
|
273
|
+
logger.warn(` Failed to remove worktree ${wtPath}: ${e}`);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
// Optional: Delete run directory? Maybe keep logs for a while.
|
|
278
|
+
// logger.info(`Deleting run directory: ${latestRun.path}`);
|
|
279
|
+
// fs.rmSync(latestRun.path, { recursive: true, force: true });
|
|
280
|
+
}
|
|
281
|
+
// 9. Update flow status in meta
|
|
282
|
+
if (fs.existsSync(metaPath)) {
|
|
283
|
+
try {
|
|
284
|
+
const meta = JSON.parse(fs.readFileSync(metaPath, 'utf8'));
|
|
285
|
+
meta.status = 'completed';
|
|
286
|
+
meta.integratedBranch = targetBranch;
|
|
287
|
+
meta.integratedAt = new Date().toISOString();
|
|
288
|
+
fs.writeFileSync(metaPath, JSON.stringify(meta, null, 2));
|
|
289
|
+
}
|
|
290
|
+
catch (e) {
|
|
291
|
+
logger.warn(`flow.meta.json 업데이트 실패: ${e}`);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
logger.section(`🎉 Flow Completion Success!`);
|
|
295
|
+
logger.info(`Final integrated branch: ${targetBranch}`);
|
|
296
|
+
logger.info(`You are now on branch: ${targetBranch}`);
|
|
297
|
+
}
|
|
298
|
+
catch (error) {
|
|
299
|
+
logger.error(`\n❌ Flow completion failed: ${error.message}`);
|
|
300
|
+
process.exit(1);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
module.exports = complete;
|
|
304
|
+
//# sourceMappingURL=complete.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"complete.js","sourceRoot":"","sources":["../../src/cli/complete.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/logs.js
CHANGED
|
@@ -41,7 +41,7 @@ const logger = __importStar(require("../utils/logger"));
|
|
|
41
41
|
const config_1 = require("../utils/config");
|
|
42
42
|
const path_1 = require("../utils/path");
|
|
43
43
|
const enhanced_logger_1 = require("../utils/enhanced-logger");
|
|
44
|
-
const
|
|
44
|
+
const formatter_1 = require("../services/logging/formatter");
|
|
45
45
|
const log_constants_1 = require("../utils/log-constants");
|
|
46
46
|
const log_viewer_1 = require("../ui/log-viewer");
|
|
47
47
|
/**
|
|
@@ -154,26 +154,26 @@ function listLanes(runDir) {
|
|
|
154
154
|
.filter(d => fs.statSync((0, path_1.safeJoin)(lanesDir, d)).isDirectory());
|
|
155
155
|
}
|
|
156
156
|
/**
|
|
157
|
-
* Read and display text logs
|
|
157
|
+
* Read and display text logs (converted from JSONL)
|
|
158
158
|
*/
|
|
159
159
|
function displayTextLogs(laneDir, options) {
|
|
160
|
-
|
|
161
|
-
const readableLog = (0, path_1.safeJoin)(laneDir, 'terminal-readable.log');
|
|
162
|
-
const rawLog = (0, path_1.safeJoin)(laneDir, 'terminal-raw.log');
|
|
163
|
-
if (options.raw) {
|
|
164
|
-
logFile = rawLog;
|
|
165
|
-
}
|
|
166
|
-
else {
|
|
167
|
-
// Default to readable log (clean option also uses readable now)
|
|
168
|
-
logFile = readableLog;
|
|
169
|
-
}
|
|
160
|
+
const logFile = (0, path_1.safeJoin)(laneDir, 'terminal.jsonl');
|
|
170
161
|
if (!fs.existsSync(logFile)) {
|
|
171
162
|
console.log('No log file found.');
|
|
172
163
|
return;
|
|
173
164
|
}
|
|
174
|
-
|
|
175
|
-
let lines =
|
|
176
|
-
|
|
165
|
+
const entries = (0, enhanced_logger_1.readJsonLog)(logFile);
|
|
166
|
+
let lines = entries.map(entry => {
|
|
167
|
+
const ts = new Date(entry.timestamp).toLocaleTimeString('en-US', { hour12: false });
|
|
168
|
+
const level = entry.level || 'info';
|
|
169
|
+
const content = entry.content || entry.message || '';
|
|
170
|
+
if (options.raw) {
|
|
171
|
+
// In "raw" mode for JSONL, we show a basic text representation
|
|
172
|
+
return `[${ts}] [${level.toUpperCase()}] ${content}`;
|
|
173
|
+
}
|
|
174
|
+
return `[${ts}] [${level.toUpperCase()}] ${(0, formatter_1.stripAnsi)(content)}`;
|
|
175
|
+
});
|
|
176
|
+
// Apply filter
|
|
177
177
|
if (options.filter) {
|
|
178
178
|
const filterLower = options.filter.toLowerCase();
|
|
179
179
|
lines = lines.filter(line => line.toLowerCase().includes(filterLower));
|
|
@@ -182,10 +182,6 @@ function displayTextLogs(laneDir, options) {
|
|
|
182
182
|
if (options.tail && lines.length > options.tail) {
|
|
183
183
|
lines = lines.slice(-options.tail);
|
|
184
184
|
}
|
|
185
|
-
// Clean ANSI if needed (for clean mode or default fallback)
|
|
186
|
-
if (!options.raw) {
|
|
187
|
-
lines = lines.map(line => (0, enhanced_logger_1.stripAnsi)(line));
|
|
188
|
-
}
|
|
189
185
|
console.log(lines.join('\n'));
|
|
190
186
|
}
|
|
191
187
|
/**
|
|
@@ -207,7 +203,7 @@ function displayMainLogs(runDir, options) {
|
|
|
207
203
|
lines = lines.slice(-options.tail);
|
|
208
204
|
}
|
|
209
205
|
if (options.clean) {
|
|
210
|
-
lines = lines.map(line => (0,
|
|
206
|
+
lines = lines.map(line => (0, formatter_1.stripAnsi)(line));
|
|
211
207
|
}
|
|
212
208
|
console.log(lines.join('\n'));
|
|
213
209
|
}
|
|
@@ -245,7 +241,7 @@ function displayJsonLogs(laneDir, options) {
|
|
|
245
241
|
const message = entry.message || '';
|
|
246
242
|
const levelColor = getLevelColor(level);
|
|
247
243
|
const ts = new Date(entry.timestamp).toLocaleTimeString();
|
|
248
|
-
const formattedMsg = (0,
|
|
244
|
+
const formattedMsg = (0, formatter_1.formatPotentialJsonMessage)(message);
|
|
249
245
|
console.log(`${levelColor}[${ts}] [${level.toUpperCase().padEnd(6)}]${logger.COLORS.reset} ${formattedMsg}`);
|
|
250
246
|
}
|
|
251
247
|
}
|
|
@@ -375,7 +371,7 @@ function displayMergedLogs(runDir, options) {
|
|
|
375
371
|
console.log(`${logger.COLORS.gray}[${ts}]${logger.COLORS.reset} ${laneColor}[${lanePad}]${logger.COLORS.reset} ${logger.COLORS.cyan}── Session Ended ──${logger.COLORS.reset}`);
|
|
376
372
|
continue;
|
|
377
373
|
}
|
|
378
|
-
const formattedMsg = (0,
|
|
374
|
+
const formattedMsg = (0, formatter_1.formatPotentialJsonMessage)(message);
|
|
379
375
|
console.log(`${logger.COLORS.gray}[${ts}]${logger.COLORS.reset} ${laneColor}[${lanePad}]${logger.COLORS.reset} ${levelColor}[${levelPad}]${logger.COLORS.reset} ${formattedMsg}`);
|
|
380
376
|
}
|
|
381
377
|
console.log(`\n${logger.COLORS.cyan}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${logger.COLORS.reset}`);
|
|
@@ -483,7 +479,7 @@ function followAllLogs(runDir, options) {
|
|
|
483
479
|
}
|
|
484
480
|
continue;
|
|
485
481
|
}
|
|
486
|
-
const formattedMsg = (0,
|
|
482
|
+
const formattedMsg = (0, formatter_1.formatPotentialJsonMessage)(message);
|
|
487
483
|
console.log(`${logger.COLORS.gray}[${ts}]${logger.COLORS.reset} ${entry.laneColor}[${lanePad}]${logger.COLORS.reset} ${levelColor}[${levelPad}]${logger.COLORS.reset} ${formattedMsg}`);
|
|
488
484
|
}
|
|
489
485
|
}, 100);
|
|
@@ -619,31 +615,19 @@ function escapeHtml(text) {
|
|
|
619
615
|
* Follow logs in real-time
|
|
620
616
|
*/
|
|
621
617
|
function followLogs(laneDir, options) {
|
|
622
|
-
|
|
623
|
-
const readableLog = (0, path_1.safeJoin)(laneDir, 'terminal-readable.log');
|
|
624
|
-
const rawLog = (0, path_1.safeJoin)(laneDir, 'terminal-raw.log');
|
|
625
|
-
if (options.raw) {
|
|
626
|
-
logFile = rawLog;
|
|
627
|
-
}
|
|
628
|
-
else {
|
|
629
|
-
// Default to readable log
|
|
630
|
-
logFile = readableLog;
|
|
631
|
-
}
|
|
618
|
+
const logFile = (0, path_1.safeJoin)(laneDir, 'terminal.jsonl');
|
|
632
619
|
if (!fs.existsSync(logFile)) {
|
|
633
620
|
console.log('Waiting for log file...');
|
|
634
621
|
}
|
|
635
622
|
let lastSize = 0;
|
|
636
623
|
try {
|
|
637
|
-
// Use statSync directly to avoid TOCTOU race condition
|
|
638
624
|
lastSize = fs.statSync(logFile).size;
|
|
639
625
|
}
|
|
640
626
|
catch {
|
|
641
|
-
// File doesn't exist yet or other error - start from 0
|
|
642
627
|
lastSize = 0;
|
|
643
628
|
}
|
|
644
629
|
console.log(`${logger.COLORS.cyan}Following ${logFile}... (Ctrl+C to stop)${logger.COLORS.reset}\n`);
|
|
645
630
|
const checkInterval = setInterval(() => {
|
|
646
|
-
// Use fstat on open fd to avoid TOCTOU race condition
|
|
647
631
|
let fd = null;
|
|
648
632
|
try {
|
|
649
633
|
fd = fs.openSync(logFile, 'r');
|
|
@@ -651,25 +635,36 @@ function followLogs(laneDir, options) {
|
|
|
651
635
|
if (stats.size > lastSize) {
|
|
652
636
|
const buffer = Buffer.alloc(stats.size - lastSize);
|
|
653
637
|
fs.readSync(fd, buffer, 0, buffer.length, lastSize);
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
638
|
+
const content = buffer.toString();
|
|
639
|
+
const lines = content.split('\n').filter(l => l.trim());
|
|
640
|
+
for (const line of lines) {
|
|
641
|
+
try {
|
|
642
|
+
const entry = JSON.parse(line);
|
|
643
|
+
const ts = new Date(entry.timestamp).toLocaleTimeString('en-US', { hour12: false });
|
|
644
|
+
const level = entry.level || 'info';
|
|
645
|
+
const levelColor = getLevelColor(level);
|
|
646
|
+
const message = entry.content || entry.message || '';
|
|
647
|
+
// Apply level filter
|
|
648
|
+
if (options.level && level !== options.level)
|
|
649
|
+
continue;
|
|
650
|
+
// Apply filter
|
|
651
|
+
if (options.filter) {
|
|
652
|
+
const filterLower = options.filter.toLowerCase();
|
|
653
|
+
if (!message.toLowerCase().includes(filterLower))
|
|
654
|
+
continue;
|
|
655
|
+
}
|
|
656
|
+
const displayMsg = options.raw ? message : (0, formatter_1.stripAnsi)(message);
|
|
657
|
+
console.log(`${logger.COLORS.gray}[${ts}]${logger.COLORS.reset} ${levelColor}[${level.toUpperCase().padEnd(6)}]${logger.COLORS.reset} ${displayMsg}`);
|
|
658
|
+
}
|
|
659
|
+
catch {
|
|
660
|
+
// Skip invalid JSON
|
|
661
|
+
}
|
|
667
662
|
}
|
|
668
663
|
lastSize = stats.size;
|
|
669
664
|
}
|
|
670
665
|
}
|
|
671
666
|
catch {
|
|
672
|
-
// Ignore errors
|
|
667
|
+
// Ignore errors
|
|
673
668
|
}
|
|
674
669
|
finally {
|
|
675
670
|
if (fd !== null) {
|
|
@@ -718,7 +713,7 @@ function followMainLogs(runDir, options) {
|
|
|
718
713
|
content = lines.filter(line => line.toLowerCase().includes(filterLower)).join('\n');
|
|
719
714
|
}
|
|
720
715
|
if (options.clean) {
|
|
721
|
-
content = (0,
|
|
716
|
+
content = (0, formatter_1.stripAnsi)(content);
|
|
722
717
|
}
|
|
723
718
|
if (content.trim()) {
|
|
724
719
|
process.stdout.write(content);
|
|
@@ -758,16 +753,11 @@ function displaySummary(runDir) {
|
|
|
758
753
|
}
|
|
759
754
|
for (const lane of lanes) {
|
|
760
755
|
const laneDir = (0, path_1.safeJoin)(runDir, 'lanes', lane);
|
|
761
|
-
const
|
|
762
|
-
const readableLog = (0, path_1.safeJoin)(laneDir, 'terminal-readable.log');
|
|
756
|
+
const jsonlLog = (0, path_1.safeJoin)(laneDir, 'terminal.jsonl');
|
|
763
757
|
console.log(` ${logger.COLORS.green}📁 ${lane}${logger.COLORS.reset}`);
|
|
764
|
-
if (fs.existsSync(
|
|
765
|
-
const stats = fs.statSync(
|
|
766
|
-
console.log(` └─ terminal
|
|
767
|
-
}
|
|
768
|
-
if (fs.existsSync(rawLog)) {
|
|
769
|
-
const stats = fs.statSync(rawLog);
|
|
770
|
-
console.log(` └─ terminal-raw.log ${formatSize(stats.size)}`);
|
|
758
|
+
if (fs.existsSync(jsonlLog)) {
|
|
759
|
+
const stats = fs.statSync(jsonlLog);
|
|
760
|
+
console.log(` └─ terminal.jsonl ${formatSize(stats.size)} ${logger.COLORS.yellow}(unified)${logger.COLORS.reset}`);
|
|
771
761
|
}
|
|
772
762
|
console.log('');
|
|
773
763
|
}
|
|
@@ -856,7 +846,7 @@ async function logs(args) {
|
|
|
856
846
|
}
|
|
857
847
|
let content = fs.readFileSync(logFile, 'utf8');
|
|
858
848
|
if (options.clean) {
|
|
859
|
-
content = (0,
|
|
849
|
+
content = (0, formatter_1.stripAnsi)(content);
|
|
860
850
|
}
|
|
861
851
|
fs.writeFileSync(options.output, content, 'utf8');
|
|
862
852
|
console.log(`Exported main log to: ${options.output}`);
|