@cloudstreamsoftware/claude-tools 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +152 -37
- package/agents/INDEX.md +183 -0
- package/agents/architect.md +247 -0
- package/agents/build-error-resolver.md +555 -0
- package/agents/catalyst-deployer.md +132 -0
- package/agents/code-reviewer.md +121 -0
- package/agents/compliance-auditor.md +148 -0
- package/agents/creator-architect.md +395 -0
- package/agents/deluge-reviewer.md +98 -0
- package/agents/doc-updater.md +471 -0
- package/agents/e2e-runner.md +711 -0
- package/agents/planner.md +122 -0
- package/agents/refactor-cleaner.md +309 -0
- package/agents/security-reviewer.md +582 -0
- package/agents/tdd-guide.md +302 -0
- package/config/versions.json +63 -0
- package/dist/hooks/hooks.json +209 -0
- package/dist/index.js +47 -0
- package/dist/lib/asset-value.js +609 -0
- package/dist/lib/client-manager.js +300 -0
- package/dist/lib/command-matcher.js +242 -0
- package/dist/lib/cross-session-patterns.js +754 -0
- package/dist/lib/intent-classifier.js +1075 -0
- package/dist/lib/package-manager.js +374 -0
- package/dist/lib/recommendation-engine.js +597 -0
- package/dist/lib/session-memory.js +489 -0
- package/dist/lib/skill-effectiveness.js +486 -0
- package/dist/lib/skill-matcher.js +595 -0
- package/dist/lib/tutorial-metrics.js +242 -0
- package/dist/lib/tutorial-progress.js +209 -0
- package/dist/lib/tutorial-renderer.js +431 -0
- package/dist/lib/utils.js +380 -0
- package/dist/lib/verify-formatter.js +143 -0
- package/dist/lib/workflow-state.js +249 -0
- package/hooks/hooks.json +209 -0
- package/package.json +5 -1
- package/scripts/aggregate-sessions.js +290 -0
- package/scripts/branch-name-validator.js +291 -0
- package/scripts/build.js +101 -0
- package/scripts/commands/client-switch.js +231 -0
- package/scripts/deprecate-skill.js +610 -0
- package/scripts/diagnose.js +324 -0
- package/scripts/doc-freshness.js +168 -0
- package/scripts/generate-weekly-digest.js +393 -0
- package/scripts/health-check.js +270 -0
- package/scripts/hooks/credential-check.js +101 -0
- package/scripts/hooks/evaluate-session.js +81 -0
- package/scripts/hooks/pre-compact.js +66 -0
- package/scripts/hooks/prompt-analyzer.js +276 -0
- package/scripts/hooks/prompt-router.js +422 -0
- package/scripts/hooks/quality-gate-enforcer.js +371 -0
- package/scripts/hooks/session-end.js +156 -0
- package/scripts/hooks/session-start.js +195 -0
- package/scripts/hooks/skill-injector.js +333 -0
- package/scripts/hooks/suggest-compact.js +58 -0
- package/scripts/lib/asset-value.js +609 -0
- package/scripts/lib/client-manager.js +300 -0
- package/scripts/lib/command-matcher.js +242 -0
- package/scripts/lib/cross-session-patterns.js +754 -0
- package/scripts/lib/intent-classifier.js +1075 -0
- package/scripts/lib/package-manager.js +374 -0
- package/scripts/lib/recommendation-engine.js +597 -0
- package/scripts/lib/session-memory.js +489 -0
- package/scripts/lib/skill-effectiveness.js +486 -0
- package/scripts/lib/skill-matcher.js +595 -0
- package/scripts/lib/tutorial-metrics.js +242 -0
- package/scripts/lib/tutorial-progress.js +209 -0
- package/scripts/lib/tutorial-renderer.js +431 -0
- package/scripts/lib/utils.js +380 -0
- package/scripts/lib/verify-formatter.js +143 -0
- package/scripts/lib/workflow-state.js +249 -0
- package/scripts/onboard.js +363 -0
- package/scripts/quarterly-report.js +692 -0
- package/scripts/setup-package-manager.js +204 -0
- package/scripts/sync-upstream.js +391 -0
- package/scripts/test.js +108 -0
- package/scripts/tutorial-runner.js +351 -0
- package/scripts/validate-all.js +201 -0
- package/scripts/verifiers/agents.js +245 -0
- package/scripts/verifiers/config.js +186 -0
- package/scripts/verifiers/environment.js +123 -0
- package/scripts/verifiers/hooks.js +188 -0
- package/scripts/verifiers/index.js +38 -0
- package/scripts/verifiers/persistence.js +140 -0
- package/scripts/verifiers/plugin.js +215 -0
- package/scripts/verifiers/skills.js +209 -0
- package/scripts/verify-setup.js +164 -0
- package/skills/INDEX.md +157 -0
- package/skills/backend-patterns/SKILL.md +586 -0
- package/skills/backend-patterns/catalyst-patterns.md +128 -0
- package/skills/bigquery-patterns/SKILL.md +27 -0
- package/skills/bigquery-patterns/performance-optimization.md +518 -0
- package/skills/bigquery-patterns/query-patterns.md +372 -0
- package/skills/bigquery-patterns/schema-design.md +78 -0
- package/skills/cloudstream-project-template/SKILL.md +20 -0
- package/skills/cloudstream-project-template/structure.md +65 -0
- package/skills/coding-standards/SKILL.md +524 -0
- package/skills/coding-standards/deluge-standards.md +83 -0
- package/skills/compliance-patterns/SKILL.md +28 -0
- package/skills/compliance-patterns/hipaa/audit-requirements.md +251 -0
- package/skills/compliance-patterns/hipaa/baa-process.md +298 -0
- package/skills/compliance-patterns/hipaa/data-archival-strategy.md +387 -0
- package/skills/compliance-patterns/hipaa/phi-handling.md +52 -0
- package/skills/compliance-patterns/pci-dss/saq-a-requirements.md +307 -0
- package/skills/compliance-patterns/pci-dss/tokenization-patterns.md +382 -0
- package/skills/compliance-patterns/pci-dss/zoho-checkout-patterns.md +56 -0
- package/skills/compliance-patterns/soc2/access-controls.md +344 -0
- package/skills/compliance-patterns/soc2/audit-logging.md +458 -0
- package/skills/compliance-patterns/soc2/change-management.md +403 -0
- package/skills/compliance-patterns/soc2/deluge-execution-logging.md +407 -0
- package/skills/consultancy-workflows/SKILL.md +19 -0
- package/skills/consultancy-workflows/client-isolation.md +21 -0
- package/skills/consultancy-workflows/documentation-automation.md +454 -0
- package/skills/consultancy-workflows/handoff-procedures.md +257 -0
- package/skills/consultancy-workflows/knowledge-capture.md +513 -0
- package/skills/consultancy-workflows/time-tracking.md +26 -0
- package/skills/continuous-learning/SKILL.md +84 -0
- package/skills/continuous-learning/config.json +18 -0
- package/skills/continuous-learning/evaluate-session.sh +60 -0
- package/skills/continuous-learning-v2/SKILL.md +126 -0
- package/skills/continuous-learning-v2/config.json +61 -0
- package/skills/frontend-patterns/SKILL.md +635 -0
- package/skills/frontend-patterns/zoho-widget-patterns.md +103 -0
- package/skills/gcp-data-engineering/SKILL.md +36 -0
- package/skills/gcp-data-engineering/bigquery/performance-optimization.md +337 -0
- package/skills/gcp-data-engineering/dataflow/error-handling.md +496 -0
- package/skills/gcp-data-engineering/dataflow/pipeline-patterns.md +444 -0
- package/skills/gcp-data-engineering/dbt/model-organization.md +63 -0
- package/skills/gcp-data-engineering/dbt/testing-patterns.md +503 -0
- package/skills/gcp-data-engineering/medallion-architecture/bronze-layer.md +60 -0
- package/skills/gcp-data-engineering/medallion-architecture/gold-layer.md +311 -0
- package/skills/gcp-data-engineering/medallion-architecture/layer-transitions.md +517 -0
- package/skills/gcp-data-engineering/medallion-architecture/silver-layer.md +305 -0
- package/skills/gcp-data-engineering/zoho-to-gcp/data-extraction.md +543 -0
- package/skills/gcp-data-engineering/zoho-to-gcp/real-time-vs-batch.md +337 -0
- package/skills/security-review/SKILL.md +498 -0
- package/skills/security-review/compliance-checklist.md +53 -0
- package/skills/strategic-compact/SKILL.md +67 -0
- package/skills/tdd-workflow/SKILL.md +413 -0
- package/skills/tdd-workflow/zoho-testing.md +124 -0
- package/skills/tutorial/SKILL.md +249 -0
- package/skills/tutorial/docs/ACCESSIBILITY.md +169 -0
- package/skills/tutorial/lessons/00-philosophy-and-workflow.md +198 -0
- package/skills/tutorial/lessons/01-basics.md +81 -0
- package/skills/tutorial/lessons/02-training.md +86 -0
- package/skills/tutorial/lessons/03-commands.md +109 -0
- package/skills/tutorial/lessons/04-workflows.md +115 -0
- package/skills/tutorial/lessons/05-compliance.md +116 -0
- package/skills/tutorial/lessons/06-zoho.md +121 -0
- package/skills/tutorial/lessons/07-hooks-system.md +277 -0
- package/skills/tutorial/lessons/08-mcp-servers.md +316 -0
- package/skills/tutorial/lessons/09-client-management.md +215 -0
- package/skills/tutorial/lessons/10-testing-e2e.md +260 -0
- package/skills/tutorial/lessons/11-skills-deep-dive.md +272 -0
- package/skills/tutorial/lessons/12-rules-system.md +326 -0
- package/skills/tutorial/lessons/13-golden-standard-graduation.md +213 -0
- package/skills/tutorial/lessons/14-fork-setup-and-sync.md +312 -0
- package/skills/tutorial/lessons/15-living-examples-system.md +221 -0
- package/skills/tutorial/tracks/accelerated/README.md +134 -0
- package/skills/tutorial/tracks/accelerated/assessment/checkpoint-1.md +161 -0
- package/skills/tutorial/tracks/accelerated/assessment/checkpoint-2.md +175 -0
- package/skills/tutorial/tracks/accelerated/day-1-core-concepts.md +234 -0
- package/skills/tutorial/tracks/accelerated/day-2-essential-commands.md +270 -0
- package/skills/tutorial/tracks/accelerated/day-3-workflow-mastery.md +305 -0
- package/skills/tutorial/tracks/accelerated/day-4-compliance-zoho.md +304 -0
- package/skills/tutorial/tracks/accelerated/day-5-hooks-skills.md +344 -0
- package/skills/tutorial/tracks/accelerated/day-6-client-testing.md +386 -0
- package/skills/tutorial/tracks/accelerated/day-7-graduation.md +369 -0
- package/skills/zoho-patterns/CHANGELOG.md +108 -0
- package/skills/zoho-patterns/SKILL.md +446 -0
- package/skills/zoho-patterns/analytics/dashboard-patterns.md +352 -0
- package/skills/zoho-patterns/analytics/zoho-to-bigquery-pipeline.md +427 -0
- package/skills/zoho-patterns/catalyst/appsail-deployment.md +349 -0
- package/skills/zoho-patterns/catalyst/context-close-patterns.md +354 -0
- package/skills/zoho-patterns/catalyst/cron-batch-processing.md +374 -0
- package/skills/zoho-patterns/catalyst/function-patterns.md +439 -0
- package/skills/zoho-patterns/creator/form-design.md +304 -0
- package/skills/zoho-patterns/creator/publish-api-patterns.md +313 -0
- package/skills/zoho-patterns/creator/widget-integration.md +306 -0
- package/skills/zoho-patterns/creator/workflow-automation.md +253 -0
- package/skills/zoho-patterns/deluge/api-patterns.md +468 -0
- package/skills/zoho-patterns/deluge/batch-processing.md +403 -0
- package/skills/zoho-patterns/deluge/cross-app-integration.md +356 -0
- package/skills/zoho-patterns/deluge/error-handling.md +423 -0
- package/skills/zoho-patterns/deluge/syntax-reference.md +65 -0
- package/skills/zoho-patterns/integration/cors-proxy-architecture.md +426 -0
- package/skills/zoho-patterns/integration/crm-books-native-sync.md +277 -0
- package/skills/zoho-patterns/integration/oauth-token-management.md +461 -0
- package/skills/zoho-patterns/integration/zoho-flow-patterns.md +334 -0
|
@@ -0,0 +1,422 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Prompt Router Hook - Intelligent Prompt Preprocessing
|
|
5
|
+
*
|
|
6
|
+
* This hook runs on UserPromptSubmit to:
|
|
7
|
+
* 1. Detect user intent from natural language
|
|
8
|
+
* 2. Suggest or auto-convert to optimal commands
|
|
9
|
+
* 3. Track workflow state and warn about skipped phases
|
|
10
|
+
* 4. Log routing decisions for analytics
|
|
11
|
+
*
|
|
12
|
+
* Performance Target: <100ms (non-blocking)
|
|
13
|
+
*
|
|
14
|
+
* Hook Type: UserPromptSubmit
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
const fs = require('fs');
|
|
18
|
+
const path = require('path');
|
|
19
|
+
|
|
20
|
+
// Import utilities
|
|
21
|
+
const { readStdinJson, log, output, getClaudeDir, ensureDir } = require('../lib/utils');
|
|
22
|
+
|
|
23
|
+
// Import router components
|
|
24
|
+
const { classifyIntent, INTENT_TYPES, THRESHOLDS } = require('../lib/intent-classifier');
|
|
25
|
+
const { matchCommand, formatCommand } = require('../lib/command-matcher');
|
|
26
|
+
const {
|
|
27
|
+
getWorkflowState,
|
|
28
|
+
startWorkflow,
|
|
29
|
+
advancePhase,
|
|
30
|
+
checkSkippedPhases,
|
|
31
|
+
getNextPhase,
|
|
32
|
+
isCriticalPhase,
|
|
33
|
+
detectWorkflowType,
|
|
34
|
+
} = require('../lib/workflow-state');
|
|
35
|
+
|
|
36
|
+
// Configuration defaults
|
|
37
|
+
const DEFAULT_CONFIG = {
|
|
38
|
+
enabled: true,
|
|
39
|
+
autoConvertThreshold: 0.8,
|
|
40
|
+
suggestionThreshold: 0.5,
|
|
41
|
+
workflowEnforcement: 'warn', // 'suggest' | 'warn' | 'block'
|
|
42
|
+
analytics: {
|
|
43
|
+
enabled: true,
|
|
44
|
+
logFile: null, // Will be set dynamically
|
|
45
|
+
},
|
|
46
|
+
debug: false,
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Load configuration from file or use defaults
|
|
51
|
+
*/
|
|
52
|
+
function loadConfig() {
|
|
53
|
+
const configPath = path.join(__dirname, '..', '..', 'config', 'prompt-router.json');
|
|
54
|
+
|
|
55
|
+
try {
|
|
56
|
+
if (fs.existsSync(configPath)) {
|
|
57
|
+
const content = fs.readFileSync(configPath, 'utf8');
|
|
58
|
+
const userConfig = JSON.parse(content);
|
|
59
|
+
return { ...DEFAULT_CONFIG, ...userConfig };
|
|
60
|
+
}
|
|
61
|
+
} catch (err) {
|
|
62
|
+
// Config error - use defaults
|
|
63
|
+
log(`[PromptRouter] Config error: ${err.message}, using defaults`);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return DEFAULT_CONFIG;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Check if routing is disabled via environment variable
|
|
71
|
+
*/
|
|
72
|
+
function isDisabled() {
|
|
73
|
+
return process.env.DISABLE_PROMPT_ROUTER === 'true';
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Log routing decision for analytics
|
|
78
|
+
*/
|
|
79
|
+
function logRoutingDecision(decision) {
|
|
80
|
+
const config = loadConfig();
|
|
81
|
+
|
|
82
|
+
if (!config.analytics?.enabled) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
try {
|
|
87
|
+
const analyticsDir = path.join(getClaudeDir(), 'analytics');
|
|
88
|
+
ensureDir(analyticsDir);
|
|
89
|
+
|
|
90
|
+
const logFile = path.join(analyticsDir, 'routing-decisions.json');
|
|
91
|
+
|
|
92
|
+
// Read existing log or create new
|
|
93
|
+
let logData = [];
|
|
94
|
+
if (fs.existsSync(logFile)) {
|
|
95
|
+
try {
|
|
96
|
+
const content = fs.readFileSync(logFile, 'utf8');
|
|
97
|
+
logData = JSON.parse(content);
|
|
98
|
+
} catch {
|
|
99
|
+
logData = [];
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Add new decision (keep last 1000 entries)
|
|
104
|
+
logData.push({
|
|
105
|
+
...decision,
|
|
106
|
+
timestamp: new Date().toISOString(),
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
if (logData.length > 1000) {
|
|
110
|
+
logData = logData.slice(-1000);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
fs.writeFileSync(logFile, JSON.stringify(logData, null, 2));
|
|
114
|
+
} catch (err) {
|
|
115
|
+
// Silent fail - don't block on analytics errors
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Model reason explanations - helps users understand WHY a model is suggested
|
|
121
|
+
*/
|
|
122
|
+
const MODEL_REASONS = {
|
|
123
|
+
opus: {
|
|
124
|
+
PLANNING: 'complex planning requires deep reasoning',
|
|
125
|
+
ARCHITECTURE: 'system design needs comprehensive analysis',
|
|
126
|
+
SECURITY: 'security review requires thorough examination',
|
|
127
|
+
COMPLIANCE: 'regulatory compliance needs careful attention',
|
|
128
|
+
ZOHO: 'Zoho architecture decisions are complex',
|
|
129
|
+
},
|
|
130
|
+
sonnet: {
|
|
131
|
+
TESTING: 'test execution is well-defined',
|
|
132
|
+
REVIEW: 'code review is routine work',
|
|
133
|
+
DEBUG: 'build fixes follow clear patterns',
|
|
134
|
+
REFACTOR: 'cleanup is straightforward',
|
|
135
|
+
DEPLOY: 'deployment verification is procedural',
|
|
136
|
+
},
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Intent to workflow sequence mapping
|
|
141
|
+
* Returns the recommended workflow phases for a given intent
|
|
142
|
+
*/
|
|
143
|
+
const INTENT_WORKFLOWS = {
|
|
144
|
+
PLANNING: 'plan → tdd → review → verify',
|
|
145
|
+
TESTING: 'tdd → verify',
|
|
146
|
+
REVIEW: 'review → verify',
|
|
147
|
+
SECURITY: 'security-review → verify',
|
|
148
|
+
COMPLIANCE: 'compliance-check → review → verify',
|
|
149
|
+
DEBUG: 'investigate → fix → verify',
|
|
150
|
+
REFACTOR: 'plan → refactor → review → verify',
|
|
151
|
+
ZOHO: 'architect → deluge-review → deploy → verify',
|
|
152
|
+
DEPLOY: 'verify → deploy',
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Get workflow sequence for an intent
|
|
157
|
+
*/
|
|
158
|
+
function getWorkflowSequence(intent) {
|
|
159
|
+
return INTENT_WORKFLOWS[intent] || 'proceed directly';
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Format routing message for user
|
|
164
|
+
*/
|
|
165
|
+
function formatRoutingMessage(classification, commandMapping, workflowWarnings) {
|
|
166
|
+
const messages = [];
|
|
167
|
+
|
|
168
|
+
// Intent detection message
|
|
169
|
+
if (classification.autoConvert && commandMapping) {
|
|
170
|
+
messages.push(
|
|
171
|
+
`[Router] Detected ${classification.primaryIntent} intent (${Math.round(classification.confidence * 100)}% confidence)`
|
|
172
|
+
);
|
|
173
|
+
messages.push(
|
|
174
|
+
`[Router] Suggested: ${commandMapping.command} with ${commandMapping.agent} agent`
|
|
175
|
+
);
|
|
176
|
+
|
|
177
|
+
// Add model suggestion with reason
|
|
178
|
+
const modelReasons = MODEL_REASONS[commandMapping.model] || {};
|
|
179
|
+
const reason = modelReasons[classification.primaryIntent] || 'optimal for this task';
|
|
180
|
+
messages.push(`[Router] Optimal model: ${commandMapping.model} - ${reason}`);
|
|
181
|
+
messages.push(`[Router] Tip: Switch models in Claude settings for best results`);
|
|
182
|
+
} else if (classification.suggestOnly && commandMapping) {
|
|
183
|
+
messages.push(
|
|
184
|
+
`[Router] Detected ${classification.primaryIntent} intent (${Math.round(classification.confidence * 100)}% confidence)`
|
|
185
|
+
);
|
|
186
|
+
messages.push(`[Router] Suggestion: Consider using ${commandMapping.command} for this task`);
|
|
187
|
+
|
|
188
|
+
// Add model suggestion for suggestions too
|
|
189
|
+
const modelReasons = MODEL_REASONS[commandMapping.model] || {};
|
|
190
|
+
const reason = modelReasons[classification.primaryIntent] || 'optimal for this task';
|
|
191
|
+
messages.push(`[Router] Optimal model: ${commandMapping.model} - ${reason}`);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Workflow warnings
|
|
195
|
+
if (workflowWarnings && workflowWarnings.length > 0) {
|
|
196
|
+
for (const warning of workflowWarnings) {
|
|
197
|
+
messages.push(`[Router] Warning: ${warning}`);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Secondary intents
|
|
202
|
+
if (classification.secondaryIntents && classification.secondaryIntents.length > 0) {
|
|
203
|
+
messages.push(`[Router] Also detected: ${classification.secondaryIntents.join(', ')}`);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return messages;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Check workflow state and generate warnings
|
|
211
|
+
*/
|
|
212
|
+
function checkWorkflow(classification) {
|
|
213
|
+
const warnings = [];
|
|
214
|
+
const config = loadConfig();
|
|
215
|
+
|
|
216
|
+
if (config.workflowEnforcement === 'suggest' || !classification.primaryIntent) {
|
|
217
|
+
return warnings;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
const workflowState = getWorkflowState();
|
|
221
|
+
const suggestedWorkflow = detectWorkflowType(classification.primaryIntent);
|
|
222
|
+
|
|
223
|
+
// If no active workflow but we detected a workflow-related intent
|
|
224
|
+
if (!workflowState && suggestedWorkflow) {
|
|
225
|
+
// Start a new workflow
|
|
226
|
+
startWorkflow(suggestedWorkflow, 'Auto-detected from prompt');
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
if (workflowState) {
|
|
230
|
+
// Map intent to phase
|
|
231
|
+
const intentToPhase = {
|
|
232
|
+
PLANNING: 'plan',
|
|
233
|
+
TESTING: 'tdd',
|
|
234
|
+
REVIEW: 'review',
|
|
235
|
+
DEBUG: 'fix',
|
|
236
|
+
DEPLOY: 'verify',
|
|
237
|
+
REFACTOR: 'refactor',
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
const targetPhase = intentToPhase[classification.primaryIntent];
|
|
241
|
+
|
|
242
|
+
if (targetPhase) {
|
|
243
|
+
const skippedPhases = checkSkippedPhases(targetPhase);
|
|
244
|
+
|
|
245
|
+
for (const skipped of skippedPhases) {
|
|
246
|
+
if (isCriticalPhase(skipped, workflowState.type)) {
|
|
247
|
+
warnings.push(
|
|
248
|
+
`Skipping critical phase '${skipped}' - consider running /${skipped} first`
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// Advance to this phase
|
|
254
|
+
advancePhase(targetPhase);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// Suggest next phase
|
|
258
|
+
const nextPhase = getNextPhase();
|
|
259
|
+
if (nextPhase && classification.primaryIntent !== 'UNKNOWN') {
|
|
260
|
+
// Only suggest if we're not at the suggested phase
|
|
261
|
+
const currentPhaseFromIntent = intentToPhase[classification.primaryIntent];
|
|
262
|
+
if (currentPhaseFromIntent !== nextPhase) {
|
|
263
|
+
warnings.push(`Next recommended phase: /${nextPhase}`);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
return warnings;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Main hook execution
|
|
273
|
+
*/
|
|
274
|
+
async function main() {
|
|
275
|
+
const startTime = Date.now();
|
|
276
|
+
|
|
277
|
+
try {
|
|
278
|
+
// Check if disabled
|
|
279
|
+
if (isDisabled()) {
|
|
280
|
+
// Pass through unchanged
|
|
281
|
+
const input = await readStdinJson();
|
|
282
|
+
output(JSON.stringify(input));
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// Load config
|
|
287
|
+
const config = loadConfig();
|
|
288
|
+
|
|
289
|
+
if (!config.enabled) {
|
|
290
|
+
const input = await readStdinJson();
|
|
291
|
+
output(JSON.stringify(input));
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// Read hook input from stdin
|
|
296
|
+
const input = await readStdinJson();
|
|
297
|
+
|
|
298
|
+
// Get the user's prompt
|
|
299
|
+
const userPrompt = input.user_prompt || input.prompt || '';
|
|
300
|
+
|
|
301
|
+
// Classify the intent
|
|
302
|
+
const classification = classifyIntent(userPrompt);
|
|
303
|
+
|
|
304
|
+
// If routing should be skipped, pass through
|
|
305
|
+
if (classification.skipRouting) {
|
|
306
|
+
if (config.debug) {
|
|
307
|
+
log(`[PromptRouter] Skipping routing: ${classification.reason}`);
|
|
308
|
+
}
|
|
309
|
+
output(JSON.stringify(input));
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// Match to command if we have a valid intent
|
|
314
|
+
let commandMapping = null;
|
|
315
|
+
if (classification.primaryIntent !== INTENT_TYPES.UNKNOWN) {
|
|
316
|
+
commandMapping = matchCommand(classification.primaryIntent);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// Check workflow state
|
|
320
|
+
const workflowWarnings = checkWorkflow(classification);
|
|
321
|
+
|
|
322
|
+
// Log routing decision
|
|
323
|
+
logRoutingDecision({
|
|
324
|
+
prompt: userPrompt.substring(0, 200), // Truncate for privacy
|
|
325
|
+
intent: classification.primaryIntent,
|
|
326
|
+
confidence: classification.confidence,
|
|
327
|
+
autoConvert: classification.autoConvert,
|
|
328
|
+
suggestOnly: classification.suggestOnly,
|
|
329
|
+
command: commandMapping?.command || null,
|
|
330
|
+
workflowWarnings: workflowWarnings.length,
|
|
331
|
+
processingTime: Date.now() - startTime,
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
// Format messages
|
|
335
|
+
const messages = formatRoutingMessage(classification, commandMapping, workflowWarnings);
|
|
336
|
+
|
|
337
|
+
// Output messages to stderr (visible to user)
|
|
338
|
+
if (
|
|
339
|
+
messages.length > 0 &&
|
|
340
|
+
(classification.autoConvert || classification.suggestOnly || workflowWarnings.length > 0)
|
|
341
|
+
) {
|
|
342
|
+
for (const msg of messages) {
|
|
343
|
+
log(msg);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
// Debug mode - output decision without acting
|
|
348
|
+
if (config.debug) {
|
|
349
|
+
log(
|
|
350
|
+
`[PromptRouter] DEBUG: ${JSON.stringify({
|
|
351
|
+
intent: classification.primaryIntent,
|
|
352
|
+
confidence: classification.confidence,
|
|
353
|
+
command: commandMapping?.command,
|
|
354
|
+
autoConvert: classification.autoConvert,
|
|
355
|
+
processingTime: Date.now() - startTime,
|
|
356
|
+
})}`
|
|
357
|
+
);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
// Output structured routing suggestion block for Claude to parse and act on
|
|
361
|
+
// This block is picked up by the hook-awareness and prompt-routing rules
|
|
362
|
+
if ((classification.autoConvert || classification.suggestOnly) && commandMapping) {
|
|
363
|
+
const confidencePercent = Math.round(classification.confidence * 100);
|
|
364
|
+
const workflow = getWorkflowSequence(classification.primaryIntent);
|
|
365
|
+
|
|
366
|
+
// Output structured suggestion block that Claude will see and act on
|
|
367
|
+
log('');
|
|
368
|
+
log('[ROUTING SUGGESTION]');
|
|
369
|
+
log(`Intent: ${classification.primaryIntent} (${confidencePercent}% confidence)`);
|
|
370
|
+
log(
|
|
371
|
+
`Recommended: ${commandMapping.command} with ${commandMapping.agent} agent (${commandMapping.model})`
|
|
372
|
+
);
|
|
373
|
+
log(`Workflow: ${workflow}`);
|
|
374
|
+
|
|
375
|
+
// Include secondary intents if detected (multi-intent prompt)
|
|
376
|
+
if (classification.secondaryIntents && classification.secondaryIntents.length > 0) {
|
|
377
|
+
log(`Additional intents: ${classification.secondaryIntents.join(', ')}`);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
log('');
|
|
381
|
+
log('ACTION REQUIRED: Use AskUserQuestion to present routing options to user');
|
|
382
|
+
log('Options to present:');
|
|
383
|
+
log(
|
|
384
|
+
` 1. "Use ${commandMapping.agent} agent (Recommended)" - Specialized ${classification.primaryIntent.toLowerCase()} handling`
|
|
385
|
+
);
|
|
386
|
+
log(' 2. "Proceed directly" - Quick response without specialized agent');
|
|
387
|
+
log(' 3. "Show workflow details" - See full workflow sequence');
|
|
388
|
+
log('[/ROUTING SUGGESTION]');
|
|
389
|
+
log('');
|
|
390
|
+
|
|
391
|
+
// Also add metadata to input for potential programmatic use
|
|
392
|
+
input._routerSuggestion = {
|
|
393
|
+
command: commandMapping.command,
|
|
394
|
+
agent: commandMapping.agent,
|
|
395
|
+
model: commandMapping.model,
|
|
396
|
+
originalPrompt: userPrompt,
|
|
397
|
+
formattedCommand: formatCommand(classification.primaryIntent, userPrompt),
|
|
398
|
+
workflow: workflow,
|
|
399
|
+
confidence: classification.confidence,
|
|
400
|
+
secondaryIntents: classification.secondaryIntents || [],
|
|
401
|
+
actionRequired: true,
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
// Pass through the input (potentially modified)
|
|
406
|
+
output(JSON.stringify(input));
|
|
407
|
+
|
|
408
|
+
// Log performance
|
|
409
|
+
const elapsed = Date.now() - startTime;
|
|
410
|
+
if (elapsed > 100) {
|
|
411
|
+
log(`[PromptRouter] Performance warning: ${elapsed}ms (target: <100ms)`);
|
|
412
|
+
}
|
|
413
|
+
} catch (err) {
|
|
414
|
+
// On error, log but don't block
|
|
415
|
+
log(`[PromptRouter] Error: ${err.message}`);
|
|
416
|
+
// Pass through empty to avoid blocking
|
|
417
|
+
output('{}');
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
// Run
|
|
422
|
+
main();
|