@litmers/cursorflow-orchestrator 0.1.40 → 0.2.3
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 +0 -2
- package/README.md +8 -3
- package/commands/cursorflow-init.md +0 -4
- package/dist/cli/index.js +0 -6
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/logs.js +108 -9
- package/dist/cli/logs.js.map +1 -1
- package/dist/cli/models.js +20 -3
- package/dist/cli/models.js.map +1 -1
- package/dist/cli/monitor.d.ts +7 -10
- package/dist/cli/monitor.js +1103 -1239
- package/dist/cli/monitor.js.map +1 -1
- package/dist/cli/resume.js +21 -1
- package/dist/cli/resume.js.map +1 -1
- package/dist/cli/run.js +28 -9
- package/dist/cli/run.js.map +1 -1
- package/dist/cli/signal.d.ts +6 -1
- package/dist/cli/signal.js +99 -13
- package/dist/cli/signal.js.map +1 -1
- package/dist/cli/tasks.js +3 -46
- package/dist/cli/tasks.js.map +1 -1
- package/dist/core/agent-supervisor.d.ts +23 -0
- package/dist/core/agent-supervisor.js +42 -0
- package/dist/core/agent-supervisor.js.map +1 -0
- package/dist/core/auto-recovery.d.ts +3 -117
- package/dist/core/auto-recovery.js +4 -482
- package/dist/core/auto-recovery.js.map +1 -1
- package/dist/core/failure-policy.d.ts +0 -53
- package/dist/core/failure-policy.js +7 -175
- package/dist/core/failure-policy.js.map +1 -1
- package/dist/core/git-lifecycle-manager.d.ts +284 -0
- package/dist/core/git-lifecycle-manager.js +778 -0
- package/dist/core/git-lifecycle-manager.js.map +1 -0
- package/dist/core/git-pipeline-coordinator.d.ts +21 -0
- package/dist/core/git-pipeline-coordinator.js +205 -0
- package/dist/core/git-pipeline-coordinator.js.map +1 -0
- package/dist/core/intervention.d.ts +170 -0
- package/dist/core/intervention.js +408 -0
- package/dist/core/intervention.js.map +1 -0
- package/dist/core/lane-state-machine.d.ts +423 -0
- package/dist/core/lane-state-machine.js +890 -0
- package/dist/core/lane-state-machine.js.map +1 -0
- package/dist/core/orchestrator.d.ts +4 -1
- package/dist/core/orchestrator.js +39 -65
- package/dist/core/orchestrator.js.map +1 -1
- package/dist/core/runner/agent.d.ts +7 -1
- package/dist/core/runner/agent.js +54 -36
- package/dist/core/runner/agent.js.map +1 -1
- package/dist/core/runner/pipeline.js +283 -123
- package/dist/core/runner/pipeline.js.map +1 -1
- package/dist/core/runner/task.d.ts +4 -5
- package/dist/core/runner/task.js +6 -80
- package/dist/core/runner/task.js.map +1 -1
- package/dist/core/runner.js +8 -2
- package/dist/core/runner.js.map +1 -1
- package/dist/core/stall-detection.d.ts +11 -4
- package/dist/core/stall-detection.js +64 -27
- package/dist/core/stall-detection.js.map +1 -1
- package/dist/hooks/contexts/index.d.ts +104 -0
- package/dist/hooks/contexts/index.js +134 -0
- package/dist/hooks/contexts/index.js.map +1 -0
- package/dist/hooks/data-accessor.d.ts +86 -0
- package/dist/hooks/data-accessor.js +410 -0
- package/dist/hooks/data-accessor.js.map +1 -0
- package/dist/hooks/flow-controller.d.ts +136 -0
- package/dist/hooks/flow-controller.js +351 -0
- package/dist/hooks/flow-controller.js.map +1 -0
- package/dist/hooks/index.d.ts +68 -0
- package/dist/hooks/index.js +105 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/hooks/manager.d.ts +129 -0
- package/dist/hooks/manager.js +389 -0
- package/dist/hooks/manager.js.map +1 -0
- package/dist/hooks/types.d.ts +463 -0
- package/dist/hooks/types.js +45 -0
- package/dist/hooks/types.js.map +1 -0
- package/dist/services/logging/buffer.d.ts +2 -2
- package/dist/services/logging/buffer.js +95 -42
- package/dist/services/logging/buffer.js.map +1 -1
- package/dist/services/logging/console.js +6 -1
- package/dist/services/logging/console.js.map +1 -1
- package/dist/services/logging/formatter.d.ts +9 -4
- package/dist/services/logging/formatter.js +64 -18
- package/dist/services/logging/formatter.js.map +1 -1
- package/dist/services/logging/index.d.ts +0 -1
- package/dist/services/logging/index.js +0 -1
- package/dist/services/logging/index.js.map +1 -1
- package/dist/services/logging/paths.d.ts +8 -0
- package/dist/services/logging/paths.js +48 -0
- package/dist/services/logging/paths.js.map +1 -0
- package/dist/services/logging/raw-log.d.ts +6 -0
- package/dist/services/logging/raw-log.js +37 -0
- package/dist/services/logging/raw-log.js.map +1 -0
- package/dist/services/process/index.js +1 -1
- package/dist/services/process/index.js.map +1 -1
- package/dist/types/agent.d.ts +15 -0
- package/dist/types/config.d.ts +22 -1
- package/dist/types/event-categories.d.ts +601 -0
- package/dist/types/event-categories.js +233 -0
- package/dist/types/event-categories.js.map +1 -0
- package/dist/types/events.d.ts +0 -20
- package/dist/types/flow.d.ts +10 -6
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.js +17 -3
- package/dist/types/index.js.map +1 -1
- package/dist/types/lane.d.ts +1 -1
- package/dist/types/logging.d.ts +1 -1
- package/dist/types/task.d.ts +12 -1
- package/dist/ui/log-viewer.d.ts +3 -0
- package/dist/ui/log-viewer.js +3 -0
- package/dist/ui/log-viewer.js.map +1 -1
- package/dist/utils/config.js +10 -1
- package/dist/utils/config.js.map +1 -1
- package/dist/utils/cursor-agent.d.ts +11 -1
- package/dist/utils/cursor-agent.js +63 -16
- package/dist/utils/cursor-agent.js.map +1 -1
- package/dist/utils/enhanced-logger.d.ts +5 -1
- package/dist/utils/enhanced-logger.js +98 -19
- package/dist/utils/enhanced-logger.js.map +1 -1
- package/dist/utils/event-registry.d.ts +222 -0
- package/dist/utils/event-registry.js +463 -0
- package/dist/utils/event-registry.js.map +1 -0
- package/dist/utils/events.d.ts +1 -13
- package/dist/utils/events.js.map +1 -1
- package/dist/utils/flow.d.ts +10 -0
- package/dist/utils/flow.js +75 -0
- package/dist/utils/flow.js.map +1 -1
- package/dist/utils/log-constants.d.ts +1 -0
- package/dist/utils/log-constants.js +2 -1
- package/dist/utils/log-constants.js.map +1 -1
- package/dist/utils/log-formatter.d.ts +2 -1
- package/dist/utils/log-formatter.js +10 -10
- package/dist/utils/log-formatter.js.map +1 -1
- package/dist/utils/logger.d.ts +11 -0
- package/dist/utils/logger.js +82 -3
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils/repro-thinking-logs.js +0 -13
- package/dist/utils/repro-thinking-logs.js.map +1 -1
- package/dist/utils/run-service.js +1 -1
- package/dist/utils/run-service.js.map +1 -1
- package/examples/README.md +0 -2
- package/examples/demo-project/README.md +1 -2
- package/package.json +13 -34
- package/scripts/setup-security.sh +0 -1
- package/scripts/test-log-parser.ts +171 -0
- package/scripts/verify-change.sh +272 -0
- package/src/cli/index.ts +0 -6
- package/src/cli/logs.ts +121 -10
- package/src/cli/models.ts +20 -3
- package/src/cli/monitor.ts +1273 -1342
- package/src/cli/resume.ts +27 -1
- package/src/cli/run.ts +29 -11
- package/src/cli/signal.ts +120 -18
- package/src/cli/tasks.ts +2 -59
- package/src/core/agent-supervisor.ts +64 -0
- package/src/core/auto-recovery.ts +14 -590
- package/src/core/failure-policy.ts +7 -229
- package/src/core/git-lifecycle-manager.ts +1011 -0
- package/src/core/git-pipeline-coordinator.ts +221 -0
- package/src/core/intervention.ts +463 -0
- package/src/core/lane-state-machine.ts +1097 -0
- package/src/core/orchestrator.ts +48 -64
- package/src/core/runner/agent.ts +77 -39
- package/src/core/runner/pipeline.ts +318 -138
- package/src/core/runner/task.ts +12 -97
- package/src/core/runner.ts +8 -2
- package/src/core/stall-detection.ts +74 -27
- package/src/hooks/contexts/index.ts +256 -0
- package/src/hooks/data-accessor.ts +488 -0
- package/src/hooks/flow-controller.ts +425 -0
- package/src/hooks/index.ts +154 -0
- package/src/hooks/manager.ts +434 -0
- package/src/hooks/types.ts +544 -0
- package/src/services/logging/buffer.ts +104 -43
- package/src/services/logging/console.ts +7 -1
- package/src/services/logging/formatter.ts +74 -18
- package/src/services/logging/index.ts +0 -2
- package/src/services/logging/paths.ts +14 -0
- package/src/services/logging/raw-log.ts +43 -0
- package/src/services/process/index.ts +1 -1
- package/src/types/agent.ts +15 -0
- package/src/types/config.ts +23 -1
- package/src/types/event-categories.ts +663 -0
- package/src/types/events.ts +0 -25
- package/src/types/flow.ts +10 -6
- package/src/types/index.ts +50 -4
- package/src/types/lane.ts +1 -2
- package/src/types/logging.ts +2 -1
- package/src/types/task.ts +12 -1
- package/src/ui/log-viewer.ts +3 -0
- package/src/utils/config.ts +11 -1
- package/src/utils/cursor-agent.ts +68 -16
- package/src/utils/enhanced-logger.ts +105 -19
- package/src/utils/event-registry.ts +595 -0
- package/src/utils/events.ts +0 -16
- package/src/utils/flow.ts +83 -0
- package/src/utils/log-constants.ts +2 -1
- package/src/utils/log-formatter.ts +10 -11
- package/src/utils/logger.ts +49 -3
- package/src/utils/repro-thinking-logs.ts +0 -15
- package/src/utils/run-service.ts +1 -1
- package/dist/cli/prepare.d.ts +0 -7
- package/dist/cli/prepare.js +0 -690
- package/dist/cli/prepare.js.map +0 -1
- package/dist/services/logging/file-writer.d.ts +0 -71
- package/dist/services/logging/file-writer.js +0 -516
- package/dist/services/logging/file-writer.js.map +0 -1
- package/dist/types/review.d.ts +0 -17
- package/dist/types/review.js +0 -6
- package/dist/types/review.js.map +0 -1
- package/scripts/ai-security-check.js +0 -233
- package/src/cli/prepare.ts +0 -777
- package/src/services/logging/file-writer.ts +0 -526
- package/src/types/review.ts +0 -20
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* CursorFlow Hook System - Flow Controller Implementation
|
|
4
|
+
*
|
|
5
|
+
* Hook 핸들러에서 실행 플로우를 제어하기 위한 구현체입니다.
|
|
6
|
+
* pause, resume, injectTask 등의 기능을 제공합니다.
|
|
7
|
+
*/
|
|
8
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
9
|
+
if (k2 === undefined) k2 = k;
|
|
10
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
11
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
13
|
+
}
|
|
14
|
+
Object.defineProperty(o, k2, desc);
|
|
15
|
+
}) : (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
o[k2] = m[k];
|
|
18
|
+
}));
|
|
19
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
20
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
21
|
+
}) : function(o, v) {
|
|
22
|
+
o["default"] = v;
|
|
23
|
+
});
|
|
24
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
+
var ownKeys = function(o) {
|
|
26
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
+
var ar = [];
|
|
28
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
+
return ar;
|
|
30
|
+
};
|
|
31
|
+
return ownKeys(o);
|
|
32
|
+
};
|
|
33
|
+
return function (mod) {
|
|
34
|
+
if (mod && mod.__esModule) return mod;
|
|
35
|
+
var result = {};
|
|
36
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
+
__setModuleDefault(result, mod);
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
40
|
+
})();
|
|
41
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
+
exports.FlowRetryError = exports.FlowAbortError = exports.FlowControllerImpl = void 0;
|
|
43
|
+
exports.createFlowController = createFlowController;
|
|
44
|
+
const fs = __importStar(require("fs"));
|
|
45
|
+
const path_1 = require("../utils/path");
|
|
46
|
+
const logger = __importStar(require("../utils/logger"));
|
|
47
|
+
const events_1 = require("../utils/events");
|
|
48
|
+
// ============================================================================
|
|
49
|
+
// Flow Controller Implementation
|
|
50
|
+
// ============================================================================
|
|
51
|
+
/**
|
|
52
|
+
* FlowController 구현체
|
|
53
|
+
*/
|
|
54
|
+
class FlowControllerImpl {
|
|
55
|
+
options;
|
|
56
|
+
state;
|
|
57
|
+
pauseResolver = null;
|
|
58
|
+
constructor(options) {
|
|
59
|
+
this.options = options;
|
|
60
|
+
this.state = {
|
|
61
|
+
isPaused: false,
|
|
62
|
+
isAborted: false,
|
|
63
|
+
shouldRetry: false,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
// ==========================================================================
|
|
67
|
+
// Flow Control Methods
|
|
68
|
+
// ==========================================================================
|
|
69
|
+
/**
|
|
70
|
+
* 플로우 일시 중지
|
|
71
|
+
*/
|
|
72
|
+
async pause(reason) {
|
|
73
|
+
if (this.state.isPaused) {
|
|
74
|
+
logger.warn(`[Hook] Already paused, ignoring duplicate pause request`);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
this.state.isPaused = true;
|
|
78
|
+
this.state.reason = reason;
|
|
79
|
+
logger.info(`[Hook] Flow paused: ${reason}`);
|
|
80
|
+
// 이벤트 발행
|
|
81
|
+
events_1.events.emit('lane.paused', {
|
|
82
|
+
laneName: this.options.laneName,
|
|
83
|
+
reason,
|
|
84
|
+
});
|
|
85
|
+
// Pause 상태 파일 생성 (외부에서 확인 가능)
|
|
86
|
+
const pauseFile = (0, path_1.safeJoin)(this.options.runDir, 'paused.json');
|
|
87
|
+
fs.writeFileSync(pauseFile, JSON.stringify({
|
|
88
|
+
paused: true,
|
|
89
|
+
reason,
|
|
90
|
+
timestamp: Date.now(),
|
|
91
|
+
}, null, 2));
|
|
92
|
+
// resume이 호출될 때까지 대기
|
|
93
|
+
return new Promise((resolve) => {
|
|
94
|
+
this.pauseResolver = (data) => {
|
|
95
|
+
this.state.isPaused = false;
|
|
96
|
+
this.state.resumeData = data;
|
|
97
|
+
// Pause 파일 삭제
|
|
98
|
+
try {
|
|
99
|
+
fs.unlinkSync(pauseFile);
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
// Ignore
|
|
103
|
+
}
|
|
104
|
+
resolve();
|
|
105
|
+
};
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* 플로우 재개
|
|
110
|
+
*/
|
|
111
|
+
resume(data) {
|
|
112
|
+
if (!this.state.isPaused) {
|
|
113
|
+
logger.warn(`[Hook] Not paused, ignoring resume request`);
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
logger.info(`[Hook] Flow resumed`);
|
|
117
|
+
// 이벤트 발행
|
|
118
|
+
events_1.events.emit('lane.resumed', {
|
|
119
|
+
laneName: this.options.laneName,
|
|
120
|
+
});
|
|
121
|
+
if (this.pauseResolver) {
|
|
122
|
+
this.pauseResolver(data);
|
|
123
|
+
this.pauseResolver = null;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Lane 중단
|
|
128
|
+
*/
|
|
129
|
+
abort(reason) {
|
|
130
|
+
this.state.isAborted = true;
|
|
131
|
+
this.state.reason = reason;
|
|
132
|
+
logger.error(`[Hook] Flow aborted: ${reason}`);
|
|
133
|
+
// 이벤트 발행
|
|
134
|
+
events_1.events.emit('lane.failed', {
|
|
135
|
+
laneName: this.options.laneName,
|
|
136
|
+
exitCode: 1,
|
|
137
|
+
error: reason,
|
|
138
|
+
});
|
|
139
|
+
// Abort 예외 던지기 (Runner에서 catch)
|
|
140
|
+
throw new FlowAbortError(reason);
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* 현재 태스크 재시도
|
|
144
|
+
*/
|
|
145
|
+
retry(options) {
|
|
146
|
+
this.state.shouldRetry = true;
|
|
147
|
+
this.state.retryPrompt = options?.modifiedPrompt;
|
|
148
|
+
logger.info(`[Hook] Task retry requested${options?.modifiedPrompt ? ' with modified prompt' : ''}`);
|
|
149
|
+
throw new FlowRetryError(options?.modifiedPrompt);
|
|
150
|
+
}
|
|
151
|
+
// ==========================================================================
|
|
152
|
+
// Task Manipulation Methods
|
|
153
|
+
// ==========================================================================
|
|
154
|
+
/**
|
|
155
|
+
* 다음에 실행할 태스크 삽입
|
|
156
|
+
*/
|
|
157
|
+
injectTask(task) {
|
|
158
|
+
const insertIndex = this.options.currentTaskIndex + 1;
|
|
159
|
+
// 태스크 배열에 삽입
|
|
160
|
+
this.options.tasks.splice(insertIndex, 0, task);
|
|
161
|
+
logger.info(`[Hook] Injected task "${task.name}" at index ${insertIndex}`);
|
|
162
|
+
// tasks.json 파일 업데이트
|
|
163
|
+
this.persistTasks();
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* 현재 태스크 프롬프트 수정 (beforeTask에서만 유효)
|
|
167
|
+
*/
|
|
168
|
+
modifyCurrentPrompt(newPrompt) {
|
|
169
|
+
this.state.modifiedCurrentPrompt = newPrompt;
|
|
170
|
+
const currentTask = this.options.tasks[this.options.currentTaskIndex];
|
|
171
|
+
if (currentTask) {
|
|
172
|
+
logger.info(`[Hook] Modified prompt for task "${currentTask.name}"`);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* 다음 태스크 수정
|
|
177
|
+
*/
|
|
178
|
+
modifyNextTask(modifier) {
|
|
179
|
+
const nextIndex = this.options.currentTaskIndex + 1;
|
|
180
|
+
if (nextIndex >= this.options.tasks.length) {
|
|
181
|
+
logger.warn(`[Hook] No next task to modify`);
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
const nextTask = this.options.tasks[nextIndex];
|
|
185
|
+
const modifiedTask = modifier(nextTask);
|
|
186
|
+
this.options.tasks[nextIndex] = modifiedTask;
|
|
187
|
+
logger.info(`[Hook] Modified next task "${modifiedTask.name}"`);
|
|
188
|
+
// tasks.json 파일 업데이트
|
|
189
|
+
this.persistTasks();
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* 남은 태스크 전체 교체
|
|
193
|
+
*/
|
|
194
|
+
replaceRemainingTasks(tasks) {
|
|
195
|
+
const currentIndex = this.options.currentTaskIndex;
|
|
196
|
+
// 현재까지의 태스크 유지, 이후 교체
|
|
197
|
+
const completedTasks = this.options.tasks.slice(0, currentIndex + 1);
|
|
198
|
+
this.options.tasks.length = 0;
|
|
199
|
+
this.options.tasks.push(...completedTasks, ...tasks);
|
|
200
|
+
logger.info(`[Hook] Replaced remaining tasks with ${tasks.length} new tasks`);
|
|
201
|
+
// tasks.json 파일 업데이트
|
|
202
|
+
this.persistTasks();
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* tasks.json 파일에 변경사항 저장
|
|
206
|
+
*/
|
|
207
|
+
persistTasks() {
|
|
208
|
+
try {
|
|
209
|
+
const tasksFile = this.options.tasksFile;
|
|
210
|
+
if (fs.existsSync(tasksFile)) {
|
|
211
|
+
const config = JSON.parse(fs.readFileSync(tasksFile, 'utf8'));
|
|
212
|
+
config.tasks = this.options.tasks;
|
|
213
|
+
fs.writeFileSync(tasksFile, JSON.stringify(config, null, 2));
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
catch (error) {
|
|
217
|
+
logger.warn(`[Hook] Failed to persist tasks: ${error}`);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
// ==========================================================================
|
|
221
|
+
// Agent Communication Methods
|
|
222
|
+
// ==========================================================================
|
|
223
|
+
/**
|
|
224
|
+
* AI 에이전트에게 메시지 전송 (현재 세션)
|
|
225
|
+
*/
|
|
226
|
+
async sendMessage(message) {
|
|
227
|
+
const { agentSupervisor, worktreeDir, chatId, laneName, runDir } = this.options;
|
|
228
|
+
if (!agentSupervisor) {
|
|
229
|
+
throw new Error('AgentSupervisor not available');
|
|
230
|
+
}
|
|
231
|
+
logger.info(`[Hook] Sending message to agent`);
|
|
232
|
+
try {
|
|
233
|
+
const result = await agentSupervisor.sendTaskPrompt({
|
|
234
|
+
workspaceDir: worktreeDir,
|
|
235
|
+
chatId,
|
|
236
|
+
prompt: message,
|
|
237
|
+
laneName,
|
|
238
|
+
signalDir: runDir,
|
|
239
|
+
taskName: 'hook-intervention',
|
|
240
|
+
});
|
|
241
|
+
return result.resultText || '';
|
|
242
|
+
}
|
|
243
|
+
catch (error) {
|
|
244
|
+
logger.error(`[Hook] Failed to send message: ${error.message}`);
|
|
245
|
+
throw error;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* 별도 AI 호출 (새 세션)
|
|
250
|
+
*/
|
|
251
|
+
async callAI(prompt, options) {
|
|
252
|
+
const { agentSupervisor, worktreeDir, laneName, runDir } = this.options;
|
|
253
|
+
if (!agentSupervisor) {
|
|
254
|
+
throw new Error('AgentSupervisor not available');
|
|
255
|
+
}
|
|
256
|
+
logger.info(`[Hook] Calling AI with new session`);
|
|
257
|
+
try {
|
|
258
|
+
// 새 채팅 세션 생성
|
|
259
|
+
const newChatId = agentSupervisor.createChat(worktreeDir);
|
|
260
|
+
const result = await agentSupervisor.sendTaskPrompt({
|
|
261
|
+
workspaceDir: worktreeDir,
|
|
262
|
+
chatId: newChatId,
|
|
263
|
+
prompt,
|
|
264
|
+
model: options?.model,
|
|
265
|
+
laneName,
|
|
266
|
+
signalDir: runDir,
|
|
267
|
+
timeout: options?.timeout,
|
|
268
|
+
taskName: 'hook-ai-call',
|
|
269
|
+
});
|
|
270
|
+
return result.resultText || '';
|
|
271
|
+
}
|
|
272
|
+
catch (error) {
|
|
273
|
+
logger.error(`[Hook] Failed to call AI: ${error.message}`);
|
|
274
|
+
throw error;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
// ==========================================================================
|
|
278
|
+
// State Access Methods
|
|
279
|
+
// ==========================================================================
|
|
280
|
+
/**
|
|
281
|
+
* 현재 상태 조회
|
|
282
|
+
*/
|
|
283
|
+
getState() {
|
|
284
|
+
return { ...this.state };
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* 수정된 프롬프트 조회 (beforeTask에서 설정된 경우)
|
|
288
|
+
*/
|
|
289
|
+
getModifiedPrompt() {
|
|
290
|
+
return this.state.modifiedCurrentPrompt;
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* 재개 데이터 조회
|
|
294
|
+
*/
|
|
295
|
+
getResumeData() {
|
|
296
|
+
return this.state.resumeData;
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* 상태 리셋
|
|
300
|
+
*/
|
|
301
|
+
resetState() {
|
|
302
|
+
this.state = {
|
|
303
|
+
isPaused: false,
|
|
304
|
+
isAborted: false,
|
|
305
|
+
shouldRetry: false,
|
|
306
|
+
};
|
|
307
|
+
this.pauseResolver = null;
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* 옵션 업데이트
|
|
311
|
+
*/
|
|
312
|
+
updateOptions(updates) {
|
|
313
|
+
this.options = { ...this.options, ...updates };
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
exports.FlowControllerImpl = FlowControllerImpl;
|
|
317
|
+
// ============================================================================
|
|
318
|
+
// Custom Errors
|
|
319
|
+
// ============================================================================
|
|
320
|
+
/**
|
|
321
|
+
* Flow 중단 에러
|
|
322
|
+
*/
|
|
323
|
+
class FlowAbortError extends Error {
|
|
324
|
+
constructor(reason) {
|
|
325
|
+
super(`Flow aborted: ${reason}`);
|
|
326
|
+
this.name = 'FlowAbortError';
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
exports.FlowAbortError = FlowAbortError;
|
|
330
|
+
/**
|
|
331
|
+
* Flow 재시도 에러
|
|
332
|
+
*/
|
|
333
|
+
class FlowRetryError extends Error {
|
|
334
|
+
modifiedPrompt;
|
|
335
|
+
constructor(modifiedPrompt) {
|
|
336
|
+
super('Flow retry requested');
|
|
337
|
+
this.name = 'FlowRetryError';
|
|
338
|
+
this.modifiedPrompt = modifiedPrompt;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
exports.FlowRetryError = FlowRetryError;
|
|
342
|
+
// ============================================================================
|
|
343
|
+
// Factory Function
|
|
344
|
+
// ============================================================================
|
|
345
|
+
/**
|
|
346
|
+
* FlowController 인스턴스 생성
|
|
347
|
+
*/
|
|
348
|
+
function createFlowController(options) {
|
|
349
|
+
return new FlowControllerImpl(options);
|
|
350
|
+
}
|
|
351
|
+
//# sourceMappingURL=flow-controller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flow-controller.js","sourceRoot":"","sources":["../../src/hooks/flow-controller.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgaH,oDAEC;AAhaD,uCAAyB;AACzB,wCAAyC;AACzC,wDAA0C;AAC1C,4CAAyC;AAsDzC,+EAA+E;AAC/E,iCAAiC;AACjC,+EAA+E;AAE/E;;GAEG;AACH,MAAa,kBAAkB;IACrB,OAAO,CAAwB;IAC/B,KAAK,CAAmB;IACxB,aAAa,GAAkC,IAAI,CAAC;IAE5D,YAAY,OAA8B;QACxC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,KAAK,GAAG;YACX,QAAQ,EAAE,KAAK;YACf,SAAS,EAAE,KAAK;YAChB,WAAW,EAAE,KAAK;SACnB,CAAC;IACJ,CAAC;IAED,6EAA6E;IAC7E,uBAAuB;IACvB,6EAA6E;IAE7E;;OAEG;IACH,KAAK,CAAC,KAAK,CAAC,MAAc;QACxB,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;YACxB,MAAM,CAAC,IAAI,CAAC,yDAAyD,CAAC,CAAC;YACvE,OAAO;QACT,CAAC;QAED,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC;QAC3B,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC;QAE3B,MAAM,CAAC,IAAI,CAAC,uBAAuB,MAAM,EAAE,CAAC,CAAC;QAE7C,SAAS;QACT,eAAM,CAAC,IAAI,CAAC,aAAoB,EAAE;YAChC,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,QAAQ;YAC/B,MAAM;SACP,CAAC,CAAC;QAEH,8BAA8B;QAC9B,MAAM,SAAS,GAAG,IAAA,eAAQ,EAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;QAC/D,EAAE,CAAC,aAAa,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC;YACzC,MAAM,EAAE,IAAI;YACZ,MAAM;YACN,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;SACtB,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAEb,qBAAqB;QACrB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YAC7B,IAAI,CAAC,aAAa,GAAG,CAAC,IAAI,EAAE,EAAE;gBAC5B,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,KAAK,CAAC;gBAC5B,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,IAAI,CAAC;gBAE7B,cAAc;gBACd,IAAI,CAAC;oBACH,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;gBAC3B,CAAC;gBAAC,MAAM,CAAC;oBACP,SAAS;gBACX,CAAC;gBAED,OAAO,EAAE,CAAC;YACZ,CAAC,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,IAAU;QACf,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;YACzB,MAAM,CAAC,IAAI,CAAC,4CAA4C,CAAC,CAAC;YAC1D,OAAO;QACT,CAAC;QAED,MAAM,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;QAEnC,SAAS;QACT,eAAM,CAAC,IAAI,CAAC,cAAqB,EAAE;YACjC,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,QAAQ;SAChC,CAAC,CAAC;QAEH,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACvB,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;YACzB,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;QAC5B,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,MAAc;QAClB,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC;QAC5B,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC;QAE3B,MAAM,CAAC,KAAK,CAAC,wBAAwB,MAAM,EAAE,CAAC,CAAC;QAE/C,SAAS;QACT,eAAM,CAAC,IAAI,CAAC,aAAoB,EAAE;YAChC,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,QAAQ;YAC/B,QAAQ,EAAE,CAAC;YACX,KAAK,EAAE,MAAM;SACd,CAAC,CAAC;QAEH,gCAAgC;QAChC,MAAM,IAAI,cAAc,CAAC,MAAM,CAAC,CAAC;IACnC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,OAAqC;QACzC,IAAI,CAAC,KAAK,CAAC,WAAW,GAAG,IAAI,CAAC;QAC9B,IAAI,CAAC,KAAK,CAAC,WAAW,GAAG,OAAO,EAAE,cAAc,CAAC;QAEjD,MAAM,CAAC,IAAI,CAAC,8BAA8B,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC,uBAAuB,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAEpG,MAAM,IAAI,cAAc,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;IACpD,CAAC;IAED,6EAA6E;IAC7E,4BAA4B;IAC5B,6EAA6E;IAE7E;;OAEG;IACH,UAAU,CAAC,IAAoB;QAC7B,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,gBAAgB,GAAG,CAAC,CAAC;QAEtD,aAAa;QACb,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC;QAEhD,MAAM,CAAC,IAAI,CAAC,yBAAyB,IAAI,CAAC,IAAI,cAAc,WAAW,EAAE,CAAC,CAAC;QAE3E,qBAAqB;QACrB,IAAI,CAAC,YAAY,EAAE,CAAC;IACtB,CAAC;IAED;;OAEG;IACH,mBAAmB,CAAC,SAAiB;QACnC,IAAI,CAAC,KAAK,CAAC,qBAAqB,GAAG,SAAS,CAAC;QAE7C,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;QACtE,IAAI,WAAW,EAAE,CAAC;YAChB,MAAM,CAAC,IAAI,CAAC,oCAAoC,WAAW,CAAC,IAAI,GAAG,CAAC,CAAC;QACvE,CAAC;IACH,CAAC;IAED;;OAEG;IACH,cAAc,CAAC,QAAkD;QAC/D,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,gBAAgB,GAAG,CAAC,CAAC;QAEpD,IAAI,SAAS,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;YAC3C,MAAM,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC;YAC7C,OAAO;QACT,CAAC;QAED,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QAC/C,MAAM,YAAY,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACxC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,GAAG,YAAY,CAAC;QAE7C,MAAM,CAAC,IAAI,CAAC,8BAA8B,YAAY,CAAC,IAAI,GAAG,CAAC,CAAC;QAEhE,qBAAqB;QACrB,IAAI,CAAC,YAAY,EAAE,CAAC;IACtB,CAAC;IAED;;OAEG;IACH,qBAAqB,CAAC,KAAuB;QAC3C,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC;QAEnD,sBAAsB;QACtB,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,YAAY,GAAG,CAAC,CAAC,CAAC;QACrE,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;QAC9B,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,cAAc,EAAE,GAAG,KAAK,CAAC,CAAC;QAErD,MAAM,CAAC,IAAI,CAAC,wCAAwC,KAAK,CAAC,MAAM,YAAY,CAAC,CAAC;QAE9E,qBAAqB;QACrB,IAAI,CAAC,YAAY,EAAE,CAAC;IACtB,CAAC;IAED;;OAEG;IACK,YAAY;QAClB,IAAI,CAAC;YACH,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC;YAEzC,IAAI,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC7B,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC;gBAC9D,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC;gBAClC,EAAE,CAAC,aAAa,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YAC/D,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,IAAI,CAAC,mCAAmC,KAAK,EAAE,CAAC,CAAC;QAC1D,CAAC;IACH,CAAC;IAED,6EAA6E;IAC7E,8BAA8B;IAC9B,6EAA6E;IAE7E;;OAEG;IACH,KAAK,CAAC,WAAW,CAAC,OAAe;QAC/B,MAAM,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC;QAEhF,IAAI,CAAC,eAAe,EAAE,CAAC;YACrB,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;QACnD,CAAC;QAED,MAAM,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC;QAE/C,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,cAAc,CAAC;gBAClD,YAAY,EAAE,WAAW;gBACzB,MAAM;gBACN,MAAM,EAAE,OAAO;gBACf,QAAQ;gBACR,SAAS,EAAE,MAAM;gBACjB,QAAQ,EAAE,mBAAmB;aAC9B,CAAC,CAAC;YAEH,OAAO,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC;QACjC,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,MAAM,CAAC,KAAK,CAAC,kCAAkC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YAChE,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,MAAM,CAAC,MAAc,EAAE,OAAuB;QAClD,MAAM,EAAE,eAAe,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC;QAExE,IAAI,CAAC,eAAe,EAAE,CAAC;YACrB,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;QACnD,CAAC;QAED,MAAM,CAAC,IAAI,CAAC,oCAAoC,CAAC,CAAC;QAElD,IAAI,CAAC;YACH,aAAa;YACb,MAAM,SAAS,GAAG,eAAe,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;YAE1D,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,cAAc,CAAC;gBAClD,YAAY,EAAE,WAAW;gBACzB,MAAM,EAAE,SAAS;gBACjB,MAAM;gBACN,KAAK,EAAE,OAAO,EAAE,KAAK;gBACrB,QAAQ;gBACR,SAAS,EAAE,MAAM;gBACjB,OAAO,EAAE,OAAO,EAAE,OAAO;gBACzB,QAAQ,EAAE,cAAc;aACzB,CAAC,CAAC;YAEH,OAAO,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC;QACjC,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,MAAM,CAAC,KAAK,CAAC,6BAA6B,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YAC3D,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED,6EAA6E;IAC7E,uBAAuB;IACvB,6EAA6E;IAE7E;;OAEG;IACH,QAAQ;QACN,OAAO,EAAE,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC;IAC3B,CAAC;IAED;;OAEG;IACH,iBAAiB;QACf,OAAO,IAAI,CAAC,KAAK,CAAC,qBAAqB,CAAC;IAC1C,CAAC;IAED;;OAEG;IACH,aAAa;QACX,OAAO,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC;IAC/B,CAAC;IAED;;OAEG;IACH,UAAU;QACR,IAAI,CAAC,KAAK,GAAG;YACX,QAAQ,EAAE,KAAK;YACf,SAAS,EAAE,KAAK;YAChB,WAAW,EAAE,KAAK;SACnB,CAAC;QACF,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;IAC5B,CAAC;IAED;;OAEG;IACH,aAAa,CAAC,OAAuC;QACnD,IAAI,CAAC,OAAO,GAAG,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,GAAG,OAAO,EAAE,CAAC;IACjD,CAAC;CACF;AA1TD,gDA0TC;AAED,+EAA+E;AAC/E,gBAAgB;AAChB,+EAA+E;AAE/E;;GAEG;AACH,MAAa,cAAe,SAAQ,KAAK;IACvC,YAAY,MAAc;QACxB,KAAK,CAAC,iBAAiB,MAAM,EAAE,CAAC,CAAC;QACjC,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;IAC/B,CAAC;CACF;AALD,wCAKC;AAED;;GAEG;AACH,MAAa,cAAe,SAAQ,KAAK;IAChC,cAAc,CAAU;IAE/B,YAAY,cAAuB;QACjC,KAAK,CAAC,sBAAsB,CAAC,CAAC;QAC9B,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;QAC7B,IAAI,CAAC,cAAc,GAAG,cAAc,CAAC;IACvC,CAAC;CACF;AARD,wCAQC;AAED,+EAA+E;AAC/E,mBAAmB;AACnB,+EAA+E;AAE/E;;GAEG;AACH,SAAgB,oBAAoB,CAAC,OAA8B;IACjE,OAAO,IAAI,kBAAkB,CAAC,OAAO,CAAC,CAAC;AACzC,CAAC"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CursorFlow Hook System
|
|
3
|
+
*
|
|
4
|
+
* 외부 개발자가 Supervisor AI, 모니터링 시스템, 커스텀 로직 등을
|
|
5
|
+
* 구현할 수 있도록 제공하는 Hook API입니다.
|
|
6
|
+
*
|
|
7
|
+
* ## Quick Start
|
|
8
|
+
*
|
|
9
|
+
* ```typescript
|
|
10
|
+
* import { hooks, HookPoint } from '@litmers/cursorflow-orchestrator';
|
|
11
|
+
*
|
|
12
|
+
* // 태스크 완료 후 결과 리뷰
|
|
13
|
+
* hooks.register({
|
|
14
|
+
* point: HookPoint.AFTER_TASK,
|
|
15
|
+
* mode: 'sync',
|
|
16
|
+
* name: 'my-reviewer',
|
|
17
|
+
* handler: async (ctx) => {
|
|
18
|
+
* // 수정된 파일 확인
|
|
19
|
+
* const files = await ctx.getData.git.getChangedFiles();
|
|
20
|
+
* console.log('Modified files:', files.map(f => f.path));
|
|
21
|
+
*
|
|
22
|
+
* // AI 응답 분석
|
|
23
|
+
* const response = await ctx.getData.conversation.getLastResponse();
|
|
24
|
+
*
|
|
25
|
+
* // 필요시 추가 태스크 삽입
|
|
26
|
+
* if (needsFix(response)) {
|
|
27
|
+
* ctx.flow.injectTask({
|
|
28
|
+
* name: 'Fix: ' + ctx.task.name,
|
|
29
|
+
* prompt: 'Fix the issues...',
|
|
30
|
+
* });
|
|
31
|
+
* }
|
|
32
|
+
* },
|
|
33
|
+
* });
|
|
34
|
+
* ```
|
|
35
|
+
*
|
|
36
|
+
* ## Hook Points
|
|
37
|
+
*
|
|
38
|
+
* | Hook Point | 트리거 시점 | 주요 용도 |
|
|
39
|
+
* |------------|------------|----------|
|
|
40
|
+
* | `beforeTask` | 태스크 실행 직전 | 프롬프트 검토/수정 |
|
|
41
|
+
* | `afterTask` | 태스크 완료 직후 | 결과 리뷰, 태스크 삽입 |
|
|
42
|
+
* | `onError` | 에러 발생 시 | 에러 분석, 복구 |
|
|
43
|
+
* | `onStall` | 응답 없음 감지 시 | 상황 분석, 개입 |
|
|
44
|
+
* | `onLaneEnd` | Lane 종료 시 | 최종 리뷰, 보고서 |
|
|
45
|
+
*
|
|
46
|
+
* ## Configuration
|
|
47
|
+
*
|
|
48
|
+
* `.cursorflow.json`에서 Hook 설정:
|
|
49
|
+
*
|
|
50
|
+
* ```json
|
|
51
|
+
* {
|
|
52
|
+
* "hooks": {
|
|
53
|
+
* "file": "./cursorflow.hooks.ts",
|
|
54
|
+
* "timeout": 30000,
|
|
55
|
+
* "continueOnError": false
|
|
56
|
+
* }
|
|
57
|
+
* }
|
|
58
|
+
* ```
|
|
59
|
+
*
|
|
60
|
+
* @module hooks
|
|
61
|
+
*/
|
|
62
|
+
export { HookPoint, HookMode, HookContext, BeforeTaskContext, AfterTaskContext, OnErrorContext, OnStallContext, OnLaneEndContext, ChangedFile, Commit, Message, TaskResult, TaskDefinition, ToolCall, ErrorLog, DependencyResult, HookDataAccessor, FlowController, AICallOptions, HookRegistration, HookExecutionResult, HookHandlerMap, HooksConfig, } from './types';
|
|
63
|
+
export { HookManager, hooks, getHookManager, resetHookManager, } from './manager';
|
|
64
|
+
export { HookDataAccessorImpl, DataAccessorOptions, createDataAccessor, } from './data-accessor';
|
|
65
|
+
export { FlowControllerImpl, FlowControllerOptions, FlowControlState, FlowAbortError, FlowRetryError, createFlowController, } from './flow-controller';
|
|
66
|
+
export { BaseContextOptions, createBeforeTaskContext, createAfterTaskContext, createOnErrorContext, createOnStallContext, createOnLaneEndContext, } from './contexts';
|
|
67
|
+
import { hooks as hooksSingleton } from './manager';
|
|
68
|
+
export default hooksSingleton;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* CursorFlow Hook System
|
|
4
|
+
*
|
|
5
|
+
* 외부 개발자가 Supervisor AI, 모니터링 시스템, 커스텀 로직 등을
|
|
6
|
+
* 구현할 수 있도록 제공하는 Hook API입니다.
|
|
7
|
+
*
|
|
8
|
+
* ## Quick Start
|
|
9
|
+
*
|
|
10
|
+
* ```typescript
|
|
11
|
+
* import { hooks, HookPoint } from '@litmers/cursorflow-orchestrator';
|
|
12
|
+
*
|
|
13
|
+
* // 태스크 완료 후 결과 리뷰
|
|
14
|
+
* hooks.register({
|
|
15
|
+
* point: HookPoint.AFTER_TASK,
|
|
16
|
+
* mode: 'sync',
|
|
17
|
+
* name: 'my-reviewer',
|
|
18
|
+
* handler: async (ctx) => {
|
|
19
|
+
* // 수정된 파일 확인
|
|
20
|
+
* const files = await ctx.getData.git.getChangedFiles();
|
|
21
|
+
* console.log('Modified files:', files.map(f => f.path));
|
|
22
|
+
*
|
|
23
|
+
* // AI 응답 분석
|
|
24
|
+
* const response = await ctx.getData.conversation.getLastResponse();
|
|
25
|
+
*
|
|
26
|
+
* // 필요시 추가 태스크 삽입
|
|
27
|
+
* if (needsFix(response)) {
|
|
28
|
+
* ctx.flow.injectTask({
|
|
29
|
+
* name: 'Fix: ' + ctx.task.name,
|
|
30
|
+
* prompt: 'Fix the issues...',
|
|
31
|
+
* });
|
|
32
|
+
* }
|
|
33
|
+
* },
|
|
34
|
+
* });
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* ## Hook Points
|
|
38
|
+
*
|
|
39
|
+
* | Hook Point | 트리거 시점 | 주요 용도 |
|
|
40
|
+
* |------------|------------|----------|
|
|
41
|
+
* | `beforeTask` | 태스크 실행 직전 | 프롬프트 검토/수정 |
|
|
42
|
+
* | `afterTask` | 태스크 완료 직후 | 결과 리뷰, 태스크 삽입 |
|
|
43
|
+
* | `onError` | 에러 발생 시 | 에러 분석, 복구 |
|
|
44
|
+
* | `onStall` | 응답 없음 감지 시 | 상황 분석, 개입 |
|
|
45
|
+
* | `onLaneEnd` | Lane 종료 시 | 최종 리뷰, 보고서 |
|
|
46
|
+
*
|
|
47
|
+
* ## Configuration
|
|
48
|
+
*
|
|
49
|
+
* `.cursorflow.json`에서 Hook 설정:
|
|
50
|
+
*
|
|
51
|
+
* ```json
|
|
52
|
+
* {
|
|
53
|
+
* "hooks": {
|
|
54
|
+
* "file": "./cursorflow.hooks.ts",
|
|
55
|
+
* "timeout": 30000,
|
|
56
|
+
* "continueOnError": false
|
|
57
|
+
* }
|
|
58
|
+
* }
|
|
59
|
+
* ```
|
|
60
|
+
*
|
|
61
|
+
* @module hooks
|
|
62
|
+
*/
|
|
63
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
64
|
+
exports.createOnLaneEndContext = exports.createOnStallContext = exports.createOnErrorContext = exports.createAfterTaskContext = exports.createBeforeTaskContext = exports.createFlowController = exports.FlowRetryError = exports.FlowAbortError = exports.FlowControllerImpl = exports.createDataAccessor = exports.HookDataAccessorImpl = exports.resetHookManager = exports.getHookManager = exports.hooks = exports.HookManager = exports.HookPoint = void 0;
|
|
65
|
+
// ============================================================================
|
|
66
|
+
// Type Exports
|
|
67
|
+
// ============================================================================
|
|
68
|
+
var types_1 = require("./types");
|
|
69
|
+
// Hook Points & Modes
|
|
70
|
+
Object.defineProperty(exports, "HookPoint", { enumerable: true, get: function () { return types_1.HookPoint; } });
|
|
71
|
+
// ============================================================================
|
|
72
|
+
// Manager Exports
|
|
73
|
+
// ============================================================================
|
|
74
|
+
var manager_1 = require("./manager");
|
|
75
|
+
Object.defineProperty(exports, "HookManager", { enumerable: true, get: function () { return manager_1.HookManager; } });
|
|
76
|
+
Object.defineProperty(exports, "hooks", { enumerable: true, get: function () { return manager_1.hooks; } });
|
|
77
|
+
Object.defineProperty(exports, "getHookManager", { enumerable: true, get: function () { return manager_1.getHookManager; } });
|
|
78
|
+
Object.defineProperty(exports, "resetHookManager", { enumerable: true, get: function () { return manager_1.resetHookManager; } });
|
|
79
|
+
// ============================================================================
|
|
80
|
+
// Implementation Exports (for advanced usage)
|
|
81
|
+
// ============================================================================
|
|
82
|
+
var data_accessor_1 = require("./data-accessor");
|
|
83
|
+
Object.defineProperty(exports, "HookDataAccessorImpl", { enumerable: true, get: function () { return data_accessor_1.HookDataAccessorImpl; } });
|
|
84
|
+
Object.defineProperty(exports, "createDataAccessor", { enumerable: true, get: function () { return data_accessor_1.createDataAccessor; } });
|
|
85
|
+
var flow_controller_1 = require("./flow-controller");
|
|
86
|
+
Object.defineProperty(exports, "FlowControllerImpl", { enumerable: true, get: function () { return flow_controller_1.FlowControllerImpl; } });
|
|
87
|
+
Object.defineProperty(exports, "FlowAbortError", { enumerable: true, get: function () { return flow_controller_1.FlowAbortError; } });
|
|
88
|
+
Object.defineProperty(exports, "FlowRetryError", { enumerable: true, get: function () { return flow_controller_1.FlowRetryError; } });
|
|
89
|
+
Object.defineProperty(exports, "createFlowController", { enumerable: true, get: function () { return flow_controller_1.createFlowController; } });
|
|
90
|
+
// ============================================================================
|
|
91
|
+
// Context Builder Exports (for internal/advanced usage)
|
|
92
|
+
// ============================================================================
|
|
93
|
+
var contexts_1 = require("./contexts");
|
|
94
|
+
Object.defineProperty(exports, "createBeforeTaskContext", { enumerable: true, get: function () { return contexts_1.createBeforeTaskContext; } });
|
|
95
|
+
Object.defineProperty(exports, "createAfterTaskContext", { enumerable: true, get: function () { return contexts_1.createAfterTaskContext; } });
|
|
96
|
+
Object.defineProperty(exports, "createOnErrorContext", { enumerable: true, get: function () { return contexts_1.createOnErrorContext; } });
|
|
97
|
+
Object.defineProperty(exports, "createOnStallContext", { enumerable: true, get: function () { return contexts_1.createOnStallContext; } });
|
|
98
|
+
Object.defineProperty(exports, "createOnLaneEndContext", { enumerable: true, get: function () { return contexts_1.createOnLaneEndContext; } });
|
|
99
|
+
// ============================================================================
|
|
100
|
+
// Re-export for convenience
|
|
101
|
+
// ============================================================================
|
|
102
|
+
// Default export: hooks singleton
|
|
103
|
+
const manager_2 = require("./manager");
|
|
104
|
+
exports.default = manager_2.hooks;
|
|
105
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4DG;;;AAEH,+EAA+E;AAC/E,eAAe;AACf,+EAA+E;AAE/E,iCAmCiB;AAlCf,sBAAsB;AACtB,kGAAA,SAAS,OAAA;AAmCX,+EAA+E;AAC/E,kBAAkB;AAClB,+EAA+E;AAE/E,qCAKmB;AAJjB,sGAAA,WAAW,OAAA;AACX,gGAAA,KAAK,OAAA;AACL,yGAAA,cAAc,OAAA;AACd,2GAAA,gBAAgB,OAAA;AAGlB,+EAA+E;AAC/E,8CAA8C;AAC9C,+EAA+E;AAE/E,iDAIyB;AAHvB,qHAAA,oBAAoB,OAAA;AAEpB,mHAAA,kBAAkB,OAAA;AAGpB,qDAO2B;AANzB,qHAAA,kBAAkB,OAAA;AAGlB,iHAAA,cAAc,OAAA;AACd,iHAAA,cAAc,OAAA;AACd,uHAAA,oBAAoB,OAAA;AAGtB,+EAA+E;AAC/E,wDAAwD;AACxD,+EAA+E;AAE/E,uCAOoB;AALlB,mHAAA,uBAAuB,OAAA;AACvB,kHAAA,sBAAsB,OAAA;AACtB,gHAAA,oBAAoB,OAAA;AACpB,gHAAA,oBAAoB,OAAA;AACpB,kHAAA,sBAAsB,OAAA;AAGxB,+EAA+E;AAC/E,4BAA4B;AAC5B,+EAA+E;AAE/E,kCAAkC;AAClC,uCAAoD;AACpD,kBAAe,eAAc,CAAC"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CursorFlow Hook System - Hook Manager
|
|
3
|
+
*
|
|
4
|
+
* Hook 등록 및 실행을 관리하는 중앙 매니저입니다.
|
|
5
|
+
* 외부 개발자가 Hook을 등록하고 CursorFlow가 적절한 시점에 실행합니다.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import { hooks, HookPoint } from '@litmers/cursorflow-orchestrator';
|
|
10
|
+
*
|
|
11
|
+
* hooks.register({
|
|
12
|
+
* point: HookPoint.AFTER_TASK,
|
|
13
|
+
* mode: 'sync',
|
|
14
|
+
* handler: async (ctx) => {
|
|
15
|
+
* // Your logic here
|
|
16
|
+
* },
|
|
17
|
+
* });
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
import { HookPoint, HookMode, HookRegistration, HookExecutionResult, HookContext, BeforeTaskContext, AfterTaskContext, OnErrorContext, OnStallContext, OnLaneEndContext, HooksConfig } from './types';
|
|
21
|
+
/**
|
|
22
|
+
* Hook Manager 클래스
|
|
23
|
+
*
|
|
24
|
+
* 싱글톤 패턴으로 구현되어 전역에서 접근 가능합니다.
|
|
25
|
+
*/
|
|
26
|
+
export declare class HookManager {
|
|
27
|
+
private static instance;
|
|
28
|
+
/** 등록된 Hook 목록 (Hook Point별로 분류) */
|
|
29
|
+
private hooks;
|
|
30
|
+
/** 설정 */
|
|
31
|
+
private config;
|
|
32
|
+
private constructor();
|
|
33
|
+
/**
|
|
34
|
+
* 싱글톤 인스턴스 획득
|
|
35
|
+
*/
|
|
36
|
+
static getInstance(): HookManager;
|
|
37
|
+
/**
|
|
38
|
+
* 인스턴스 리셋 (테스트용)
|
|
39
|
+
*/
|
|
40
|
+
static resetInstance(): void;
|
|
41
|
+
/**
|
|
42
|
+
* 설정 업데이트
|
|
43
|
+
*/
|
|
44
|
+
configure(config: Partial<HooksConfig>): void;
|
|
45
|
+
/**
|
|
46
|
+
* 현재 설정 조회
|
|
47
|
+
*/
|
|
48
|
+
getConfig(): HooksConfig;
|
|
49
|
+
/**
|
|
50
|
+
* Hook 등록
|
|
51
|
+
*
|
|
52
|
+
* @param registration Hook 등록 정보
|
|
53
|
+
* @returns 등록 해제 함수
|
|
54
|
+
*/
|
|
55
|
+
register<T extends HookPoint>(registration: HookRegistration<T>): () => void;
|
|
56
|
+
/**
|
|
57
|
+
* Hook 등록 해제
|
|
58
|
+
*/
|
|
59
|
+
private unregister;
|
|
60
|
+
/**
|
|
61
|
+
* 특정 Hook Point의 모든 Hook 제거
|
|
62
|
+
*/
|
|
63
|
+
clearHooks(point?: HookPoint): void;
|
|
64
|
+
/**
|
|
65
|
+
* 등록된 Hook 수 조회
|
|
66
|
+
*/
|
|
67
|
+
getHookCount(point?: HookPoint): number;
|
|
68
|
+
/**
|
|
69
|
+
* Hook 등록 여부 확인
|
|
70
|
+
*/
|
|
71
|
+
hasHooks(point: HookPoint): boolean;
|
|
72
|
+
/**
|
|
73
|
+
* beforeTask Hook 실행
|
|
74
|
+
*/
|
|
75
|
+
executeBeforeTask(context: BeforeTaskContext): Promise<HookExecutionResult[]>;
|
|
76
|
+
/**
|
|
77
|
+
* afterTask Hook 실행
|
|
78
|
+
*/
|
|
79
|
+
executeAfterTask(context: AfterTaskContext): Promise<HookExecutionResult[]>;
|
|
80
|
+
/**
|
|
81
|
+
* onError Hook 실행
|
|
82
|
+
*/
|
|
83
|
+
executeOnError(context: OnErrorContext): Promise<HookExecutionResult[]>;
|
|
84
|
+
/**
|
|
85
|
+
* onStall Hook 실행
|
|
86
|
+
*/
|
|
87
|
+
executeOnStall(context: OnStallContext): Promise<HookExecutionResult[]>;
|
|
88
|
+
/**
|
|
89
|
+
* onLaneEnd Hook 실행
|
|
90
|
+
*/
|
|
91
|
+
executeOnLaneEnd(context: OnLaneEndContext): Promise<HookExecutionResult[]>;
|
|
92
|
+
/**
|
|
93
|
+
* 일반 Hook 실행
|
|
94
|
+
*/
|
|
95
|
+
execute<T extends HookPoint>(point: T, context: HookContext): Promise<HookExecutionResult[]>;
|
|
96
|
+
/**
|
|
97
|
+
* 단일 Hook 실행
|
|
98
|
+
*/
|
|
99
|
+
private executeHook;
|
|
100
|
+
/**
|
|
101
|
+
* 파일에서 Hook 로드
|
|
102
|
+
*/
|
|
103
|
+
loadHooksFromFile(filePath: string): Promise<number>;
|
|
104
|
+
/**
|
|
105
|
+
* 등록된 Hook 목록 조회
|
|
106
|
+
*/
|
|
107
|
+
listHooks(point?: HookPoint): Array<{
|
|
108
|
+
point: HookPoint;
|
|
109
|
+
name: string;
|
|
110
|
+
mode: HookMode;
|
|
111
|
+
priority: number;
|
|
112
|
+
}>;
|
|
113
|
+
/**
|
|
114
|
+
* 디버그 정보 출력
|
|
115
|
+
*/
|
|
116
|
+
debug(): void;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* 전역 HookManager 인스턴스
|
|
120
|
+
*/
|
|
121
|
+
export declare const hooks: HookManager;
|
|
122
|
+
/**
|
|
123
|
+
* HookManager 인스턴스 획득
|
|
124
|
+
*/
|
|
125
|
+
export declare function getHookManager(): HookManager;
|
|
126
|
+
/**
|
|
127
|
+
* HookManager 인스턴스 리셋 (테스트용)
|
|
128
|
+
*/
|
|
129
|
+
export declare function resetHookManager(): void;
|