agent-enderun 0.1.10 → 0.2.1
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/.enderun/BRAIN_DASHBOARD.md +43 -0
- package/.enderun/ENDERUN.md +203 -0
- package/.enderun/PROJECT_MEMORY.md +137 -36
- package/.enderun/agents/analyst.md +21 -10
- package/.enderun/agents/backend.md +12 -11
- package/.enderun/agents/explorer.md +10 -7
- package/.enderun/agents/frontend.md +9 -20
- package/.enderun/agents/git.md +16 -12
- package/.enderun/agents/manager.md +14 -15
- package/.enderun/agents/mobile.md +5 -5
- package/.enderun/agents/native.md +5 -5
- package/.enderun/benchmarks/.gitkeep +0 -0
- package/.enderun/cli-commands.json +13 -1
- package/.enderun/config.json +1 -1
- package/.enderun/docs/api/README.md +10 -9
- package/.enderun/docs/api/auth.md +11 -0
- package/.enderun/docs/api/errors.md +7 -0
- package/.enderun/docs/error-handling.md +12 -0
- package/.enderun/docs/privacy.md +3 -0
- package/.enderun/docs/security.md +12 -0
- package/.enderun/docs/tech-stack.md +1 -0
- package/.enderun/docs/troubleshooting.md +7 -0
- package/.enderun/knowledge/api_design_rules.md +6 -0
- package/.enderun/knowledge/async_error_handling.md +18 -0
- package/.enderun/knowledge/branded_types_pattern.md +1 -0
- package/.enderun/knowledge/code_review_checklist.md +7 -0
- package/.enderun/knowledge/contract_versioning.md +7 -0
- package/.enderun/knowledge/database_migration.md +6 -0
- package/.enderun/knowledge/deployment_checklist.md +7 -0
- package/.enderun/knowledge/git_commit_strategy.md +10 -0
- package/.enderun/knowledge/legacy_onboarding.md +7 -0
- package/.enderun/knowledge/monitoring_setup.md +5 -0
- package/.enderun/knowledge/performance_guidelines.md +11 -0
- package/.enderun/knowledge/repository_patterns.md +9 -0
- package/.enderun/knowledge/security_scanning.md +6 -0
- package/.enderun/knowledge/testing_standards.md +7 -0
- package/.enderun/knowledge/troubleshooting_guide.md +5 -0
- package/.enderun/knowledge/zero_ui_library_policy.md +1 -0
- package/.enderun/logs/analyst.json +1 -0
- package/.enderun/logs/backend.json +1 -0
- package/.enderun/logs/explorer.json +1 -0
- package/.enderun/logs/frontend.json +1 -0
- package/.enderun/logs/git.json +1 -0
- package/.enderun/logs/manager.json +363 -0
- package/.enderun/logs/mobile.json +1 -0
- package/.enderun/logs/native.json +1 -0
- package/.enderun/monitoring/.gitkeep +0 -0
- package/ENDERUN.md +8 -8
- package/LICENSE +21 -0
- package/README.md +595 -195
- package/bin/cli.js +292 -79
- package/package.json +42 -2
- package/packages/framework-mcp/README.md +47 -81
- package/packages/framework-mcp/dist/index.js +13 -971
- package/packages/framework-mcp/dist/schemas.js +84 -0
- package/packages/framework-mcp/dist/tools/academy.js +184 -0
- package/packages/framework-mcp/dist/tools/codebase.js +294 -0
- package/packages/framework-mcp/dist/tools/contract.js +95 -0
- package/packages/framework-mcp/dist/tools/database.js +52 -0
- package/packages/framework-mcp/dist/tools/framework.js +161 -0
- package/packages/framework-mcp/dist/tools/git.js +53 -0
- package/packages/framework-mcp/dist/tools/index.js +42 -0
- package/packages/framework-mcp/dist/tools/knowledge.js +69 -0
- package/packages/framework-mcp/dist/tools/memory.js +94 -0
- package/packages/framework-mcp/dist/tools/messages.js +71 -0
- package/packages/framework-mcp/dist/tools/repository.js +76 -0
- package/packages/framework-mcp/dist/tools/security.js +122 -0
- package/packages/framework-mcp/dist/utils.js +82 -0
- package/packages/framework-mcp/package.json +1 -1
- package/packages/framework-mcp/src/index.ts +20 -970
- package/packages/framework-mcp/src/schemas.ts +106 -0
- package/packages/framework-mcp/src/tools/academy.ts +178 -0
- package/packages/framework-mcp/src/tools/codebase.ts +284 -0
- package/packages/framework-mcp/src/tools/contract.ts +91 -0
- package/packages/framework-mcp/src/tools/database.ts +49 -0
- package/packages/framework-mcp/src/tools/framework.ts +157 -0
- package/packages/framework-mcp/src/tools/git.ts +43 -0
- package/packages/framework-mcp/src/tools/index.ts +45 -0
- package/packages/framework-mcp/src/tools/knowledge.ts +68 -0
- package/packages/framework-mcp/src/tools/memory.ts +88 -0
- package/packages/framework-mcp/src/tools/messages.ts +70 -0
- package/packages/framework-mcp/src/tools/repository.ts +76 -0
- package/packages/framework-mcp/src/tools/security.ts +122 -0
- package/packages/framework-mcp/src/utils.ts +90 -0
- package/packages/shared-types/README.md +28 -51
- package/packages/shared-types/dist/index.d.ts +80 -48
- package/packages/shared-types/dist/index.d.ts.map +1 -1
- package/packages/shared-types/dist/index.js +5 -8
- package/packages/shared-types/dist/index.js.map +1 -1
- package/packages/shared-types/package.json +1 -1
- package/packages/shared-types/src/index.ts +79 -51
- package/CHANGELOG.md +0 -97
- package/CLAUDE.md +0 -7
- package/CODEX.md +0 -7
- package/CURSOR.md +0 -7
- package/GEMINI.md +0 -7
- package/docs/tech-stack.md +0 -10
- package/gemini-extension.json +0 -5
- package/packages/framework-mcp/tsconfig.json +0 -15
- package/packages/shared-types/contract.version.json +0 -9
- package/packages/shared-types/tsconfig.json +0 -17
- package/panda.config.ts +0 -20
- /package/{docs → .enderun/docs}/project-docs.md +0 -0
package/bin/cli.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
console.log("🤖 Agent Enderun CLI — Initializing...");
|
|
3
2
|
|
|
4
3
|
import fs from "fs";
|
|
5
4
|
import path from "path";
|
|
@@ -177,12 +176,12 @@ function mergePackageJson(targetPath, sourcePath) {
|
|
|
177
176
|
function updateGitIgnore(targetPath, frameworkDir = ".enderun") {
|
|
178
177
|
const IGNORE_LINES = [
|
|
179
178
|
"# AI-Enderun",
|
|
180
|
-
".
|
|
179
|
+
".enderun/logs/*.json",
|
|
181
180
|
".claude/logs/*.json",
|
|
182
181
|
".cursor/logs/*.json",
|
|
183
182
|
".codex/logs/*.json",
|
|
184
183
|
".enderun/logs/*.json",
|
|
185
|
-
".
|
|
184
|
+
".enderun/*.lock",
|
|
186
185
|
".claude/*.lock",
|
|
187
186
|
".cursor/*.lock",
|
|
188
187
|
".codex/*.lock",
|
|
@@ -312,35 +311,37 @@ async function initCommand(selectedAdapter) {
|
|
|
312
311
|
};
|
|
313
312
|
|
|
314
313
|
const targetBase = selectedAdapter ? `.${selectedAdapter}` : ".enderun";
|
|
314
|
+
|
|
315
315
|
const targetFrameworkDir = path.join(targetDir, targetBase);
|
|
316
316
|
|
|
317
317
|
const CORE_FILES = [
|
|
318
318
|
".enderun",
|
|
319
|
-
|
|
319
|
+
|
|
320
320
|
"mcp.json",
|
|
321
321
|
".env.example",
|
|
322
322
|
"ENDERUN.md",
|
|
323
|
-
".
|
|
324
|
-
".enderun/config.json",
|
|
325
|
-
".enderun/STATUS.md",
|
|
323
|
+
"package.json",
|
|
326
324
|
"packages/framework-mcp",
|
|
327
325
|
"packages/shared-types",
|
|
328
|
-
"panda.config.ts",
|
|
329
326
|
];
|
|
330
327
|
|
|
331
328
|
const DIRS_TO_CREATE = [
|
|
329
|
+
targetBase,
|
|
332
330
|
`${targetBase}/agents`,
|
|
333
331
|
`${targetBase}/docs/api`,
|
|
332
|
+
`${targetBase}/knowledge`,
|
|
333
|
+
`${targetBase}/benchmarks`,
|
|
334
|
+
`${targetBase}/monitoring`,
|
|
334
335
|
`${targetBase}/logs`,
|
|
335
336
|
`${targetBase}/messages`,
|
|
336
337
|
"apps/web",
|
|
337
338
|
"apps/backend",
|
|
338
|
-
|
|
339
|
+
|
|
339
340
|
"packages/shared-types",
|
|
340
341
|
"packages/framework-mcp",
|
|
341
342
|
];
|
|
342
343
|
|
|
343
|
-
console.log(
|
|
344
|
+
console.log(`🚀 Installing Agent Enderun (Adapter: ${selectedAdapter || "all"})...`);
|
|
344
345
|
|
|
345
346
|
// Ensure target framework base exists
|
|
346
347
|
if (!fs.existsSync(targetFrameworkDir)) {
|
|
@@ -357,13 +358,12 @@ async function initCommand(selectedAdapter) {
|
|
|
357
358
|
}
|
|
358
359
|
|
|
359
360
|
let filesToProcess = [...CORE_FILES];
|
|
360
|
-
|
|
361
361
|
if (selectedAdapter) {
|
|
362
362
|
if (!ADAPTERS[selectedAdapter]) {
|
|
363
363
|
console.error(`❌ Invalid adapter: ${selectedAdapter}. Available: gemini, claude, cursor, codex`);
|
|
364
364
|
process.exit(1);
|
|
365
365
|
}
|
|
366
|
-
filesToProcess
|
|
366
|
+
filesToProcess.push(...ADAPTERS[selectedAdapter]);
|
|
367
367
|
} else {
|
|
368
368
|
Object.values(ADAPTERS).forEach(list => filesToProcess.push(...list));
|
|
369
369
|
}
|
|
@@ -387,7 +387,7 @@ async function initCommand(selectedAdapter) {
|
|
|
387
387
|
let dest = path.join(targetDir, item);
|
|
388
388
|
|
|
389
389
|
// FORCED CLEANUP: Delete existing framework directories in target before copying
|
|
390
|
-
if (["packages/framework-mcp", "packages/shared-types", ".enderun", ".
|
|
390
|
+
if (["packages/framework-mcp", "packages/shared-types", ".enderun", ".enderun", ".claude", ".cursor", ".codex"].includes(item)) {
|
|
391
391
|
if (fs.existsSync(dest)) {
|
|
392
392
|
try {
|
|
393
393
|
fs.rmSync(dest, { recursive: true, force: true });
|
|
@@ -397,38 +397,27 @@ async function initCommand(selectedAdapter) {
|
|
|
397
397
|
}
|
|
398
398
|
}
|
|
399
399
|
|
|
400
|
-
// Clean up existing lockfiles in target
|
|
401
|
-
if (fs.existsSync(dest)) {
|
|
402
|
-
const lockFile = path.join(dest, "package-lock.json");
|
|
403
|
-
if (fs.existsSync(lockFile)) {
|
|
404
|
-
fs.unlinkSync(lockFile);
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
|
|
408
400
|
// Remap core framework files to targetBase
|
|
409
401
|
if (item === ".enderun" || item.startsWith(".enderun/")) {
|
|
410
402
|
dest = path.join(targetDir, item.replace(".enderun", targetBase));
|
|
411
403
|
}
|
|
412
404
|
if (item === "ENDERUN.md") dest = path.join(targetFrameworkDir, "ENDERUN.md");
|
|
413
|
-
|
|
414
|
-
|
|
405
|
+
|
|
406
|
+
// Check if item is an adapter pointer file
|
|
407
|
+
const isAdapterPointer = Object.values(ADAPTERS).flat().includes(item);
|
|
408
|
+
if (isAdapterPointer) {
|
|
409
|
+
dest = path.join(targetDir, item);
|
|
415
410
|
}
|
|
416
411
|
|
|
417
412
|
if (fs.existsSync(src)) {
|
|
418
413
|
if (fs.lstatSync(src).isDirectory()) {
|
|
419
|
-
|
|
420
|
-
const skipFiles = (item === ".enderun") ? ["logs", "PROJECT_MEMORY.md", "BRAIN_DASHBOARD.md", "PROJECT_MEMORY.lock"] : [];
|
|
414
|
+
const skipFiles = (item === ".enderun") ? ["logs", "PROJECT_MEMORY.md", "PROJECT_MEMORY.lock"] : [];
|
|
421
415
|
const isDocs = item === "docs";
|
|
422
416
|
copyDir(src, dest, new Set(skipFiles), isDocs, targetBase, targetScope);
|
|
423
417
|
} else {
|
|
424
|
-
//
|
|
425
|
-
if (item === "package.json") continue;
|
|
426
|
-
if (item === "ENDERUN.md" && fs.existsSync(dest)) {
|
|
427
|
-
console.log(`ℹ️ Skipping ENDERUN.md (already exists in ${targetBase}).`);
|
|
428
|
-
continue;
|
|
429
|
-
}
|
|
418
|
+
if (item === "package.json") continue; // We merge it later
|
|
430
419
|
|
|
431
|
-
if (fs.existsSync(dest)) {
|
|
420
|
+
if (fs.existsSync(dest) && !isAdapterPointer) {
|
|
432
421
|
console.log(`ℹ️ Skipping existing file: ${item}`);
|
|
433
422
|
continue;
|
|
434
423
|
}
|
|
@@ -440,16 +429,16 @@ async function initCommand(selectedAdapter) {
|
|
|
440
429
|
content = content.replace(/\{\{FRAMEWORK_DIR\}\}/g, targetBase);
|
|
441
430
|
content = content.replace(/\{\{ADAPTER\}\}/g, selectedAdapter || "enderun");
|
|
442
431
|
|
|
443
|
-
// Sanitize workspace: protocol in all text files
|
|
444
432
|
if (ext === ".json") {
|
|
445
433
|
try {
|
|
446
434
|
const json = JSON.parse(content);
|
|
447
435
|
content = JSON.stringify(sanitizeJson(json, targetScope), null, 2);
|
|
436
|
+
// Ensure variable replacement even inside JSON strings if any
|
|
437
|
+
content = content.replace(/\{\{FRAMEWORK_DIR\}\}/g, targetBase);
|
|
438
|
+
content = content.replace(/\{\{ADAPTER\}\}/g, selectedAdapter || "enderun");
|
|
448
439
|
} catch (e) {
|
|
449
440
|
content = content.replace(/workspace:[^"'\s]*/g, "*");
|
|
450
441
|
}
|
|
451
|
-
} else {
|
|
452
|
-
content = content.replace(/workspace:[^"'\s]*/g, "*");
|
|
453
442
|
}
|
|
454
443
|
|
|
455
444
|
fs.writeFileSync(dest, content);
|
|
@@ -461,84 +450,63 @@ async function initCommand(selectedAdapter) {
|
|
|
461
450
|
}
|
|
462
451
|
}
|
|
463
452
|
|
|
464
|
-
//
|
|
453
|
+
// Merge Package JSON
|
|
465
454
|
mergePackageJson(path.join(targetDir, "package.json"), path.join(sourceDir, "package.json"));
|
|
466
455
|
updateGitIgnore(path.join(targetDir, ".gitignore"), targetBase);
|
|
467
456
|
|
|
468
457
|
const finalMemoryPath = path.join(targetDir, targetBase, "PROJECT_MEMORY.md");
|
|
469
458
|
initializeMemory(finalMemoryPath, targetBase);
|
|
470
459
|
|
|
471
|
-
// Deep clean ALL package.json files in target directory (removes workspace: and unocss)
|
|
472
460
|
deepCleanProtocols(targetDir, targetScope);
|
|
473
461
|
|
|
474
|
-
// Initialize git if missing
|
|
475
462
|
if (!fs.existsSync(path.join(targetDir, ".git"))) {
|
|
476
463
|
try {
|
|
477
464
|
const { execSync } = await import("child_process");
|
|
478
465
|
execSync("git init", { cwd: targetDir, stdio: "ignore" });
|
|
479
466
|
console.log("✅ Git repository initialized.");
|
|
480
|
-
} catch (e) {
|
|
481
|
-
console.warn("⚠️ Could not initialize git automatically. Please run 'git init' manually.");
|
|
482
|
-
}
|
|
467
|
+
} catch (e) {}
|
|
483
468
|
}
|
|
484
469
|
|
|
485
|
-
// --- Post-Install Hooks (Smart Setup) ---
|
|
486
|
-
|
|
487
470
|
console.log("\n🛠️ Running smart configuration for adapters...");
|
|
488
471
|
|
|
489
|
-
// Universal Gemini Compatibility (Symlink)
|
|
490
|
-
try {
|
|
491
|
-
const geminiDir = path.join(targetDir, ".gemini");
|
|
492
|
-
const geminiAgentsDir = path.join(geminiDir, "agents");
|
|
493
|
-
const frameworkAgentsDir = path.join(targetDir, targetBase, "agents");
|
|
494
472
|
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
if (targetBase !== ".gemini" && !fs.existsSync(geminiAgentsDir)) {
|
|
500
|
-
const relativePath = path.relative(geminiDir, frameworkAgentsDir);
|
|
501
|
-
fs.symlinkSync(relativePath, geminiAgentsDir, "dir");
|
|
502
|
-
console.log(`🔗 Omni-Agent: Created symlink from .gemini/agents to ${targetBase}/agents`);
|
|
503
|
-
}
|
|
504
|
-
} catch (err) {
|
|
505
|
-
// Silently ignore if symlink fails (e.g. on non-compatible OS)
|
|
473
|
+
if (selectedAdapter === "gemini") {
|
|
474
|
+
console.log(`💎 Gemini: Adapter GEMINI.md and ${targetBase}/ folder are ready.`);
|
|
506
475
|
}
|
|
507
476
|
|
|
508
|
-
if (selectedAdapter === "claude"
|
|
477
|
+
if (selectedAdapter === "claude") {
|
|
509
478
|
const mcpPath = path.join(targetDir, "packages/framework-mcp/src/index.ts");
|
|
510
479
|
console.log("\n📝 Claude Code Setup:");
|
|
511
480
|
console.log("To enable Agent Enderun tools in Claude Code, run this command:");
|
|
512
481
|
console.log(`\x1b[36mclaude config add framework-mcp npx tsx ${mcpPath}\x1b[0m`);
|
|
513
482
|
}
|
|
514
483
|
|
|
515
|
-
if (selectedAdapter === "cursor"
|
|
516
|
-
|
|
484
|
+
if (selectedAdapter === "cursor") {
|
|
485
|
+
const cursorRulesPath = path.join(targetDir, ".cursorrules");
|
|
486
|
+
const cursorMdPath = path.join(targetDir, "CURSOR.md");
|
|
487
|
+
if (fs.existsSync(cursorMdPath) && !fs.existsSync(cursorRulesPath)) {
|
|
488
|
+
fs.copyFileSync(cursorMdPath, cursorRulesPath);
|
|
489
|
+
console.log("🔗 Cursor: Synchronized CURSOR.md to .cursorrules");
|
|
490
|
+
}
|
|
517
491
|
}
|
|
518
492
|
|
|
519
493
|
const pkgMgr = getPackageManager();
|
|
520
|
-
console.log(`\nℹ️ Detected package manager: ${pkgMgr}`);
|
|
521
494
|
const installCmd = pkgMgr === "npm" ? "npm install" : `${pkgMgr} install`;
|
|
522
495
|
const buildCmd = pkgMgr === "npm" ? "npm run enderun:build" : `${pkgMgr} run enderun:build`;
|
|
523
496
|
|
|
524
|
-
console.log(
|
|
497
|
+
console.log(`\n✨ Framework scaffolded! (v${FRAMEWORK_VERSION})`);
|
|
525
498
|
|
|
526
499
|
try {
|
|
527
500
|
const { execSync } = await import("child_process");
|
|
528
|
-
|
|
529
501
|
console.log(`\n📦 Step 1/3: Running '${installCmd}'...`);
|
|
530
502
|
execSync(installCmd, { stdio: "inherit" });
|
|
531
|
-
|
|
532
503
|
console.log(`\n🏗️ Step 2/3: Running '${buildCmd}'...`);
|
|
533
504
|
execSync(buildCmd, { stdio: "inherit" });
|
|
534
|
-
|
|
535
505
|
console.log(`\n🔍 Step 3/3: Running 'agent-enderun check'...`);
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
console.log("\n🚀 Agent Enderun is fully installed, built and verified!");
|
|
506
|
+
checkCommand();
|
|
507
|
+
console.log("\n🚀 Agent Enderun is fully installed and verified!");
|
|
540
508
|
} catch (error) {
|
|
541
|
-
console.error("\n❌ Automatic installation failed.
|
|
509
|
+
console.error("\n❌ Automatic installation failed. Run manually:");
|
|
542
510
|
console.log(`👉 ${installCmd} && ${buildCmd}`);
|
|
543
511
|
}
|
|
544
512
|
}
|
|
@@ -593,8 +561,12 @@ function checkCommand() {
|
|
|
593
561
|
{ name: "Shared Types", path: "packages/shared-types/package.json" },
|
|
594
562
|
{ name: "MCP Server", path: "packages/framework-mcp/package.json" },
|
|
595
563
|
{ name: "Tech Stack", path: path.join(frameworkDir, "docs/tech-stack.md") },
|
|
596
|
-
{ name: "
|
|
564
|
+
{ name: "Panda CSS Config", path: "panda.config.ts" },
|
|
565
|
+
{ name: "Requirements", path: path.join(frameworkDir, "docs/project-docs.md") },
|
|
597
566
|
{ name: "API Registry", path: path.join(frameworkDir, "docs/api/README.md") },
|
|
567
|
+
{ name: "Security Policy", path: path.join(frameworkDir, "docs/security.md") },
|
|
568
|
+
{ name: "Privacy Policy", path: path.join(frameworkDir, "docs/privacy.md") },
|
|
569
|
+
{ name: "Brain Dashboard", path: path.join(frameworkDir, "BRAIN_DASHBOARD.md") },
|
|
598
570
|
];
|
|
599
571
|
|
|
600
572
|
for (const check of checks) {
|
|
@@ -637,6 +609,7 @@ function checkCommand() {
|
|
|
637
609
|
console.log("\n🚀 All systems green! Agent Enderun is ready for orchestration.");
|
|
638
610
|
} else {
|
|
639
611
|
console.log(`\n⚠️ Found ${issues} issues. Please fix them before starting.`);
|
|
612
|
+
process.exit(1);
|
|
640
613
|
}
|
|
641
614
|
}
|
|
642
615
|
|
|
@@ -835,6 +808,156 @@ function verifyContractCommand() {
|
|
|
835
808
|
}
|
|
836
809
|
}
|
|
837
810
|
|
|
811
|
+
function securityAuditCommand(targetPath) {
|
|
812
|
+
console.log(`🔍 Running Advanced Security Audit on: ${targetPath}...`);
|
|
813
|
+
const scanRules = [
|
|
814
|
+
{ pattern: /sql`/, message: "Potential Raw SQL usage detected", severity: "HIGH" },
|
|
815
|
+
{ pattern: /(password|secret|api_?key)\s*[:=]\s*['"][^'"]+['"]/i, message: "Potential hardcoded secret detected", severity: "CRITICAL" },
|
|
816
|
+
{ pattern: /:\s*any(?!\w)/, message: "Usage of 'any' type detected", severity: "MEDIUM" },
|
|
817
|
+
{ pattern: /\.innerHTML\s*=/, message: "Unsafe innerHTML assignment detected", severity: "MEDIUM" },
|
|
818
|
+
];
|
|
819
|
+
const issues = [];
|
|
820
|
+
const files = collectFiles(path.join(targetDir, targetPath), [".ts", ".tsx", ".js", ".jsx"]);
|
|
821
|
+
files.forEach(f => {
|
|
822
|
+
const content = fs.readFileSync(f, "utf8");
|
|
823
|
+
const lines = content.split("\n");
|
|
824
|
+
lines.forEach((line, i) => {
|
|
825
|
+
scanRules.forEach(rule => {
|
|
826
|
+
if (rule.pattern.test(line)) {
|
|
827
|
+
issues.push(`[${rule.severity}] ${rule.message} in ${path.relative(targetDir, f)}:${i+1}`);
|
|
828
|
+
}
|
|
829
|
+
});
|
|
830
|
+
});
|
|
831
|
+
});
|
|
832
|
+
if (issues.length === 0) {
|
|
833
|
+
console.log("✅ No security issues detected.");
|
|
834
|
+
} else {
|
|
835
|
+
issues.forEach(issue => console.log(`⚠️ ${issue}`));
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
function complianceCheckCommand(targetPath) {
|
|
840
|
+
console.log(`📜 Checking Constitution Compliance: ${targetPath}...`);
|
|
841
|
+
const violations = [];
|
|
842
|
+
const forbidden = ["@shadcn", "mui", "@chakra-ui", "tailwindcss"];
|
|
843
|
+
const files = collectFiles(path.join(targetDir, targetPath), [".ts", ".tsx", ".js", ".jsx", ".md"]);
|
|
844
|
+
files.forEach(f => {
|
|
845
|
+
const content = fs.readFileSync(f, "utf8");
|
|
846
|
+
forbidden.forEach(lib => {
|
|
847
|
+
if (content.includes(lib)) violations.push(`${path.relative(targetDir, f)}: Forbidden library '${lib}' found.`);
|
|
848
|
+
});
|
|
849
|
+
if (f.endsWith(".ts") && content.includes("interface") && content.match(/ID\s*:\s*string/)) {
|
|
850
|
+
violations.push(`${path.relative(targetDir, f)}: Potential Branded Types violation (ID typed as string).`);
|
|
851
|
+
}
|
|
852
|
+
});
|
|
853
|
+
if (violations.length === 0) {
|
|
854
|
+
console.log("✅ All systems compliant with ENDERUN.md.");
|
|
855
|
+
} else {
|
|
856
|
+
violations.forEach(v => console.log(`❌ ${v}`));
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
function gitCommitCommand(traceId) {
|
|
861
|
+
try {
|
|
862
|
+
const diff = cp.execSync("git diff --staged", { encoding: "utf8" });
|
|
863
|
+
if (!diff) {
|
|
864
|
+
console.log("ℹ️ No staged changes found. Use 'git add' first.");
|
|
865
|
+
return;
|
|
866
|
+
}
|
|
867
|
+
const files = cp.execSync("git diff --staged --name-only", { encoding: "utf8" }).split("\n").filter(Boolean);
|
|
868
|
+
let type = "feat", scope = "code";
|
|
869
|
+
if (files.some(f => f.includes(".md"))) type = "docs";
|
|
870
|
+
else if (files.some(f => f.includes("shared-types"))) type = "arch";
|
|
871
|
+
else if (files.some(f => f.includes("bin/cli.js"))) type = "fix";
|
|
872
|
+
|
|
873
|
+
const summary = files.length === 1 ? `update ${path.basename(files[0])}` : `update ${files.length} files`;
|
|
874
|
+
console.log(`\n### SUGGESTED COMMIT MESSAGE ###\n\n[${traceId}] ${type}(${scope}): ${summary}\n`);
|
|
875
|
+
} catch (e) {
|
|
876
|
+
console.log("❌ Git command failed.");
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
function explorerGraphCommand(targetPath) {
|
|
881
|
+
console.log(`🗺️ Generating Dependency Graph for: ${targetPath}...`);
|
|
882
|
+
const files = collectFiles(path.join(targetDir, targetPath), [".ts", ".tsx"]);
|
|
883
|
+
const edges = [];
|
|
884
|
+
files.forEach(f => {
|
|
885
|
+
const content = fs.readFileSync(f, "utf8");
|
|
886
|
+
const name = path.basename(f, path.extname(f));
|
|
887
|
+
const imports = content.match(/from\s+['"]\.\.?\/[^'"]+['"]/g) || [];
|
|
888
|
+
imports.forEach(imp => {
|
|
889
|
+
const target = path.basename(imp.split(/['"]/)[1]);
|
|
890
|
+
edges.push(`${name} --> ${target}`);
|
|
891
|
+
});
|
|
892
|
+
});
|
|
893
|
+
if (edges.length === 0) {
|
|
894
|
+
console.log("ℹ️ No internal dependencies found.");
|
|
895
|
+
} else {
|
|
896
|
+
console.log("\n```mermaid\ngraph TD\n" + Array.from(new Set(edges)).join("\n") + "\n```\n");
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
function explorerAuditCommand(targetPath) {
|
|
901
|
+
console.log(`🧠 Codebase Intelligence Scan: ${targetPath}...`);
|
|
902
|
+
const files = collectFiles(path.join(targetDir, targetPath), [".ts", ".tsx"]);
|
|
903
|
+
const complexity = [];
|
|
904
|
+
files.forEach(f => {
|
|
905
|
+
const content = fs.readFileSync(f, "utf8");
|
|
906
|
+
const lines = content.split("\n").length;
|
|
907
|
+
if (lines > 300) complexity.push(`${path.relative(targetDir, f)} (${lines} lines)`);
|
|
908
|
+
});
|
|
909
|
+
if (complexity.length > 0) {
|
|
910
|
+
console.log("\n⚠️ Complexity Spikes:");
|
|
911
|
+
complexity.forEach(c => console.log(`- ${c}`));
|
|
912
|
+
} else {
|
|
913
|
+
console.log("✅ Codebase structure looks clean.");
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
function collectFiles(dir, extensions) {
|
|
918
|
+
let results = [];
|
|
919
|
+
if (!fs.existsSync(dir)) return results;
|
|
920
|
+
const list = fs.readdirSync(dir);
|
|
921
|
+
list.forEach(file => {
|
|
922
|
+
file = path.join(dir, file);
|
|
923
|
+
const stat = fs.statSync(file);
|
|
924
|
+
if (stat && stat.isDirectory()) {
|
|
925
|
+
if (!file.includes("node_modules") && !file.includes(".git")) {
|
|
926
|
+
results = results.concat(collectFiles(file, extensions));
|
|
927
|
+
}
|
|
928
|
+
} else {
|
|
929
|
+
if (extensions.includes(path.extname(file))) {
|
|
930
|
+
results.push(file);
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
});
|
|
934
|
+
return results;
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
function runScriptCommand(script, projectPath) {
|
|
938
|
+
const fullPath = path.join(targetDir, projectPath);
|
|
939
|
+
if (!fs.existsSync(fullPath)) {
|
|
940
|
+
console.log(`❌ Project path not found: ${projectPath}`);
|
|
941
|
+
return;
|
|
942
|
+
}
|
|
943
|
+
console.log(`🚀 Running 'npm run ${script}' in ${projectPath}...`);
|
|
944
|
+
try {
|
|
945
|
+
cp.spawnSync("npm", ["run", script], { cwd: fullPath, stdio: "inherit", shell: true });
|
|
946
|
+
} catch (e) {
|
|
947
|
+
console.log(`❌ Failed to run script: ${e.message}`);
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
|
|
951
|
+
function gitSyncCommand() {
|
|
952
|
+
console.log("🔄 Syncing with remote repository...");
|
|
953
|
+
try {
|
|
954
|
+
cp.execSync("git pull origin main --rebase", { stdio: "inherit" });
|
|
955
|
+
console.log("✅ Successfully synced and rebased.");
|
|
956
|
+
} catch (e) {
|
|
957
|
+
console.log("❌ Sync failed. Please resolve conflicts manually.");
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
|
|
838
961
|
function logAgentActionCommand(data) {
|
|
839
962
|
const frameworkDir = getFrameworkDir();
|
|
840
963
|
const logsDir = path.join(targetDir, frameworkDir, "logs");
|
|
@@ -921,6 +1044,11 @@ function updateProjectMemoryCommand(section, content) {
|
|
|
921
1044
|
async function main() {
|
|
922
1045
|
const [command, ...args] = process.argv.slice(2);
|
|
923
1046
|
|
|
1047
|
+
// Skip header for version and mcp commands to keep output clean
|
|
1048
|
+
if (command !== "version" && command !== "-v" && command !== "--version" && command !== "mcp") {
|
|
1049
|
+
console.log("🤖 Agent Enderun CLI — Initializing...");
|
|
1050
|
+
}
|
|
1051
|
+
|
|
924
1052
|
switch (command) {
|
|
925
1053
|
case "init":
|
|
926
1054
|
await initCommand(args[0]);
|
|
@@ -938,6 +1066,19 @@ async function main() {
|
|
|
938
1066
|
case "verify-contract":
|
|
939
1067
|
verifyContractCommand();
|
|
940
1068
|
break;
|
|
1069
|
+
case "mcp": {
|
|
1070
|
+
const mcpServerPath = path.join(sourceDir, "packages/framework-mcp/dist/index.js");
|
|
1071
|
+
if (fs.existsSync(mcpServerPath)) {
|
|
1072
|
+
const { spawn } = await import("child_process");
|
|
1073
|
+
// Use node to execute the built MCP server
|
|
1074
|
+
const child = spawn("node", [mcpServerPath], { stdio: "inherit" });
|
|
1075
|
+
child.on("exit", (code) => process.exit(code || 0));
|
|
1076
|
+
} else {
|
|
1077
|
+
console.error("❌ MCP Server not built. Run 'npm run enderun:build' first.");
|
|
1078
|
+
process.exit(1);
|
|
1079
|
+
}
|
|
1080
|
+
break;
|
|
1081
|
+
}
|
|
941
1082
|
case "log_agent_action": {
|
|
942
1083
|
// Handle both structured JSON and positional args
|
|
943
1084
|
let data = {};
|
|
@@ -978,9 +1119,75 @@ async function main() {
|
|
|
978
1119
|
updateProjectMemoryCommand(section, content);
|
|
979
1120
|
break;
|
|
980
1121
|
}
|
|
1122
|
+
case "update_knowledge_base": {
|
|
1123
|
+
const topic = args[0];
|
|
1124
|
+
const content = args.slice(1).join(" ");
|
|
1125
|
+
if (!topic || !content) {
|
|
1126
|
+
console.error("❌ Usage: agent-enderun update_knowledge_base <topic> <content>");
|
|
1127
|
+
process.exit(1);
|
|
1128
|
+
}
|
|
1129
|
+
const frameworkDir = getFrameworkDir();
|
|
1130
|
+
const kbDir = path.join(targetDir, frameworkDir, "knowledge");
|
|
1131
|
+
if (!fs.existsSync(kbDir)) fs.mkdirSync(kbDir, { recursive: true });
|
|
1132
|
+
const fileName = topic.replace(/[^a-z0-9]/gi, "_").toLowerCase() + ".md";
|
|
1133
|
+
fs.writeFileSync(path.join(kbDir, fileName), content);
|
|
1134
|
+
console.log(`✅ Knowledge base updated: ${topic}`);
|
|
1135
|
+
break;
|
|
1136
|
+
}
|
|
1137
|
+
case "search_knowledge_base": {
|
|
1138
|
+
const query = args[0];
|
|
1139
|
+
if (!query) {
|
|
1140
|
+
console.error("❌ Usage: agent-enderun search_knowledge_base <query>");
|
|
1141
|
+
process.exit(1);
|
|
1142
|
+
}
|
|
1143
|
+
const frameworkDir = getFrameworkDir();
|
|
1144
|
+
const kbDir = path.join(targetDir, frameworkDir, "knowledge");
|
|
1145
|
+
if (!fs.existsSync(kbDir)) {
|
|
1146
|
+
console.log("ℹ️ Knowledge base is empty.");
|
|
1147
|
+
break;
|
|
1148
|
+
}
|
|
1149
|
+
const files = fs.readdirSync(kbDir).filter(f => f.endsWith(".md"));
|
|
1150
|
+
let found = false;
|
|
1151
|
+
for (const file of files) {
|
|
1152
|
+
const content = fs.readFileSync(path.join(kbDir, file), "utf-8");
|
|
1153
|
+
if (content.toLowerCase().includes(query.toLowerCase()) || file.toLowerCase().includes(query.toLowerCase())) {
|
|
1154
|
+
console.log(`\n### ${file.replace(".md", "")}\n${content.slice(0, 300)}...`);
|
|
1155
|
+
found = true;
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1158
|
+
if (!found) console.log("ℹ️ No matching entries found.");
|
|
1159
|
+
break;
|
|
1160
|
+
}
|
|
981
1161
|
case "check":
|
|
982
1162
|
checkCommand();
|
|
983
1163
|
break;
|
|
1164
|
+
case "check:security":
|
|
1165
|
+
securityAuditCommand(args[0] || ".");
|
|
1166
|
+
break;
|
|
1167
|
+
case "check:compliance":
|
|
1168
|
+
complianceCheckCommand(args[0] || ".");
|
|
1169
|
+
break;
|
|
1170
|
+
case "git:commit":
|
|
1171
|
+
gitCommitCommand(args[0] || "TRACE-ID-MISSING");
|
|
1172
|
+
break;
|
|
1173
|
+
case "explorer:graph":
|
|
1174
|
+
explorerGraphCommand(args[0] || ".");
|
|
1175
|
+
break;
|
|
1176
|
+
case "explorer:audit":
|
|
1177
|
+
explorerAuditCommand(args[0] || ".");
|
|
1178
|
+
break;
|
|
1179
|
+
case "frontend:dev":
|
|
1180
|
+
runScriptCommand("dev", "apps/web");
|
|
1181
|
+
break;
|
|
1182
|
+
case "frontend:build":
|
|
1183
|
+
runScriptCommand("build", "apps/web");
|
|
1184
|
+
break;
|
|
1185
|
+
case "mobile:dev":
|
|
1186
|
+
runScriptCommand("start", "apps/mobile");
|
|
1187
|
+
break;
|
|
1188
|
+
case "git:sync":
|
|
1189
|
+
gitSyncCommand();
|
|
1190
|
+
break;
|
|
984
1191
|
case "version":
|
|
985
1192
|
case "-v":
|
|
986
1193
|
case "--version":
|
|
@@ -991,12 +1198,18 @@ async function main() {
|
|
|
991
1198
|
🤖 Agent Enderun CLI (v${FRAMEWORK_VERSION})
|
|
992
1199
|
|
|
993
1200
|
Available Commands:
|
|
994
|
-
init [adapter]
|
|
995
|
-
check
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1201
|
+
init [adapter] Initialize the framework (gemini, claude, cursor, codex)
|
|
1202
|
+
check Full health check
|
|
1203
|
+
check:security Run security audit scan
|
|
1204
|
+
check:compliance Run constitution compliance check
|
|
1205
|
+
status Show current phase and task status
|
|
1206
|
+
trace:new <desc> Generate a new Trace ID
|
|
1207
|
+
verify-contract Check shared types integrity
|
|
1208
|
+
explorer:graph Generate dependency graph
|
|
1209
|
+
explorer:audit Codebase intelligence scan
|
|
1210
|
+
git:commit <id> Suggest semantic commit message
|
|
1211
|
+
mcp Start the MCP server
|
|
1212
|
+
version Show version information
|
|
1000
1213
|
|
|
1001
1214
|
Example:
|
|
1002
1215
|
agent-enderun trace:new "Auth module design" backend P1
|
package/package.json
CHANGED
|
@@ -1,23 +1,63 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-enderun",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
|
+
"description": "The Supreme AI Governance & Orchestration Framework for Enterprise Development",
|
|
5
|
+
"author": "Yusuf BEKAR",
|
|
6
|
+
"license": "MIT",
|
|
4
7
|
"type": "module",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/ysf-bkr/Agent-Enderun.git"
|
|
11
|
+
},
|
|
12
|
+
"homepage": "https://github.com/ysf-bkr/Agent-Enderun#readme",
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/ysf-bkr/Agent-Enderun/issues"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"ai",
|
|
18
|
+
"governance",
|
|
19
|
+
"orchestration",
|
|
20
|
+
"agents",
|
|
21
|
+
"mcp",
|
|
22
|
+
"typescript",
|
|
23
|
+
"framework"
|
|
24
|
+
],
|
|
5
25
|
"workspaces": [
|
|
6
26
|
"packages/*"
|
|
7
27
|
],
|
|
8
28
|
"bin": {
|
|
9
29
|
"agent-enderun": "bin/cli.js"
|
|
10
30
|
},
|
|
31
|
+
"files": [
|
|
32
|
+
"bin",
|
|
33
|
+
"packages/shared-types/dist",
|
|
34
|
+
"packages/shared-types/src",
|
|
35
|
+
"packages/shared-types/package.json",
|
|
36
|
+
"packages/shared-types/README.md",
|
|
37
|
+
"packages/framework-mcp/dist",
|
|
38
|
+
"packages/framework-mcp/src",
|
|
39
|
+
"packages/framework-mcp/package.json",
|
|
40
|
+
"packages/framework-mcp/README.md",
|
|
41
|
+
".enderun",
|
|
42
|
+
"ENDERUN.md",
|
|
43
|
+
"README.md",
|
|
44
|
+
"LICENSE",
|
|
45
|
+
"mcp.json",
|
|
46
|
+
".env.example"
|
|
47
|
+
],
|
|
11
48
|
"scripts": {
|
|
12
49
|
"enderun:build": "npm run build --prefix packages/shared-types && npm run build --prefix packages/framework-mcp",
|
|
13
50
|
"enderun:status": "agent-enderun status",
|
|
14
51
|
"enderun:trace": "agent-enderun trace:new",
|
|
15
52
|
"enderun:verify": "agent-enderun verify-contract"
|
|
16
53
|
},
|
|
54
|
+
"publishConfig": {
|
|
55
|
+
"access": "public"
|
|
56
|
+
},
|
|
17
57
|
"dependencies": {},
|
|
18
58
|
"devDependencies": {},
|
|
19
59
|
"enderun": {
|
|
20
|
-
"version": "0.1
|
|
60
|
+
"version": "0.2.1",
|
|
21
61
|
"initializedAt": "2026-05-09T13:24:27.472Z"
|
|
22
62
|
}
|
|
23
63
|
}
|