atabey 0.0.7 ā 0.0.8
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 +1 -1
- package/dist/src/cli/adapters/core.js +12 -19
- package/dist/src/cli/adapters/core.js.map +1 -1
- package/dist/src/shared/constants.d.ts +1 -0
- package/dist/src/shared/constants.js +1 -0
- package/dist/src/shared/constants.js.map +1 -1
- package/dist/tests/adapter.test.js +3 -2
- package/dist/tests/adapter.test.js.map +1 -1
- package/framework-mcp/dist/constants.js +64 -0
- package/framework-mcp/dist/framework-mcp/src/constants.js +64 -0
- package/framework-mcp/dist/framework-mcp/src/index.js +144 -0
- package/framework-mcp/dist/framework-mcp/src/resources/index.js +58 -0
- package/framework-mcp/dist/framework-mcp/src/tools/control_plane/locking.js +82 -0
- package/framework-mcp/dist/framework-mcp/src/tools/control_plane/registry.js +35 -0
- package/framework-mcp/dist/framework-mcp/src/tools/definitions.js +322 -0
- package/framework-mcp/dist/framework-mcp/src/tools/file_system/batch_surgical_edit.js +64 -0
- package/framework-mcp/dist/framework-mcp/src/tools/file_system/patch_file.js +34 -0
- package/framework-mcp/dist/framework-mcp/src/tools/file_system/read_file.js +51 -0
- package/framework-mcp/dist/framework-mcp/src/tools/file_system/replace_text.js +50 -0
- package/framework-mcp/dist/framework-mcp/src/tools/file_system/write_file.js +43 -0
- package/framework-mcp/dist/framework-mcp/src/tools/framework/audit_deps.js +41 -0
- package/framework-mcp/dist/framework-mcp/src/tools/framework/get_status.js +5 -0
- package/framework-mcp/dist/framework-mcp/src/tools/framework/orchestrate.js +5 -0
- package/framework-mcp/dist/framework-mcp/src/tools/framework/run_tests.js +27 -0
- package/framework-mcp/dist/framework-mcp/src/tools/framework/submit_plan.js +13 -0
- package/framework-mcp/dist/framework-mcp/src/tools/framework/update_contract_hash.js +5 -0
- package/framework-mcp/dist/framework-mcp/src/tools/framework/update_memory.js +8 -0
- package/framework-mcp/dist/framework-mcp/src/tools/index.js +62 -0
- package/framework-mcp/dist/framework-mcp/src/tools/memory/get_insights.js +34 -0
- package/framework-mcp/dist/framework-mcp/src/tools/memory/read_memory.js +28 -0
- package/framework-mcp/dist/framework-mcp/src/tools/messaging/log_action.js +22 -0
- package/framework-mcp/dist/framework-mcp/src/tools/messaging/send_message.js +94 -0
- package/framework-mcp/dist/framework-mcp/src/tools/observability/check_ports.js +26 -0
- package/framework-mcp/dist/framework-mcp/src/tools/observability/get_health.js +19 -0
- package/framework-mcp/dist/framework-mcp/src/tools/quality/check_lint.js +30 -0
- package/framework-mcp/dist/framework-mcp/src/tools/search/get_gaps.js +48 -0
- package/framework-mcp/dist/framework-mcp/src/tools/search/get_map.js +43 -0
- package/framework-mcp/dist/framework-mcp/src/tools/search/grep_search.js +75 -0
- package/framework-mcp/dist/framework-mcp/src/tools/search/list_dir.js +28 -0
- package/framework-mcp/dist/framework-mcp/src/tools/shell/run_command.js +56 -0
- package/framework-mcp/dist/framework-mcp/src/tools/types.js +1 -0
- package/framework-mcp/dist/framework-mcp/src/utils/cli.js +59 -0
- package/framework-mcp/dist/framework-mcp/src/utils/compliance.js +231 -0
- package/framework-mcp/dist/framework-mcp/src/utils/fs.js +44 -0
- package/framework-mcp/dist/framework-mcp/src/utils/metrics.js +56 -0
- package/framework-mcp/dist/framework-mcp/src/utils/permissions.js +71 -0
- package/framework-mcp/dist/framework-mcp/src/utils/security.js +60 -0
- package/framework-mcp/dist/index.js +144 -0
- package/framework-mcp/dist/resources/index.js +58 -0
- package/framework-mcp/dist/src/cli/adapters/core.js +71 -0
- package/framework-mcp/dist/src/cli/adapters/index.js +5 -0
- package/framework-mcp/dist/src/cli/adapters/paths.js +101 -0
- package/framework-mcp/dist/src/cli/adapters/scaffold.js +71 -0
- package/framework-mcp/dist/src/cli/adapters/utils.js +75 -0
- package/framework-mcp/dist/src/cli/commands/approve.js +63 -0
- package/framework-mcp/dist/src/cli/commands/check.js +181 -0
- package/framework-mcp/dist/src/cli/commands/compliance.js +50 -0
- package/framework-mcp/dist/src/cli/commands/contract.js +50 -0
- package/framework-mcp/dist/src/cli/commands/dashboard.js +123 -0
- package/framework-mcp/dist/src/cli/commands/explorer.js +42 -0
- package/framework-mcp/dist/src/cli/commands/git.js +40 -0
- package/framework-mcp/dist/src/cli/commands/init/create-agent.js +58 -0
- package/framework-mcp/dist/src/cli/commands/init/scaffold-core.js +112 -0
- package/framework-mcp/dist/src/cli/commands/init/scaffold-docs.js +34 -0
- package/framework-mcp/dist/src/cli/commands/init/scaffold-ops.js +80 -0
- package/framework-mcp/dist/src/cli/commands/init/scaffold-standards.js +67 -0
- package/framework-mcp/dist/src/cli/commands/init.js +167 -0
- package/framework-mcp/dist/src/cli/commands/knowledge.js +42 -0
- package/framework-mcp/dist/src/cli/commands/lint.js +22 -0
- package/framework-mcp/dist/src/cli/commands/log.js +10 -0
- package/framework-mcp/dist/src/cli/commands/memory.js +4 -0
- package/framework-mcp/dist/src/cli/commands/orchestrate.js +159 -0
- package/framework-mcp/dist/src/cli/commands/plan.js +117 -0
- package/framework-mcp/dist/src/cli/commands/script.js +19 -0
- package/framework-mcp/dist/src/cli/commands/security.js +36 -0
- package/framework-mcp/dist/src/cli/commands/status.js +97 -0
- package/framework-mcp/dist/src/cli/commands/trace.js +109 -0
- package/framework-mcp/dist/src/cli/index.js +338 -0
- package/framework-mcp/dist/src/cli/shims.js +66 -0
- package/framework-mcp/dist/src/cli/utils/claude.js +56 -0
- package/framework-mcp/dist/src/cli/utils/compliance.js +173 -0
- package/framework-mcp/dist/src/cli/utils/config-schema.js +42 -0
- package/framework-mcp/dist/src/cli/utils/fs.js +137 -0
- package/framework-mcp/dist/src/cli/utils/i18n.js +30 -0
- package/framework-mcp/dist/src/cli/utils/memory.js +276 -0
- package/framework-mcp/dist/src/cli/utils/pkg.js +282 -0
- package/framework-mcp/dist/src/cli/utils/schemas.js +19 -0
- package/framework-mcp/dist/src/cli/utils/string.js +49 -0
- package/framework-mcp/dist/src/cli/utils/time.js +27 -0
- package/framework-mcp/dist/src/cli/utils/ui.js +58 -0
- package/framework-mcp/dist/src/contracts/index.js +1 -0
- package/framework-mcp/dist/src/contracts/tasks.js +20 -0
- package/framework-mcp/dist/src/dashboard/vite.config.js +15 -0
- package/framework-mcp/dist/src/modules/adapters/definitions.js +140 -0
- package/framework-mcp/dist/src/modules/adapters/registry.js +18 -0
- package/framework-mcp/dist/src/modules/adapters/shared.js +104 -0
- package/framework-mcp/dist/src/modules/adapters/types.js +1 -0
- package/framework-mcp/dist/src/modules/agents/definitions.js +457 -0
- package/framework-mcp/dist/src/modules/agents/registry/analyst.js +39 -0
- package/framework-mcp/dist/src/modules/agents/registry/architect.js +42 -0
- package/framework-mcp/dist/src/modules/agents/registry/backend.js +49 -0
- package/framework-mcp/dist/src/modules/agents/registry/database.js +45 -0
- package/framework-mcp/dist/src/modules/agents/registry/devops.js +45 -0
- package/framework-mcp/dist/src/modules/agents/registry/explorer.js +36 -0
- package/framework-mcp/dist/src/modules/agents/registry/frontend.js +51 -0
- package/framework-mcp/dist/src/modules/agents/registry/git.js +36 -0
- package/framework-mcp/dist/src/modules/agents/registry/manager.js +53 -0
- package/framework-mcp/dist/src/modules/agents/registry/mobile.js +39 -0
- package/framework-mcp/dist/src/modules/agents/registry/native.js +39 -0
- package/framework-mcp/dist/src/modules/agents/registry/quality.js +41 -0
- package/framework-mcp/dist/src/modules/agents/registry/security.js +43 -0
- package/framework-mcp/dist/src/modules/agents/types.js +1 -0
- package/framework-mcp/dist/src/modules/engines/evaluation-engine.js +102 -0
- package/framework-mcp/dist/src/modules/engines/health-engine.js +49 -0
- package/framework-mcp/dist/src/modules/engines/planning-engine.js +78 -0
- package/framework-mcp/dist/src/modules/engines/risk-engine.js +105 -0
- package/framework-mcp/dist/src/modules/engines/routing-engine.js +73 -0
- package/framework-mcp/dist/src/modules/engines/types.js +1 -0
- package/framework-mcp/dist/src/modules/skills/definitions.js +70 -0
- package/framework-mcp/dist/src/shared/constants.js +187 -0
- package/framework-mcp/dist/src/shared/errors.js +68 -0
- package/framework-mcp/dist/src/shared/fs.js +51 -0
- package/framework-mcp/dist/src/shared/logger.js +116 -0
- package/framework-mcp/dist/src/shared/storage.js +207 -0
- package/framework-mcp/dist/src/shared/types.js +12 -0
- package/framework-mcp/dist/tools/control_plane/locking.js +82 -0
- package/framework-mcp/dist/tools/control_plane/registry.js +35 -0
- package/framework-mcp/dist/tools/definitions.js +322 -0
- package/framework-mcp/dist/tools/file_system/batch_surgical_edit.js +64 -0
- package/framework-mcp/dist/tools/file_system/patch_file.js +34 -0
- package/framework-mcp/dist/tools/file_system/read_file.js +51 -0
- package/framework-mcp/dist/tools/file_system/replace_text.js +50 -0
- package/framework-mcp/dist/tools/file_system/write_file.js +43 -0
- package/framework-mcp/dist/tools/framework/audit_deps.js +41 -0
- package/framework-mcp/dist/tools/framework/get_status.js +5 -0
- package/framework-mcp/dist/tools/framework/orchestrate.js +5 -0
- package/framework-mcp/dist/tools/framework/run_tests.js +27 -0
- package/framework-mcp/dist/tools/framework/submit_plan.js +13 -0
- package/framework-mcp/dist/tools/framework/update_contract_hash.js +5 -0
- package/framework-mcp/dist/tools/framework/update_memory.js +8 -0
- package/framework-mcp/dist/tools/index.js +62 -0
- package/framework-mcp/dist/tools/memory/get_insights.js +34 -0
- package/framework-mcp/dist/tools/memory/read_memory.js +28 -0
- package/framework-mcp/dist/tools/messaging/log_action.js +22 -0
- package/framework-mcp/dist/tools/messaging/send_message.js +94 -0
- package/framework-mcp/dist/tools/observability/check_ports.js +26 -0
- package/framework-mcp/dist/tools/observability/get_health.js +19 -0
- package/framework-mcp/dist/tools/quality/check_lint.js +30 -0
- package/framework-mcp/dist/tools/search/get_gaps.js +48 -0
- package/framework-mcp/dist/tools/search/get_map.js +43 -0
- package/framework-mcp/dist/tools/search/grep_search.js +75 -0
- package/framework-mcp/dist/tools/search/list_dir.js +28 -0
- package/framework-mcp/dist/tools/shell/run_command.js +56 -0
- package/framework-mcp/dist/tools/types.js +1 -0
- package/framework-mcp/dist/utils/cli.js +59 -0
- package/framework-mcp/dist/utils/compliance.js +231 -0
- package/framework-mcp/dist/utils/fs.js +44 -0
- package/framework-mcp/dist/utils/metrics.js +56 -0
- package/framework-mcp/dist/utils/permissions.js +71 -0
- package/framework-mcp/dist/utils/security.js +60 -0
- package/framework-mcp/package.json +35 -0
- package/mcp.json +1 -1
- package/package.json +6 -3
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { Storage } from "../../../src/shared/storage.js";
|
|
2
|
+
/**
|
|
3
|
+
* [DATA] MCP Resource Definitions
|
|
4
|
+
*/
|
|
5
|
+
export const RESOURCES = [
|
|
6
|
+
{
|
|
7
|
+
uri: "atabey://army/status",
|
|
8
|
+
name: "Agent Army Status",
|
|
9
|
+
description: "Real-time state and active tasks of all specialized agents.",
|
|
10
|
+
mimeType: "text/markdown"
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
uri: "atabey://plan/active",
|
|
14
|
+
name: "Active Execution Plan",
|
|
15
|
+
description: "The current DAG of tasks and their completion status.",
|
|
16
|
+
mimeType: "text/markdown"
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
uri: "atabey://memory/project",
|
|
20
|
+
name: "Project Memory",
|
|
21
|
+
description: "The central source of truth for project context (PROJECT_MEMORY.md).",
|
|
22
|
+
mimeType: "text/markdown"
|
|
23
|
+
}
|
|
24
|
+
];
|
|
25
|
+
export async function handleReadResource(uri) {
|
|
26
|
+
if (uri === "atabey://army/status") {
|
|
27
|
+
const agents = Storage.getAllAgents();
|
|
28
|
+
let md = "# [AI] Agent Army Status\n\n| Agent | State | Active Task | Last Updated |\n| :--- | :--- | :--- | :--- |\n";
|
|
29
|
+
agents.forEach((a) => {
|
|
30
|
+
md += `| @${a.name} | ${a.state} | ${a.task} | ${a.last_updated} |\n`;
|
|
31
|
+
});
|
|
32
|
+
return md;
|
|
33
|
+
}
|
|
34
|
+
if (uri === "atabey://plan/active") {
|
|
35
|
+
const tasks = Storage.getTasks();
|
|
36
|
+
let md = "# š Active Execution Plan\n\n| ID | Task | Agent | Status | Dependencies |\n| :--- | :--- | :--- | :--- | :--- |\n";
|
|
37
|
+
tasks.forEach((t) => {
|
|
38
|
+
const deps = t.dependencies.join(", ") || "-";
|
|
39
|
+
md += `| ${t.id} | ${t.description} | ${t.agent} | ${t.status} | ${deps} |\n`;
|
|
40
|
+
});
|
|
41
|
+
return md;
|
|
42
|
+
}
|
|
43
|
+
if (uri === "atabey://memory/project") {
|
|
44
|
+
const fs = await import("fs");
|
|
45
|
+
const path = await import("path");
|
|
46
|
+
const { getFrameworkDir } = await import("../../../src/cli/utils/memory.js");
|
|
47
|
+
const projectRoot = process.env.ATABEY_PROJECT_ROOT || process.cwd();
|
|
48
|
+
const fwDir = getFrameworkDir();
|
|
49
|
+
const p = path.isAbsolute(fwDir)
|
|
50
|
+
? path.join(fwDir, "memory", "PROJECT_MEMORY.md")
|
|
51
|
+
: path.join(projectRoot, fwDir, "memory", "PROJECT_MEMORY.md");
|
|
52
|
+
if (fs.existsSync(p)) {
|
|
53
|
+
return fs.readFileSync(p, "utf8");
|
|
54
|
+
}
|
|
55
|
+
return "Project memory not found. Run 'atabey init' first.";
|
|
56
|
+
}
|
|
57
|
+
throw new Error(`Unknown resource URI: ${uri}`);
|
|
58
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { writeJsonFile } from "../utils/fs.js";
|
|
4
|
+
import { getPackageRoot } from "../utils/pkg.js";
|
|
5
|
+
import { MCP } from "../../shared/constants.js";
|
|
6
|
+
import { ADAPTER_CONFIGS, POST_INIT_HANDLERS } from "../../modules/adapters/definitions.js";
|
|
7
|
+
export const ADAPTERS = ADAPTER_CONFIGS;
|
|
8
|
+
export const SHIM_FILES = Object.keys(ADAPTERS).map((id) => ADAPTERS[id].shimFile);
|
|
9
|
+
export const FRAMEWORK_DIR_CANDIDATES = [
|
|
10
|
+
".atabey",
|
|
11
|
+
".cursor",
|
|
12
|
+
".claude",
|
|
13
|
+
".github",
|
|
14
|
+
".grok",
|
|
15
|
+
".antigravity",
|
|
16
|
+
".agent",
|
|
17
|
+
".gemini/antigravity-cli",
|
|
18
|
+
".gemini",
|
|
19
|
+
".agents",
|
|
20
|
+
"antigravity-cli"
|
|
21
|
+
];
|
|
22
|
+
export function buildMcpServerEntry(projectRoot) {
|
|
23
|
+
const packageRoot = getPackageRoot();
|
|
24
|
+
// Check if we are running in the framework local development repository itself
|
|
25
|
+
const isLocalFrameworkDev = path.resolve(packageRoot) === path.resolve(projectRoot);
|
|
26
|
+
let relativePath;
|
|
27
|
+
if (isLocalFrameworkDev) {
|
|
28
|
+
// In local framework dev, always use the build path directly relative to project root
|
|
29
|
+
let mcpServerPath = path.join(packageRoot, MCP.SERVER_DIST_PATH);
|
|
30
|
+
if (!fs.existsSync(mcpServerPath)) {
|
|
31
|
+
mcpServerPath = path.join(packageRoot, "../atabey-mcp/dist/index.js");
|
|
32
|
+
}
|
|
33
|
+
if (!fs.existsSync(mcpServerPath)) {
|
|
34
|
+
mcpServerPath = path.join(projectRoot, "node_modules/atabey-mcp/dist/index.js");
|
|
35
|
+
}
|
|
36
|
+
if (!fs.existsSync(mcpServerPath)) {
|
|
37
|
+
console.warn("[WARN] MCP Server not found. Did you run 'npm run build' inside atabey-mcp?");
|
|
38
|
+
}
|
|
39
|
+
relativePath = path.relative(projectRoot, mcpServerPath) || mcpServerPath;
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
// If we are initializing in a user's project:
|
|
43
|
+
// We target the atabey-mcp package which is a dependency of atabey.
|
|
44
|
+
// This ensures a stable path across different npm/pnpm/yarn setups.
|
|
45
|
+
relativePath = "node_modules/atabey-mcp/dist/index.js";
|
|
46
|
+
// Fallback check if it actually exists in a different location during init
|
|
47
|
+
const localAtabeyPath = path.join(projectRoot, "node_modules/atabey", MCP.SERVER_DIST_PATH);
|
|
48
|
+
if (!fs.existsSync(path.join(projectRoot, relativePath)) && fs.existsSync(localAtabeyPath)) {
|
|
49
|
+
relativePath = path.join("node_modules/atabey", MCP.SERVER_DIST_PATH);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
command: "node",
|
|
54
|
+
args: [relativePath],
|
|
55
|
+
env: {
|
|
56
|
+
[MCP.PROJECT_ROOT_ENV]: projectRoot,
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
export function runAdapterPostInit(adapter, projectRoot) {
|
|
61
|
+
const mcpEntry = buildMcpServerEntry(projectRoot);
|
|
62
|
+
const mcpBlock = { mcpServers: { [MCP.SERVER_NAME]: mcpEntry } };
|
|
63
|
+
const postInitFn = POST_INIT_HANDLERS[adapter.id];
|
|
64
|
+
if (postInitFn) {
|
|
65
|
+
postInitFn(projectRoot, mcpBlock);
|
|
66
|
+
}
|
|
67
|
+
const rootMcpPath = path.join(projectRoot, MCP.ROOT_CONFIG_FILE);
|
|
68
|
+
if (!fs.existsSync(rootMcpPath)) {
|
|
69
|
+
writeJsonFile(rootMcpPath, mcpBlock);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { ADAPTER_IDS } from "../../modules/adapters/types.js";
|
|
2
|
+
export { ADAPTERS, FRAMEWORK_DIR_CANDIDATES, runAdapterPostInit, buildMcpServerEntry } from "./core.js";
|
|
3
|
+
export { resolveAdapter, isAdapterShimFile, remapFrameworkContent } from "./utils.js";
|
|
4
|
+
export { scaffoldAgents } from "./scaffold.js";
|
|
5
|
+
export { resolveAgentsDir, mirrorUnifiedAgentsToNative } from "./paths.js";
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { ADAPTER_IDS } from "../../modules/adapters/types.js";
|
|
4
|
+
import { LEGACY_AGENT_LAYOUT_BASES, UNIFIED_ADAPTER_SLUG, UNIFIED_HUB_DIR, pathJoin, unifiedAdapterPath, } from "../../shared/constants.js";
|
|
5
|
+
import { ADAPTERS } from "./core.js";
|
|
6
|
+
export { CORE_FRAMEWORK_DIR, UNIFIED_HUB_DIR, UNIFIED_ADAPTER_SLUG, } from "../../shared/constants.js";
|
|
7
|
+
export function unifiedAdapterRoot(aiToolDir, adapterId) {
|
|
8
|
+
return pathJoin(aiToolDir, UNIFIED_ADAPTER_SLUG[adapterId]);
|
|
9
|
+
}
|
|
10
|
+
export function resolveAgentsDir(adapterId, isUnified, aiToolDir = UNIFIED_HUB_DIR) {
|
|
11
|
+
const adapter = ADAPTERS[adapterId];
|
|
12
|
+
if (!isUnified) {
|
|
13
|
+
return {
|
|
14
|
+
agentsDir: adapter.agentsDir ?? pathJoin(adapter.frameworkDir, "agents"),
|
|
15
|
+
agentsExt: adapter.agentsExt ?? ".md",
|
|
16
|
+
nestedAntigravity: adapterId === "antigravity-cli",
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
const base = unifiedAdapterRoot(aiToolDir, adapterId);
|
|
20
|
+
switch (adapterId) {
|
|
21
|
+
case "cursor":
|
|
22
|
+
return { agentsDir: pathJoin(base, "rules"), agentsExt: ".mdc", nestedAntigravity: false };
|
|
23
|
+
case "codex":
|
|
24
|
+
return { agentsDir: pathJoin(base, "instructions"), agentsExt: ".md", nestedAntigravity: false };
|
|
25
|
+
case "antigravity-cli":
|
|
26
|
+
// Antigravity CLI expects workspace agents at .agents/agents/{agent_name}/agent.json
|
|
27
|
+
return { agentsDir: pathJoin(aiToolDir, "agents"), agentsExt: ".json", nestedAntigravity: true };
|
|
28
|
+
default:
|
|
29
|
+
return { agentsDir: pathJoin(base, "agents"), agentsExt: ".md", nestedAntigravity: false };
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
export function getUnifiedAgentLayoutBases(aiToolDir = UNIFIED_HUB_DIR) {
|
|
33
|
+
return ADAPTER_IDS.map((id) => resolveAgentsDir(id, true, aiToolDir).agentsDir);
|
|
34
|
+
}
|
|
35
|
+
const AGENT_INSTRUCTION_CANDIDATES = [
|
|
36
|
+
(n) => ADAPTER_IDS.flatMap((id) => {
|
|
37
|
+
const { agentsDir, nestedAntigravity, agentsExt } = resolveAgentsDir(id, true);
|
|
38
|
+
if (nestedAntigravity) {
|
|
39
|
+
return [pathJoin(agentsDir, n, "agent.json"), pathJoin(agentsDir, n, "agent.md")];
|
|
40
|
+
}
|
|
41
|
+
return [pathJoin(agentsDir, `${n}${agentsExt}`)];
|
|
42
|
+
}),
|
|
43
|
+
(n) => LEGACY_AGENT_LAYOUT_BASES.flatMap((base) => {
|
|
44
|
+
if (base.includes("antigravity")) {
|
|
45
|
+
return [pathJoin(base, n, "agent.json"), pathJoin(base, n, "agent.md")];
|
|
46
|
+
}
|
|
47
|
+
const ext = base.includes("rules") ? ".mdc" : ".md";
|
|
48
|
+
return [pathJoin(base, `${n}${ext}`)];
|
|
49
|
+
}),
|
|
50
|
+
];
|
|
51
|
+
export function findAgentInstruction(projectRoot, agentName) {
|
|
52
|
+
for (const buildPaths of AGENT_INSTRUCTION_CANDIDATES) {
|
|
53
|
+
for (const rel of buildPaths(agentName)) {
|
|
54
|
+
const full = path.join(projectRoot, rel);
|
|
55
|
+
if (fs.existsSync(full))
|
|
56
|
+
return rel;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
export function detectActiveAgentLayouts(projectRoot) {
|
|
62
|
+
const unified = getUnifiedAgentLayoutBases()
|
|
63
|
+
.filter((b) => fs.existsSync(path.join(projectRoot, b)));
|
|
64
|
+
const legacy = LEGACY_AGENT_LAYOUT_BASES
|
|
65
|
+
.filter((b) => fs.existsSync(path.join(projectRoot, b)));
|
|
66
|
+
return [...new Set([...unified, ...legacy])];
|
|
67
|
+
}
|
|
68
|
+
function copyDirectoryRecursive(src, dest) {
|
|
69
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
70
|
+
for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
|
|
71
|
+
const srcPath = path.join(src, entry.name);
|
|
72
|
+
const destPath = path.join(dest, entry.name);
|
|
73
|
+
if (entry.isDirectory()) {
|
|
74
|
+
copyDirectoryRecursive(srcPath, destPath);
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
fs.copyFileSync(srcPath, destPath);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
export function mirrorUnifiedAgentsToNative(projectRoot, adapterId) {
|
|
82
|
+
const { agentsDir: unifiedDir } = resolveAgentsDir(adapterId, true);
|
|
83
|
+
const nativeRel = ADAPTERS[adapterId].agentsDir;
|
|
84
|
+
if (!nativeRel)
|
|
85
|
+
return;
|
|
86
|
+
const src = path.join(projectRoot, unifiedDir);
|
|
87
|
+
const dest = path.join(projectRoot, nativeRel);
|
|
88
|
+
if (!fs.existsSync(src) || path.resolve(src) === path.resolve(dest))
|
|
89
|
+
return;
|
|
90
|
+
if (fs.existsSync(dest)) {
|
|
91
|
+
fs.rmSync(dest, { recursive: true, force: true });
|
|
92
|
+
}
|
|
93
|
+
copyDirectoryRecursive(src, dest);
|
|
94
|
+
}
|
|
95
|
+
/** Cursor global rule destinations (native + unified hub). */
|
|
96
|
+
export function getCursorGlobalRulePaths(projectRoot) {
|
|
97
|
+
return [
|
|
98
|
+
path.join(projectRoot, ADAPTERS.cursor.frameworkDir, "rules", "global.mdc"),
|
|
99
|
+
path.join(projectRoot, unifiedAdapterPath(UNIFIED_ADAPTER_SLUG.cursor, "rules", "global.mdc")),
|
|
100
|
+
];
|
|
101
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { writeTextFile } from "../utils/fs.js";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import fs from "fs";
|
|
4
|
+
import { getPackageRoot } from "../utils/pkg.js";
|
|
5
|
+
import { ALL_AGENTS, toClaudeCodeMd, toGeminiCliMd, toCodexMd, toAntigravityJson, toCursorMdc } from "../../modules/agents/definitions.js";
|
|
6
|
+
import { ADAPTERS } from "./core.js";
|
|
7
|
+
export function scaffoldAgents(projectRoot, adapterId, dryRun, agentsToScaffold, explicitDestDir, explicitExt, paths, backendLanguage, _language) {
|
|
8
|
+
const adapter = ADAPTERS[adapterId];
|
|
9
|
+
if (!adapter)
|
|
10
|
+
return;
|
|
11
|
+
const allowedAgents = agentsToScaffold ? new Set(agentsToScaffold) : undefined;
|
|
12
|
+
const destAgentsDir = explicitDestDir ? path.join(projectRoot, explicitDestDir) : (adapter.agentsDir ? path.join(projectRoot, adapter.agentsDir) : null);
|
|
13
|
+
const extension = explicitExt || adapter.agentsExt || ".md";
|
|
14
|
+
if (!destAgentsDir)
|
|
15
|
+
return;
|
|
16
|
+
const baseKnowledgeDir = path.join(getPackageRoot(), "templates/standards");
|
|
17
|
+
try {
|
|
18
|
+
if (!dryRun)
|
|
19
|
+
fs.mkdirSync(destAgentsDir, { recursive: true });
|
|
20
|
+
for (const agent of ALL_AGENTS) {
|
|
21
|
+
if (allowedAgents && !allowedAgents.has(agent.name))
|
|
22
|
+
continue;
|
|
23
|
+
let content = "";
|
|
24
|
+
let fileName = `${agent.name}${extension}`;
|
|
25
|
+
let secondaryContent = null;
|
|
26
|
+
let secondaryFileName = null;
|
|
27
|
+
switch (adapterId) {
|
|
28
|
+
case "gemini":
|
|
29
|
+
content = toGeminiCliMd(agent, baseKnowledgeDir, paths, backendLanguage);
|
|
30
|
+
break;
|
|
31
|
+
case "grok":
|
|
32
|
+
// Grok uses same Gemini-compatible YAML format
|
|
33
|
+
content = toGeminiCliMd(agent, baseKnowledgeDir, paths, backendLanguage);
|
|
34
|
+
break;
|
|
35
|
+
case "claude":
|
|
36
|
+
content = toClaudeCodeMd(agent, baseKnowledgeDir, paths, backendLanguage);
|
|
37
|
+
break;
|
|
38
|
+
case "cursor":
|
|
39
|
+
content = toCursorMdc(agent, baseKnowledgeDir, paths, backendLanguage);
|
|
40
|
+
break;
|
|
41
|
+
case "codex":
|
|
42
|
+
content = toCodexMd(agent, baseKnowledgeDir, paths, backendLanguage);
|
|
43
|
+
break;
|
|
44
|
+
case "antigravity-cli": {
|
|
45
|
+
// Antigravity uses nested folders: agents/{name}/agent.json and agents/{name}/agent.md
|
|
46
|
+
const agentDir = path.join(destAgentsDir, agent.name);
|
|
47
|
+
if (!dryRun)
|
|
48
|
+
fs.mkdirSync(agentDir, { recursive: true });
|
|
49
|
+
content = toAntigravityJson(agent, baseKnowledgeDir, paths, backendLanguage);
|
|
50
|
+
fileName = path.join(agent.name, "agent.json");
|
|
51
|
+
secondaryContent = `# [ATABEY] Agent Atabey ā @${agent.name}\n\n${agent.instructions.identity}\n\n${agent.instructions.mission}`;
|
|
52
|
+
secondaryFileName = path.join(agent.name, "agent.md");
|
|
53
|
+
break;
|
|
54
|
+
}
|
|
55
|
+
default:
|
|
56
|
+
// Fallback to Gemini format
|
|
57
|
+
content = toGeminiCliMd(agent, baseKnowledgeDir, paths, backendLanguage);
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
60
|
+
if (!dryRun) {
|
|
61
|
+
writeTextFile(path.join(destAgentsDir, fileName), content, dryRun);
|
|
62
|
+
if (secondaryContent && secondaryFileName) {
|
|
63
|
+
writeTextFile(path.join(destAgentsDir, secondaryFileName), secondaryContent, dryRun);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
catch (e) {
|
|
69
|
+
console.warn(`[WARN] Failed to scaffold agents for ${adapterId}: ${e}`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { logger } from "../../shared/logger.js";
|
|
4
|
+
import { UI } from "../utils/ui.js";
|
|
5
|
+
import { ADAPTERS, SHIM_FILES } from "./core.js";
|
|
6
|
+
export function resolveAdapter(input) {
|
|
7
|
+
let normalized = (input || "gemini").toLowerCase();
|
|
8
|
+
if (normalized === "antigravity") {
|
|
9
|
+
normalized = "antigravity-cli";
|
|
10
|
+
}
|
|
11
|
+
else if (normalized === "copilot" || normalized === "github") {
|
|
12
|
+
normalized = "codex";
|
|
13
|
+
}
|
|
14
|
+
let config;
|
|
15
|
+
if (normalized in ADAPTERS) {
|
|
16
|
+
config = { ...ADAPTERS[normalized] };
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
UI.warning(`Unknown adapter "${input}". Falling back to gemini.`);
|
|
20
|
+
config = { ...ADAPTERS.gemini };
|
|
21
|
+
}
|
|
22
|
+
return config;
|
|
23
|
+
}
|
|
24
|
+
export function isAdapterShimFile(fileName) {
|
|
25
|
+
return SHIM_FILES.includes(fileName);
|
|
26
|
+
}
|
|
27
|
+
export function remapFrameworkContent(content, frameworkDir, adapterId) {
|
|
28
|
+
let result = content;
|
|
29
|
+
result = result.replace(/\{\{FRAMEWORK_DIR\}\}/g, frameworkDir);
|
|
30
|
+
result = result.replace(/\{\{ADAPTER\}\}/g, adapterId);
|
|
31
|
+
let agentFolder = "agents";
|
|
32
|
+
let knowledgeFolder = "knowledge";
|
|
33
|
+
if (frameworkDir !== ".atabey") {
|
|
34
|
+
if (adapterId === "antigravity-cli") {
|
|
35
|
+
agentFolder = "agents";
|
|
36
|
+
knowledgeFolder = "rules";
|
|
37
|
+
}
|
|
38
|
+
// Note: Grok uses the same directory structure as Gemini (".grok/agents").
|
|
39
|
+
// No override needed ā default agentFolder = "agents" is correct.
|
|
40
|
+
}
|
|
41
|
+
const frameworkPattern = ".atabey/";
|
|
42
|
+
result = result.replace(new RegExp(frameworkPattern + "agents/", "g"), `${frameworkDir}/${agentFolder}/`);
|
|
43
|
+
result = result.replace(new RegExp(frameworkPattern + "knowledge/", "g"), `${frameworkDir}/${knowledgeFolder}/`);
|
|
44
|
+
result = result.replace(/\.atabey\//g, `${frameworkDir}/`);
|
|
45
|
+
result = result.replace(/`\.atabey`/g, `\`${frameworkDir}\``);
|
|
46
|
+
result = result.replace(/\.atabey(?![\w/-])/g, frameworkDir);
|
|
47
|
+
let backend = "apps/backend";
|
|
48
|
+
let frontend = "apps/web";
|
|
49
|
+
let docs = "docs";
|
|
50
|
+
let tests = "tests";
|
|
51
|
+
try {
|
|
52
|
+
const configPath = path.join(process.cwd(), frameworkDir, "config.json");
|
|
53
|
+
if (fs.existsSync(configPath)) {
|
|
54
|
+
const config = JSON.parse(fs.readFileSync(configPath, "utf8"));
|
|
55
|
+
if (config.paths) {
|
|
56
|
+
if (config.paths.backend)
|
|
57
|
+
backend = config.paths.backend;
|
|
58
|
+
if (config.paths.frontend)
|
|
59
|
+
frontend = config.paths.frontend;
|
|
60
|
+
if (config.paths.docs)
|
|
61
|
+
docs = config.paths.docs;
|
|
62
|
+
if (config.paths.tests)
|
|
63
|
+
tests = config.paths.tests;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
catch (err) {
|
|
68
|
+
logger.debug("Failed to read config.json in remapFrameworkContent", err);
|
|
69
|
+
}
|
|
70
|
+
result = result.replace(/\{\{BACKEND_DIR\}\}/g, backend);
|
|
71
|
+
result = result.replace(/\{\{FRONTEND_DIR\}\}/g, frontend);
|
|
72
|
+
result = result.replace(/\{\{DOCS_DIR\}\}/g, docs);
|
|
73
|
+
result = result.replace(/\{\{TESTS_DIR\}\}/g, tests);
|
|
74
|
+
return result;
|
|
75
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { getFrameworkDir } from "../utils/memory.js";
|
|
4
|
+
import { UI } from "../utils/ui.js";
|
|
5
|
+
import { writeTextFile, appendFile } from "../utils/fs.js";
|
|
6
|
+
import { ValidationError } from "../../shared/errors.js";
|
|
7
|
+
import { HermesMessageSchema } from "./orchestrate.js";
|
|
8
|
+
export async function approveCommand(traceId) {
|
|
9
|
+
const frameworkDir = getFrameworkDir();
|
|
10
|
+
const messagesDir = path.join(frameworkDir, "messages");
|
|
11
|
+
if (!fs.existsSync(messagesDir)) {
|
|
12
|
+
throw new ValidationError("No messages directory found.", null, "Ensure the framework is initialized and the Hermes orchestrator has been run at least once.");
|
|
13
|
+
}
|
|
14
|
+
const files = fs.readdirSync(messagesDir).filter((f) => f.endsWith(".json"));
|
|
15
|
+
let found = false;
|
|
16
|
+
for (const file of files) {
|
|
17
|
+
const filePath = path.join(messagesDir, file);
|
|
18
|
+
try {
|
|
19
|
+
const content = fs.readFileSync(filePath, "utf8").trim();
|
|
20
|
+
if (!content)
|
|
21
|
+
continue;
|
|
22
|
+
const lines = content.split("\n");
|
|
23
|
+
let updated = false;
|
|
24
|
+
const newLines = lines.map((line) => {
|
|
25
|
+
if (!line.trim())
|
|
26
|
+
return line;
|
|
27
|
+
try {
|
|
28
|
+
const parsed = JSON.parse(line);
|
|
29
|
+
const msg = HermesMessageSchema.parse(parsed);
|
|
30
|
+
if (msg.traceId === traceId && msg.status === "PENDING" && (msg.category === "ALERT" || msg.category === "ACTION")) {
|
|
31
|
+
msg.status = "APPROVED";
|
|
32
|
+
updated = true;
|
|
33
|
+
found = true;
|
|
34
|
+
UI.success(`Approved message from ${msg.from} to ${msg.to} (Action: ${msg.action || "None"})`);
|
|
35
|
+
}
|
|
36
|
+
return JSON.stringify(msg);
|
|
37
|
+
}
|
|
38
|
+
catch (e) {
|
|
39
|
+
UI.error(`Skipping invalid Hermes message during approval: ${e.message}`);
|
|
40
|
+
return line;
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
if (updated) {
|
|
44
|
+
writeTextFile(filePath, newLines.join("\n") + "\n");
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
catch (e) {
|
|
48
|
+
UI.error(`Error reading or updating message file ${file}: ${e.message}`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (found) {
|
|
52
|
+
// Log user approval to audit log
|
|
53
|
+
const auditPath = path.join(frameworkDir, "observability/audit_log.md");
|
|
54
|
+
if (fs.existsSync(auditPath)) {
|
|
55
|
+
const logEntry = "\n- **[" + new Date().toISOString() + "]** USER -> @manager | APPROVED | Trace: " + traceId;
|
|
56
|
+
appendFile(auditPath, logEntry);
|
|
57
|
+
}
|
|
58
|
+
UI.success("Successfully approved Trace: " + traceId);
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
throw new ValidationError(`No pending approval request found for Trace ID: ${traceId}`, null, "Run 'npx atabey status' to see active traces and ensure the ID is correct and pending approval.");
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { execSync } from "child_process";
|
|
4
|
+
import { getFrameworkDir, getMemoryPath, getConfiguredPaths, isFrameworkDevelopmentRepo, readState } from "../utils/memory.js";
|
|
5
|
+
import { getPackageVersion, getValidatorPath } from "../utils/pkg.js";
|
|
6
|
+
import { UI } from "../utils/ui.js";
|
|
7
|
+
import { logger } from "../../shared/logger.js";
|
|
8
|
+
import { scanProjectCompliance } from "../utils/compliance.js";
|
|
9
|
+
import { ALL_AGENTS } from "../../modules/agents/definitions.js";
|
|
10
|
+
import { detectActiveAgentLayouts, findAgentInstruction } from "../adapters/paths.js";
|
|
11
|
+
import { verifyApiContractCommand } from "./contract.js";
|
|
12
|
+
export async function checkCommand() {
|
|
13
|
+
UI.intent("Agent Atabey Health Check", `Checking system health and discipline rules (v${getPackageVersion()})...`);
|
|
14
|
+
let issues = 0;
|
|
15
|
+
const state = readState();
|
|
16
|
+
if (!state) {
|
|
17
|
+
UI.error("Memory state not found. Run 'init' first.");
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
const frameworkDir = getFrameworkDir();
|
|
21
|
+
const memoryPath = getMemoryPath();
|
|
22
|
+
const pathsMap = getConfiguredPaths();
|
|
23
|
+
UI.success(`Using framework dir: ${frameworkDir}`);
|
|
24
|
+
// --- Contract Gate (Phase 2+ Discipline) ---
|
|
25
|
+
if (["PHASE_2", "PHASE_3", "PHASE_4"].includes(state.phase)) {
|
|
26
|
+
console.warn("\nš Validating API Contracts (Phase 2+ Required)...");
|
|
27
|
+
try {
|
|
28
|
+
const contractOk = await verifyApiContractCommand({ silent: true });
|
|
29
|
+
if (!contractOk) {
|
|
30
|
+
UI.error("Contract verification FAILED! You cannot be in Phase 2+ with unverified contracts.");
|
|
31
|
+
issues++;
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
UI.success("API Contracts verified and sealed.");
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
UI.error("Error during contract verification.");
|
|
39
|
+
issues++;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
let knowledgeDir = "knowledge";
|
|
43
|
+
if (frameworkDir === ".github")
|
|
44
|
+
knowledgeDir = "instructions";
|
|
45
|
+
const constitutionPath = fs.existsSync(path.join(process.cwd(), "ATABEY.md")) ? "ATABEY.md" : path.join(frameworkDir, "ATABEY.md");
|
|
46
|
+
const rootPandaPath = path.join(process.cwd(), "panda.config.ts");
|
|
47
|
+
const appPandaPath = path.join(pathsMap.frontend, "panda.config.ts");
|
|
48
|
+
if (fs.existsSync(rootPandaPath)) {
|
|
49
|
+
UI.error(`Panda CSS config must NOT be at the root directory! Move it to '${pathsMap.frontend}/panda.config.ts'.`);
|
|
50
|
+
issues++;
|
|
51
|
+
}
|
|
52
|
+
const isFrameworkDevelopment = isFrameworkDevelopmentRepo();
|
|
53
|
+
const checks = [
|
|
54
|
+
{ name: "Constitution (ATABEY.md)", path: constitutionPath },
|
|
55
|
+
{ name: "Memory (PROJECT_MEMORY.md)", path: path.relative(process.cwd(), memoryPath) },
|
|
56
|
+
{ name: "Command Map (cli-commands.json)", path: path.join(frameworkDir, "cli-commands.json") },
|
|
57
|
+
{ name: "Framework Config (config.json)", path: path.join(frameworkDir, "config.json") },
|
|
58
|
+
{ name: "Agent Status (STATUS.md)", path: path.join(frameworkDir, "STATUS.md") },
|
|
59
|
+
{ name: "MCP Config (mcp.json)", path: "mcp.json" },
|
|
60
|
+
{ name: "ESLint Config (eslint.config.js)", path: "eslint.config.js", optional: !isFrameworkDevelopment },
|
|
61
|
+
{ name: "ESLint Standards", path: path.join(frameworkDir, `${knowledgeDir}/eslint-standards.md`) },
|
|
62
|
+
{ name: "CRUD Governance Standards", path: path.join(frameworkDir, `${knowledgeDir}/crud-governance.md`) },
|
|
63
|
+
{ name: "Architecture Standards", path: path.join(frameworkDir, `${knowledgeDir}/architecture-standards.md`) },
|
|
64
|
+
{ name: "Frontend Standards", path: path.join(frameworkDir, `${knowledgeDir}/frontend-standards.md`) },
|
|
65
|
+
{ name: "Vite Standards", path: path.join(frameworkDir, `${knowledgeDir}/vite-standards.md`), optional: true },
|
|
66
|
+
{ name: "Next.js Standards", path: path.join(frameworkDir, `${knowledgeDir}/nextjs-standards.md`), optional: true },
|
|
67
|
+
{ name: "Tailwind Standards", path: path.join(frameworkDir, `${knowledgeDir}/tailwind-standards.md`), optional: true },
|
|
68
|
+
{ name: "Mobile Standards", path: path.join(frameworkDir, `${knowledgeDir}/mobile-standards.md`) },
|
|
69
|
+
{ name: "Security Standards", path: path.join(frameworkDir, `${knowledgeDir}/security-standards.md`) },
|
|
70
|
+
{ name: "Quality & Discipline Standards", path: path.join(frameworkDir, `${knowledgeDir}/quality-standards.md`) },
|
|
71
|
+
{ name: "Logging & Secrets Standards", path: path.join(frameworkDir, `${knowledgeDir}/logging-and-secrets.md`) },
|
|
72
|
+
{ name: "Testing Standards", path: path.join(frameworkDir, `${knowledgeDir}/testing-standards.md`) },
|
|
73
|
+
{ name: "i18n Standards", path: path.join(frameworkDir, `${knowledgeDir}/i18n-standards.md`) },
|
|
74
|
+
{ name: ".env.example", path: ".env.example" },
|
|
75
|
+
...(isFrameworkDevelopment ? [{ name: "MCP Server", path: "framework-mcp/package.json" }] : []),
|
|
76
|
+
{ name: "Panda CSS Config", path: appPandaPath, optional: true },
|
|
77
|
+
];
|
|
78
|
+
for (const check of checks) {
|
|
79
|
+
const fullPath = path.isAbsolute(check.path) ? check.path : path.join(process.cwd(), check.path);
|
|
80
|
+
if (fs.existsSync(fullPath)) {
|
|
81
|
+
UI.success(`${check.name} found.`);
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
if (check.optional) {
|
|
85
|
+
UI.warning(`${check.name} MISSING! (${check.path}) [Optional]`);
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
UI.error(`${check.name} MISSING! (${check.path})`);
|
|
89
|
+
issues++;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
// Agent Army Check
|
|
94
|
+
console.warn("\n[SECURITY] Running Agent Army Compliance...");
|
|
95
|
+
try {
|
|
96
|
+
const validatorScript = getValidatorPath();
|
|
97
|
+
execSync(`node "${validatorScript}"`, { stdio: "pipe" });
|
|
98
|
+
UI.success("Agent Army AL validation PASSED.");
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
const err = error;
|
|
102
|
+
UI.error(`Agent Army AL validation FAILED: ${err.message}`);
|
|
103
|
+
if (err.stderr)
|
|
104
|
+
console.error(err.stderr.toString());
|
|
105
|
+
issues++;
|
|
106
|
+
}
|
|
107
|
+
// Agent Documentation Check (Live Integrity)
|
|
108
|
+
console.warn("\nš Checking Agent Integrity (Instructions)...");
|
|
109
|
+
const projectRoot = process.cwd();
|
|
110
|
+
const activeLayouts = detectActiveAgentLayouts(projectRoot);
|
|
111
|
+
if (activeLayouts.length > 0) {
|
|
112
|
+
UI.success(`Active agent layout(s): ${activeLayouts.join(", ")}`);
|
|
113
|
+
ALL_AGENTS.forEach((agent) => {
|
|
114
|
+
const found = findAgentInstruction(projectRoot, agent.name);
|
|
115
|
+
if (found) {
|
|
116
|
+
UI.success(`Instructions for @${agent.name} found at ${found}`);
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
UI.error(`Instructions for @${agent.name} MISSING! Run 'atabey init' to scaffold.`);
|
|
120
|
+
issues++;
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
UI.warning("No active agent instruction directory detected. Run 'atabey init [adapter]' first.");
|
|
126
|
+
issues++;
|
|
127
|
+
}
|
|
128
|
+
// Code Quality - Using the new Compliance Scanner
|
|
129
|
+
console.warn("\nāļø Checking Discipline (Code Quality)...");
|
|
130
|
+
const complianceIssues = scanProjectCompliance();
|
|
131
|
+
if (complianceIssues.length > 0) {
|
|
132
|
+
complianceIssues.forEach(issue => {
|
|
133
|
+
UI.error(`${issue.rule} in ${issue.file}:${issue.line}`);
|
|
134
|
+
});
|
|
135
|
+
issues += complianceIssues.length;
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
UI.success("No compliance issues detected.");
|
|
139
|
+
}
|
|
140
|
+
const rootTestFiles = checkRootTestFiles();
|
|
141
|
+
if (rootTestFiles.length > 0) {
|
|
142
|
+
UI.warning(`Test files found in the root directory: ${rootTestFiles.join(", ")}. It is recommended to place all test files under the 'tests/' folder or application-specific directories.`);
|
|
143
|
+
}
|
|
144
|
+
try {
|
|
145
|
+
UI.intent("Type Check", "Running 'npx tsc --noEmit' (this may take a few seconds)...");
|
|
146
|
+
execSync("npx tsc --noEmit", { stdio: "pipe" });
|
|
147
|
+
UI.success("TypeScript type check PASSED.");
|
|
148
|
+
}
|
|
149
|
+
catch (err) {
|
|
150
|
+
UI.warning("TypeScript type check FAILED or 'tsc' not found. This is a non-blocking warning for lightweight checks.");
|
|
151
|
+
logger.debug("npx tsc --noEmit check failed", err);
|
|
152
|
+
}
|
|
153
|
+
if (issues === 0) {
|
|
154
|
+
UI.success("\n[START] All systems green! Agent Atabey is ready.");
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
UI.error(`\n[WARN] Found ${issues} issues. Please fix them.`);
|
|
158
|
+
process.exit(1);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
function checkRootTestFiles() {
|
|
162
|
+
const rootDir = process.cwd();
|
|
163
|
+
if (!fs.existsSync(rootDir))
|
|
164
|
+
return [];
|
|
165
|
+
const files = fs.readdirSync(rootDir);
|
|
166
|
+
const testFiles = [];
|
|
167
|
+
for (const file of files) {
|
|
168
|
+
const fullPath = path.join(rootDir, file);
|
|
169
|
+
try {
|
|
170
|
+
if (fs.statSync(fullPath).isFile()) {
|
|
171
|
+
if (file.includes(".test.") || file.includes(".spec.")) {
|
|
172
|
+
testFiles.push(file);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
catch (err) {
|
|
177
|
+
logger.debug(`Failed to stat file ${fullPath} in checkRootTestFiles`, err);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return testFiles;
|
|
181
|
+
}
|