codymaster 4.4.5 → 4.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +33 -0
- package/README.md +29 -14
- package/commands/demo.md +1 -1
- package/dist/context-bus.js +70 -0
- package/dist/context-db.js +265 -0
- package/dist/continuity.js +12 -0
- package/dist/file-watcher.js +79 -0
- package/dist/index.js +152 -1
- package/dist/l0-indexer.js +158 -0
- package/dist/mcp-context-server.js +400 -0
- package/dist/migrate-json-to-sqlite.js +126 -0
- package/dist/skill-chain.js +19 -3
- package/dist/token-budget.js +108 -0
- package/dist/uri-resolver.js +203 -0
- package/package.json +5 -1
- package/scripts/gate-0-secrets.js +63 -0
- package/scripts/gate-1-syntax.js +53 -0
- package/scripts/gate-5-dist-verify.js +55 -0
- package/scripts/gate-6-smoke-test.js +30 -0
- package/scripts/index-codebase.sh +552 -0
- package/scripts/mcp-bridge.js +284 -0
- package/scripts/postinstall.js +301 -0
- package/scripts/security-fixer.js +143 -0
- package/scripts/security-scan.js +55 -0
- package/scripts/test-gemini.js +13 -0
- package/scripts/todo-bridge.js +112 -0
- package/skills/_shared/helpers.md +50 -14
- package/skills/cm-autopilot/SKILL.md +29 -0
- package/skills/cm-autopilot/scripts/autopilot.py +190 -0
- package/skills/cm-continuity/SKILL.md +90 -28
- package/skills/cm-skill-chain/SKILL.md +47 -1
- package/skills/cm-start/SKILL.md +11 -2
- package/skills/boxme-git-config/SKILL.md +0 -56
- package/skills/boxme-local-dev/SKILL.md +0 -66
- package/skills/jobs-to-be-done/SKILL.md +0 -266
- package/skills/jobs-to-be-done/references/case-studies.md +0 -154
- package/skills/jobs-to-be-done/references/competitive-strategy.md +0 -280
- package/skills/jobs-to-be-done/references/diagnostics.md +0 -158
- package/skills/jobs-to-be-done/references/innovation-process.md +0 -392
- package/skills/jobs-to-be-done/references/organizational-change.md +0 -328
- package/skills/marketplace-report-crawler/SKILL.md +0 -176
- package/skills/marketplace-report-crawler/config/accounts.json +0 -41
- package/skills/marketplace-report-crawler/config/report-types.json +0 -422
- package/skills/marketplace-report-crawler/config/sessions.json +0 -3
- package/skills/marketplace-report-crawler/scripts/ab-wrapper.sh +0 -102
- package/skills/marketplace-report-crawler/scripts/browser-actions/lazada/lazada-actions.js +0 -114
- package/skills/marketplace-report-crawler/scripts/browser-actions/shopee/shopee-actions.js +0 -94
- package/skills/marketplace-report-crawler/scripts/browser-actions/tiktok/tiktok-actions.js +0 -272
- package/skills/marketplace-report-crawler/scripts/crawl-runner.js +0 -281
- package/skills/marketplace-report-crawler/scripts/session-check.sh +0 -72
- package/skills/marketplace-report-crawler/scripts/session-manager.sh +0 -349
- package/skills/marketplace-report-crawler/scripts/setup-folders.sh +0 -83
- package/skills/medical-research/SKILL.md +0 -194
- package/skills/medical-research/scripts/evidence_checker.py +0 -288
- package/skills/mom-test/SKILL.md +0 -267
- package/skills/mom-test/references/avoiding-bad-data.md +0 -221
- package/skills/mom-test/references/case-studies.md +0 -306
- package/skills/mom-test/references/commitment-advancement.md +0 -219
- package/skills/mom-test/references/finding-conversations.md +0 -251
- package/skills/mom-test/references/processing-learning.md +0 -256
- package/skills/mom-test/references/question-patterns.md +0 -198
- package/skills/pandasai-analytics/SKILL.md +0 -251
- package/skills/release-it/SKILL.md +0 -235
- package/skills/release-it/references/anti-patterns.md +0 -279
- package/skills/release-it/references/capacity-planning.md +0 -285
- package/skills/release-it/references/chaos-engineering.md +0 -325
- package/skills/release-it/references/deployment-strategies.md +0 -331
- package/skills/release-it/references/observability.md +0 -301
- package/skills/release-it/references/stability-patterns.md +0 -355
- package/skills/skill-creator-ultra/.agents/workflows/skill-audit.md +0 -37
- package/skills/skill-creator-ultra/.agents/workflows/skill-compare.md +0 -34
- package/skills/skill-creator-ultra/.agents/workflows/skill-export.md +0 -51
- package/skills/skill-creator-ultra/.agents/workflows/skill-generate.md +0 -39
- package/skills/skill-creator-ultra/.agents/workflows/skill-scaffold.md +0 -52
- package/skills/skill-creator-ultra/.agents/workflows/skill-simulate.md +0 -25
- package/skills/skill-creator-ultra/.agents/workflows/skill-stats.md +0 -31
- package/skills/skill-creator-ultra/.agents/workflows/skill-validate.md +0 -25
- package/skills/skill-creator-ultra/README.md +0 -1242
- package/skills/skill-creator-ultra/SKILL.md +0 -388
- package/skills/skill-creator-ultra/agents/analyzer.md +0 -274
- package/skills/skill-creator-ultra/agents/comparator.md +0 -202
- package/skills/skill-creator-ultra/agents/grader.md +0 -223
- package/skills/skill-creator-ultra/assets/eval_review.html +0 -146
- package/skills/skill-creator-ultra/eval-viewer/generate_review.py +0 -471
- package/skills/skill-creator-ultra/eval-viewer/viewer.html +0 -1325
- package/skills/skill-creator-ultra/examples/example_anthropic_frontend.md +0 -109
- package/skills/skill-creator-ultra/examples/example_anthropic_pdf.md +0 -116
- package/skills/skill-creator-ultra/examples/example_api_docs.md +0 -189
- package/skills/skill-creator-ultra/examples/example_db_migration.md +0 -253
- package/skills/skill-creator-ultra/examples/example_git_commit.md +0 -111
- package/skills/skill-creator-ultra/install.ps1 +0 -289
- package/skills/skill-creator-ultra/install.sh +0 -313
- package/skills/skill-creator-ultra/phases/phase1_interview.md +0 -202
- package/skills/skill-creator-ultra/phases/phase2_extract.md +0 -55
- package/skills/skill-creator-ultra/phases/phase3_detect.md +0 -57
- package/skills/skill-creator-ultra/phases/phase4_generate.md +0 -543
- package/skills/skill-creator-ultra/phases/phase5_test.md +0 -319
- package/skills/skill-creator-ultra/phases/phase6_eval.md +0 -301
- package/skills/skill-creator-ultra/phases/phase7_iterate.md +0 -103
- package/skills/skill-creator-ultra/phases/phase8_optimize.md +0 -113
- package/skills/skill-creator-ultra/resources/advanced_patterns.md +0 -499
- package/skills/skill-creator-ultra/resources/anti_patterns.md +0 -376
- package/skills/skill-creator-ultra/resources/blueprints.md +0 -498
- package/skills/skill-creator-ultra/resources/checklist.md +0 -243
- package/skills/skill-creator-ultra/resources/composition_cookbook.md +0 -291
- package/skills/skill-creator-ultra/resources/description_optimization.md +0 -90
- package/skills/skill-creator-ultra/resources/eval_guide.md +0 -133
- package/skills/skill-creator-ultra/resources/industry_questions.md +0 -189
- package/skills/skill-creator-ultra/resources/interview_questions.md +0 -200
- package/skills/skill-creator-ultra/resources/pattern_detection.md +0 -200
- package/skills/skill-creator-ultra/resources/prompt_engineering.md +0 -531
- package/skills/skill-creator-ultra/resources/schemas.md +0 -430
- package/skills/skill-creator-ultra/resources/script_integration.md +0 -593
- package/skills/skill-creator-ultra/resources/scripts_guide.md +0 -339
- package/skills/skill-creator-ultra/resources/skill_template.md +0 -124
- package/skills/skill-creator-ultra/resources/skill_writing_guide.md +0 -634
- package/skills/skill-creator-ultra/resources/versioning_guide.md +0 -193
- package/skills/skill-creator-ultra/scripts/ci_eval.py +0 -200
- package/skills/skill-creator-ultra/scripts/package_skill.py +0 -165
- package/skills/skill-creator-ultra/scripts/simulate_skill.py +0 -398
- package/skills/skill-creator-ultra/scripts/skill_audit.py +0 -611
- package/skills/skill-creator-ultra/scripts/skill_compare.py +0 -265
- package/skills/skill-creator-ultra/scripts/skill_export.py +0 -334
- package/skills/skill-creator-ultra/scripts/skill_scaffold.py +0 -403
- package/skills/skill-creator-ultra/scripts/skill_stats.py +0 -339
- package/skills/skill-creator-ultra/scripts/validate_skill.py +0 -411
- package/skills/tailwind-mastery/SKILL.md +0 -229
- package/skills/vercel-react-best-practices/AGENTS.md +0 -3373
- package/skills/vercel-react-best-practices/README.md +0 -123
- package/skills/vercel-react-best-practices/SKILL.md +0 -143
- package/skills/vercel-react-best-practices/rules/_sections.md +0 -46
- package/skills/vercel-react-best-practices/rules/_template.md +0 -28
- package/skills/vercel-react-best-practices/rules/advanced-event-handler-refs.md +0 -55
- package/skills/vercel-react-best-practices/rules/advanced-init-once.md +0 -42
- package/skills/vercel-react-best-practices/rules/advanced-use-latest.md +0 -39
- package/skills/vercel-react-best-practices/rules/async-api-routes.md +0 -38
- package/skills/vercel-react-best-practices/rules/async-defer-await.md +0 -80
- package/skills/vercel-react-best-practices/rules/async-dependencies.md +0 -51
- package/skills/vercel-react-best-practices/rules/async-parallel.md +0 -28
- package/skills/vercel-react-best-practices/rules/async-suspense-boundaries.md +0 -99
- package/skills/vercel-react-best-practices/rules/bundle-barrel-imports.md +0 -59
- package/skills/vercel-react-best-practices/rules/bundle-conditional.md +0 -31
- package/skills/vercel-react-best-practices/rules/bundle-defer-third-party.md +0 -49
- package/skills/vercel-react-best-practices/rules/bundle-dynamic-imports.md +0 -35
- package/skills/vercel-react-best-practices/rules/bundle-preload.md +0 -50
- package/skills/vercel-react-best-practices/rules/client-event-listeners.md +0 -74
- package/skills/vercel-react-best-practices/rules/client-localstorage-schema.md +0 -71
- package/skills/vercel-react-best-practices/rules/client-passive-event-listeners.md +0 -48
- package/skills/vercel-react-best-practices/rules/client-swr-dedup.md +0 -56
- package/skills/vercel-react-best-practices/rules/js-batch-dom-css.md +0 -107
- package/skills/vercel-react-best-practices/rules/js-cache-function-results.md +0 -80
- package/skills/vercel-react-best-practices/rules/js-cache-property-access.md +0 -28
- package/skills/vercel-react-best-practices/rules/js-cache-storage.md +0 -70
- package/skills/vercel-react-best-practices/rules/js-combine-iterations.md +0 -32
- package/skills/vercel-react-best-practices/rules/js-early-exit.md +0 -50
- package/skills/vercel-react-best-practices/rules/js-flatmap-filter.md +0 -60
- package/skills/vercel-react-best-practices/rules/js-hoist-regexp.md +0 -45
- package/skills/vercel-react-best-practices/rules/js-index-maps.md +0 -37
- package/skills/vercel-react-best-practices/rules/js-length-check-first.md +0 -49
- package/skills/vercel-react-best-practices/rules/js-min-max-loop.md +0 -82
- package/skills/vercel-react-best-practices/rules/js-set-map-lookups.md +0 -24
- package/skills/vercel-react-best-practices/rules/js-tosorted-immutable.md +0 -57
- package/skills/vercel-react-best-practices/rules/rendering-activity.md +0 -26
- package/skills/vercel-react-best-practices/rules/rendering-animate-svg-wrapper.md +0 -47
- package/skills/vercel-react-best-practices/rules/rendering-conditional-render.md +0 -40
- package/skills/vercel-react-best-practices/rules/rendering-content-visibility.md +0 -38
- package/skills/vercel-react-best-practices/rules/rendering-hoist-jsx.md +0 -46
- package/skills/vercel-react-best-practices/rules/rendering-hydration-no-flicker.md +0 -82
- package/skills/vercel-react-best-practices/rules/rendering-hydration-suppress-warning.md +0 -30
- package/skills/vercel-react-best-practices/rules/rendering-resource-hints.md +0 -85
- package/skills/vercel-react-best-practices/rules/rendering-script-defer-async.md +0 -68
- package/skills/vercel-react-best-practices/rules/rendering-svg-precision.md +0 -28
- package/skills/vercel-react-best-practices/rules/rendering-usetransition-loading.md +0 -75
- package/skills/vercel-react-best-practices/rules/rerender-defer-reads.md +0 -39
- package/skills/vercel-react-best-practices/rules/rerender-dependencies.md +0 -45
- package/skills/vercel-react-best-practices/rules/rerender-derived-state-no-effect.md +0 -40
- package/skills/vercel-react-best-practices/rules/rerender-derived-state.md +0 -29
- package/skills/vercel-react-best-practices/rules/rerender-functional-setstate.md +0 -74
- package/skills/vercel-react-best-practices/rules/rerender-lazy-state-init.md +0 -58
- package/skills/vercel-react-best-practices/rules/rerender-memo-with-default-value.md +0 -38
- package/skills/vercel-react-best-practices/rules/rerender-memo.md +0 -44
- package/skills/vercel-react-best-practices/rules/rerender-move-effect-to-event.md +0 -45
- package/skills/vercel-react-best-practices/rules/rerender-no-inline-components.md +0 -82
- package/skills/vercel-react-best-practices/rules/rerender-simple-expression-in-memo.md +0 -35
- package/skills/vercel-react-best-practices/rules/rerender-split-combined-hooks.md +0 -64
- package/skills/vercel-react-best-practices/rules/rerender-transitions.md +0 -40
- package/skills/vercel-react-best-practices/rules/rerender-use-deferred-value.md +0 -59
- package/skills/vercel-react-best-practices/rules/rerender-use-ref-transient-values.md +0 -73
- package/skills/vercel-react-best-practices/rules/server-after-nonblocking.md +0 -73
- package/skills/vercel-react-best-practices/rules/server-auth-actions.md +0 -96
- package/skills/vercel-react-best-practices/rules/server-cache-lru.md +0 -41
- package/skills/vercel-react-best-practices/rules/server-cache-react.md +0 -76
- package/skills/vercel-react-best-practices/rules/server-dedup-props.md +0 -65
- package/skills/vercel-react-best-practices/rules/server-hoist-static-io.md +0 -142
- package/skills/vercel-react-best-practices/rules/server-parallel-fetching.md +0 -83
- package/skills/vercel-react-best-practices/rules/server-serialization.md +0 -38
- package/skills/web-design-guidelines/SKILL.md +0 -39
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* 🛠️ CodyMaster Security Fixer
|
|
4
|
+
* Automated remediation for security vulnerabilities and secret leaks.
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* node scripts/security-fixer.js # Audit only
|
|
8
|
+
* node scripts/security-fixer.js --fix # Audit + Fix
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const fs = require('fs');
|
|
12
|
+
const path = require('path');
|
|
13
|
+
const { execSync } = require('child_process');
|
|
14
|
+
|
|
15
|
+
const DANGEROUS_PATTERNS = [
|
|
16
|
+
{ name: 'Service Key Variable', regex: /(?:SERVICE_KEY|SERVICE_ROLE)\s*[=:]\s*['\"][a-zA-Z0-9._\/-]{20,}/g },
|
|
17
|
+
{ name: 'Anon Key Variable', regex: /ANON_KEY\s*[=:]\s*['\"][a-zA-Z0-9._\/-]{20,}/g },
|
|
18
|
+
{ name: 'Private Key Block', regex: /-----BEGIN\s+(RSA|EC|DSA|OPENSSH)?\s*PRIVATE KEY-----/g },
|
|
19
|
+
{ name: 'JWT Token', regex: /eyJ[a-zA-Z0-9_-]{10,}\.[a-zA-Z0-9_-]{10,}\.[a-zA-Z0-9_-]{10,}/g },
|
|
20
|
+
{ name: 'Generic API Key', regex: /(?:api[_-]?key|api[_-]?secret|access[_-]?token)\s*[=:]\s*['\"][a-zA-Z0-9\/+=]{20,}['\"/]/gi },
|
|
21
|
+
{ name: 'AWS Key', regex: /AKIA[0-9A-Z]{16}/g },
|
|
22
|
+
{ name: 'Slack Token', regex: /xox[baprs]-[0-9a-zA-Z-]{10,}/g },
|
|
23
|
+
{ name: 'GitHub Token', regex: /gh[ps]_[a-zA-Z0-9]{36,}/g },
|
|
24
|
+
{ name: 'Stripe Key', regex: /[sr]k_(test|live)_[a-zA-Z0-9]{20,}/g },
|
|
25
|
+
{ name: 'DB Password', regex: /(?:DB_PASSWORD|DATABASE_URL)\s*[=:]\s*['\"][^'\"]{8,}/gi },
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
const SKIP_DIRS = ['node_modules', '.git', 'dist', '.wrangler', '.next', 'coverage', '.cm'];
|
|
29
|
+
const SCAN_EXTS = ['.js', '.ts', '.jsx', '.tsx', '.json', '.toml', '.yaml', '.yml',
|
|
30
|
+
'.env', '.cfg', '.conf', '.ini', '.md', '.html', '.jsonc'];
|
|
31
|
+
|
|
32
|
+
const args = process.argv.slice(2);
|
|
33
|
+
const shouldFix = args.includes('--fix');
|
|
34
|
+
const isDryRun = args.includes('--dry-run');
|
|
35
|
+
|
|
36
|
+
let findings = [];
|
|
37
|
+
|
|
38
|
+
function scanDir(dir) {
|
|
39
|
+
try {
|
|
40
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
41
|
+
for (const entry of entries) {
|
|
42
|
+
if (SKIP_DIRS.includes(entry.name)) continue;
|
|
43
|
+
const fullPath = path.join(dir, entry.name);
|
|
44
|
+
if (entry.isDirectory()) {
|
|
45
|
+
scanDir(fullPath);
|
|
46
|
+
} else if (entry.isFile() && SCAN_EXTS.some(ext => entry.name.endsWith(ext))) {
|
|
47
|
+
const content = fs.readFileSync(fullPath, 'utf-8');
|
|
48
|
+
let fileStatus = { file: fullPath, issues: [] };
|
|
49
|
+
|
|
50
|
+
for (const pattern of DANGEROUS_PATTERNS) {
|
|
51
|
+
const matches = content.match(pattern.regex);
|
|
52
|
+
if (matches) {
|
|
53
|
+
fileStatus.issues.push({ pattern: pattern.name, matches: matches });
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (fileStatus.issues.length > 0) {
|
|
58
|
+
findings.push(fileStatus);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
} catch (e) {}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
console.log('🔍 Starting Security Audit...');
|
|
66
|
+
scanDir('.');
|
|
67
|
+
|
|
68
|
+
if (findings.length === 0) {
|
|
69
|
+
console.log('✅ No vulnerabilities detected.');
|
|
70
|
+
process.exit(0);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
console.error(`❌ Found ${findings.length} files with issues:`);
|
|
74
|
+
findings.forEach(f => {
|
|
75
|
+
console.error(` ⚠ ${f.file}`);
|
|
76
|
+
f.issues.forEach(i => console.error(` - ${i.pattern}: ${i.matches.length} matches`));
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
if (shouldFix) {
|
|
80
|
+
console.log('\n🔧 Applying Automated Remediation...');
|
|
81
|
+
findings.forEach(f => {
|
|
82
|
+
let content = fs.readFileSync(f.file, 'utf-8');
|
|
83
|
+
let originalContent = content;
|
|
84
|
+
|
|
85
|
+
f.issues.forEach(issue => {
|
|
86
|
+
issue.matches.forEach(match => {
|
|
87
|
+
const half = Math.floor(match.length / 2);
|
|
88
|
+
const prefix = match.substring(0, Math.max(4, match.length - 12));
|
|
89
|
+
const masked = prefix + '*'.repeat(match.length - prefix.length);
|
|
90
|
+
content = content.replace(match, masked);
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
if (content !== originalContent) {
|
|
95
|
+
if (isDryRun) {
|
|
96
|
+
console.log(` [DRY RUN] Would mask secrets in ${f.file}`);
|
|
97
|
+
} else {
|
|
98
|
+
fs.writeFileSync(f.file, content);
|
|
99
|
+
console.log(` ✅ Masked secrets in ${f.file}`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Auto-gitignore check
|
|
104
|
+
if (!SKIP_DIRS.includes(path.basename(f.file))) {
|
|
105
|
+
const gitIgnorePath = path.join(path.dirname(f.file), '.gitignore');
|
|
106
|
+
const fileName = path.basename(f.file);
|
|
107
|
+
if (fs.existsSync(gitIgnorePath)) {
|
|
108
|
+
const gitIgnoreContent = fs.readFileSync(gitIgnorePath, 'utf-8');
|
|
109
|
+
if (!gitIgnoreContent.includes(fileName)) {
|
|
110
|
+
if (isDryRun) {
|
|
111
|
+
console.log(` [DRY RUN] Would add ${fileName} to ${gitIgnorePath}`);
|
|
112
|
+
} else {
|
|
113
|
+
fs.appendFileSync(gitIgnorePath, `\n${fileName}\n`);
|
|
114
|
+
console.log(` ✅ Added ${fileName} to .gitignore`);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
// Dependency check
|
|
122
|
+
console.log('\n📦 Checking for dependency vulnerabilities...');
|
|
123
|
+
try {
|
|
124
|
+
execSync('npm audit fix', { stdio: 'inherit' });
|
|
125
|
+
} catch (e) {
|
|
126
|
+
console.error(' ⚠️ npm audit fix failed or found issues that require manual attention.');
|
|
127
|
+
}
|
|
128
|
+
} else {
|
|
129
|
+
console.log('\n💡 Tip: Run with --fix to apply automated remediation.');
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Generate Report
|
|
133
|
+
const report = {
|
|
134
|
+
timestamp: new Date().toISOString(),
|
|
135
|
+
summary: {
|
|
136
|
+
total_files_scanned: findings.length, // approximation of issues
|
|
137
|
+
total_issues: findings.reduce((acc, f) => acc + f.issues.length, 0),
|
|
138
|
+
},
|
|
139
|
+
findings: findings
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
fs.writeFileSync('security-report.json', JSON.stringify(report, null, 2));
|
|
143
|
+
console.log('\n📊 Security report generated: security-report.json');
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
|
|
4
|
+
const DANGEROUS_PATTERNS = [
|
|
5
|
+
{ name: 'Service Key Variable', regex: /(?:SERVICE_KEY|SERVICE_ROLE)\s*[=:]\s*['\"][a-zA-Z0-9._\/-]{20,}/g },
|
|
6
|
+
{ name: 'Anon Key Variable', regex: /ANON_KEY\s*[=:]\s*['\"][a-zA-Z0-9._\/-]{20,}/g },
|
|
7
|
+
{ name: 'Private Key Block', regex: /-----BEGIN\s+(RSA|EC|DSA|OPENSSH)?\s*PRIVATE KEY-----/g },
|
|
8
|
+
{ name: 'JWT Token', regex: /eyJ[a-zA-Z0-9_-]{10,}\.[a-zA-Z0-9_-]{10,}\.[a-zA-Z0-9_-]{10,}/g },
|
|
9
|
+
{ name: 'Generic API Key', regex: /(?:api[_-]?key|api[_-]?secret|access[_-]?token)\s*[=:]\s*['\"][a-zA-Z0-9\/+=]{20,}['\"/]/gi },
|
|
10
|
+
{ name: 'AWS Key', regex: /AKIA[0-9A-Z]{16}/g },
|
|
11
|
+
{ name: 'Slack Token', regex: /xox[baprs]-[0-9a-zA-Z-]{10,}/g },
|
|
12
|
+
{ name: 'GitHub Token', regex: /gh[ps]_[a-zA-Z0-9]{36,}/g },
|
|
13
|
+
{ name: 'Stripe Key', regex: /[sr]k_(test|live)_[a-zA-Z0-9]{20,}/g },
|
|
14
|
+
{ name: 'DB Password', regex: /(?:DB_PASSWORD|DATABASE_URL)\s*[=:]\s*['\"][^'\"]{8,}/gi },
|
|
15
|
+
];
|
|
16
|
+
|
|
17
|
+
const SKIP_DIRS = ['node_modules', '.git', 'dist', '.wrangler', '.next', 'coverage'];
|
|
18
|
+
const SCAN_EXTS = ['.js', '.ts', '.jsx', '.tsx', '.json', '.toml', '.yaml', '.yml',
|
|
19
|
+
'.env', '.cfg', '.conf', '.ini', '.md', '.html', '.jsonc'];
|
|
20
|
+
|
|
21
|
+
let findings = [];
|
|
22
|
+
|
|
23
|
+
function scanDir(dir) {
|
|
24
|
+
try {
|
|
25
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
26
|
+
for (const entry of entries) {
|
|
27
|
+
if (SKIP_DIRS.includes(entry.name)) continue;
|
|
28
|
+
const fullPath = path.join(dir, entry.name);
|
|
29
|
+
if (entry.isDirectory()) {
|
|
30
|
+
scanDir(fullPath);
|
|
31
|
+
} else if (entry.isFile() && SCAN_EXTS.some(ext => entry.name.endsWith(ext))) {
|
|
32
|
+
const content = fs.readFileSync(fullPath, 'utf-8');
|
|
33
|
+
for (const pattern of DANGEROUS_PATTERNS) {
|
|
34
|
+
const matches = content.match(pattern.regex);
|
|
35
|
+
if (matches) {
|
|
36
|
+
findings.push({ file: fullPath, pattern: pattern.name, count: matches.length });
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
} catch (e) { /* skip unreadable dirs */ }
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
scanDir('.');
|
|
45
|
+
|
|
46
|
+
if (findings.length > 0) {
|
|
47
|
+
console.error('❌ SECRET SCAN FOUND ' + findings.length + ' POTENTIAL ISSUES:');
|
|
48
|
+
findings.forEach(f => {
|
|
49
|
+
console.error(' ⚠ ' + f.file + ' — ' + f.pattern + ' (' + f.count + ' match(es))');
|
|
50
|
+
});
|
|
51
|
+
console.error('');
|
|
52
|
+
process.exit(1);
|
|
53
|
+
} else {
|
|
54
|
+
console.log('✅ Repo scan: no secrets detected');
|
|
55
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
const { exec, spawn } = require('child_process');
|
|
2
|
+
|
|
3
|
+
// Method 1: exec
|
|
4
|
+
exec('gemini -y -p "Hello!"', (err, stdout, stderr) => {
|
|
5
|
+
console.log('EXEC Result:', stdout || stderr);
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
// Method 2: spawn
|
|
9
|
+
const child = spawn('gemini', ['-y', '-p', 'Hello!']);
|
|
10
|
+
let out = '';
|
|
11
|
+
child.stdout.on('data', d => out += d);
|
|
12
|
+
child.stderr.on('data', d => out += d);
|
|
13
|
+
child.on('close', () => console.log('SPAWN Result:', out));
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* cm-dashboard Todo Bridge — Phase 1 (Claude Code PostToolUse hook)
|
|
4
|
+
*
|
|
5
|
+
* Invoked by Claude Code as a PostToolUse hook on every TodoWrite event.
|
|
6
|
+
* Reads the hook payload from stdin, maps todos to dashboard tasks,
|
|
7
|
+
* and POSTs each to /api/tasks/auto-sync.
|
|
8
|
+
*
|
|
9
|
+
* Install:
|
|
10
|
+
* cp scripts/todo-bridge.js ~/.claude/scripts/todo-bridge.js
|
|
11
|
+
*
|
|
12
|
+
* Hook config (~/.claude/settings.json):
|
|
13
|
+
* {
|
|
14
|
+
* "hooks": {
|
|
15
|
+
* "PostToolUse": [{
|
|
16
|
+
* "matcher": "TodoWrite",
|
|
17
|
+
* "hooks": [{ "type": "command", "command": "node ~/.claude/scripts/todo-bridge.js" }]
|
|
18
|
+
* }]
|
|
19
|
+
* }
|
|
20
|
+
* }
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
'use strict';
|
|
24
|
+
|
|
25
|
+
const http = require('http');
|
|
26
|
+
const path = require('path');
|
|
27
|
+
|
|
28
|
+
const DASHBOARD_PORT = process.env.CM_DASHBOARD_PORT || 6969;
|
|
29
|
+
|
|
30
|
+
// Map TodoWrite status → dashboard column
|
|
31
|
+
const STATUS_MAP = {
|
|
32
|
+
pending: 'backlog',
|
|
33
|
+
in_progress: 'in-progress',
|
|
34
|
+
completed: 'done',
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
// Map TodoWrite priority → dashboard priority
|
|
38
|
+
const PRIORITY_MAP = {
|
|
39
|
+
high: 'high',
|
|
40
|
+
medium: 'medium',
|
|
41
|
+
low: 'low',
|
|
42
|
+
urgent: 'urgent',
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
function postJson(payload) {
|
|
46
|
+
return new Promise((resolve) => {
|
|
47
|
+
const body = JSON.stringify(payload);
|
|
48
|
+
const req = http.request(
|
|
49
|
+
{
|
|
50
|
+
hostname: 'localhost',
|
|
51
|
+
port: DASHBOARD_PORT,
|
|
52
|
+
path: '/api/tasks/auto-sync',
|
|
53
|
+
method: 'POST',
|
|
54
|
+
headers: {
|
|
55
|
+
'Content-Type': 'application/json',
|
|
56
|
+
'Content-Length': Buffer.byteLength(body),
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
(res) => {
|
|
60
|
+
res.resume(); // drain
|
|
61
|
+
resolve(res.statusCode);
|
|
62
|
+
}
|
|
63
|
+
);
|
|
64
|
+
req.on('error', () => resolve(null)); // silent — dashboard may not be running
|
|
65
|
+
req.write(body);
|
|
66
|
+
req.end();
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async function main() {
|
|
71
|
+
// Read stdin
|
|
72
|
+
const chunks = [];
|
|
73
|
+
for await (const chunk of process.stdin) chunks.push(chunk);
|
|
74
|
+
const raw = Buffer.concat(chunks).toString('utf8').trim();
|
|
75
|
+
if (!raw) process.exit(0);
|
|
76
|
+
|
|
77
|
+
let payload;
|
|
78
|
+
try {
|
|
79
|
+
payload = JSON.parse(raw);
|
|
80
|
+
} catch {
|
|
81
|
+
process.exit(0); // not JSON — ignore
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Only handle TodoWrite
|
|
85
|
+
if (payload.tool_name !== 'TodoWrite') process.exit(0);
|
|
86
|
+
|
|
87
|
+
const todos = payload.tool_input?.todos;
|
|
88
|
+
if (!Array.isArray(todos) || todos.length === 0) process.exit(0);
|
|
89
|
+
|
|
90
|
+
const sessionId = payload.session_id || 'unknown';
|
|
91
|
+
const cwd = payload.cwd || process.cwd();
|
|
92
|
+
const projectName = path.basename(cwd);
|
|
93
|
+
|
|
94
|
+
// Fire all syncs concurrently
|
|
95
|
+
await Promise.all(
|
|
96
|
+
todos.map((todo) => {
|
|
97
|
+
const column = STATUS_MAP[todo.status] || 'backlog';
|
|
98
|
+
return postJson({
|
|
99
|
+
conversationId: `${sessionId}:${todo.id}`,
|
|
100
|
+
title: todo.content,
|
|
101
|
+
status: column,
|
|
102
|
+
agent: 'claude-code',
|
|
103
|
+
priority: PRIORITY_MAP[todo.priority] || 'medium',
|
|
104
|
+
projectName,
|
|
105
|
+
});
|
|
106
|
+
})
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
process.exit(0);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
main().catch(() => process.exit(0)); // always silent
|
|
@@ -7,20 +7,56 @@
|
|
|
7
7
|
|
|
8
8
|
## #Load-Working-Memory
|
|
9
9
|
|
|
10
|
-
Before executing any significant action, ALWAYS:
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
10
|
+
Before executing any significant action, ALWAYS load context in this order (cheapest → richest):
|
|
11
|
+
|
|
12
|
+
### Step 1 — Check context bus (free, ~50 tokens)
|
|
13
|
+
```
|
|
14
|
+
Read .cm/context-bus.json (or: cm continuity bus)
|
|
15
|
+
→ If active pipeline found:
|
|
16
|
+
- Note current_step and pipeline name
|
|
17
|
+
- Read shared_context to see what upstream skills already produced
|
|
18
|
+
- SKIP re-doing any work already recorded in shared_context
|
|
19
|
+
→ If no bus: fresh session, proceed normally
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### Step 2 — Load L0 indexes first (~600 tokens total)
|
|
23
|
+
```
|
|
24
|
+
Read .cm/learnings-index.md (~100 tokens) — IDs + 1-line summaries
|
|
25
|
+
Read .cm/skeleton-index.md (~500 tokens) — modules, entry points, config files
|
|
26
|
+
|
|
27
|
+
→ If a specific learning ID looks relevant → resolve cm://memory/learnings/{id} for full detail
|
|
28
|
+
→ If a specific module looks relevant → resolve cm://resources/skeleton at L2 for full detail
|
|
29
|
+
→ Otherwise: L0 is sufficient — DO NOT load full files
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Step 3 — Scope-filter learnings (only if L0 flags relevant entries)
|
|
33
|
+
```
|
|
34
|
+
Query: cm_query(scope="learnings", query="{current module or error type}", limit=5)
|
|
35
|
+
OR read .cm/memory/learnings.json filtered to scope == "global" | "module:X"
|
|
36
|
+
|
|
37
|
+
Rules:
|
|
38
|
+
NEVER load status = "invalidated" (proven wrong)
|
|
39
|
+
CAUTION status = "corrected" (verify before applying)
|
|
40
|
+
TRUST high reinforceCount + recent lastRelevant
|
|
41
|
+
SKIP learnings for other modules (noise + wasted tokens)
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Step 4 — Check working memory
|
|
45
|
+
```
|
|
46
|
+
Read .cm/CONTINUITY.md → Active Goal, Next Actions, current phase
|
|
47
|
+
Run Memory Audit (decay + conflict detection) — see cm-continuity
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Step 5 — Token budget check (before injecting large context)
|
|
51
|
+
```
|
|
52
|
+
cm continuity budget (or: loadBudget + checkBudget in code)
|
|
53
|
+
→ If category is over soft limit → use L0/L1 depth instead of L2
|
|
54
|
+
→ Never inject full skeleton (20KB) when skeleton-index.md (~2KB) suffices
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
> **Token savings v5:** Full cold load ~3,200 tokens → Smart Spine load ~700 tokens (78% reduction).
|
|
58
|
+
> L0 indexes + context bus + scope filter make this possible.
|
|
59
|
+
> Only escalate to L2 when L0/L1 explicitly flag the need.
|
|
24
60
|
|
|
25
61
|
---
|
|
26
62
|
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: cm-autopilot
|
|
3
|
+
description: Easy-to-use conversational CLI (Claude Code style) for non-technical users to spawn parallel AI tasks supervised by a visual web dashboard.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# CM AutoPilot CLI — Conversational Task Supervisor
|
|
7
|
+
|
|
8
|
+
> **Just talk to it. It plans, splits, and watches parallel tasks for you.**
|
|
9
|
+
|
|
10
|
+
## What it does
|
|
11
|
+
- Provides a conversational CLI interface using `rich` and `prompt_toolkit`.
|
|
12
|
+
- Translates user intent into multiple parallel tasks.
|
|
13
|
+
- Integrates with `cm-content-factory`'s Dashboard (`localhost:5050`) for a visual way to track multi-threading.
|
|
14
|
+
- Allows non-technical users to utilize the Cody Master skill set effortlessly.
|
|
15
|
+
|
|
16
|
+
## Requirements
|
|
17
|
+
- Python 3.9+
|
|
18
|
+
- `rich`
|
|
19
|
+
- `prompt_toolkit`
|
|
20
|
+
|
|
21
|
+
## How to run
|
|
22
|
+
|
|
23
|
+
1. Launch the conversational CLI:
|
|
24
|
+
```bash
|
|
25
|
+
python3 skills/cm-autopilot/scripts/autopilot.py
|
|
26
|
+
```
|
|
27
|
+
2. The CLI will ask what you want to do. Explain your complex request (e.g., "Dịch 10 bài báo sang tiếng anh", "Research 5 competitors").
|
|
28
|
+
3. The AutoPilot will generate tasks and push them into the Queue.
|
|
29
|
+
4. AutoPilot will automatically start the visual Dashboard at `http://localhost:5050` so you can watch your jobs execute in parallel.
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
AutoPilot CLI — Conversational Interface for Cody Master Skills
|
|
4
|
+
|
|
5
|
+
This is a Claude Code-style interactive CLI. It talks to the user,
|
|
6
|
+
understands their goals, creates a plan, and then parallelizes
|
|
7
|
+
tasks into the Agent Dispatcher (queue) while launching the Visual
|
|
8
|
+
Dashboard for easy tracking.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import sys
|
|
12
|
+
import time
|
|
13
|
+
import os
|
|
14
|
+
import subprocess
|
|
15
|
+
import threading
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
|
|
18
|
+
# Add cm-content-factory to sys.path to reuse the dispatcher and state manager
|
|
19
|
+
SKILLS_DIR = Path(__file__).resolve().parent.parent.parent
|
|
20
|
+
CF_SCRIPTS = SKILLS_DIR / "cm-content-factory" / "scripts"
|
|
21
|
+
sys.path.append(str(CF_SCRIPTS))
|
|
22
|
+
|
|
23
|
+
try:
|
|
24
|
+
from agent_dispatcher import AgentDispatcher
|
|
25
|
+
from state_manager import StateManager
|
|
26
|
+
from rich.console import Console
|
|
27
|
+
from rich.markdown import Markdown
|
|
28
|
+
from rich.panel import Panel
|
|
29
|
+
from rich.prompt import Prompt
|
|
30
|
+
from rich.progress import Progress, SpinnerColumn, TextColumn
|
|
31
|
+
except ImportError:
|
|
32
|
+
print("Please install requirements: pip install rich prompt_toolkit")
|
|
33
|
+
sys.exit(1)
|
|
34
|
+
|
|
35
|
+
console = Console()
|
|
36
|
+
project_root = Path(os.getcwd()).resolve()
|
|
37
|
+
|
|
38
|
+
dispatcher = AgentDispatcher(str(project_root))
|
|
39
|
+
state_mgr = StateManager(str(project_root))
|
|
40
|
+
|
|
41
|
+
DASHBOARD_PROCESS = None
|
|
42
|
+
|
|
43
|
+
def start_dashboard():
|
|
44
|
+
"""Starts the cm-content-factory dashboard server in the background."""
|
|
45
|
+
global DASHBOARD_PROCESS
|
|
46
|
+
dashboard_script = CF_SCRIPTS / "dashboard_server.py"
|
|
47
|
+
if dashboard_script.exists():
|
|
48
|
+
DASHBOARD_PROCESS = subprocess.Popen(
|
|
49
|
+
[sys.executable, str(dashboard_script), "--port", "5050", "--no-open"],
|
|
50
|
+
stdout=subprocess.DEVNULL,
|
|
51
|
+
stderr=subprocess.DEVNULL
|
|
52
|
+
)
|
|
53
|
+
return True
|
|
54
|
+
return False
|
|
55
|
+
|
|
56
|
+
def show_welcome():
|
|
57
|
+
console.print(Panel.fit(
|
|
58
|
+
"[bold cyan]🚀 Welcome to Cody Master AutoPilot[/bold cyan]\n"
|
|
59
|
+
"[dim]Your conversational AI orchestrator.[/dim]\n\n"
|
|
60
|
+
"Tell me what you want to achieve, and I will plan, split,\n"
|
|
61
|
+
"and execute parallel tasks for you. No technical skills required.",
|
|
62
|
+
title="AutoPilot v1.0", border_style="cyan"
|
|
63
|
+
))
|
|
64
|
+
|
|
65
|
+
def mock_llm_task_parser(prompt: str) -> list:
|
|
66
|
+
"""
|
|
67
|
+
Mock parser that simulates an LLM breaking down a user request
|
|
68
|
+
into parallel tasks based on keywords.
|
|
69
|
+
"""
|
|
70
|
+
tasks = []
|
|
71
|
+
lower_prompt = prompt.lower()
|
|
72
|
+
|
|
73
|
+
if "dịch" in lower_prompt or "translate" in lower_prompt:
|
|
74
|
+
# Example: Dịch 5 bài báo
|
|
75
|
+
count = 5
|
|
76
|
+
for w in lower_prompt.split():
|
|
77
|
+
if w.isdigit():
|
|
78
|
+
count = int(w)
|
|
79
|
+
break
|
|
80
|
+
for i in range(1, count + 1):
|
|
81
|
+
tasks.append({
|
|
82
|
+
"id": f"translate-{int(time.time()*100)}-{i}",
|
|
83
|
+
"type": "translate",
|
|
84
|
+
"meta": {"file": f"article_{i}.txt", "target_lang": "en"}
|
|
85
|
+
})
|
|
86
|
+
elif "research" in lower_prompt or "tìm hiểu" in lower_prompt:
|
|
87
|
+
tasks.append({"id": f"res-1", "type": "research", "meta": {"topic": "Market Trends"}})
|
|
88
|
+
tasks.append({"id": f"res-2", "type": "research", "meta": {"topic": "Competitors"}})
|
|
89
|
+
tasks.append({"id": f"res-3", "type": "research", "meta": {"topic": "Keywords"}})
|
|
90
|
+
else:
|
|
91
|
+
# Generic fallback
|
|
92
|
+
tasks.append({"id": f"task-1", "type": "general", "meta": {"instruction": prompt}})
|
|
93
|
+
tasks.append({"id": f"task-2", "type": "general", "meta": {"instruction": "Review output"}})
|
|
94
|
+
|
|
95
|
+
return tasks
|
|
96
|
+
|
|
97
|
+
def background_worker(worker_id: str):
|
|
98
|
+
"""A simple worker loop simulating parallel execution of tasks."""
|
|
99
|
+
state_mgr.register_agent(worker_id, "autopilot_worker")
|
|
100
|
+
while True:
|
|
101
|
+
task = dispatcher.claim_next(worker_id)
|
|
102
|
+
if not task:
|
|
103
|
+
time.sleep(2)
|
|
104
|
+
continue
|
|
105
|
+
|
|
106
|
+
# Log active phase
|
|
107
|
+
phase_map = {"translate": "write", "research": "extract", "general": "plan"}
|
|
108
|
+
phase = phase_map.get(task["type"], "write")
|
|
109
|
+
state_mgr.update_phase(phase, "running", progress=0.1)
|
|
110
|
+
state_mgr.add_task(task["id"], "running", task["meta"])
|
|
111
|
+
|
|
112
|
+
# Simulate work
|
|
113
|
+
dispatcher.heartbeat(worker_id, task["id"])
|
|
114
|
+
time.sleep(3) # Heavy work
|
|
115
|
+
|
|
116
|
+
state_mgr.add_task(task["id"], "done", task["meta"])
|
|
117
|
+
dispatcher.complete(task["id"], worker_id, {"result": "success"})
|
|
118
|
+
state_mgr.log_event("info", f"[{worker_id}] Completed task: {task['id']}")
|
|
119
|
+
|
|
120
|
+
# Check if phase done
|
|
121
|
+
q = dispatcher.get_queue()
|
|
122
|
+
if q["queued"] == 0 and q["claimed"] == 0:
|
|
123
|
+
state_mgr.update_phase(phase, "done", progress=1.0)
|
|
124
|
+
|
|
125
|
+
def main_loop():
|
|
126
|
+
# Reset queue and state for fresh start
|
|
127
|
+
dispatcher.reset()
|
|
128
|
+
state_mgr.reset()
|
|
129
|
+
|
|
130
|
+
# Start dashboard
|
|
131
|
+
if start_dashboard():
|
|
132
|
+
state_mgr.log_event("info", "Dashboard Server started on port 5050")
|
|
133
|
+
|
|
134
|
+
# Start background workers (simulating multiple parallel agents)
|
|
135
|
+
for i in range(3):
|
|
136
|
+
t = threading.Thread(target=background_worker, args=(f"worker-{i+1}",), daemon=True)
|
|
137
|
+
t.start()
|
|
138
|
+
|
|
139
|
+
try:
|
|
140
|
+
while True:
|
|
141
|
+
user_input = Prompt.ask("\n[bold green]You[/bold green]")
|
|
142
|
+
if user_input.lower() in ("exit", "quit", "q"):
|
|
143
|
+
break
|
|
144
|
+
|
|
145
|
+
if not user_input.strip():
|
|
146
|
+
continue
|
|
147
|
+
|
|
148
|
+
with Progress(
|
|
149
|
+
SpinnerColumn(),
|
|
150
|
+
TextColumn("[progress.description]{task.description}"),
|
|
151
|
+
transient=True
|
|
152
|
+
) as progress:
|
|
153
|
+
progress.add_task("Thinking and Planning...", total=None)
|
|
154
|
+
time.sleep(1.5) # Simulate LLM thinking
|
|
155
|
+
tasks = mock_llm_task_parser(user_input)
|
|
156
|
+
|
|
157
|
+
console.print(f"[bold blue]AutoPilot:[/bold blue] I've analyzed your request and created [bold]{len(tasks)}[/bold] parallel tasks.")
|
|
158
|
+
|
|
159
|
+
# Queue them
|
|
160
|
+
dispatcher.enqueue_batch(tasks)
|
|
161
|
+
for t in tasks:
|
|
162
|
+
state_mgr.add_task(t["id"], "queued", t["meta"])
|
|
163
|
+
|
|
164
|
+
console.print("[dim]Tasks have been dispatched to the worker queue.[/dim]")
|
|
165
|
+
console.print(f"👉 [bold magenta]Watch live progress at: http://localhost:5050[/bold magenta]")
|
|
166
|
+
|
|
167
|
+
# Simple live status wait
|
|
168
|
+
with Progress() as pb:
|
|
169
|
+
task_pb = pb.add_task("Executing Pipeline...", total=len(tasks))
|
|
170
|
+
while True:
|
|
171
|
+
q = dispatcher.get_queue()
|
|
172
|
+
completed = q["done"] + q["failed"]
|
|
173
|
+
pb.update(task_pb, completed=completed)
|
|
174
|
+
|
|
175
|
+
if completed >= len(tasks):
|
|
176
|
+
break
|
|
177
|
+
time.sleep(1)
|
|
178
|
+
|
|
179
|
+
console.print("\n[bold green]✅ All tasks completed successfully![/bold green]")
|
|
180
|
+
|
|
181
|
+
except KeyboardInterrupt:
|
|
182
|
+
console.print("\n[dim]Shutting down...[/dim]")
|
|
183
|
+
|
|
184
|
+
finally:
|
|
185
|
+
if DASHBOARD_PROCESS:
|
|
186
|
+
DASHBOARD_PROCESS.terminate()
|
|
187
|
+
|
|
188
|
+
if __name__ == "__main__":
|
|
189
|
+
show_welcome()
|
|
190
|
+
main_loop()
|