@cloudstreamsoftware/claude-tools 1.0.0 → 1.2.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/bin/cloudstream-setup.js +16 -6
- 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,101 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Credential Check Hook - Scan for hardcoded credentials
|
|
4
|
+
*
|
|
5
|
+
* Cross-platform (Windows, macOS, Linux)
|
|
6
|
+
*
|
|
7
|
+
* Runs on PreToolUse for Edit|Write operations.
|
|
8
|
+
* Scans the content being written for hardcoded Zoho/GCP credentials.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const { readStdinJson, log } = require('../lib/utils');
|
|
12
|
+
|
|
13
|
+
// Patterns that indicate hardcoded credentials
|
|
14
|
+
const CREDENTIAL_PATTERNS = [
|
|
15
|
+
// Zoho OAuth tokens
|
|
16
|
+
{ pattern: /1000\.[a-f0-9]{32}\.[a-f0-9]{32}/i, name: 'Zoho OAuth Access Token' },
|
|
17
|
+
{ pattern: /1000\.[a-f0-9]{32,}/i, name: 'Zoho OAuth Token (possible)' },
|
|
18
|
+
{ pattern: /Zoho-oauthtoken\s+[^\s"'${}]+/i, name: 'Zoho OAuth Header with token' },
|
|
19
|
+
|
|
20
|
+
// Zoho Client IDs/Secrets (not env var references)
|
|
21
|
+
{ pattern: /client_id["':\s]+1000\.\w+/i, name: 'Zoho Client ID' },
|
|
22
|
+
{ pattern: /client_secret["':\s]+[a-f0-9]{32,}/i, name: 'Zoho Client Secret' },
|
|
23
|
+
|
|
24
|
+
// GCP Service Account Keys
|
|
25
|
+
{ pattern: /"type":\s*"service_account"/i, name: 'GCP Service Account JSON' },
|
|
26
|
+
{ pattern: /"private_key":\s*"-----BEGIN/i, name: 'GCP Private Key' },
|
|
27
|
+
{ pattern: /"private_key_id":\s*"[a-f0-9]{40}"/i, name: 'GCP Private Key ID' },
|
|
28
|
+
|
|
29
|
+
// Generic API keys (long hex strings not in env var patterns)
|
|
30
|
+
{
|
|
31
|
+
pattern: /["']\b[A-Za-z0-9]{32,64}\b["'](?!\s*[,;]\s*\/\/\s*(test|example|placeholder))/i,
|
|
32
|
+
name: 'Possible API Key (long string)',
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
// AWS keys (in case of cross-cloud work)
|
|
36
|
+
{ pattern: /AKIA[0-9A-Z]{16}/i, name: 'AWS Access Key ID' },
|
|
37
|
+
|
|
38
|
+
// Generic secrets
|
|
39
|
+
{ pattern: /password["':\s]+=["'\s]+[^${\s][^\s"']{8,}/i, name: 'Hardcoded Password' },
|
|
40
|
+
];
|
|
41
|
+
|
|
42
|
+
// Patterns to EXCLUDE (these are safe - env var references, placeholders)
|
|
43
|
+
const SAFE_PATTERNS = [
|
|
44
|
+
/\$\{[A-Z_]+\}/, // ${ENV_VAR}
|
|
45
|
+
/process\.env\./, // process.env.VAR
|
|
46
|
+
/YOUR_.*_HERE/, // Placeholder text
|
|
47
|
+
/example|placeholder|test/i, // Example values
|
|
48
|
+
/["']?\$[A-Z_]+["']?/, // $ENV_VAR references
|
|
49
|
+
/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/i, // UUIDs
|
|
50
|
+
/\b[0-9a-f]{40}\b/, // Git SHA hashes (40 hex chars)
|
|
51
|
+
];
|
|
52
|
+
|
|
53
|
+
async function main() {
|
|
54
|
+
const input = await readStdinJson();
|
|
55
|
+
|
|
56
|
+
// Get the content being written/edited
|
|
57
|
+
const content = input.tool_input?.new_string || input.tool_input?.content || '';
|
|
58
|
+
|
|
59
|
+
if (!content) {
|
|
60
|
+
console.log(JSON.stringify(input));
|
|
61
|
+
process.exit(0);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const findings = [];
|
|
65
|
+
const lines = content.split('\n');
|
|
66
|
+
|
|
67
|
+
for (let i = 0; i < lines.length; i++) {
|
|
68
|
+
const line = lines[i];
|
|
69
|
+
|
|
70
|
+
// Skip if line matches safe patterns
|
|
71
|
+
const isSafe = SAFE_PATTERNS.some((p) => p.test(line));
|
|
72
|
+
if (isSafe) continue;
|
|
73
|
+
|
|
74
|
+
for (const { pattern, name } of CREDENTIAL_PATTERNS) {
|
|
75
|
+
if (pattern.test(line)) {
|
|
76
|
+
findings.push({ line: i + 1, type: name, content: line.trim().substring(0, 80) });
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (findings.length > 0) {
|
|
82
|
+
log('[CredentialCheck] BLOCKED: Potential hardcoded credentials detected!');
|
|
83
|
+
for (const f of findings.slice(0, 5)) {
|
|
84
|
+
log(` Line ${f.line}: ${f.type}`);
|
|
85
|
+
log(` ${f.content}...`);
|
|
86
|
+
}
|
|
87
|
+
log('[CredentialCheck] Use environment variables or Zoho Connections instead.');
|
|
88
|
+
log('[CredentialCheck] If this is a false positive, review and confirm the content is safe.');
|
|
89
|
+
process.exit(2); // Block the operation
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Pass through if clean
|
|
93
|
+
console.log(JSON.stringify(input));
|
|
94
|
+
process.exit(0);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
main().catch((err) => {
|
|
98
|
+
console.error('[CredentialCheck] Error:', err.message);
|
|
99
|
+
// Don't block on hook errors
|
|
100
|
+
process.exit(0);
|
|
101
|
+
});
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Continuous Learning - Session Evaluator
|
|
4
|
+
*
|
|
5
|
+
* Cross-platform (Windows, macOS, Linux)
|
|
6
|
+
*
|
|
7
|
+
* Runs on Stop hook to extract reusable patterns from Claude Code sessions
|
|
8
|
+
*
|
|
9
|
+
* Why Stop hook instead of UserPromptSubmit:
|
|
10
|
+
* - Stop runs once at session end (lightweight)
|
|
11
|
+
* - UserPromptSubmit runs every message (heavy, adds latency)
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
const path = require('path');
|
|
15
|
+
const fs = require('fs');
|
|
16
|
+
const { getLearnedSkillsDir, ensureDir, readFile, countInFile, log } = require('../lib/utils');
|
|
17
|
+
|
|
18
|
+
async function main() {
|
|
19
|
+
// Get script directory to find config
|
|
20
|
+
const scriptDir = __dirname;
|
|
21
|
+
const configFile = path.join(
|
|
22
|
+
scriptDir,
|
|
23
|
+
'..',
|
|
24
|
+
'..',
|
|
25
|
+
'skills',
|
|
26
|
+
'continuous-learning',
|
|
27
|
+
'config.json'
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
// Default configuration
|
|
31
|
+
let minSessionLength = 10;
|
|
32
|
+
let learnedSkillsPath = getLearnedSkillsDir();
|
|
33
|
+
|
|
34
|
+
// Load config if exists
|
|
35
|
+
const configContent = readFile(configFile);
|
|
36
|
+
if (configContent) {
|
|
37
|
+
try {
|
|
38
|
+
const config = JSON.parse(configContent);
|
|
39
|
+
minSessionLength = config.min_session_length || 10;
|
|
40
|
+
|
|
41
|
+
if (config.learned_skills_path) {
|
|
42
|
+
// Handle ~ in path
|
|
43
|
+
learnedSkillsPath = config.learned_skills_path.replace(/^~/, require('os').homedir());
|
|
44
|
+
}
|
|
45
|
+
} catch {
|
|
46
|
+
// Invalid config, use defaults
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Ensure learned skills directory exists
|
|
51
|
+
ensureDir(learnedSkillsPath);
|
|
52
|
+
|
|
53
|
+
// Get transcript path from environment (set by Claude Code)
|
|
54
|
+
const transcriptPath = process.env.CLAUDE_TRANSCRIPT_PATH;
|
|
55
|
+
|
|
56
|
+
if (!transcriptPath || !fs.existsSync(transcriptPath)) {
|
|
57
|
+
process.exit(0);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Count user messages in session
|
|
61
|
+
const messageCount = countInFile(transcriptPath, /"type":"user"/g);
|
|
62
|
+
|
|
63
|
+
// Skip short sessions
|
|
64
|
+
if (messageCount < minSessionLength) {
|
|
65
|
+
log(`[ContinuousLearning] Session too short (${messageCount} messages), skipping`);
|
|
66
|
+
process.exit(0);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Signal to Claude that session should be evaluated for extractable patterns
|
|
70
|
+
log(
|
|
71
|
+
`[ContinuousLearning] Session has ${messageCount} messages - evaluate for extractable patterns`
|
|
72
|
+
);
|
|
73
|
+
log(`[ContinuousLearning] Save learned skills to: ${learnedSkillsPath}`);
|
|
74
|
+
|
|
75
|
+
process.exit(0);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
main().catch((err) => {
|
|
79
|
+
console.error('[ContinuousLearning] Error:', err.message);
|
|
80
|
+
process.exit(0);
|
|
81
|
+
});
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* PreCompact Hook - Save state before context compaction
|
|
4
|
+
*
|
|
5
|
+
* Cross-platform (Windows, macOS, Linux)
|
|
6
|
+
*
|
|
7
|
+
* Runs before Claude compacts context, giving you a chance to
|
|
8
|
+
* preserve important state that might get lost in summarization.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const path = require('path');
|
|
12
|
+
const {
|
|
13
|
+
getSessionsDir,
|
|
14
|
+
getDateTimeString,
|
|
15
|
+
getTimeString,
|
|
16
|
+
findFiles,
|
|
17
|
+
ensureDir,
|
|
18
|
+
appendFile,
|
|
19
|
+
writeFile,
|
|
20
|
+
log,
|
|
21
|
+
} = require('../lib/utils');
|
|
22
|
+
|
|
23
|
+
async function main() {
|
|
24
|
+
const sessionsDir = getSessionsDir();
|
|
25
|
+
const compactionLog = path.join(sessionsDir, 'compaction-log.txt');
|
|
26
|
+
|
|
27
|
+
ensureDir(sessionsDir);
|
|
28
|
+
|
|
29
|
+
// Log compaction event with timestamp
|
|
30
|
+
const timestamp = getDateTimeString();
|
|
31
|
+
appendFile(compactionLog, `[${timestamp}] Context compaction triggered\n`);
|
|
32
|
+
|
|
33
|
+
// If there's an active session file, note the compaction
|
|
34
|
+
const sessions = findFiles(sessionsDir, '*.tmp');
|
|
35
|
+
|
|
36
|
+
if (sessions.length > 0) {
|
|
37
|
+
const activeSession = sessions[0].path;
|
|
38
|
+
const timeStr = getTimeString();
|
|
39
|
+
appendFile(
|
|
40
|
+
activeSession,
|
|
41
|
+
`\n---\n**[Compaction occurred at ${timeStr}]** - Context was summarized\n`
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Preserve compliance mode and client context
|
|
46
|
+
const clientContext = {
|
|
47
|
+
timestamp: timestamp,
|
|
48
|
+
complianceMode: process.env.CLOUDSTREAM_COMPLIANCE_MODE || 'standard',
|
|
49
|
+
activeClient: process.env.CLOUDSTREAM_CLIENT_ID || 'unknown',
|
|
50
|
+
zohoOrg: process.env.ZOHO_ORG_ID || 'not-set',
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const contextFile = path.join(sessionsDir, 'pre-compact-context.json');
|
|
54
|
+
writeFile(contextFile, JSON.stringify(clientContext, null, 2));
|
|
55
|
+
|
|
56
|
+
log('[PreCompact] State saved before compaction');
|
|
57
|
+
log(
|
|
58
|
+
`[PreCompact] Client: ${clientContext.activeClient} | Compliance: ${clientContext.complianceMode}`
|
|
59
|
+
);
|
|
60
|
+
process.exit(0);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
main().catch((err) => {
|
|
64
|
+
console.error('[PreCompact] Error:', err.message);
|
|
65
|
+
process.exit(0);
|
|
66
|
+
});
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Prompt Analyzer Hook - Real-Time Correction Detection
|
|
5
|
+
*
|
|
6
|
+
* This hook runs on UserPromptSubmit to detect corrections in real-time.
|
|
7
|
+
* When a user says "no", "actually", "instead", etc., we capture the
|
|
8
|
+
* correction pattern immediately for same-session learning.
|
|
9
|
+
*
|
|
10
|
+
* Performance Target: <100ms (non-blocking, lightweight analysis)
|
|
11
|
+
*
|
|
12
|
+
* Hook Type: UserPromptSubmit
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
const { readStdinJson, log, output } = require('../lib/utils');
|
|
16
|
+
const {
|
|
17
|
+
recordCorrection,
|
|
18
|
+
incrementMessageCount,
|
|
19
|
+
updateContext,
|
|
20
|
+
hasCorrection,
|
|
21
|
+
} = require('../lib/session-memory');
|
|
22
|
+
|
|
23
|
+
// Correction detection patterns
|
|
24
|
+
const CORRECTION_PATTERNS = {
|
|
25
|
+
// Direct negation
|
|
26
|
+
negation: [
|
|
27
|
+
/^no[,.]?\s/i,
|
|
28
|
+
/^that's (wrong|incorrect|not right)/i,
|
|
29
|
+
/^that (is|was) (wrong|incorrect|not right)/i,
|
|
30
|
+
/^not (what|how|that)/i,
|
|
31
|
+
/^wrong[,.]?\s/i,
|
|
32
|
+
],
|
|
33
|
+
|
|
34
|
+
// Redirection
|
|
35
|
+
redirection: [
|
|
36
|
+
/^(actually|instead)[,.]?\s/i,
|
|
37
|
+
/^i (meant|want|need)/i,
|
|
38
|
+
/^what i (meant|want|need)/i,
|
|
39
|
+
/^let me clarify/i,
|
|
40
|
+
/^to clarify/i,
|
|
41
|
+
],
|
|
42
|
+
|
|
43
|
+
// Explicit stop commands
|
|
44
|
+
stopCommands: [
|
|
45
|
+
/^(don't|do not|stop|never)\s/i,
|
|
46
|
+
/^please (don't|do not|stop)/i,
|
|
47
|
+
/^avoid\s/i,
|
|
48
|
+
/^(skip|ignore)\s/i,
|
|
49
|
+
],
|
|
50
|
+
|
|
51
|
+
// Preference statements
|
|
52
|
+
preferences: [
|
|
53
|
+
/^(always|prefer|use)\s/i,
|
|
54
|
+
/^i (prefer|like|want)\s/i,
|
|
55
|
+
/^(from now on|going forward)/i,
|
|
56
|
+
],
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
// Technology detection patterns
|
|
60
|
+
const TECHNOLOGY_PATTERNS = {
|
|
61
|
+
zoho: /\b(zoho|creator|catalyst|deluge|crm|books|analytics)\b/i,
|
|
62
|
+
gcp: /\b(gcp|bigquery|dataflow|cloud (function|storage|run)|google cloud)\b/i,
|
|
63
|
+
react: /\b(react|tsx|jsx|component|hook|usestate|useeffect)\b/i,
|
|
64
|
+
typescript: /\b(typescript|ts|type|interface|enum)\b/i,
|
|
65
|
+
node: /\b(node|npm|pnpm|yarn|express|fastify)\b/i,
|
|
66
|
+
python: /\b(python|pip|django|flask|pandas)\b/i,
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
// Compliance mode detection
|
|
70
|
+
const COMPLIANCE_PATTERNS = {
|
|
71
|
+
hipaa: /\b(hipaa|phi|ephi|healthcare|patient|medical)\b/i,
|
|
72
|
+
soc2: /\b(soc2|soc 2|audit log|access control)\b/i,
|
|
73
|
+
pci: /\b(pci|pci-dss|payment|card|checkout)\b/i,
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Analyze user prompt for corrections and context
|
|
78
|
+
*/
|
|
79
|
+
function analyzePrompt(prompt) {
|
|
80
|
+
if (!prompt || typeof prompt !== 'string') {
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const analysis = {
|
|
85
|
+
isCorrection: false,
|
|
86
|
+
correctionType: null,
|
|
87
|
+
correctionMatch: null,
|
|
88
|
+
technologies: [],
|
|
89
|
+
complianceMode: null,
|
|
90
|
+
suggestedCategory: 'general',
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
// Trim and normalize
|
|
94
|
+
const normalizedPrompt = prompt.trim();
|
|
95
|
+
|
|
96
|
+
// Check for corrections
|
|
97
|
+
for (const [type, patterns] of Object.entries(CORRECTION_PATTERNS)) {
|
|
98
|
+
for (const pattern of patterns) {
|
|
99
|
+
if (pattern.test(normalizedPrompt)) {
|
|
100
|
+
analysis.isCorrection = true;
|
|
101
|
+
analysis.correctionType = type;
|
|
102
|
+
analysis.correctionMatch = pattern.toString();
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
if (analysis.isCorrection) break;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Determine correction category based on content
|
|
110
|
+
if (analysis.isCorrection) {
|
|
111
|
+
if (
|
|
112
|
+
/\b(format|indent|space|tab|semicolon|quote|naming|variable|function name)\b/i.test(
|
|
113
|
+
normalizedPrompt
|
|
114
|
+
)
|
|
115
|
+
) {
|
|
116
|
+
analysis.suggestedCategory = 'code_style';
|
|
117
|
+
} else if (
|
|
118
|
+
/\b(approach|algorithm|pattern|architecture|design|solution)\b/i.test(normalizedPrompt)
|
|
119
|
+
) {
|
|
120
|
+
analysis.suggestedCategory = 'approach';
|
|
121
|
+
} else if (/\b(tool|command|use|run|execute)\b/i.test(normalizedPrompt)) {
|
|
122
|
+
analysis.suggestedCategory = 'tool_usage';
|
|
123
|
+
} else if (/\b(explain|describe|tell|say|word|phrase)\b/i.test(normalizedPrompt)) {
|
|
124
|
+
analysis.suggestedCategory = 'communication';
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Detect technologies
|
|
129
|
+
for (const [tech, pattern] of Object.entries(TECHNOLOGY_PATTERNS)) {
|
|
130
|
+
if (pattern.test(normalizedPrompt)) {
|
|
131
|
+
analysis.technologies.push(tech);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Detect compliance mode
|
|
136
|
+
for (const [mode, pattern] of Object.entries(COMPLIANCE_PATTERNS)) {
|
|
137
|
+
if (pattern.test(normalizedPrompt)) {
|
|
138
|
+
analysis.complianceMode = mode;
|
|
139
|
+
break;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return analysis;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Extract what Claude did wrong from the correction message
|
|
148
|
+
*/
|
|
149
|
+
function extractOriginalBehavior(prompt) {
|
|
150
|
+
// Try to extract what was being corrected
|
|
151
|
+
const extractors = [
|
|
152
|
+
/don't\s+(.+?)(?:\.|$)/i,
|
|
153
|
+
/stop\s+(.+?)(?:\.|$)/i,
|
|
154
|
+
/never\s+(.+?)(?:\.|$)/i,
|
|
155
|
+
/avoid\s+(.+?)(?:\.|$)/i,
|
|
156
|
+
/instead of\s+(.+?),/i,
|
|
157
|
+
/not\s+(.+?),\s*(but|use|do)/i,
|
|
158
|
+
];
|
|
159
|
+
|
|
160
|
+
for (const pattern of extractors) {
|
|
161
|
+
const match = prompt.match(pattern);
|
|
162
|
+
if (match && match[1]) {
|
|
163
|
+
return match[1].trim();
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Fallback: return first 50 chars as context
|
|
168
|
+
return prompt.substring(0, 50) + (prompt.length > 50 ? '...' : '');
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Extract what the user wants instead
|
|
173
|
+
*/
|
|
174
|
+
function extractCorrectedBehavior(prompt) {
|
|
175
|
+
// Try to extract the correction
|
|
176
|
+
const extractors = [
|
|
177
|
+
/instead[,.]?\s+(.+?)(?:\.|$)/i,
|
|
178
|
+
/use\s+(.+?)(?:\s+instead|\.|$)/i,
|
|
179
|
+
/do\s+(.+?)(?:\s+instead|\.|$)/i,
|
|
180
|
+
/(?:prefer|want|like)\s+(.+?)(?:\.|$)/i,
|
|
181
|
+
/should\s+(.+?)(?:\.|$)/i,
|
|
182
|
+
];
|
|
183
|
+
|
|
184
|
+
for (const pattern of extractors) {
|
|
185
|
+
const match = prompt.match(pattern);
|
|
186
|
+
if (match && match[1]) {
|
|
187
|
+
return match[1].trim();
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// Fallback: return the prompt itself as the correction
|
|
192
|
+
return prompt.substring(0, 100) + (prompt.length > 100 ? '...' : '');
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Main hook execution
|
|
197
|
+
*/
|
|
198
|
+
async function main() {
|
|
199
|
+
try {
|
|
200
|
+
// Read hook input from stdin
|
|
201
|
+
const input = await readStdinJson();
|
|
202
|
+
|
|
203
|
+
// Get the user's prompt
|
|
204
|
+
const userPrompt = input.user_prompt || input.prompt || '';
|
|
205
|
+
|
|
206
|
+
// Increment message count
|
|
207
|
+
incrementMessageCount();
|
|
208
|
+
|
|
209
|
+
// Analyze the prompt
|
|
210
|
+
const analysis = analyzePrompt(userPrompt);
|
|
211
|
+
|
|
212
|
+
if (!analysis) {
|
|
213
|
+
// Pass through unchanged
|
|
214
|
+
output(JSON.stringify(input));
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// Update context with detected technologies and compliance mode
|
|
219
|
+
if (analysis.technologies.length > 0 || analysis.complianceMode) {
|
|
220
|
+
updateContext({
|
|
221
|
+
technologies: analysis.technologies,
|
|
222
|
+
complianceMode: analysis.complianceMode,
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// If this is a correction, record it
|
|
227
|
+
if (analysis.isCorrection) {
|
|
228
|
+
const original = extractOriginalBehavior(userPrompt);
|
|
229
|
+
const corrected = extractCorrectedBehavior(userPrompt);
|
|
230
|
+
|
|
231
|
+
// Check if we've seen this correction before
|
|
232
|
+
const previousCorrection = hasCorrection(analysis.suggestedCategory, original);
|
|
233
|
+
|
|
234
|
+
if (previousCorrection) {
|
|
235
|
+
// We've made this mistake before - this is serious
|
|
236
|
+
log(
|
|
237
|
+
`[Learning] REPEATED CORRECTION detected: "${original}" (seen ${previousCorrection.count + 1}x)`
|
|
238
|
+
);
|
|
239
|
+
log(`[Learning] Consider creating a rule to prevent this pattern`);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// Record the correction
|
|
243
|
+
const record = recordCorrection({
|
|
244
|
+
category: analysis.suggestedCategory,
|
|
245
|
+
original,
|
|
246
|
+
corrected,
|
|
247
|
+
context: {
|
|
248
|
+
type: analysis.correctionType,
|
|
249
|
+
technologies: analysis.technologies,
|
|
250
|
+
fullPrompt: userPrompt.substring(0, 200),
|
|
251
|
+
},
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
// Log for visibility
|
|
255
|
+
log(
|
|
256
|
+
`[Learning] Correction recorded: ${analysis.suggestedCategory} - "${original.substring(0, 40)}..."`
|
|
257
|
+
);
|
|
258
|
+
|
|
259
|
+
// If this is a stopCommand, make it very visible
|
|
260
|
+
if (analysis.correctionType === 'stopCommands') {
|
|
261
|
+
log(`[Learning] STOP COMMAND: Will avoid "${original}" in this session`);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// Pass through the input unchanged (we just recorded, didn't modify)
|
|
266
|
+
output(JSON.stringify(input));
|
|
267
|
+
} catch (err) {
|
|
268
|
+
// On error, log but don't block
|
|
269
|
+
log(`[PromptAnalyzer] Error: ${err.message}`);
|
|
270
|
+
// Pass through empty to avoid blocking
|
|
271
|
+
output('{}');
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// Run
|
|
276
|
+
main();
|