@su-record/vibe 2.5.11 → 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.
- package/CLAUDE.md +243 -0
- package/LICENSE +21 -21
- package/README.md +262 -262
- package/agents/architect-low.md +41 -41
- package/agents/architect-medium.md +59 -59
- package/agents/architect.md +80 -80
- package/agents/build-error-resolver.md +115 -115
- package/agents/compounder.md +261 -261
- package/agents/diagrammer.md +178 -178
- package/agents/e2e-tester.md +266 -266
- package/agents/explorer-low.md +42 -42
- package/agents/explorer-medium.md +59 -59
- package/agents/explorer.md +48 -48
- package/agents/implementer-low.md +43 -43
- package/agents/implementer-medium.md +52 -52
- package/agents/implementer.md +54 -54
- package/agents/refactor-cleaner.md +143 -143
- package/agents/research/best-practices-agent.md +189 -189
- package/agents/research/codebase-patterns-agent.md +147 -147
- package/agents/research/framework-docs-agent.md +178 -178
- package/agents/research/security-advisory-agent.md +203 -203
- package/agents/review/architecture-reviewer.md +107 -107
- package/agents/review/complexity-reviewer.md +116 -116
- package/agents/review/data-integrity-reviewer.md +88 -88
- package/agents/review/git-history-reviewer.md +103 -103
- package/agents/review/performance-reviewer.md +86 -86
- package/agents/review/python-reviewer.md +150 -150
- package/agents/review/rails-reviewer.md +139 -139
- package/agents/review/react-reviewer.md +144 -144
- package/agents/review/security-reviewer.md +80 -80
- package/agents/review/simplicity-reviewer.md +140 -140
- package/agents/review/test-coverage-reviewer.md +116 -116
- package/agents/review/typescript-reviewer.md +127 -127
- package/agents/searcher.md +54 -54
- package/agents/simplifier.md +120 -120
- package/agents/tester.md +49 -49
- package/agents/ui-previewer.md +129 -129
- package/commands/vibe.analyze.md +356 -356
- package/commands/vibe.reason.md +329 -329
- package/commands/vibe.review.md +326 -326
- package/commands/vibe.run.md +1117 -1051
- package/commands/vibe.spec.md +1058 -1058
- package/commands/vibe.utils.md +353 -296
- package/commands/vibe.verify.md +375 -375
- package/dist/cli/collaborator.js +52 -52
- package/dist/cli/detect.js +32 -32
- package/dist/cli/index.js +102 -102
- package/dist/cli/llm.js +144 -144
- package/dist/cli/mcp.d.ts +49 -0
- package/dist/cli/mcp.d.ts.map +1 -0
- package/dist/cli/mcp.js +169 -0
- package/dist/cli/mcp.js.map +1 -0
- package/dist/cli/postinstall.js +180 -2
- package/dist/cli/postinstall.js.map +1 -1
- package/dist/cli/setup/GlobalInstaller.d.ts +24 -0
- package/dist/cli/setup/GlobalInstaller.d.ts.map +1 -0
- package/dist/cli/setup/GlobalInstaller.js +130 -0
- package/dist/cli/setup/GlobalInstaller.js.map +1 -0
- package/dist/cli/setup/LanguageDetector.d.ts +16 -0
- package/dist/cli/setup/LanguageDetector.d.ts.map +1 -0
- package/dist/cli/setup/LanguageDetector.js +49 -0
- package/dist/cli/setup/LanguageDetector.js.map +1 -0
- package/dist/cli/setup/LegacyMigration.d.ts +25 -0
- package/dist/cli/setup/LegacyMigration.d.ts.map +1 -0
- package/dist/cli/setup/LegacyMigration.js +162 -0
- package/dist/cli/setup/LegacyMigration.js.map +1 -0
- package/dist/cli/setup/ProjectSetup.d.ts +30 -0
- package/dist/cli/setup/ProjectSetup.d.ts.map +1 -0
- package/dist/cli/setup/ProjectSetup.js +238 -0
- package/dist/cli/setup/ProjectSetup.js.map +1 -0
- package/dist/cli/setup/index.d.ts +14 -0
- package/dist/cli/setup/index.d.ts.map +1 -0
- package/dist/cli/setup/index.js +18 -0
- package/dist/cli/setup/index.js.map +1 -0
- package/dist/cli/setup.d.ts +10 -77
- package/dist/cli/setup.d.ts.map +1 -1
- package/dist/cli/setup.js +15 -592
- package/dist/cli/setup.js.map +1 -1
- package/dist/lib/DeepInit.d.ts +0 -2
- package/dist/lib/DeepInit.d.ts.map +1 -1
- package/dist/lib/DeepInit.js +24 -26
- package/dist/lib/DeepInit.js.map +1 -1
- package/dist/lib/IterationTracker.d.ts +0 -2
- package/dist/lib/IterationTracker.d.ts.map +1 -1
- package/dist/lib/IterationTracker.js +11 -13
- package/dist/lib/IterationTracker.js.map +1 -1
- package/dist/lib/ModelRouter.d.ts +0 -2
- package/dist/lib/ModelRouter.d.ts.map +1 -1
- package/dist/lib/ModelRouter.js +0 -2
- package/dist/lib/ModelRouter.js.map +1 -1
- package/dist/lib/OrchestrateWorkflow.d.ts +1 -3
- package/dist/lib/OrchestrateWorkflow.d.ts.map +1 -1
- package/dist/lib/OrchestrateWorkflow.js +1 -3
- package/dist/lib/OrchestrateWorkflow.js.map +1 -1
- package/dist/lib/PythonParser.js +108 -108
- package/dist/lib/SkillFrontmatter.d.ts +0 -2
- package/dist/lib/SkillFrontmatter.d.ts.map +1 -1
- package/dist/lib/SkillFrontmatter.js +28 -30
- package/dist/lib/SkillFrontmatter.js.map +1 -1
- package/dist/lib/SkillQualityGate.d.ts +0 -2
- package/dist/lib/SkillQualityGate.d.ts.map +1 -1
- package/dist/lib/SkillQualityGate.js +9 -11
- package/dist/lib/SkillQualityGate.js.map +1 -1
- package/dist/lib/SkillRepository.d.ts +117 -0
- package/dist/lib/SkillRepository.d.ts.map +1 -0
- package/dist/lib/SkillRepository.js +477 -0
- package/dist/lib/SkillRepository.js.map +1 -0
- package/dist/lib/UltraQA.d.ts +0 -2
- package/dist/lib/UltraQA.d.ts.map +1 -1
- package/dist/lib/UltraQA.js +77 -79
- package/dist/lib/UltraQA.js.map +1 -1
- package/dist/lib/gemini-mcp.d.ts +10 -0
- package/dist/lib/gemini-mcp.d.ts.map +1 -0
- package/dist/lib/gemini-mcp.js +353 -0
- package/dist/lib/gemini-mcp.js.map +1 -0
- package/dist/lib/gpt-api.js +4 -4
- package/dist/lib/gpt-mcp.d.ts +10 -0
- package/dist/lib/gpt-mcp.d.ts.map +1 -0
- package/dist/lib/gpt-mcp.js +352 -0
- package/dist/lib/gpt-mcp.js.map +1 -0
- package/dist/lib/llm/auth/ApiKeyManager.d.ts +21 -0
- package/dist/lib/llm/auth/ApiKeyManager.d.ts.map +1 -0
- package/dist/lib/llm/auth/ApiKeyManager.js +43 -0
- package/dist/lib/llm/auth/ApiKeyManager.js.map +1 -0
- package/dist/lib/llm/auth/ConfigManager.d.ts +29 -0
- package/dist/lib/llm/auth/ConfigManager.d.ts.map +1 -0
- package/dist/lib/llm/auth/ConfigManager.js +67 -0
- package/dist/lib/llm/auth/ConfigManager.js.map +1 -0
- package/dist/lib/llm/auth/index.d.ts +25 -0
- package/dist/lib/llm/auth/index.d.ts.map +1 -0
- package/dist/lib/llm/auth/index.js +83 -0
- package/dist/lib/llm/auth/index.js.map +1 -0
- package/dist/lib/llm/index.d.ts +10 -0
- package/dist/lib/llm/index.d.ts.map +1 -0
- package/dist/lib/llm/index.js +12 -0
- package/dist/lib/llm/index.js.map +1 -0
- package/dist/lib/llm/types.d.ts +96 -0
- package/dist/lib/llm/types.d.ts.map +1 -0
- package/dist/lib/llm/types.js +17 -0
- package/dist/lib/llm/types.js.map +1 -0
- package/dist/lib/llm/utils/index.d.ts +6 -0
- package/dist/lib/llm/utils/index.d.ts.map +1 -0
- package/dist/lib/llm/utils/index.js +6 -0
- package/dist/lib/llm/utils/index.js.map +1 -0
- package/dist/lib/llm/utils/retry.d.ts +25 -0
- package/dist/lib/llm/utils/retry.d.ts.map +1 -0
- package/dist/lib/llm/utils/retry.js +72 -0
- package/dist/lib/llm/utils/retry.js.map +1 -0
- package/dist/lib/llm/utils/stream.d.ts +13 -0
- package/dist/lib/llm/utils/stream.d.ts.map +1 -0
- package/dist/lib/llm/utils/stream.js +110 -0
- package/dist/lib/llm/utils/stream.js.map +1 -0
- package/dist/lib/memory/KnowledgeGraph.js +4 -4
- package/dist/lib/memory/MemorySearch.js +20 -20
- package/dist/lib/memory/MemoryStorage.js +64 -64
- package/dist/orchestrator/AgentExecutor.d.ts +23 -0
- package/dist/orchestrator/AgentExecutor.d.ts.map +1 -0
- package/dist/orchestrator/AgentExecutor.js +231 -0
- package/dist/orchestrator/AgentExecutor.js.map +1 -0
- package/dist/orchestrator/AgentManager.d.ts +73 -0
- package/dist/orchestrator/AgentManager.d.ts.map +1 -0
- package/dist/orchestrator/AgentManager.js +184 -0
- package/dist/orchestrator/AgentManager.js.map +1 -0
- package/dist/orchestrator/LLMCluster.d.ts +70 -0
- package/dist/orchestrator/LLMCluster.d.ts.map +1 -0
- package/dist/orchestrator/LLMCluster.js +91 -0
- package/dist/orchestrator/LLMCluster.js.map +1 -0
- package/dist/orchestrator/MultiLlmResearch.d.ts +27 -0
- package/dist/orchestrator/MultiLlmResearch.d.ts.map +1 -0
- package/dist/orchestrator/MultiLlmResearch.js +145 -0
- package/dist/orchestrator/MultiLlmResearch.js.map +1 -0
- package/dist/orchestrator/SessionStore.d.ts +41 -0
- package/dist/orchestrator/SessionStore.d.ts.map +1 -0
- package/dist/orchestrator/SessionStore.js +117 -0
- package/dist/orchestrator/SessionStore.js.map +1 -0
- package/dist/orchestrator/SmartRouter.d.ts +68 -0
- package/dist/orchestrator/SmartRouter.d.ts.map +1 -0
- package/dist/orchestrator/SmartRouter.js +256 -0
- package/dist/orchestrator/SmartRouter.js.map +1 -0
- package/dist/orchestrator/backgroundAgent.d.ts +10 -28
- package/dist/orchestrator/backgroundAgent.d.ts.map +1 -1
- package/dist/orchestrator/backgroundAgent.js +11 -346
- package/dist/orchestrator/backgroundAgent.js.map +1 -1
- package/dist/orchestrator/index.d.ts +3 -0
- package/dist/orchestrator/index.d.ts.map +1 -1
- package/dist/orchestrator/index.js +4 -0
- package/dist/orchestrator/index.js.map +1 -1
- package/dist/orchestrator/orchestrator.d.ts +19 -154
- package/dist/orchestrator/orchestrator.d.ts.map +1 -1
- package/dist/orchestrator/orchestrator.js +90 -514
- package/dist/orchestrator/orchestrator.js.map +1 -1
- package/dist/orchestrator/parallelResearch.d.ts +5 -12
- package/dist/orchestrator/parallelResearch.d.ts.map +1 -1
- package/dist/orchestrator/parallelResearch.js +10 -193
- package/dist/orchestrator/parallelResearch.js.map +1 -1
- package/dist/tools/analytics/getUsageAnalytics.d.ts +10 -0
- package/dist/tools/analytics/getUsageAnalytics.d.ts.map +1 -0
- package/dist/tools/analytics/getUsageAnalytics.js +246 -0
- package/dist/tools/analytics/getUsageAnalytics.js.map +1 -0
- package/dist/tools/analytics/index.d.ts +5 -0
- package/dist/tools/analytics/index.d.ts.map +1 -0
- package/dist/tools/analytics/index.js +5 -0
- package/dist/tools/analytics/index.js.map +1 -0
- package/dist/tools/convention/analyzeComplexity.test.js +115 -115
- package/dist/tools/convention/getCodingGuide.d.ts +7 -0
- package/dist/tools/convention/getCodingGuide.d.ts.map +1 -0
- package/dist/tools/convention/getCodingGuide.js +69 -0
- package/dist/tools/convention/getCodingGuide.js.map +1 -0
- package/dist/tools/convention/validateCodeQuality.test.js +104 -104
- package/dist/tools/index.d.ts +2 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +2 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/planning/analyzeRequirements.d.ts +9 -0
- package/dist/tools/planning/analyzeRequirements.d.ts.map +1 -0
- package/dist/tools/planning/analyzeRequirements.js +171 -0
- package/dist/tools/planning/analyzeRequirements.js.map +1 -0
- package/dist/tools/planning/createUserStories.d.ts +9 -0
- package/dist/tools/planning/createUserStories.d.ts.map +1 -0
- package/dist/tools/planning/createUserStories.js +124 -0
- package/dist/tools/planning/createUserStories.js.map +1 -0
- package/dist/tools/planning/featureRoadmap.d.ts +10 -0
- package/dist/tools/planning/featureRoadmap.d.ts.map +1 -0
- package/dist/tools/planning/featureRoadmap.js +207 -0
- package/dist/tools/planning/featureRoadmap.js.map +1 -0
- package/dist/tools/planning/generatePrd.d.ts +11 -0
- package/dist/tools/planning/generatePrd.d.ts.map +1 -0
- package/dist/tools/planning/generatePrd.js +161 -0
- package/dist/tools/planning/generatePrd.js.map +1 -0
- package/dist/tools/planning/index.d.ts +8 -0
- package/dist/tools/planning/index.d.ts.map +1 -0
- package/dist/tools/planning/index.js +8 -0
- package/dist/tools/planning/index.js.map +1 -0
- package/dist/tools/prompt/analyzePrompt.d.ts +7 -0
- package/dist/tools/prompt/analyzePrompt.d.ts.map +1 -0
- package/dist/tools/prompt/analyzePrompt.js +150 -0
- package/dist/tools/prompt/analyzePrompt.js.map +1 -0
- package/dist/tools/prompt/enhancePrompt.d.ts +8 -0
- package/dist/tools/prompt/enhancePrompt.d.ts.map +1 -0
- package/dist/tools/prompt/enhancePrompt.js +110 -0
- package/dist/tools/prompt/enhancePrompt.js.map +1 -0
- package/dist/tools/prompt/enhancePromptGemini.d.ts +8 -0
- package/dist/tools/prompt/enhancePromptGemini.d.ts.map +1 -0
- package/dist/tools/prompt/enhancePromptGemini.js +332 -0
- package/dist/tools/prompt/enhancePromptGemini.js.map +1 -0
- package/dist/tools/prompt/index.d.ts +7 -0
- package/dist/tools/prompt/index.d.ts.map +1 -0
- package/dist/tools/prompt/index.js +7 -0
- package/dist/tools/prompt/index.js.map +1 -0
- package/dist/tools/reasoning/applyReasoningFramework.d.ts +8 -0
- package/dist/tools/reasoning/applyReasoningFramework.d.ts.map +1 -0
- package/dist/tools/reasoning/applyReasoningFramework.js +266 -0
- package/dist/tools/reasoning/applyReasoningFramework.js.map +1 -0
- package/dist/tools/reasoning/index.d.ts +5 -0
- package/dist/tools/reasoning/index.d.ts.map +1 -0
- package/dist/tools/reasoning/index.js +5 -0
- package/dist/tools/reasoning/index.js.map +1 -0
- package/dist/tools/thinking/analyzeProblem.d.ts +7 -0
- package/dist/tools/thinking/analyzeProblem.d.ts.map +1 -0
- package/dist/tools/thinking/analyzeProblem.js +55 -0
- package/dist/tools/thinking/analyzeProblem.js.map +1 -0
- package/dist/tools/thinking/breakDownProblem.d.ts +8 -0
- package/dist/tools/thinking/breakDownProblem.d.ts.map +1 -0
- package/dist/tools/thinking/breakDownProblem.js +145 -0
- package/dist/tools/thinking/breakDownProblem.js.map +1 -0
- package/dist/tools/thinking/createThinkingChain.d.ts +7 -0
- package/dist/tools/thinking/createThinkingChain.d.ts.map +1 -0
- package/dist/tools/thinking/createThinkingChain.js +44 -0
- package/dist/tools/thinking/createThinkingChain.js.map +1 -0
- package/dist/tools/thinking/formatAsPlan.d.ts +9 -0
- package/dist/tools/thinking/formatAsPlan.d.ts.map +1 -0
- package/dist/tools/thinking/formatAsPlan.js +78 -0
- package/dist/tools/thinking/formatAsPlan.js.map +1 -0
- package/dist/tools/thinking/index.d.ts +10 -0
- package/dist/tools/thinking/index.d.ts.map +1 -0
- package/dist/tools/thinking/index.js +10 -0
- package/dist/tools/thinking/index.js.map +1 -0
- package/dist/tools/thinking/stepByStepAnalysis.d.ts +8 -0
- package/dist/tools/thinking/stepByStepAnalysis.d.ts.map +1 -0
- package/dist/tools/thinking/stepByStepAnalysis.js +63 -0
- package/dist/tools/thinking/stepByStepAnalysis.js.map +1 -0
- package/dist/tools/thinking/thinkAloudProcess.d.ts +8 -0
- package/dist/tools/thinking/thinkAloudProcess.d.ts.map +1 -0
- package/dist/tools/thinking/thinkAloudProcess.js +80 -0
- package/dist/tools/thinking/thinkAloudProcess.js.map +1 -0
- package/hooks/hooks.json +222 -222
- package/hooks/scripts/code-check.js +22 -22
- package/hooks/scripts/code-review.js +22 -22
- package/hooks/scripts/complexity.js +22 -22
- package/hooks/scripts/compound.js +23 -23
- package/hooks/scripts/context-save.js +33 -33
- package/hooks/scripts/generate-brand-assets.js +472 -0
- package/hooks/scripts/hud-multiline.js +262 -264
- package/hooks/scripts/hud-status.js +291 -293
- package/hooks/scripts/keyword-detector.js +214 -216
- package/hooks/scripts/llm-orchestrate.js +171 -171
- package/hooks/scripts/post-edit.js +97 -97
- package/hooks/scripts/post-tool-verify.js +210 -212
- package/hooks/scripts/pre-tool-guard.js +125 -127
- package/hooks/scripts/recall.js +22 -22
- package/hooks/scripts/session-start.js +30 -30
- package/hooks/scripts/skill-injector.js +191 -193
- package/hooks/scripts/utils.js +97 -97
- package/languages/csharp-unity.md +515 -515
- package/languages/gdscript-godot.md +470 -470
- package/languages/ruby-rails.md +489 -489
- package/languages/typescript-angular.md +433 -433
- package/languages/typescript-astro.md +416 -416
- package/languages/typescript-electron.md +406 -406
- package/languages/typescript-nestjs.md +524 -524
- package/languages/typescript-svelte.md +407 -407
- package/languages/typescript-tauri.md +365 -365
- package/package.json +83 -83
- package/skills/brand-assets.md +141 -0
- package/skills/commerce-patterns.md +361 -0
- package/skills/context7-usage.md +102 -102
- package/skills/e2e-commerce.md +304 -0
- package/skills/frontend-design.md +92 -0
- package/skills/git-worktree.md +181 -181
- package/skills/parallel-research.md +77 -77
- package/skills/priority-todos.md +239 -239
- package/skills/seo-checklist.md +244 -0
- package/skills/tool-fallback.md +190 -190
- package/skills/vibe-capabilities.md +161 -161
- package/vibe/constitution.md +227 -227
- package/vibe/rules/core/communication-guide.md +98 -98
- package/vibe/rules/core/development-philosophy.md +52 -52
- package/vibe/rules/core/quick-start.md +102 -102
- package/vibe/rules/quality/bdd-contract-testing.md +393 -393
- package/vibe/rules/quality/checklist.md +276 -276
- package/vibe/rules/quality/testing-strategy.md +440 -440
- package/vibe/rules/standards/anti-patterns.md +541 -541
- package/vibe/rules/standards/code-structure.md +291 -291
- package/vibe/rules/standards/complexity-metrics.md +313 -313
- package/vibe/rules/standards/naming-conventions.md +198 -198
- package/vibe/setup.sh +31 -31
- package/vibe/templates/constitution-template.md +252 -252
- package/vibe/templates/contract-backend-template.md +526 -526
- package/vibe/templates/contract-frontend-template.md +599 -599
- package/vibe/templates/feature-template.md +96 -96
- package/vibe/templates/spec-template.md +221 -221
|
@@ -1,171 +1,171 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* UserPromptSubmit Hook - LLM 오케스트레이션 (GPT/Gemini)
|
|
3
|
-
*
|
|
4
|
-
* Usage:
|
|
5
|
-
* node llm-orchestrate.js <provider> <mode> "prompt"
|
|
6
|
-
* node llm-orchestrate.js <provider> <mode> "systemPrompt" "prompt"
|
|
7
|
-
*
|
|
8
|
-
* provider: gpt | gemini
|
|
9
|
-
* mode: orchestrate | orchestrate-json
|
|
10
|
-
*
|
|
11
|
-
* Features:
|
|
12
|
-
* - Exponential backoff retry (3 attempts)
|
|
13
|
-
* - Auto fallback: gemini → gpt, gpt → gemini
|
|
14
|
-
* - Overload/rate-limit detection
|
|
15
|
-
*
|
|
16
|
-
* Input: JSON from stdin with { prompt: string } (when no CLI args)
|
|
17
|
-
*/
|
|
18
|
-
import { getLibBaseUrl } from './utils.js';
|
|
19
|
-
|
|
20
|
-
const LIB_URL = getLibBaseUrl();
|
|
21
|
-
const DEFAULT_SYSTEM_PROMPT = 'You are a helpful assistant.';
|
|
22
|
-
|
|
23
|
-
const provider = process.argv[2] || 'gemini';
|
|
24
|
-
const mode = process.argv[3] || 'orchestrate';
|
|
25
|
-
|
|
26
|
-
// Retry configuration
|
|
27
|
-
const MAX_RETRIES = 3;
|
|
28
|
-
const INITIAL_DELAY_MS = 2000;
|
|
29
|
-
|
|
30
|
-
// Errors that should skip retry and go to fallback immediately
|
|
31
|
-
const SKIP_RETRY_PATTERNS = [
|
|
32
|
-
/rate.?limit/i,
|
|
33
|
-
/quota/i,
|
|
34
|
-
/unauthorized/i,
|
|
35
|
-
/forbidden/i,
|
|
36
|
-
/401/,
|
|
37
|
-
/403/,
|
|
38
|
-
/429/,
|
|
39
|
-
];
|
|
40
|
-
|
|
41
|
-
// Errors that should trigger retry with backoff
|
|
42
|
-
const RETRY_PATTERNS = [
|
|
43
|
-
/overload/i,
|
|
44
|
-
/503/,
|
|
45
|
-
/5\d\d/,
|
|
46
|
-
/network/i,
|
|
47
|
-
/timeout/i,
|
|
48
|
-
/ECONNRESET/i,
|
|
49
|
-
/ETIMEDOUT/i,
|
|
50
|
-
];
|
|
51
|
-
|
|
52
|
-
function shouldSkipRetry(errorMsg) {
|
|
53
|
-
return SKIP_RETRY_PATTERNS.some(pattern => pattern.test(errorMsg));
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
function shouldRetry(errorMsg) {
|
|
57
|
-
return RETRY_PATTERNS.some(pattern => pattern.test(errorMsg));
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
function sleep(ms) {
|
|
61
|
-
return new Promise(resolve => setTimeout(resolve, ms));
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
async function callProvider(providerName, prompt, sysPrompt, jsonMode) {
|
|
65
|
-
const modulePath = `${LIB_URL}${providerName}-api.js`;
|
|
66
|
-
const module = await import(modulePath);
|
|
67
|
-
|
|
68
|
-
const orchestrateFn = providerName === 'gpt'
|
|
69
|
-
? module.vibeGptOrchestrate
|
|
70
|
-
: module.vibeGeminiOrchestrate;
|
|
71
|
-
|
|
72
|
-
return await orchestrateFn(prompt, sysPrompt, { jsonMode });
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
async function callWithRetry(providerName, prompt, sysPrompt, jsonMode) {
|
|
76
|
-
let lastError;
|
|
77
|
-
|
|
78
|
-
for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {
|
|
79
|
-
try {
|
|
80
|
-
return { success: true, result: await callProvider(providerName, prompt, sysPrompt, jsonMode) };
|
|
81
|
-
} catch (e) {
|
|
82
|
-
lastError = e;
|
|
83
|
-
const errorMsg = e.message || String(e);
|
|
84
|
-
|
|
85
|
-
// Skip retry for auth/quota errors - go to fallback immediately
|
|
86
|
-
if (shouldSkipRetry(errorMsg)) {
|
|
87
|
-
return { success: false, error: errorMsg, skipToFallback: true };
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// Retry with backoff for transient errors
|
|
91
|
-
if (shouldRetry(errorMsg) && attempt < MAX_RETRIES) {
|
|
92
|
-
const delay = INITIAL_DELAY_MS * Math.pow(2, attempt - 1);
|
|
93
|
-
console.error(`[${providerName.toUpperCase()}] Retry ${attempt}/${MAX_RETRIES} after ${delay}ms...`);
|
|
94
|
-
await sleep(delay);
|
|
95
|
-
continue;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
// Unknown error or max retries reached
|
|
99
|
-
return { success: false, error: errorMsg, skipToFallback: false };
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
return { success: false, error: lastError?.message || 'Max retries exceeded', skipToFallback: false };
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
async function main() {
|
|
107
|
-
let prompt;
|
|
108
|
-
let systemPrompt = DEFAULT_SYSTEM_PROMPT;
|
|
109
|
-
|
|
110
|
-
// CLI argument가 있으면 사용
|
|
111
|
-
// Usage 1: node script.js gpt orchestrate "system prompt" "user prompt"
|
|
112
|
-
// Usage 2: node script.js gpt orchestrate "user prompt" (uses default system prompt)
|
|
113
|
-
const arg4 = process.argv[4]?.trim();
|
|
114
|
-
const arg5 = process.argv.slice(5).join(' ').trim();
|
|
115
|
-
|
|
116
|
-
if (arg5) {
|
|
117
|
-
// 5번째 인자가 있으면: arg4=시스템 프롬프트, arg5=사용자 프롬프트
|
|
118
|
-
systemPrompt = arg4;
|
|
119
|
-
prompt = arg5;
|
|
120
|
-
} else if (arg4) {
|
|
121
|
-
// 4번째 인자만 있으면: arg4=사용자 프롬프트 (시스템 프롬프트는 기본값)
|
|
122
|
-
prompt = arg4;
|
|
123
|
-
} else {
|
|
124
|
-
// Hook에서 호출: stdin으로 JSON 입력
|
|
125
|
-
let inputData = '';
|
|
126
|
-
for await (const chunk of process.stdin) {
|
|
127
|
-
inputData += chunk;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
try {
|
|
131
|
-
const parsed = JSON.parse(inputData);
|
|
132
|
-
prompt = parsed.prompt;
|
|
133
|
-
} catch {
|
|
134
|
-
console.log(`[${provider.toUpperCase()}] Error: Invalid JSON input`);
|
|
135
|
-
return;
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
// 접두사 제거
|
|
140
|
-
const prefixPatterns = {
|
|
141
|
-
gpt: /^(gpt[-.\s]|지피티-|vibe-gpt-)\s*/i,
|
|
142
|
-
gemini: /^(gemini[-.\s]|제미나이-|vibe-gemini-)\s*/i,
|
|
143
|
-
};
|
|
144
|
-
const cleanPrompt = prompt.replace(prefixPatterns[provider] || /^/, '').trim();
|
|
145
|
-
const jsonMode = mode === 'orchestrate-json';
|
|
146
|
-
|
|
147
|
-
// Provider chain: primary → fallback
|
|
148
|
-
const fallbackProvider = provider === 'gpt' ? 'gemini' : 'gpt';
|
|
149
|
-
const providerChain = [provider, fallbackProvider];
|
|
150
|
-
|
|
151
|
-
for (const currentProvider of providerChain) {
|
|
152
|
-
const label = currentProvider === 'gpt' ? 'GPT-5.2' : 'Gemini-3';
|
|
153
|
-
const result = await callWithRetry(currentProvider, cleanPrompt, systemPrompt, jsonMode);
|
|
154
|
-
|
|
155
|
-
if (result.success) {
|
|
156
|
-
console.log(`${label} response: ${result.result}`);
|
|
157
|
-
return;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
// Log failure and try fallback
|
|
161
|
-
if (currentProvider !== providerChain[providerChain.length - 1]) {
|
|
162
|
-
const fallbackLabel = fallbackProvider === 'gpt' ? 'GPT' : 'Gemini';
|
|
163
|
-
console.error(`[${currentProvider.toUpperCase()}] Failed: ${result.error}. Falling back to ${fallbackLabel}...`);
|
|
164
|
-
} else {
|
|
165
|
-
// All providers failed
|
|
166
|
-
console.log(`[LLM] Error: All providers failed. Last error: ${result.error}`);
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
main();
|
|
1
|
+
/**
|
|
2
|
+
* UserPromptSubmit Hook - LLM 오케스트레이션 (GPT/Gemini)
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* node llm-orchestrate.js <provider> <mode> "prompt"
|
|
6
|
+
* node llm-orchestrate.js <provider> <mode> "systemPrompt" "prompt"
|
|
7
|
+
*
|
|
8
|
+
* provider: gpt | gemini
|
|
9
|
+
* mode: orchestrate | orchestrate-json
|
|
10
|
+
*
|
|
11
|
+
* Features:
|
|
12
|
+
* - Exponential backoff retry (3 attempts)
|
|
13
|
+
* - Auto fallback: gemini → gpt, gpt → gemini
|
|
14
|
+
* - Overload/rate-limit detection
|
|
15
|
+
*
|
|
16
|
+
* Input: JSON from stdin with { prompt: string } (when no CLI args)
|
|
17
|
+
*/
|
|
18
|
+
import { getLibBaseUrl } from './utils.js';
|
|
19
|
+
|
|
20
|
+
const LIB_URL = getLibBaseUrl();
|
|
21
|
+
const DEFAULT_SYSTEM_PROMPT = 'You are a helpful assistant.';
|
|
22
|
+
|
|
23
|
+
const provider = process.argv[2] || 'gemini';
|
|
24
|
+
const mode = process.argv[3] || 'orchestrate';
|
|
25
|
+
|
|
26
|
+
// Retry configuration
|
|
27
|
+
const MAX_RETRIES = 3;
|
|
28
|
+
const INITIAL_DELAY_MS = 2000;
|
|
29
|
+
|
|
30
|
+
// Errors that should skip retry and go to fallback immediately
|
|
31
|
+
const SKIP_RETRY_PATTERNS = [
|
|
32
|
+
/rate.?limit/i,
|
|
33
|
+
/quota/i,
|
|
34
|
+
/unauthorized/i,
|
|
35
|
+
/forbidden/i,
|
|
36
|
+
/401/,
|
|
37
|
+
/403/,
|
|
38
|
+
/429/,
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
// Errors that should trigger retry with backoff
|
|
42
|
+
const RETRY_PATTERNS = [
|
|
43
|
+
/overload/i,
|
|
44
|
+
/503/,
|
|
45
|
+
/5\d\d/,
|
|
46
|
+
/network/i,
|
|
47
|
+
/timeout/i,
|
|
48
|
+
/ECONNRESET/i,
|
|
49
|
+
/ETIMEDOUT/i,
|
|
50
|
+
];
|
|
51
|
+
|
|
52
|
+
function shouldSkipRetry(errorMsg) {
|
|
53
|
+
return SKIP_RETRY_PATTERNS.some(pattern => pattern.test(errorMsg));
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function shouldRetry(errorMsg) {
|
|
57
|
+
return RETRY_PATTERNS.some(pattern => pattern.test(errorMsg));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function sleep(ms) {
|
|
61
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async function callProvider(providerName, prompt, sysPrompt, jsonMode) {
|
|
65
|
+
const modulePath = `${LIB_URL}${providerName}-api.js`;
|
|
66
|
+
const module = await import(modulePath);
|
|
67
|
+
|
|
68
|
+
const orchestrateFn = providerName === 'gpt'
|
|
69
|
+
? module.vibeGptOrchestrate
|
|
70
|
+
: module.vibeGeminiOrchestrate;
|
|
71
|
+
|
|
72
|
+
return await orchestrateFn(prompt, sysPrompt, { jsonMode });
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
async function callWithRetry(providerName, prompt, sysPrompt, jsonMode) {
|
|
76
|
+
let lastError;
|
|
77
|
+
|
|
78
|
+
for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {
|
|
79
|
+
try {
|
|
80
|
+
return { success: true, result: await callProvider(providerName, prompt, sysPrompt, jsonMode) };
|
|
81
|
+
} catch (e) {
|
|
82
|
+
lastError = e;
|
|
83
|
+
const errorMsg = e.message || String(e);
|
|
84
|
+
|
|
85
|
+
// Skip retry for auth/quota errors - go to fallback immediately
|
|
86
|
+
if (shouldSkipRetry(errorMsg)) {
|
|
87
|
+
return { success: false, error: errorMsg, skipToFallback: true };
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Retry with backoff for transient errors
|
|
91
|
+
if (shouldRetry(errorMsg) && attempt < MAX_RETRIES) {
|
|
92
|
+
const delay = INITIAL_DELAY_MS * Math.pow(2, attempt - 1);
|
|
93
|
+
console.error(`[${providerName.toUpperCase()}] Retry ${attempt}/${MAX_RETRIES} after ${delay}ms...`);
|
|
94
|
+
await sleep(delay);
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Unknown error or max retries reached
|
|
99
|
+
return { success: false, error: errorMsg, skipToFallback: false };
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return { success: false, error: lastError?.message || 'Max retries exceeded', skipToFallback: false };
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
async function main() {
|
|
107
|
+
let prompt;
|
|
108
|
+
let systemPrompt = DEFAULT_SYSTEM_PROMPT;
|
|
109
|
+
|
|
110
|
+
// CLI argument가 있으면 사용
|
|
111
|
+
// Usage 1: node script.js gpt orchestrate "system prompt" "user prompt"
|
|
112
|
+
// Usage 2: node script.js gpt orchestrate "user prompt" (uses default system prompt)
|
|
113
|
+
const arg4 = process.argv[4]?.trim();
|
|
114
|
+
const arg5 = process.argv.slice(5).join(' ').trim();
|
|
115
|
+
|
|
116
|
+
if (arg5) {
|
|
117
|
+
// 5번째 인자가 있으면: arg4=시스템 프롬프트, arg5=사용자 프롬프트
|
|
118
|
+
systemPrompt = arg4;
|
|
119
|
+
prompt = arg5;
|
|
120
|
+
} else if (arg4) {
|
|
121
|
+
// 4번째 인자만 있으면: arg4=사용자 프롬프트 (시스템 프롬프트는 기본값)
|
|
122
|
+
prompt = arg4;
|
|
123
|
+
} else {
|
|
124
|
+
// Hook에서 호출: stdin으로 JSON 입력
|
|
125
|
+
let inputData = '';
|
|
126
|
+
for await (const chunk of process.stdin) {
|
|
127
|
+
inputData += chunk;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
try {
|
|
131
|
+
const parsed = JSON.parse(inputData);
|
|
132
|
+
prompt = parsed.prompt;
|
|
133
|
+
} catch {
|
|
134
|
+
console.log(`[${provider.toUpperCase()}] Error: Invalid JSON input`);
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// 접두사 제거
|
|
140
|
+
const prefixPatterns = {
|
|
141
|
+
gpt: /^(gpt[-.\s]|지피티-|vibe-gpt-)\s*/i,
|
|
142
|
+
gemini: /^(gemini[-.\s]|제미나이-|vibe-gemini-)\s*/i,
|
|
143
|
+
};
|
|
144
|
+
const cleanPrompt = prompt.replace(prefixPatterns[provider] || /^/, '').trim();
|
|
145
|
+
const jsonMode = mode === 'orchestrate-json';
|
|
146
|
+
|
|
147
|
+
// Provider chain: primary → fallback
|
|
148
|
+
const fallbackProvider = provider === 'gpt' ? 'gemini' : 'gpt';
|
|
149
|
+
const providerChain = [provider, fallbackProvider];
|
|
150
|
+
|
|
151
|
+
for (const currentProvider of providerChain) {
|
|
152
|
+
const label = currentProvider === 'gpt' ? 'GPT-5.2' : 'Gemini-3';
|
|
153
|
+
const result = await callWithRetry(currentProvider, cleanPrompt, systemPrompt, jsonMode);
|
|
154
|
+
|
|
155
|
+
if (result.success) {
|
|
156
|
+
console.log(`${label} response: ${result.result}`);
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Log failure and try fallback
|
|
161
|
+
if (currentProvider !== providerChain[providerChain.length - 1]) {
|
|
162
|
+
const fallbackLabel = fallbackProvider === 'gpt' ? 'GPT' : 'Gemini';
|
|
163
|
+
console.error(`[${currentProvider.toUpperCase()}] Failed: ${result.error}. Falling back to ${fallbackLabel}...`);
|
|
164
|
+
} else {
|
|
165
|
+
// All providers failed
|
|
166
|
+
console.log(`[LLM] Error: All providers failed. Last error: ${result.error}`);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
main();
|
|
@@ -1,97 +1,97 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* PostToolUse Hook - Edit 후 자동 포맷팅 및 TypeScript 체크
|
|
3
|
-
*
|
|
4
|
-
* 기능:
|
|
5
|
-
* - TypeScript/JavaScript 파일 수정 시 자동 Prettier 포맷팅
|
|
6
|
-
* - TypeScript 파일 수정 시 타입 체크
|
|
7
|
-
* - console.log 감지 및 경고
|
|
8
|
-
*/
|
|
9
|
-
import { execSync } from 'child_process';
|
|
10
|
-
import { existsSync } from 'fs';
|
|
11
|
-
import { PROJECT_DIR } from './utils.js';
|
|
12
|
-
|
|
13
|
-
// Claude Code에서 전달받는 환경변수에서 파일 경로 추출
|
|
14
|
-
const toolInput = process.env.TOOL_INPUT || '{}';
|
|
15
|
-
|
|
16
|
-
function main() {
|
|
17
|
-
try {
|
|
18
|
-
const input = JSON.parse(toolInput);
|
|
19
|
-
const filePath = input.file_path || input.path || '';
|
|
20
|
-
|
|
21
|
-
if (!filePath) {
|
|
22
|
-
return;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
// TypeScript/JavaScript 파일인지 확인
|
|
26
|
-
const isTs = /\.(ts|tsx)$/.test(filePath);
|
|
27
|
-
const isJs = /\.(js|jsx|mjs|cjs)$/.test(filePath);
|
|
28
|
-
|
|
29
|
-
if (!isTs && !isJs) {
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const results = [];
|
|
34
|
-
|
|
35
|
-
// Prettier 포맷팅 (prettier가 설치된 경우만)
|
|
36
|
-
const prettierConfig = [
|
|
37
|
-
`${PROJECT_DIR}/.prettierrc`,
|
|
38
|
-
`${PROJECT_DIR}/.prettierrc.json`,
|
|
39
|
-
`${PROJECT_DIR}/.prettierrc.js`,
|
|
40
|
-
`${PROJECT_DIR}/prettier.config.js`,
|
|
41
|
-
].find(p => existsSync(p));
|
|
42
|
-
|
|
43
|
-
if (prettierConfig || existsSync(`${PROJECT_DIR}/node_modules/.bin/prettier`)) {
|
|
44
|
-
try {
|
|
45
|
-
execSync(`npx prettier --write "${filePath}" 2>/dev/null`, {
|
|
46
|
-
cwd: PROJECT_DIR,
|
|
47
|
-
stdio: 'pipe',
|
|
48
|
-
timeout: 10000,
|
|
49
|
-
});
|
|
50
|
-
results.push('formatted');
|
|
51
|
-
} catch {
|
|
52
|
-
// Prettier 실패는 무시
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// TypeScript 타입 체크 (tsconfig가 있는 경우만)
|
|
57
|
-
if (isTs && existsSync(`${PROJECT_DIR}/tsconfig.json`)) {
|
|
58
|
-
try {
|
|
59
|
-
execSync(`npx tsc --noEmit --skipLibCheck 2>&1 | head -5`, {
|
|
60
|
-
cwd: PROJECT_DIR,
|
|
61
|
-
stdio: 'pipe',
|
|
62
|
-
timeout: 30000,
|
|
63
|
-
});
|
|
64
|
-
results.push('types OK');
|
|
65
|
-
} catch (e) {
|
|
66
|
-
const output = e.stdout?.toString() || '';
|
|
67
|
-
const errorCount = (output.match(/error TS/g) || []).length;
|
|
68
|
-
if (errorCount > 0) {
|
|
69
|
-
results.push(`${errorCount} type errors`);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// console.log 감지
|
|
75
|
-
try {
|
|
76
|
-
const grepResult = execSync(
|
|
77
|
-
`grep -n "console\\.log" "${filePath}" 2>/dev/null | head -3`,
|
|
78
|
-
{ cwd: PROJECT_DIR, stdio: 'pipe', encoding: 'utf-8' }
|
|
79
|
-
);
|
|
80
|
-
if (grepResult.trim()) {
|
|
81
|
-
const lines = grepResult.trim().split('\n').map(l => l.split(':')[0]).join(',');
|
|
82
|
-
results.push(`console.log at line ${lines}`);
|
|
83
|
-
}
|
|
84
|
-
} catch {
|
|
85
|
-
// grep 실패는 console.log 없음을 의미
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
if (results.length > 0) {
|
|
89
|
-
console.log(`[POST-EDIT] ${filePath.split('/').pop()}: ${results.join(' | ')}`);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
} catch {
|
|
93
|
-
// 조용히 실패
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
main();
|
|
1
|
+
/**
|
|
2
|
+
* PostToolUse Hook - Edit 후 자동 포맷팅 및 TypeScript 체크
|
|
3
|
+
*
|
|
4
|
+
* 기능:
|
|
5
|
+
* - TypeScript/JavaScript 파일 수정 시 자동 Prettier 포맷팅
|
|
6
|
+
* - TypeScript 파일 수정 시 타입 체크
|
|
7
|
+
* - console.log 감지 및 경고
|
|
8
|
+
*/
|
|
9
|
+
import { execSync } from 'child_process';
|
|
10
|
+
import { existsSync } from 'fs';
|
|
11
|
+
import { PROJECT_DIR } from './utils.js';
|
|
12
|
+
|
|
13
|
+
// Claude Code에서 전달받는 환경변수에서 파일 경로 추출
|
|
14
|
+
const toolInput = process.env.TOOL_INPUT || '{}';
|
|
15
|
+
|
|
16
|
+
function main() {
|
|
17
|
+
try {
|
|
18
|
+
const input = JSON.parse(toolInput);
|
|
19
|
+
const filePath = input.file_path || input.path || '';
|
|
20
|
+
|
|
21
|
+
if (!filePath) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// TypeScript/JavaScript 파일인지 확인
|
|
26
|
+
const isTs = /\.(ts|tsx)$/.test(filePath);
|
|
27
|
+
const isJs = /\.(js|jsx|mjs|cjs)$/.test(filePath);
|
|
28
|
+
|
|
29
|
+
if (!isTs && !isJs) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const results = [];
|
|
34
|
+
|
|
35
|
+
// Prettier 포맷팅 (prettier가 설치된 경우만)
|
|
36
|
+
const prettierConfig = [
|
|
37
|
+
`${PROJECT_DIR}/.prettierrc`,
|
|
38
|
+
`${PROJECT_DIR}/.prettierrc.json`,
|
|
39
|
+
`${PROJECT_DIR}/.prettierrc.js`,
|
|
40
|
+
`${PROJECT_DIR}/prettier.config.js`,
|
|
41
|
+
].find(p => existsSync(p));
|
|
42
|
+
|
|
43
|
+
if (prettierConfig || existsSync(`${PROJECT_DIR}/node_modules/.bin/prettier`)) {
|
|
44
|
+
try {
|
|
45
|
+
execSync(`npx prettier --write "${filePath}" 2>/dev/null`, {
|
|
46
|
+
cwd: PROJECT_DIR,
|
|
47
|
+
stdio: 'pipe',
|
|
48
|
+
timeout: 10000,
|
|
49
|
+
});
|
|
50
|
+
results.push('formatted');
|
|
51
|
+
} catch {
|
|
52
|
+
// Prettier 실패는 무시
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// TypeScript 타입 체크 (tsconfig가 있는 경우만)
|
|
57
|
+
if (isTs && existsSync(`${PROJECT_DIR}/tsconfig.json`)) {
|
|
58
|
+
try {
|
|
59
|
+
execSync(`npx tsc --noEmit --skipLibCheck 2>&1 | head -5`, {
|
|
60
|
+
cwd: PROJECT_DIR,
|
|
61
|
+
stdio: 'pipe',
|
|
62
|
+
timeout: 30000,
|
|
63
|
+
});
|
|
64
|
+
results.push('types OK');
|
|
65
|
+
} catch (e) {
|
|
66
|
+
const output = e.stdout?.toString() || '';
|
|
67
|
+
const errorCount = (output.match(/error TS/g) || []).length;
|
|
68
|
+
if (errorCount > 0) {
|
|
69
|
+
results.push(`${errorCount} type errors`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// console.log 감지
|
|
75
|
+
try {
|
|
76
|
+
const grepResult = execSync(
|
|
77
|
+
`grep -n "console\\.log" "${filePath}" 2>/dev/null | head -3`,
|
|
78
|
+
{ cwd: PROJECT_DIR, stdio: 'pipe', encoding: 'utf-8' }
|
|
79
|
+
);
|
|
80
|
+
if (grepResult.trim()) {
|
|
81
|
+
const lines = grepResult.trim().split('\n').map(l => l.split(':')[0]).join(',');
|
|
82
|
+
results.push(`console.log at line ${lines}`);
|
|
83
|
+
}
|
|
84
|
+
} catch {
|
|
85
|
+
// grep 실패는 console.log 없음을 의미
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (results.length > 0) {
|
|
89
|
+
console.log(`[POST-EDIT] ${filePath.split('/').pop()}: ${results.join(' | ')}`);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
} catch {
|
|
93
|
+
// 조용히 실패
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
main();
|