agent-enderun 0.7.1 → 0.7.5
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 +47 -0
- package/.enderun/PROJECT_MEMORY.md +139 -0
- package/.enderun/STATUS.md +62 -0
- package/.enderun/agents/agent_army_schema.json +85 -0
- package/.enderun/agents/analyst/agent.json +23 -0
- package/.enderun/agents/analyst/prompt.md +225 -0
- package/.enderun/agents/backend/agent.json +24 -0
- package/.enderun/agents/backend/prompt.md +331 -0
- package/.enderun/agents/devops/agent.json +61 -0
- package/.enderun/agents/devops/prompt.md +127 -0
- package/.enderun/agents/explorer/agent.json +22 -0
- package/.enderun/agents/explorer/prompt.md +115 -0
- package/.enderun/agents/frontend/agent.json +24 -0
- package/.enderun/agents/frontend/prompt.md +313 -0
- package/.enderun/agents/git/agent.json +22 -0
- package/.enderun/agents/git/prompt.md +99 -0
- package/.enderun/agents/manager/agent.json +48 -0
- package/.enderun/agents/manager/prompt.md +231 -0
- package/.enderun/agents/mobile/agent.json +21 -0
- package/.enderun/agents/mobile/prompt.md +91 -0
- package/.enderun/agents/native/agent.json +21 -0
- package/.enderun/agents/native/prompt.md +96 -0
- package/.enderun/agents/orchestrator/agent.json +53 -0
- package/.enderun/agents/orchestrator/prompt.md +124 -0
- package/.enderun/agents/qa/agent.json +57 -0
- package/.enderun/agents/qa/prompt.md +69 -0
- package/.enderun/agents/schema/agent-lifecycle-schema.json +65 -0
- package/.enderun/agents/security/agent.json +54 -0
- package/.enderun/agents/security/prompt.md +154 -0
- package/.enderun/gemini.md +19 -0
- package/.enderun/knowledge/corporate-governance/analyst-contract-integrity-guide.md +92 -0
- package/.enderun/knowledge/corporate-governance/audit-logging-standard.md +59 -0
- package/.enderun/knowledge/corporate-governance/backend-high-risk-endpoint-guide.md +125 -0
- package/.enderun/knowledge/corporate-governance/branded-types-law.md +77 -0
- package/.enderun/knowledge/corporate-governance/contract-drift-detection-simulation.md +92 -0
- package/.enderun/knowledge/corporate-governance/corporate-governance-playbook.md +89 -0
- package/.enderun/knowledge/corporate-governance/corporate-project-kickoff-checklist.md +56 -0
- package/.enderun/knowledge/corporate-governance/corporate-project-kickoff-simulation.md +144 -0
- package/.enderun/knowledge/corporate-governance/corporate-project-scaffolding-sop.md +103 -0
- package/.enderun/knowledge/corporate-governance/domain-error-handling-standard.md +75 -0
- package/.enderun/knowledge/corporate-governance/frontend-high-risk-modal-guide.md +211 -0
- package/.enderun/knowledge/corporate-governance/governance-baseline-briefing-template.md +54 -0
- package/.enderun/knowledge/corporate-governance/high-risk-action-approval-flow-simulation.md +167 -0
- package/.enderun/knowledge/corporate-governance/high-risk-actions-managerapproval.md +76 -0
- package/.enderun/knowledge/corporate-governance/high-risk-security-modal-hermes-flow.md +49 -0
- package/.enderun/knowledge/corporate-governance/manager-first-30-days-guide.md +112 -0
- package/.enderun/knowledge/corporate-governance/manager-first-three-briefings.md +79 -0
- package/.enderun/knowledge/deployment_checklist.md +7 -0
- package/{.antigravitycli → .enderun}/knowledge/framework_vs_user_project_boundary.md +3 -3
- package/{.antigravitycli → .enderun}/knowledge/frontend_professionalization_guidelines.md +17 -20
- package/{.antigravitycli → .enderun}/knowledge/hermes_live_test_guidelines.md +9 -9
- package/{.antigravitycli → .enderun}/knowledge/hermes_protocol.md +2 -2
- package/.enderun/knowledge/kentim_constitution.md +34 -0
- package/{.antigravitycli → .enderun}/knowledge/manager_authority_audit_enforcement.md +11 -11
- package/{.antigravitycli → .enderun}/knowledge/project_scaffold_guidelines.md +8 -8
- package/{.antigravitycli → .enderun}/knowledge/reference_application_guidelines.md +7 -7
- package/.enderun/logs/analyst.json +1 -0
- package/.enderun/logs/backend.json +1 -0
- package/.enderun/logs/devops.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 +20 -0
- package/.enderun/logs/mobile.json +1 -0
- package/.enderun/logs/native.json +1 -0
- package/.enderun/logs/orchestrator.json +1 -0
- package/.enderun/logs/qa.json +1 -0
- package/.enderun/logs/security.json +1 -0
- package/.enderun/memory-graph/agent-contexts/analyst.json +1 -0
- package/.enderun/memory-graph/agent-contexts/backend.json +1 -0
- package/.enderun/memory-graph/agent-contexts/devops.json +1 -0
- package/.enderun/memory-graph/agent-contexts/explorer.json +1 -0
- package/.enderun/memory-graph/agent-contexts/frontend.json +1 -0
- package/.enderun/memory-graph/agent-contexts/git.json +1 -0
- package/.enderun/memory-graph/agent-contexts/manager.json +1 -0
- package/.enderun/memory-graph/agent-contexts/mobile.json +1 -0
- package/.enderun/memory-graph/agent-contexts/native.json +1 -0
- package/.enderun/memory-graph/agent-contexts/orchestrator.json +1 -0
- package/.enderun/memory-graph/agent-contexts/qa.json +1 -0
- package/.enderun/memory-graph/agent-contexts/security.json +1 -0
- package/.enderun/memory-graph/graph.json +26 -0
- package/.enderun/memory-graph/shared-facts.json +52 -0
- package/.enderun/monitoring/.gitkeep +0 -0
- package/.enderun/queue/README.md +36 -0
- package/ENDERUN.md +4 -4
- package/README.md +151 -89
- package/bin/cli.js +13 -2138
- package/bin/hermes-sandbox.js +0 -0
- package/bin/validate-agent-army.js +3 -3
- package/docs/architecture/approval-flows.md +2 -37
- package/docs/backend/error-handling.md +2 -51
- package/docs/frontend/component-patterns.md +2 -47
- package/docs/getting-started.md +7 -15
- package/docs/roadmap.md +2 -2
- package/framework-mcp/dist/index.js +0 -0
- package/framework-mcp/dist/schemas.js +3 -3
- package/framework-mcp/dist/tools/framework.js +17 -10
- package/framework-mcp/dist/tools/governance.js +696 -0
- package/framework-mcp/dist/tools/index.js +14 -12
- package/framework-mcp/dist/tools/memory.js +106 -0
- package/framework-mcp/dist/tools/monitoring.js +294 -0
- package/framework-mcp/dist/tools/orchestration.js +368 -0
- package/framework-mcp/dist/tools/pipeline.js +267 -0
- package/framework-mcp/dist/utils.js +25 -3
- package/framework-mcp/package.json +3 -3
- package/framework-mcp/src/schemas.ts +3 -3
- package/framework-mcp/src/tools/framework.ts +18 -10
- package/framework-mcp/src/tools/governance.ts +891 -0
- package/framework-mcp/src/tools/index.ts +14 -12
- package/framework-mcp/src/tools/memory.ts +103 -0
- package/framework-mcp/src/tools/monitoring.ts +351 -0
- package/framework-mcp/src/tools/orchestration.ts +439 -0
- package/framework-mcp/src/tools/pipeline.ts +353 -0
- package/framework-mcp/src/utils.ts +24 -3
- package/framework-mcp/tsconfig.json +2 -1
- package/gemini.md +19 -0
- package/package.json +14 -20
- package/.antigravitycli/BRAIN_DASHBOARD.md +0 -43
- package/.antigravitycli/ENDERUN.md +0 -253
- package/.antigravitycli/PROJECT_MEMORY.md +0 -78
- package/.antigravitycli/STATUS.md +0 -21
- package/.antigravitycli/agents/agent_army_schema.json +0 -79
- package/.antigravitycli/agents/analyst/agent.json +0 -55
- package/.antigravitycli/agents/backend/agent.json +0 -58
- package/.antigravitycli/agents/explorer/agent.json +0 -50
- package/.antigravitycli/agents/frontend/agent.json +0 -56
- package/.antigravitycli/agents/git/agent.json +0 -53
- package/.antigravitycli/agents/manager/agent.json +0 -82
- package/.antigravitycli/agents/mobile/agent.json +0 -52
- package/.antigravitycli/agents/native/agent.json +0 -56
- package/.antigravitycli/assets/manager.png +0 -0
- package/.antigravitycli/blueprints/README.md +0 -82
- package/.antigravitycli/blueprints/backend/errors/config/meta.json +0 -16
- package/.antigravitycli/blueprints/backend/errors/domain-error.ts +0 -64
- package/.antigravitycli/knowledge/README.md +0 -22
- package/.antigravitycli/knowledge/database_governance_guidelines.md +0 -118
- package/.antigravitycli/knowledge/deployment_checklist.md +0 -133
- package/.antigravitycli/knowledge/documentation_ownership.md +0 -122
- package/.antigravitycli/knowledge/documentation_ownership_status.md +0 -122
- package/.antigravitycli/knowledge/enterprise_capabilities_reference.md +0 -149
- package/.antigravitycli/knowledge/enterprise_frontend_adaptation.md +0 -232
- package/.antigravitycli/knowledge/enterprise_project_adaptation.md +0 -168
- package/.antigravitycli/knowledge/frontend_real_battle_test_protocol.md +0 -162
- package/antigravity.md +0 -15
- package/docs/architecture/decisions/README.md +0 -31
- package/docs/architecture/notification-strategy.md +0 -38
- package/docs/backend/audit-logging.md +0 -34
- package/docs/frontend/forms.md +0 -40
- package/docs/frontend/notifications.md +0 -37
- package/framework-mcp/dist/tools/academy.js +0 -182
- package/framework-mcp/dist/tools/database.js +0 -57
- package/framework-mcp/dist/tools/repository.js +0 -101
- package/framework-mcp/dist/tools/scaffold.js +0 -132
- package/framework-mcp/src/tools/academy.ts +0 -180
- package/framework-mcp/src/tools/database.ts +0 -54
- package/framework-mcp/src/tools/repository.ts +0 -101
- package/framework-mcp/src/tools/scaffold.ts +0 -150
- /package/{.antigravitycli/messages → .enderun/benchmarks}/.gitkeep +0 -0
- /package/{.antigravitycli → .enderun}/cli-commands.json +0 -0
- /package/{.antigravitycli → .enderun}/config.json +0 -0
- /package/{.antigravitycli → .enderun}/knowledge/api_design_rules.md +0 -0
- /package/{.antigravitycli → .enderun}/knowledge/async_error_handling.md +0 -0
- /package/{.antigravitycli → .enderun}/knowledge/blueprint_driven_construction.md +0 -0
- /package/{.antigravitycli → .enderun}/knowledge/branded_types_pattern.md +0 -0
- /package/{.antigravitycli → .enderun}/knowledge/code_review_checklist.md +0 -0
- /package/{.antigravitycli → .enderun}/knowledge/contract_versioning.md +0 -0
- /package/{.antigravitycli → .enderun}/knowledge/database_migration.md +0 -0
- /package/{.antigravitycli → .enderun}/knowledge/git_commit_strategy.md +0 -0
- /package/{.antigravitycli → .enderun}/knowledge/legacy_onboarding.md +0 -0
- /package/{.antigravitycli → .enderun}/knowledge/monitoring_setup.md +0 -0
- /package/{.antigravitycli → .enderun}/knowledge/performance_guidelines.md +0 -0
- /package/{.antigravitycli → .enderun}/knowledge/repository_patterns.md +0 -0
- /package/{.antigravitycli → .enderun}/knowledge/responsive_design_standards.md +0 -0
- /package/{.antigravitycli → .enderun}/knowledge/security_scanning.md +0 -0
- /package/{.antigravitycli → .enderun}/knowledge/testing_standards.md +0 -0
- /package/{.antigravitycli → .enderun}/knowledge/troubleshooting_guide.md +0 -0
- /package/{.antigravitycli → .enderun}/knowledge/zero_ui_library_policy.md +0 -0
|
@@ -3,26 +3,27 @@ import { frameworkTools, frameworkHandlers } from "./framework.js";
|
|
|
3
3
|
import { securityTools, securityHandlers } from "./security.js";
|
|
4
4
|
import { memoryTools, memoryHandlers } from "./memory.js";
|
|
5
5
|
import { contractTools, contractHandlers } from "./contract.js";
|
|
6
|
-
import { academyTools, academyHandlers } from "./academy.js";
|
|
7
6
|
import { messageTools, messageHandlers } from "./messages.js";
|
|
8
7
|
import { gitTools, gitHandlers } from "./git.js";
|
|
9
|
-
import { databaseTools, databaseHandlers } from "./database.js";
|
|
10
8
|
import { knowledgeTools, knowledgeHandlers } from "./knowledge.js";
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
9
|
+
import { governanceTools, governanceHandlers } from "./governance.js";
|
|
10
|
+
import { orchestrationTools, orchestrationHandlers } from "./orchestration.js";
|
|
11
|
+
import { monitoringTools, monitoringHandlers } from "./monitoring.js";
|
|
12
|
+
import { pipelineTools, pipelineHandlers } from "./pipeline.js";
|
|
13
13
|
export const allTools = [
|
|
14
14
|
...codebaseTools,
|
|
15
15
|
...frameworkTools,
|
|
16
16
|
...securityTools,
|
|
17
17
|
...memoryTools,
|
|
18
18
|
...contractTools,
|
|
19
|
-
...academyTools,
|
|
20
19
|
...messageTools,
|
|
21
20
|
...gitTools,
|
|
22
|
-
...databaseTools,
|
|
23
21
|
...knowledgeTools,
|
|
24
|
-
...
|
|
25
|
-
|
|
22
|
+
...governanceTools,
|
|
23
|
+
// v1.0 Army Core
|
|
24
|
+
...orchestrationTools,
|
|
25
|
+
...monitoringTools,
|
|
26
|
+
...pipelineTools,
|
|
26
27
|
];
|
|
27
28
|
export const allHandlers = {
|
|
28
29
|
...codebaseHandlers,
|
|
@@ -30,13 +31,14 @@ export const allHandlers = {
|
|
|
30
31
|
...securityHandlers,
|
|
31
32
|
...memoryHandlers,
|
|
32
33
|
...contractHandlers,
|
|
33
|
-
...academyHandlers,
|
|
34
34
|
...messageHandlers,
|
|
35
35
|
...gitHandlers,
|
|
36
|
-
...databaseHandlers,
|
|
37
36
|
...knowledgeHandlers,
|
|
38
|
-
...
|
|
39
|
-
|
|
37
|
+
...governanceHandlers,
|
|
38
|
+
// v1.0 Army Core
|
|
39
|
+
...orchestrationHandlers,
|
|
40
|
+
...monitoringHandlers,
|
|
41
|
+
...pipelineHandlers,
|
|
40
42
|
};
|
|
41
43
|
// Add compatibility aliases
|
|
42
44
|
allHandlers.codebase_search = allHandlers.search_codebase;
|
|
@@ -27,6 +27,45 @@ export const memoryTools = [
|
|
|
27
27
|
description: "Read the entire content of PROJECT_MEMORY.md safely. Use this instead of direct ReadFile tools to ensure framework compatibility.",
|
|
28
28
|
inputSchema: { type: "object", properties: {} },
|
|
29
29
|
},
|
|
30
|
+
{
|
|
31
|
+
name: "get_army_graph",
|
|
32
|
+
description: "Read the current Agent Army interaction graph (memory-graph/graph.json). Useful for @orchestrator and @manager to see relationships and health.",
|
|
33
|
+
inputSchema: { type: "object", properties: {} },
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
name: "get_agent_context",
|
|
37
|
+
description: "Read the private persistent context for a specific agent from memory-graph/agent-contexts/{agent}.json (without the @ prefix).",
|
|
38
|
+
inputSchema: {
|
|
39
|
+
type: "object",
|
|
40
|
+
properties: {
|
|
41
|
+
agent: { type: "string", description: "Agent name without @ (e.g. manager, orchestrator, backend)" }
|
|
42
|
+
},
|
|
43
|
+
required: ["agent"]
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
name: "update_shared_facts",
|
|
48
|
+
description: "Update the shared facts file used by the entire Agent Army (memory-graph/shared-facts.json).",
|
|
49
|
+
inputSchema: {
|
|
50
|
+
type: "object",
|
|
51
|
+
properties: {
|
|
52
|
+
facts: { type: "object", description: "Partial or full facts object to merge into shared-facts.json" }
|
|
53
|
+
},
|
|
54
|
+
required: ["facts"]
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
name: "update_agent_context",
|
|
59
|
+
description: "Update the private context for a specific agent in memory-graph/agent-contexts/.",
|
|
60
|
+
inputSchema: {
|
|
61
|
+
type: "object",
|
|
62
|
+
properties: {
|
|
63
|
+
agent: { type: "string", description: "Agent name without @" },
|
|
64
|
+
context: { type: "object", description: "Data to write/merge for this agent" }
|
|
65
|
+
},
|
|
66
|
+
required: ["agent", "context"]
|
|
67
|
+
},
|
|
68
|
+
},
|
|
30
69
|
];
|
|
31
70
|
export const memoryHandlers = {
|
|
32
71
|
update_project_memory: async (args, projectRoot) => {
|
|
@@ -91,4 +130,71 @@ export const memoryHandlers = {
|
|
|
91
130
|
return { content: [{ type: "text", text: "Failed to read project memory." }] };
|
|
92
131
|
}
|
|
93
132
|
},
|
|
133
|
+
get_army_graph: async (args, projectRoot) => {
|
|
134
|
+
try {
|
|
135
|
+
const frameworkDir = getFrameworkDir(projectRoot);
|
|
136
|
+
const graphPath = path.join(projectRoot, frameworkDir, "memory-graph", "graph.json");
|
|
137
|
+
if (!fs.existsSync(graphPath))
|
|
138
|
+
return { content: [{ type: "text", text: "Army graph not found. Run army initialization first." }] };
|
|
139
|
+
const graph = JSON.parse(fs.readFileSync(graphPath, "utf-8"));
|
|
140
|
+
return { content: [{ type: "text", text: JSON.stringify(graph, null, 2) }] };
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
return { content: [{ type: "text", text: "Failed to read army graph." }] };
|
|
144
|
+
}
|
|
145
|
+
},
|
|
146
|
+
get_agent_context: async (args, projectRoot) => {
|
|
147
|
+
try {
|
|
148
|
+
const { agent } = args;
|
|
149
|
+
if (!agent)
|
|
150
|
+
return { content: [{ type: "text", text: "Agent name required." }] };
|
|
151
|
+
const frameworkDir = getFrameworkDir(projectRoot);
|
|
152
|
+
const contextPath = path.join(projectRoot, frameworkDir, "memory-graph", "agent-contexts", `${agent.replace(/^@/, "")}.json`);
|
|
153
|
+
if (!fs.existsSync(contextPath))
|
|
154
|
+
return { content: [{ type: "text", text: `No private context found for @${agent}.` }] };
|
|
155
|
+
const ctx = JSON.parse(fs.readFileSync(contextPath, "utf-8"));
|
|
156
|
+
return { content: [{ type: "text", text: JSON.stringify(ctx, null, 2) }] };
|
|
157
|
+
}
|
|
158
|
+
catch {
|
|
159
|
+
return { content: [{ type: "text", text: "Failed to read agent context." }] };
|
|
160
|
+
}
|
|
161
|
+
},
|
|
162
|
+
update_shared_facts: async (args, projectRoot) => {
|
|
163
|
+
try {
|
|
164
|
+
const { facts } = args;
|
|
165
|
+
if (!facts)
|
|
166
|
+
return { content: [{ type: "text", text: "facts object required." }] };
|
|
167
|
+
const frameworkDir = getFrameworkDir(projectRoot);
|
|
168
|
+
const factsPath = path.join(projectRoot, frameworkDir, "memory-graph", "shared-facts.json");
|
|
169
|
+
let existing = {};
|
|
170
|
+
if (fs.existsSync(factsPath)) {
|
|
171
|
+
existing = JSON.parse(fs.readFileSync(factsPath, "utf-8"));
|
|
172
|
+
}
|
|
173
|
+
const merged = { ...existing, ...facts, updatedAt: new Date().toISOString() };
|
|
174
|
+
fs.writeFileSync(factsPath, JSON.stringify(merged, null, 2));
|
|
175
|
+
return { content: [{ type: "text", text: "Shared facts updated successfully." }] };
|
|
176
|
+
}
|
|
177
|
+
catch {
|
|
178
|
+
return { content: [{ type: "text", text: "Failed to update shared facts." }] };
|
|
179
|
+
}
|
|
180
|
+
},
|
|
181
|
+
update_agent_context: async (args, projectRoot) => {
|
|
182
|
+
try {
|
|
183
|
+
const { agent, context } = args;
|
|
184
|
+
if (!agent || !context)
|
|
185
|
+
return { content: [{ type: "text", text: "agent and context required." }] };
|
|
186
|
+
const frameworkDir = getFrameworkDir(projectRoot);
|
|
187
|
+
const ctxPath = path.join(projectRoot, frameworkDir, "memory-graph", "agent-contexts", `${agent.replace(/^@/, "")}.json`);
|
|
188
|
+
let existing = {};
|
|
189
|
+
if (fs.existsSync(ctxPath)) {
|
|
190
|
+
existing = JSON.parse(fs.readFileSync(ctxPath, "utf-8"));
|
|
191
|
+
}
|
|
192
|
+
const merged = { ...existing, ...context, updatedAt: new Date().toISOString() };
|
|
193
|
+
fs.writeFileSync(ctxPath, JSON.stringify(merged, null, 2));
|
|
194
|
+
return { content: [{ type: "text", text: `Context for @${agent} updated successfully.` }] };
|
|
195
|
+
}
|
|
196
|
+
catch {
|
|
197
|
+
return { content: [{ type: "text", text: "Failed to update agent context." }] };
|
|
198
|
+
}
|
|
199
|
+
},
|
|
94
200
|
};
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
import { promises as fs } from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { getFrameworkDir } from "../utils.js";
|
|
4
|
+
// ─── Tool Definitions ─────────────────────────────────────────────────────────
|
|
5
|
+
export const monitoringTools = [
|
|
6
|
+
{
|
|
7
|
+
name: "get_army_health_dashboard",
|
|
8
|
+
description: "Returns a comprehensive health dashboard for the entire Agent Enderun Army. Includes agent states, active tasks, health scores, queue depth, and recent blockages. Single call for full army situational awareness.",
|
|
9
|
+
inputSchema: {
|
|
10
|
+
type: "object",
|
|
11
|
+
properties: {
|
|
12
|
+
projectRoot: { type: "string", description: "Root directory of the project" },
|
|
13
|
+
},
|
|
14
|
+
required: [],
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
name: "calculate_agent_performance_score",
|
|
19
|
+
description: "Calculates a dynamic performance score for a specific agent based on their last N actions from the audit log. Returns success rate, average execution time, and blockage frequency.",
|
|
20
|
+
inputSchema: {
|
|
21
|
+
type: "object",
|
|
22
|
+
properties: {
|
|
23
|
+
agentName: { type: "string", description: "Agent identifier (e.g. @backend)" },
|
|
24
|
+
lastN: { type: "number", description: "Number of recent actions to analyze", default: 20 },
|
|
25
|
+
},
|
|
26
|
+
required: ["agentName"],
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
name: "detect_bottleneck_agents",
|
|
31
|
+
description: "Scans all agent logs and STATUS.md to identify agents that are causing delays — either by being BLOCKED, exceeding execution timeout, or having a high blockage frequency. Returns a prioritized list of bottlenecks.",
|
|
32
|
+
inputSchema: {
|
|
33
|
+
type: "object",
|
|
34
|
+
properties: {
|
|
35
|
+
thresholdMinutes: {
|
|
36
|
+
type: "number",
|
|
37
|
+
description: "Minutes after which an EXECUTING agent is considered a bottleneck",
|
|
38
|
+
default: 30,
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
required: [],
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
name: "generate_war_room_report",
|
|
46
|
+
description: "Generates a crisis-mode summary report for @manager. Includes: all BLOCKED/ERROR agents, unresolved dependencies, critical path analysis, and recommended immediate actions. Designed for high-urgency situations.",
|
|
47
|
+
inputSchema: {
|
|
48
|
+
type: "object",
|
|
49
|
+
properties: {
|
|
50
|
+
traceId: { type: "string", description: "Active Trace ID for the crisis" },
|
|
51
|
+
crisisDescription: { type: "string", description: "Brief description of the crisis or incident" },
|
|
52
|
+
},
|
|
53
|
+
required: ["traceId", "crisisDescription"],
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
];
|
|
57
|
+
// ─── Handlers ─────────────────────────────────────────────────────────────────
|
|
58
|
+
export const monitoringHandlers = {
|
|
59
|
+
async get_army_health_dashboard(_args, projectRoot) {
|
|
60
|
+
const results = {
|
|
61
|
+
generatedAt: new Date().toISOString(),
|
|
62
|
+
agents: [],
|
|
63
|
+
queueDepth: { pending: 0, processing: 0, completed: 0, failed: 0 },
|
|
64
|
+
recentBlockages: [],
|
|
65
|
+
recentBroadcasts: [],
|
|
66
|
+
overallHealth: "GREEN",
|
|
67
|
+
};
|
|
68
|
+
// Read STATUS.md
|
|
69
|
+
const frameworkDir = getFrameworkDir(projectRoot);
|
|
70
|
+
const statusPath = path.join(projectRoot, frameworkDir, "STATUS.md");
|
|
71
|
+
try {
|
|
72
|
+
const statusContent = await fs.readFile(statusPath, "utf-8");
|
|
73
|
+
const lines = statusContent
|
|
74
|
+
.split("\n")
|
|
75
|
+
.filter((l) => l.includes("|") && !l.includes("---") && !l.includes("Agent"));
|
|
76
|
+
results.agents = lines
|
|
77
|
+
.map((line) => {
|
|
78
|
+
const cells = line.split("|").map((c) => c.trim()).filter(Boolean);
|
|
79
|
+
return cells.length >= 4
|
|
80
|
+
? {
|
|
81
|
+
agent: cells[0],
|
|
82
|
+
state: cells[1],
|
|
83
|
+
currentTask: cells[2],
|
|
84
|
+
blockedBy: cells[3],
|
|
85
|
+
healthScore: cells[4] ?? "—",
|
|
86
|
+
lastAction: cells[5] ?? "—",
|
|
87
|
+
}
|
|
88
|
+
: null;
|
|
89
|
+
})
|
|
90
|
+
.filter(Boolean);
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
results.agents = [{ error: "STATUS.md not found or unreadable" }];
|
|
94
|
+
}
|
|
95
|
+
// Read queue depths
|
|
96
|
+
const queueBase = path.join(projectRoot, ".enderun", "queue");
|
|
97
|
+
for (const subdir of ["pending", "processing", "completed", "failed"]) {
|
|
98
|
+
try {
|
|
99
|
+
const files = await fs.readdir(path.join(queueBase, subdir));
|
|
100
|
+
results.queueDepth[subdir] = files.filter((f) => f.endsWith(".json")).length;
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
results.queueDepth[subdir] = 0;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
// Read orchestrator log for recent blockages and broadcasts
|
|
107
|
+
const logPath = path.join(projectRoot, ".enderun", "logs", "orchestrator.json");
|
|
108
|
+
try {
|
|
109
|
+
const logContent = await fs.readFile(logPath, "utf-8");
|
|
110
|
+
const log = JSON.parse(logContent);
|
|
111
|
+
results.recentBlockages = (log.blockages ?? []).slice(-5);
|
|
112
|
+
results.recentBroadcasts = (log.broadcasts ?? []).slice(-3);
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
// No log yet
|
|
116
|
+
}
|
|
117
|
+
// Calculate overall health
|
|
118
|
+
const blockedCount = results.agents.filter((a) => a?.state?.includes("BLOCKED") || a?.state?.includes("ERROR")).length;
|
|
119
|
+
if (blockedCount >= 3)
|
|
120
|
+
results.overallHealth = "RED";
|
|
121
|
+
else if (blockedCount >= 1)
|
|
122
|
+
results.overallHealth = "YELLOW";
|
|
123
|
+
else
|
|
124
|
+
results.overallHealth = "GREEN";
|
|
125
|
+
return { content: [{ type: "text", text: JSON.stringify(results, null, 2) }] };
|
|
126
|
+
},
|
|
127
|
+
async calculate_agent_performance_score(args, projectRoot) {
|
|
128
|
+
const { agentName, lastN } = args;
|
|
129
|
+
const n = lastN ?? 20;
|
|
130
|
+
const logName = agentName.replace("@", "") + ".json";
|
|
131
|
+
const logPath = path.join(projectRoot, ".enderun", "logs", logName);
|
|
132
|
+
try {
|
|
133
|
+
const content = await fs.readFile(logPath, "utf-8");
|
|
134
|
+
const log = JSON.parse(content);
|
|
135
|
+
const actions = (log.actions ?? []).slice(-n);
|
|
136
|
+
const total = actions.length;
|
|
137
|
+
const successful = actions.filter((a) => a.status === "SUCCESS" || a.status === "DONE").length;
|
|
138
|
+
const successRate = total > 0 ? ((successful / total) * 100).toFixed(1) + "%" : "N/A";
|
|
139
|
+
const avgDuration = total > 0
|
|
140
|
+
? (actions.reduce((sum, a) => sum + (a.durationMs ?? 0), 0) / total).toFixed(0) + "ms"
|
|
141
|
+
: "N/A";
|
|
142
|
+
return {
|
|
143
|
+
content: [
|
|
144
|
+
{
|
|
145
|
+
type: "text",
|
|
146
|
+
text: JSON.stringify({
|
|
147
|
+
agent: agentName,
|
|
148
|
+
analyzedActions: total,
|
|
149
|
+
successRate,
|
|
150
|
+
averageExecutionTime: avgDuration,
|
|
151
|
+
generatedAt: new Date().toISOString(),
|
|
152
|
+
}, null, 2),
|
|
153
|
+
},
|
|
154
|
+
],
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
catch {
|
|
158
|
+
return {
|
|
159
|
+
content: [
|
|
160
|
+
{
|
|
161
|
+
type: "text",
|
|
162
|
+
text: JSON.stringify({
|
|
163
|
+
agent: agentName,
|
|
164
|
+
error: "No log found or log is empty",
|
|
165
|
+
analyzedActions: 0,
|
|
166
|
+
}),
|
|
167
|
+
},
|
|
168
|
+
],
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
},
|
|
172
|
+
async detect_bottleneck_agents(args, projectRoot) {
|
|
173
|
+
const { thresholdMinutes } = args;
|
|
174
|
+
const threshold = thresholdMinutes ?? 30;
|
|
175
|
+
const statusPath = path.join(projectRoot, ".enderun", "STATUS.md");
|
|
176
|
+
const bottlenecks = [];
|
|
177
|
+
try {
|
|
178
|
+
const content = await fs.readFile(statusPath, "utf-8");
|
|
179
|
+
const lines = content
|
|
180
|
+
.split("\n")
|
|
181
|
+
.filter((l) => l.includes("|") && !l.includes("---") && !l.includes("Agent"));
|
|
182
|
+
for (const line of lines) {
|
|
183
|
+
const cells = line.split("|").map((c) => c.trim()).filter(Boolean);
|
|
184
|
+
if (cells.length < 2)
|
|
185
|
+
continue;
|
|
186
|
+
const [agent, state] = cells;
|
|
187
|
+
if (state.includes("BLOCKED")) {
|
|
188
|
+
bottlenecks.push({ agent, state, reason: "Agent is in BLOCKED state", severity: "CRITICAL" });
|
|
189
|
+
}
|
|
190
|
+
else if (state.includes("ERROR")) {
|
|
191
|
+
bottlenecks.push({ agent, state, reason: "Agent is in ERROR state", severity: "CRITICAL" });
|
|
192
|
+
}
|
|
193
|
+
else if (state.includes("EXECUTING")) {
|
|
194
|
+
bottlenecks.push({
|
|
195
|
+
agent,
|
|
196
|
+
state,
|
|
197
|
+
reason: `Agent has been EXECUTING for more than ${threshold} minutes (verify manually)`,
|
|
198
|
+
severity: "HIGH",
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
catch {
|
|
204
|
+
return {
|
|
205
|
+
content: [
|
|
206
|
+
{
|
|
207
|
+
type: "text",
|
|
208
|
+
text: JSON.stringify({ error: "Could not read STATUS.md" }),
|
|
209
|
+
},
|
|
210
|
+
],
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
return {
|
|
214
|
+
content: [
|
|
215
|
+
{
|
|
216
|
+
type: "text",
|
|
217
|
+
text: JSON.stringify({
|
|
218
|
+
bottlenecks,
|
|
219
|
+
total: bottlenecks.length,
|
|
220
|
+
analysisThresholdMinutes: threshold,
|
|
221
|
+
generatedAt: new Date().toISOString(),
|
|
222
|
+
}, null, 2),
|
|
223
|
+
},
|
|
224
|
+
],
|
|
225
|
+
};
|
|
226
|
+
},
|
|
227
|
+
async generate_war_room_report(args, projectRoot) {
|
|
228
|
+
const { traceId, crisisDescription } = args;
|
|
229
|
+
// Gather all data for the war room report
|
|
230
|
+
const report = {
|
|
231
|
+
warRoomReport: true,
|
|
232
|
+
traceId,
|
|
233
|
+
crisisDescription,
|
|
234
|
+
generatedAt: new Date().toISOString(),
|
|
235
|
+
agentStatuses: [],
|
|
236
|
+
queueSnapshot: {},
|
|
237
|
+
recentBlockages: [],
|
|
238
|
+
immediateActions: [],
|
|
239
|
+
};
|
|
240
|
+
// Agent statuses
|
|
241
|
+
const frameworkDir = getFrameworkDir(projectRoot);
|
|
242
|
+
const statusPath = path.join(projectRoot, frameworkDir, "STATUS.md");
|
|
243
|
+
try {
|
|
244
|
+
const content = await fs.readFile(statusPath, "utf-8");
|
|
245
|
+
const lines = content
|
|
246
|
+
.split("\n")
|
|
247
|
+
.filter((l) => l.includes("|") && !l.includes("---") && !l.includes("Agent"));
|
|
248
|
+
report.agentStatuses = lines
|
|
249
|
+
.map((l) => {
|
|
250
|
+
const cells = l.split("|").map((c) => c.trim()).filter(Boolean);
|
|
251
|
+
return cells.length >= 2 ? { agent: cells[0], state: cells[1] } : null;
|
|
252
|
+
})
|
|
253
|
+
.filter(Boolean);
|
|
254
|
+
}
|
|
255
|
+
catch {
|
|
256
|
+
report.agentStatuses = [];
|
|
257
|
+
}
|
|
258
|
+
// Queue snapshot
|
|
259
|
+
const queueBase = path.join(projectRoot, ".enderun", "queue");
|
|
260
|
+
const snapshot = {};
|
|
261
|
+
for (const dir of ["pending", "processing", "completed", "failed"]) {
|
|
262
|
+
try {
|
|
263
|
+
const files = await fs.readdir(path.join(queueBase, dir));
|
|
264
|
+
snapshot[dir] = files.length;
|
|
265
|
+
}
|
|
266
|
+
catch {
|
|
267
|
+
snapshot[dir] = 0;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
report.queueSnapshot = snapshot;
|
|
271
|
+
// Recent blockages
|
|
272
|
+
const logPath = path.join(projectRoot, ".enderun", "logs", "orchestrator.json");
|
|
273
|
+
try {
|
|
274
|
+
const logContent = await fs.readFile(logPath, "utf-8");
|
|
275
|
+
const log = JSON.parse(logContent);
|
|
276
|
+
report.recentBlockages = (log.blockages ?? []).slice(-10);
|
|
277
|
+
}
|
|
278
|
+
catch {
|
|
279
|
+
report.recentBlockages = [];
|
|
280
|
+
}
|
|
281
|
+
// Generate recommended immediate actions
|
|
282
|
+
const blockedAgents = report.agentStatuses.filter((a) => a.state.includes("BLOCKED") || a.state.includes("ERROR"));
|
|
283
|
+
if (blockedAgents.length > 0) {
|
|
284
|
+
report.immediateActions.push(`IMMEDIATE: Resolve ${blockedAgents.map((a) => a.agent).join(", ")} blockages — these are on the critical path`);
|
|
285
|
+
}
|
|
286
|
+
if ((snapshot["pending"] ?? 0) > 5) {
|
|
287
|
+
report.immediateActions.push("HIGH: Queue has excessive pending tasks — consider deploying additional agents");
|
|
288
|
+
}
|
|
289
|
+
if (report.immediateActions.length === 0) {
|
|
290
|
+
report.immediateActions.push("No critical immediate actions required — monitor agent states");
|
|
291
|
+
}
|
|
292
|
+
return { content: [{ type: "text", text: JSON.stringify(report, null, 2) }] };
|
|
293
|
+
},
|
|
294
|
+
};
|