@su-record/vibe 2.5.12 → 2.5.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/commands/vibe.analyze.md +3 -3
  2. package/commands/vibe.review.md +3 -3
  3. package/commands/vibe.run.md +75 -9
  4. package/commands/vibe.spec.md +7 -7
  5. package/commands/vibe.utils.md +62 -5
  6. package/dist/cli/setup/GlobalInstaller.d.ts +24 -0
  7. package/dist/cli/setup/GlobalInstaller.d.ts.map +1 -0
  8. package/dist/cli/setup/GlobalInstaller.js +130 -0
  9. package/dist/cli/setup/GlobalInstaller.js.map +1 -0
  10. package/dist/cli/setup/LanguageDetector.d.ts +16 -0
  11. package/dist/cli/setup/LanguageDetector.d.ts.map +1 -0
  12. package/dist/cli/setup/LanguageDetector.js +49 -0
  13. package/dist/cli/setup/LanguageDetector.js.map +1 -0
  14. package/dist/cli/setup/LegacyMigration.d.ts +25 -0
  15. package/dist/cli/setup/LegacyMigration.d.ts.map +1 -0
  16. package/dist/cli/setup/LegacyMigration.js +162 -0
  17. package/dist/cli/setup/LegacyMigration.js.map +1 -0
  18. package/dist/cli/setup/ProjectSetup.d.ts +30 -0
  19. package/dist/cli/setup/ProjectSetup.d.ts.map +1 -0
  20. package/dist/cli/setup/ProjectSetup.js +238 -0
  21. package/dist/cli/setup/ProjectSetup.js.map +1 -0
  22. package/dist/cli/setup/index.d.ts +14 -0
  23. package/dist/cli/setup/index.d.ts.map +1 -0
  24. package/dist/cli/setup/index.js +18 -0
  25. package/dist/cli/setup/index.js.map +1 -0
  26. package/dist/cli/setup.d.ts +10 -77
  27. package/dist/cli/setup.d.ts.map +1 -1
  28. package/dist/cli/setup.js +15 -592
  29. package/dist/cli/setup.js.map +1 -1
  30. package/dist/lib/llm/auth/ApiKeyManager.d.ts +21 -0
  31. package/dist/lib/llm/auth/ApiKeyManager.d.ts.map +1 -0
  32. package/dist/lib/llm/auth/ApiKeyManager.js +43 -0
  33. package/dist/lib/llm/auth/ApiKeyManager.js.map +1 -0
  34. package/dist/lib/llm/auth/ConfigManager.d.ts +29 -0
  35. package/dist/lib/llm/auth/ConfigManager.d.ts.map +1 -0
  36. package/dist/lib/llm/auth/ConfigManager.js +67 -0
  37. package/dist/lib/llm/auth/ConfigManager.js.map +1 -0
  38. package/dist/lib/llm/auth/index.d.ts +25 -0
  39. package/dist/lib/llm/auth/index.d.ts.map +1 -0
  40. package/dist/lib/llm/auth/index.js +83 -0
  41. package/dist/lib/llm/auth/index.js.map +1 -0
  42. package/dist/lib/llm/index.d.ts +10 -0
  43. package/dist/lib/llm/index.d.ts.map +1 -0
  44. package/dist/lib/llm/index.js +12 -0
  45. package/dist/lib/llm/index.js.map +1 -0
  46. package/dist/lib/llm/types.d.ts +96 -0
  47. package/dist/lib/llm/types.d.ts.map +1 -0
  48. package/dist/lib/llm/types.js +17 -0
  49. package/dist/lib/llm/types.js.map +1 -0
  50. package/dist/lib/llm/utils/index.d.ts +6 -0
  51. package/dist/lib/llm/utils/index.d.ts.map +1 -0
  52. package/dist/lib/llm/utils/index.js +6 -0
  53. package/dist/lib/llm/utils/index.js.map +1 -0
  54. package/dist/lib/llm/utils/retry.d.ts +25 -0
  55. package/dist/lib/llm/utils/retry.d.ts.map +1 -0
  56. package/dist/lib/llm/utils/retry.js +72 -0
  57. package/dist/lib/llm/utils/retry.js.map +1 -0
  58. package/dist/lib/llm/utils/stream.d.ts +13 -0
  59. package/dist/lib/llm/utils/stream.d.ts.map +1 -0
  60. package/dist/lib/llm/utils/stream.js +110 -0
  61. package/dist/lib/llm/utils/stream.js.map +1 -0
  62. package/dist/orchestrator/AgentExecutor.d.ts +23 -0
  63. package/dist/orchestrator/AgentExecutor.d.ts.map +1 -0
  64. package/dist/orchestrator/AgentExecutor.js +231 -0
  65. package/dist/orchestrator/AgentExecutor.js.map +1 -0
  66. package/dist/orchestrator/AgentManager.d.ts +73 -0
  67. package/dist/orchestrator/AgentManager.d.ts.map +1 -0
  68. package/dist/orchestrator/AgentManager.js +184 -0
  69. package/dist/orchestrator/AgentManager.js.map +1 -0
  70. package/dist/orchestrator/LLMCluster.d.ts +70 -0
  71. package/dist/orchestrator/LLMCluster.d.ts.map +1 -0
  72. package/dist/orchestrator/LLMCluster.js +91 -0
  73. package/dist/orchestrator/LLMCluster.js.map +1 -0
  74. package/dist/orchestrator/MultiLlmResearch.d.ts +27 -0
  75. package/dist/orchestrator/MultiLlmResearch.d.ts.map +1 -0
  76. package/dist/orchestrator/MultiLlmResearch.js +145 -0
  77. package/dist/orchestrator/MultiLlmResearch.js.map +1 -0
  78. package/dist/orchestrator/SessionStore.d.ts +41 -0
  79. package/dist/orchestrator/SessionStore.d.ts.map +1 -0
  80. package/dist/orchestrator/SessionStore.js +117 -0
  81. package/dist/orchestrator/SessionStore.js.map +1 -0
  82. package/dist/orchestrator/SmartRouter.d.ts +68 -0
  83. package/dist/orchestrator/SmartRouter.d.ts.map +1 -0
  84. package/dist/orchestrator/SmartRouter.js +256 -0
  85. package/dist/orchestrator/SmartRouter.js.map +1 -0
  86. package/dist/orchestrator/backgroundAgent.d.ts +10 -27
  87. package/dist/orchestrator/backgroundAgent.d.ts.map +1 -1
  88. package/dist/orchestrator/backgroundAgent.js +11 -345
  89. package/dist/orchestrator/backgroundAgent.js.map +1 -1
  90. package/dist/orchestrator/index.d.ts +3 -0
  91. package/dist/orchestrator/index.d.ts.map +1 -1
  92. package/dist/orchestrator/index.js +4 -0
  93. package/dist/orchestrator/index.js.map +1 -1
  94. package/dist/orchestrator/orchestrator.d.ts +19 -154
  95. package/dist/orchestrator/orchestrator.d.ts.map +1 -1
  96. package/dist/orchestrator/orchestrator.js +90 -514
  97. package/dist/orchestrator/orchestrator.js.map +1 -1
  98. package/dist/orchestrator/parallelResearch.d.ts +5 -12
  99. package/dist/orchestrator/parallelResearch.d.ts.map +1 -1
  100. package/dist/orchestrator/parallelResearch.js +10 -193
  101. package/dist/orchestrator/parallelResearch.js.map +1 -1
  102. package/hooks/scripts/generate-brand-assets.js +472 -0
  103. package/package.json +1 -1
  104. package/skills/brand-assets.md +141 -0
  105. package/skills/commerce-patterns.md +361 -0
  106. package/skills/e2e-commerce.md +304 -0
  107. package/skills/frontend-design.md +92 -0
  108. package/skills/seo-checklist.md +244 -0
@@ -0,0 +1,256 @@
1
+ /**
2
+ * SmartRouter - LLM 스마트 라우팅 및 fallback 관리
3
+ * orchestrator.ts에서 추출된 라우팅 전용 모듈
4
+ */
5
+ import { TASK_LLM_PRIORITY } from './types.js';
6
+ import * as gptApi from '../lib/gpt-api.js';
7
+ import * as geminiApi from '../lib/gemini-api.js';
8
+ import { debugLog } from '../lib/utils.js';
9
+ // LLM 가용성 캐시 (5분 TTL)
10
+ const LLM_CACHE_TTL = 5 * 60 * 1000;
11
+ /**
12
+ * SmartRouter - Task 유형별 최적 LLM 선택 + fallback chain
13
+ */
14
+ export class SmartRouter {
15
+ cache;
16
+ verbose;
17
+ constructor(options = {}) {
18
+ this.verbose = options.verbose ?? false;
19
+ this.cache = {
20
+ gpt: { available: true, checkedAt: 0, errorCount: 0 },
21
+ gemini: { available: true, checkedAt: 0, errorCount: 0 }
22
+ };
23
+ }
24
+ /**
25
+ * 스마트 라우팅 - 작업 유형에 따라 최적의 LLM 선택 + fallback
26
+ */
27
+ async route(request) {
28
+ const startTime = Date.now();
29
+ const { type, prompt, systemPrompt = 'You are a helpful assistant.', preferredLlm, maxRetries = 2 } = request;
30
+ // LLM 우선순위 결정
31
+ const providers = this.getProviderPriority(type, preferredLlm);
32
+ const attemptedProviders = [];
33
+ const errors = {};
34
+ // 각 LLM 순차 시도 (fallback chain)
35
+ for (const provider of providers) {
36
+ if (this.isUnavailable(provider)) {
37
+ if (this.verbose) {
38
+ debugLog(`[SmartRouter] Skipping ${provider} (recently failed)`);
39
+ }
40
+ continue;
41
+ }
42
+ attemptedProviders.push(provider);
43
+ // 재시도 로직
44
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
45
+ try {
46
+ const content = await this.callLlm(provider, prompt, systemPrompt);
47
+ this.markAvailable(provider);
48
+ return {
49
+ content,
50
+ provider,
51
+ success: true,
52
+ usedFallback: attemptedProviders.length > 1,
53
+ attemptedProviders,
54
+ duration: Date.now() - startTime
55
+ };
56
+ }
57
+ catch (error) {
58
+ const errorMsg = error instanceof Error ? error.message : String(error);
59
+ errors[provider] = errorMsg;
60
+ if (this.verbose) {
61
+ debugLog(`[SmartRouter] ${provider} attempt ${attempt + 1} failed: ${errorMsg}`);
62
+ }
63
+ if (this.shouldSkipRetry(errorMsg)) {
64
+ this.markUnavailable(provider);
65
+ break;
66
+ }
67
+ if (attempt < maxRetries) {
68
+ await this.delay(1000 * (attempt + 1));
69
+ }
70
+ }
71
+ }
72
+ this.markUnavailable(provider);
73
+ }
74
+ // 모든 외부 LLM 실패 - Claude fallback
75
+ return {
76
+ content: this.buildFallbackMessage(type, prompt, errors),
77
+ provider: 'claude',
78
+ success: true,
79
+ usedFallback: true,
80
+ attemptedProviders,
81
+ errors: errors,
82
+ duration: Date.now() - startTime
83
+ };
84
+ }
85
+ /**
86
+ * LLM 우선순위 결정
87
+ */
88
+ getProviderPriority(type, preferredLlm) {
89
+ if (preferredLlm) {
90
+ const others = TASK_LLM_PRIORITY[type].filter(p => p !== preferredLlm);
91
+ return [preferredLlm, ...others];
92
+ }
93
+ return [...TASK_LLM_PRIORITY[type]];
94
+ }
95
+ /**
96
+ * LLM 호출
97
+ */
98
+ async callLlm(provider, prompt, systemPrompt) {
99
+ switch (provider) {
100
+ case 'gpt':
101
+ return gptApi.vibeGptOrchestrate(prompt, systemPrompt, { jsonMode: false });
102
+ case 'gemini':
103
+ return geminiApi.vibeGeminiOrchestrate(prompt, systemPrompt, { jsonMode: false });
104
+ case 'claude':
105
+ throw new Error('Claude fallback - handled by caller');
106
+ default:
107
+ throw new Error(`Unknown provider: ${provider}`);
108
+ }
109
+ }
110
+ /**
111
+ * 재시도 없이 즉시 다음 LLM으로 넘어가야 하는 에러
112
+ */
113
+ shouldSkipRetry(errorMsg) {
114
+ const skipPatterns = [
115
+ 'rate limit', 'quota', 'exhausted', '429', 'usage limit', 'too many requests',
116
+ 'no token', 'token not set', 'no api key', 'api key not set',
117
+ 'missing token', 'missing api key', 'not authenticated',
118
+ 'authentication failed', 'unauthorized', '401', 'auth'
119
+ ];
120
+ const lowerMsg = errorMsg.toLowerCase();
121
+ return skipPatterns.some(pattern => lowerMsg.includes(pattern));
122
+ }
123
+ /**
124
+ * LLM 가용성 확인 (캐시 기반)
125
+ */
126
+ isUnavailable(provider) {
127
+ if (provider === 'claude')
128
+ return false;
129
+ const cache = this.cache[provider];
130
+ const now = Date.now();
131
+ if (now - cache.checkedAt > LLM_CACHE_TTL) {
132
+ cache.available = true;
133
+ cache.errorCount = 0;
134
+ return false;
135
+ }
136
+ return !cache.available || cache.errorCount >= 3;
137
+ }
138
+ /**
139
+ * LLM 가용 상태로 마킹
140
+ */
141
+ markAvailable(provider) {
142
+ if (provider === 'claude')
143
+ return;
144
+ this.cache[provider] = {
145
+ available: true,
146
+ checkedAt: Date.now(),
147
+ errorCount: 0
148
+ };
149
+ }
150
+ /**
151
+ * LLM 불가용 상태로 마킹
152
+ */
153
+ markUnavailable(provider) {
154
+ if (provider === 'claude')
155
+ return;
156
+ const cache = this.cache[provider];
157
+ cache.errorCount++;
158
+ cache.checkedAt = Date.now();
159
+ if (cache.errorCount >= 3) {
160
+ cache.available = false;
161
+ }
162
+ }
163
+ /**
164
+ * Fallback 메시지 생성
165
+ */
166
+ buildFallbackMessage(type, prompt, errors) {
167
+ const errorSummary = Object.entries(errors)
168
+ .map(([provider, msg]) => `- ${provider}: ${msg}`)
169
+ .join('\n');
170
+ return `[External LLM Unavailable - Claude Direct Handling]
171
+
172
+ All external LLMs failed. Claude should handle this ${type} task directly.
173
+
174
+ **Original Request:**
175
+ ${prompt}
176
+
177
+ **Failed Providers:**
178
+ ${errorSummary}
179
+
180
+ **Action Required:**
181
+ Claude, please handle this task using your own capabilities. Do NOT retry external LLMs.`;
182
+ }
183
+ delay(ms) {
184
+ return new Promise(resolve => setTimeout(resolve, ms));
185
+ }
186
+ // ============================================
187
+ // Convenience Methods (Smart* shortcuts)
188
+ // ============================================
189
+ async webSearch(query) {
190
+ return this.route({
191
+ type: 'web-search',
192
+ prompt: query,
193
+ systemPrompt: 'Search the web and provide relevant information.'
194
+ });
195
+ }
196
+ async architectureReview(prompt) {
197
+ return this.route({
198
+ type: 'architecture',
199
+ prompt,
200
+ systemPrompt: 'You are a software architect. Analyze and review the architecture.'
201
+ });
202
+ }
203
+ async uiuxReview(prompt) {
204
+ return this.route({
205
+ type: 'uiux',
206
+ prompt,
207
+ systemPrompt: 'You are a UI/UX expert. Analyze and provide feedback.'
208
+ });
209
+ }
210
+ async codeAnalysis(prompt) {
211
+ return this.route({
212
+ type: 'code-analysis',
213
+ prompt,
214
+ systemPrompt: 'You are a code analysis expert. Review and analyze the code.'
215
+ });
216
+ }
217
+ async debugging(prompt) {
218
+ return this.route({
219
+ type: 'debugging',
220
+ prompt,
221
+ systemPrompt: 'You are a debugging expert. Find bugs and suggest fixes.'
222
+ });
223
+ }
224
+ async codeGen(description, context) {
225
+ const prompt = context ? `${description}\n\nContext:\n${context}` : description;
226
+ return this.route({
227
+ type: 'code-gen',
228
+ prompt,
229
+ systemPrompt: 'Generate clean, well-documented code.'
230
+ });
231
+ }
232
+ /**
233
+ * 캐시 상태 조회 (디버깅용)
234
+ */
235
+ getCacheStatus() {
236
+ return { ...this.cache };
237
+ }
238
+ /**
239
+ * 캐시 초기화
240
+ */
241
+ resetCache() {
242
+ this.cache = {
243
+ gpt: { available: true, checkedAt: 0, errorCount: 0 },
244
+ gemini: { available: true, checkedAt: 0, errorCount: 0 }
245
+ };
246
+ }
247
+ }
248
+ // 싱글톤 인스턴스
249
+ let defaultRouter = null;
250
+ export function getSmartRouter(options) {
251
+ if (!defaultRouter || options) {
252
+ defaultRouter = new SmartRouter(options);
253
+ }
254
+ return defaultRouter;
255
+ }
256
+ //# sourceMappingURL=SmartRouter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SmartRouter.js","sourceRoot":"","sources":["../../src/orchestrator/SmartRouter.ts"],"names":[],"mappings":"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"}
@@ -1,30 +1,13 @@
1
1
  /**
2
2
  * Background Agent - 백그라운드 에이전트 관리
3
- */
4
- import { BackgroundAgentArgs } from './types.js';
5
- import { ToolResult } from '../types/tool.js';
6
- /**
7
- * 백그라운드 에이전트 시작
8
- */
9
- export declare function launchBackgroundAgent(args: BackgroundAgentArgs): Promise<ToolResult>;
10
- /**
11
- * 백그라운드 에이전트 결과 조회
12
- */
13
- export declare function getBackgroundAgentResult(sessionId: string): Promise<ToolResult>;
14
- /**
15
- * 백그라운드 에이전트 취소
16
- */
17
- export declare function cancelBackgroundAgent(sessionId: string): ToolResult;
18
- /**
19
- * 활성 세션 목록
20
- */
21
- export declare function listActiveSessions(): ToolResult;
22
- /**
23
- * 세션 히스토리 조회
24
- */
25
- export declare function getSessionHistory(limit?: number): ToolResult;
26
- /**
27
- * 여러 백그라운드 에이전트 동시 실행
28
- */
29
- export declare function launchParallelAgents(agentConfigs: BackgroundAgentArgs[]): Promise<ToolResult>;
3
+ *
4
+ * v2.6.0: 기능이 2개 모듈로 분리됨
5
+ * - SessionStore: 세션 저장소, 정리, 히스토리 관리
6
+ * - AgentExecutor: 에이전트 실행 로직
7
+ *
8
+ * 이 파일은 하위 호환성을 위해 모든 함수를 re-export
9
+ */
10
+ export { sessionStore, listActiveSessions, getSessionHistory } from './SessionStore.js';
11
+ export type { SessionData } from './SessionStore.js';
12
+ export { launchBackgroundAgent, getBackgroundAgentResult, cancelBackgroundAgent, launchParallelAgents } from './AgentExecutor.js';
30
13
  //# sourceMappingURL=backgroundAgent.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"backgroundAgent.d.ts","sourceRoot":"","sources":["../../src/orchestrator/backgroundAgent.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,mBAAmB,EAKpB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAwD9C;;GAEG;AACH,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,UAAU,CAAC,CAsK1F;AAED;;GAEG;AACH,wBAAsB,wBAAwB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CA2CrF;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,UAAU,CAoBnE;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,UAAU,CA4B/C;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,GAAE,MAAW,GAAG,UAAU,CAyBhE;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CACxC,YAAY,EAAE,mBAAmB,EAAE,GAClC,OAAO,CAAC,UAAU,CAAC,CA0CrB"}
1
+ {"version":3,"file":"backgroundAgent.d.ts","sourceRoot":"","sources":["../../src/orchestrator/backgroundAgent.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,iBAAiB,EAClB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGrD,OAAO,EACL,qBAAqB,EACrB,wBAAwB,EACxB,qBAAqB,EACrB,oBAAoB,EACrB,MAAM,oBAAoB,CAAC"}
@@ -1,348 +1,14 @@
1
1
  /**
2
2
  * Background Agent - 백그라운드 에이전트 관리
3
- */
4
- import { getAgentSdkQuery } from '../lib/utils.js';
5
- import { DEFAULT_MODELS, AGENT } from '../lib/constants.js';
6
- // 활성 세션 저장소
7
- const activeSessions = new Map();
8
- // 세션 히스토리 (완료된 세션 포함)
9
- const sessionHistory = [];
10
- // TTL 설정 (기본 1시간)
11
- const SESSION_TTL = 60 * 60 * 1000;
12
- const SESSION_HISTORY_TTL = 24 * 60 * 60 * 1000; // 히스토리는 24시간
13
- const CLEANUP_INTERVAL = 10 * 60 * 1000; // 10분마다 정리
14
- // 세션 정리 함수
15
- function cleanupExpiredSessions() {
16
- const now = Date.now();
17
- // 활성 세션 정리 (TTL 초과 + running 상태인 경우 취소)
18
- for (const [sessionId, session] of activeSessions.entries()) {
19
- if (now - session.createdAt > SESSION_TTL) {
20
- if (session.handle.status === 'running') {
21
- session.cancelController.abort();
22
- }
23
- activeSessions.delete(sessionId);
24
- }
25
- }
26
- // 히스토리 정리 (24시간 초과)
27
- const cutoff = now - SESSION_HISTORY_TTL;
28
- while (sessionHistory.length > 0 && sessionHistory[0].startTime < cutoff) {
29
- sessionHistory.shift();
30
- }
31
- }
32
- // 정리 타이머 시작 (모듈 로드 시 자동 시작)
33
- let cleanupTimer = null;
34
- function startCleanupTimer() {
35
- if (cleanupTimer)
36
- return;
37
- cleanupTimer = setInterval(cleanupExpiredSessions, CLEANUP_INTERVAL);
38
- // unref로 프로세스 종료를 막지 않음
39
- if (cleanupTimer.unref) {
40
- cleanupTimer.unref();
41
- }
42
- }
43
- // 모듈 로드 시 타이머 시작
44
- startCleanupTimer();
45
- /**
46
- * 백그라운드 에이전트 시작
47
- */
48
- export async function launchBackgroundAgent(args) {
49
- const { prompt, agentName = `agent-${Date.now()}`, model = DEFAULT_MODELS.BACKGROUND, maxTurns = AGENT.MAX_TURNS, allowedTools = AGENT.DEFAULT_ALLOWED_TOOLS, projectPath = process.cwd(), onProgress } = args;
50
- const query = await getAgentSdkQuery();
51
- // Agent SDK가 없으면 시뮬레이션
52
- if (!query) {
53
- const handle = {
54
- sessionId: `simulated-${Date.now()}`,
55
- agentName,
56
- status: 'completed',
57
- startTime: Date.now(),
58
- getResult: async () => ({
59
- agentName,
60
- sessionId: `simulated-${Date.now()}`,
61
- result: `[Agent SDK not installed] Would execute: ${prompt.slice(0, 100)}...`,
62
- success: true,
63
- duration: 0
64
- }),
65
- cancel: () => { }
66
- };
67
- return {
68
- content: [{
69
- type: 'text',
70
- text: `Background agent "${agentName}" started (simulated)\nSession ID: ${handle.sessionId}\n\nNote: Install @anthropic-ai/claude-agent-sdk for real execution.`
71
- }],
72
- handle
73
- };
74
- }
75
- const startTime = Date.now();
76
- const cancelController = new AbortController();
77
- let sessionId = '';
78
- let result = '';
79
- let status = 'running';
80
- // 결과 수집 Promise
81
- const resultPromise = new Promise(async (resolve) => {
82
- try {
83
- const response = query({
84
- prompt,
85
- options: {
86
- model,
87
- maxTurns,
88
- allowedTools,
89
- cwd: projectPath
90
- }
91
- });
92
- for await (const message of response) {
93
- // 취소 체크
94
- if (cancelController.signal.aborted) {
95
- status = 'cancelled';
96
- resolve({
97
- agentName,
98
- sessionId,
99
- result: 'Cancelled by user',
100
- success: false,
101
- error: 'Cancelled',
102
- duration: Date.now() - startTime
103
- });
104
- return;
105
- }
106
- const msg = message;
107
- // 세션 ID 캡처
108
- if (msg.type === 'system' && msg.subtype === 'init' && msg.session_id) {
109
- sessionId = msg.session_id;
110
- }
111
- // 진행 상황 콜백
112
- if (msg.type === 'system' && msg.subtype === 'progress' && onProgress) {
113
- onProgress(msg.content || 'Processing...');
114
- }
115
- // 결과 수집
116
- if (msg.type === 'result' && msg.result) {
117
- result = msg.result;
118
- }
119
- if (msg.type === 'assistant' && msg.message?.content) {
120
- const textContent = msg.message.content
121
- .filter(block => block.type === 'text' && block.text)
122
- .map(block => block.text)
123
- .join('\n');
124
- if (textContent) {
125
- result += textContent;
126
- }
127
- }
128
- }
129
- status = 'completed';
130
- resolve({
131
- agentName,
132
- sessionId,
133
- result: result || 'No result',
134
- success: true,
135
- duration: Date.now() - startTime
136
- });
137
- }
138
- catch (error) {
139
- status = 'failed';
140
- resolve({
141
- agentName,
142
- sessionId,
143
- result: '',
144
- success: false,
145
- error: error instanceof Error ? error.message : String(error),
146
- duration: Date.now() - startTime
147
- });
148
- }
149
- });
150
- // 핸들 생성
151
- const handle = {
152
- sessionId: sessionId || `pending-${Date.now()}`,
153
- agentName,
154
- status,
155
- startTime,
156
- getResult: () => resultPromise,
157
- cancel: () => {
158
- cancelController.abort();
159
- status = 'cancelled';
160
- }
161
- };
162
- // 세션 등록
163
- activeSessions.set(handle.sessionId, {
164
- handle,
165
- resultPromise,
166
- cancelController,
167
- createdAt: startTime
168
- });
169
- // 완료 시 히스토리에 추가
170
- resultPromise.then((result) => {
171
- sessionHistory.push({
172
- sessionId: result.sessionId,
173
- agentName: result.agentName,
174
- status: result.success ? 'completed' : 'failed',
175
- startTime,
176
- endTime: Date.now(),
177
- prompt
178
- });
179
- // 활성 세션에서 제거
180
- activeSessions.delete(handle.sessionId);
181
- });
182
- return {
183
- content: [{
184
- type: 'text',
185
- text: `Background agent "${agentName}" started\nSession ID: ${handle.sessionId}\nModel: ${model}\nMax Turns: ${maxTurns}\n\nUse getBackgroundAgentResult("${handle.sessionId}") to check status.`
186
- }],
187
- handle
188
- };
189
- }
190
- /**
191
- * 백그라운드 에이전트 결과 조회
192
- */
193
- export async function getBackgroundAgentResult(sessionId) {
194
- const session = activeSessions.get(sessionId);
195
- if (!session) {
196
- // 히스토리에서 찾기
197
- const historical = sessionHistory.find(s => s.sessionId === sessionId);
198
- if (historical) {
199
- return {
200
- content: [{
201
- type: 'text',
202
- text: `Session "${sessionId}" completed at ${new Date(historical.endTime).toISOString()}\nStatus: ${historical.status}`
203
- }]
204
- };
205
- }
206
- return {
207
- content: [{
208
- type: 'text',
209
- text: `Session "${sessionId}" not found`
210
- }]
211
- };
212
- }
213
- // 진행 중인 세션
214
- if (session.handle.status === 'running') {
215
- return {
216
- content: [{
217
- type: 'text',
218
- text: `Session "${sessionId}" is still running\nAgent: ${session.handle.agentName}\nStarted: ${new Date(session.handle.startTime).toISOString()}`
219
- }]
220
- };
221
- }
222
- // 완료된 경우 결과 반환
223
- const result = await session.resultPromise;
224
- return {
225
- content: [{
226
- type: 'text',
227
- text: `Session "${sessionId}" ${result.success ? 'completed' : 'failed'}\nDuration: ${(result.duration / 1000).toFixed(1)}s\n\nResult:\n${result.result}`
228
- }],
229
- result
230
- };
231
- }
232
- /**
233
- * 백그라운드 에이전트 취소
234
- */
235
- export function cancelBackgroundAgent(sessionId) {
236
- const session = activeSessions.get(sessionId);
237
- if (!session) {
238
- return {
239
- content: [{
240
- type: 'text',
241
- text: `Session "${sessionId}" not found or already completed`
242
- }]
243
- };
244
- }
245
- session.handle.cancel();
246
- return {
247
- content: [{
248
- type: 'text',
249
- text: `Session "${sessionId}" cancelled`
250
- }]
251
- };
252
- }
253
- /**
254
- * 활성 세션 목록
255
- */
256
- export function listActiveSessions() {
257
- const sessions = Array.from(activeSessions.values()).map(s => ({
258
- sessionId: s.handle.sessionId,
259
- agentName: s.handle.agentName,
260
- status: s.handle.status,
261
- startTime: new Date(s.handle.startTime).toISOString(),
262
- runningFor: `${((Date.now() - s.handle.startTime) / 1000).toFixed(0)}s`
263
- }));
264
- if (sessions.length === 0) {
265
- return {
266
- content: [{
267
- type: 'text',
268
- text: 'No active background agents'
269
- }]
270
- };
271
- }
272
- let summary = `## Active Background Agents (${sessions.length})\n\n`;
273
- for (const session of sessions) {
274
- summary += `- **${session.agentName}** (${session.sessionId})\n`;
275
- summary += ` Status: ${session.status} | Running: ${session.runningFor}\n`;
276
- }
277
- return {
278
- content: [{ type: 'text', text: summary }],
279
- sessions
280
- };
281
- }
282
- /**
283
- * 세션 히스토리 조회
284
- */
285
- export function getSessionHistory(limit = 10) {
286
- const recent = sessionHistory.slice(-limit).reverse();
287
- if (recent.length === 0) {
288
- return {
289
- content: [{
290
- type: 'text',
291
- text: 'No session history'
292
- }]
293
- };
294
- }
295
- let summary = `## Session History (last ${recent.length})\n\n`;
296
- for (const session of recent) {
297
- const duration = session.endTime
298
- ? `${((session.endTime - session.startTime) / 1000).toFixed(1)}s`
299
- : 'N/A';
300
- summary += `- **${session.agentName}** (${session.sessionId})\n`;
301
- summary += ` Status: ${session.status} | Duration: ${duration}\n`;
302
- }
303
- return {
304
- content: [{ type: 'text', text: summary }],
305
- history: recent
306
- };
307
- }
308
- /**
309
- * 여러 백그라운드 에이전트 동시 실행
310
- */
311
- export async function launchParallelAgents(agentConfigs) {
312
- const handles = [];
313
- const errors = [];
314
- // 병렬로 에이전트 시작
315
- const results = await Promise.all(agentConfigs.map(async (config) => {
316
- try {
317
- const result = await launchBackgroundAgent(config);
318
- if ('handle' in result) {
319
- return result.handle;
320
- }
321
- return null;
322
- }
323
- catch (error) {
324
- errors.push(`${config.agentName}: ${error instanceof Error ? error.message : String(error)}`);
325
- return null;
326
- }
327
- }));
328
- for (const result of results) {
329
- if (result) {
330
- handles.push(result);
331
- }
332
- }
333
- let summary = `## Launched ${handles.length} Background Agents\n\n`;
334
- for (const handle of handles) {
335
- summary += `- ${handle.agentName}: ${handle.sessionId}\n`;
336
- }
337
- if (errors.length > 0) {
338
- summary += `\n### Errors (${errors.length})\n`;
339
- for (const error of errors) {
340
- summary += `- ${error}\n`;
341
- }
342
- }
343
- return {
344
- content: [{ type: 'text', text: summary }],
345
- handles
346
- };
347
- }
3
+ *
4
+ * v2.6.0: 기능이 2개 모듈로 분리됨
5
+ * - SessionStore: 세션 저장소, 정리, 히스토리 관리
6
+ * - AgentExecutor: 에이전트 실행 로직
7
+ *
8
+ * 파일은 하위 호환성을 위해 모든 함수를 re-export
9
+ */
10
+ // SessionStore
11
+ export { sessionStore, listActiveSessions, getSessionHistory } from './SessionStore.js';
12
+ // AgentExecutor
13
+ export { launchBackgroundAgent, getBackgroundAgentResult, cancelBackgroundAgent, launchParallelAgents } from './AgentExecutor.js';
348
14
  //# sourceMappingURL=backgroundAgent.js.map