mergen-server 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +57 -0
- package/README.md +96 -0
- package/dist/__stubs__/calibration.js +471 -0
- package/dist/__stubs__/causal.js +601 -0
- package/dist/__stubs__/closed-source.js +150 -0
- package/dist/__stubs__/license.js +35 -0
- package/dist/__stubs__/plans.js +197 -0
- package/dist/app.js +467 -0
- package/dist/cli.js +250 -0
- package/dist/commands/agent-identity.js +79 -0
- package/dist/commands/gate.js +107 -0
- package/dist/commands/github.js +632 -0
- package/dist/commands/incident.js +644 -0
- package/dist/commands/policy.js +710 -0
- package/dist/commands/scan.js +243 -0
- package/dist/commands/setup.js +1218 -0
- package/dist/commands/shared.js +109 -0
- package/dist/commands/team.js +809 -0
- package/dist/datadog/blame-attribution.js +228 -0
- package/dist/datadog/client.js +159 -0
- package/dist/datadog/compactor.js +169 -0
- package/dist/datadog/fingerprinter.js +34 -0
- package/dist/datadog/incident-state.js +21 -0
- package/dist/datadog/line-matcher.js +56 -0
- package/dist/datadog/memory-store.js +399 -0
- package/dist/datadog/otel-trace.js +67 -0
- package/dist/index.js +505 -0
- package/dist/intelligence/action-risk.js +132 -0
- package/dist/intelligence/activity-feed.js +40 -0
- package/dist/intelligence/agent-identity.js +115 -0
- package/dist/intelligence/agent-pipeline.js +329 -0
- package/dist/intelligence/agent-profiles.js +81 -0
- package/dist/intelligence/ai-commit.js +16 -0
- package/dist/intelligence/approval-analytics.js +42 -0
- package/dist/intelligence/approval-events.js +5 -0
- package/dist/intelligence/arch-boundaries.js +94 -0
- package/dist/intelligence/arch-graph.js +117 -0
- package/dist/intelligence/autonomy.js +397 -0
- package/dist/intelligence/azure-broker.js +57 -0
- package/dist/intelligence/azure-proxy-sessions.js +49 -0
- package/dist/intelligence/baseline.js +1 -0
- package/dist/intelligence/behavior-baseline.js +134 -0
- package/dist/intelligence/billing.js +1 -0
- package/dist/intelligence/blast-radius.js +224 -0
- package/dist/intelligence/bypass.js +157 -0
- package/dist/intelligence/calibration-classifier.js +77 -0
- package/dist/intelligence/calibration-git-sync.js +74 -0
- package/dist/intelligence/calibration.js +1 -0
- package/dist/intelligence/cascade-detector.js +58 -0
- package/dist/intelligence/case-study-generator.js +126 -0
- package/dist/intelligence/causal-graph.js +126 -0
- package/dist/intelligence/causal.js +1 -0
- package/dist/intelligence/change-risk.js +102 -0
- package/dist/intelligence/compliance-report.js +134 -0
- package/dist/intelligence/confidence-report.js +85 -0
- package/dist/intelligence/corpus-to-policy.js +140 -0
- package/dist/intelligence/credential-broker.js +112 -0
- package/dist/intelligence/credential-misuse.js +39 -0
- package/dist/intelligence/debug-sessions.js +108 -0
- package/dist/intelligence/decision-escalation.js +36 -0
- package/dist/intelligence/decision-memory.js +47 -0
- package/dist/intelligence/decision-similarity.js +85 -0
- package/dist/intelligence/default-safety-tests.js +53 -0
- package/dist/intelligence/degradation-watcher.js +108 -0
- package/dist/intelligence/detector-plugins.js +70 -0
- package/dist/intelligence/detectors.js +1 -0
- package/dist/intelligence/device-auth.js +138 -0
- package/dist/intelligence/diff-size.js +42 -0
- package/dist/intelligence/ebpf-verify.js +45 -0
- package/dist/intelligence/enterprise-policy-engine.js +1122 -0
- package/dist/intelligence/error-fingerprint.js +1 -0
- package/dist/intelligence/execution-gate.js +100 -0
- package/dist/intelligence/execution-mode.js +22 -0
- package/dist/intelligence/gate-analytics.js +256 -0
- package/dist/intelligence/gate-decision.js +64 -0
- package/dist/intelligence/gcp-broker.js +50 -0
- package/dist/intelligence/git-adr-sync.js +207 -0
- package/dist/intelligence/hitl-hold.js +460 -0
- package/dist/intelligence/hypothesis-history.js +93 -0
- package/dist/intelligence/idp-identity.js +83 -0
- package/dist/intelligence/impl-critic.js +216 -0
- package/dist/intelligence/incident-autopilot.js +622 -0
- package/dist/intelligence/incident-replay.js +162 -0
- package/dist/intelligence/incident-result-cache.js +33 -0
- package/dist/intelligence/incident-similarity.js +58 -0
- package/dist/intelligence/infra-detectors.js +312 -0
- package/dist/intelligence/license.js +185 -0
- package/dist/intelligence/llm-spokesperson.js +62 -0
- package/dist/intelligence/mcp-prompts.js +320 -0
- package/dist/intelligence/mcp-resources.js +171 -0
- package/dist/intelligence/normalize.js +108 -0
- package/dist/intelligence/notifications.js +83 -0
- package/dist/intelligence/oidc-issuer.js +87 -0
- package/dist/intelligence/override-corpus.js +597 -0
- package/dist/intelligence/planning-gate.js +84 -0
- package/dist/intelligence/plans.js +223 -0
- package/dist/intelligence/platt-scaling.js +164 -0
- package/dist/intelligence/policy-proposals.js +84 -0
- package/dist/intelligence/policy-suggester.js +161 -0
- package/dist/intelligence/policy-sync.js +103 -0
- package/dist/intelligence/policy-test-runner.js +35 -0
- package/dist/intelligence/postmortem-parser.js +181 -0
- package/dist/intelligence/postmortem-retrieval.js +224 -0
- package/dist/intelligence/postmortem-store.js +596 -0
- package/dist/intelligence/pr-commenter.js +81 -0
- package/dist/intelligence/pr-policy-gate.js +38 -0
- package/dist/intelligence/pr-shadow-analyzer.js +229 -0
- package/dist/intelligence/process-tree.js +108 -0
- package/dist/intelligence/prompts.js +1 -0
- package/dist/intelligence/replay.js +38 -0
- package/dist/intelligence/repro-steps.js +1 -0
- package/dist/intelligence/resource-extractors.js +0 -0
- package/dist/intelligence/resource-file-context.js +138 -0
- package/dist/intelligence/risk-score.js +22 -0
- package/dist/intelligence/rollback.js +137 -0
- package/dist/intelligence/runbook-updater.js +143 -0
- package/dist/intelligence/sandbox.js +194 -0
- package/dist/intelligence/script-trust.js +104 -0
- package/dist/intelligence/session-metrics.js +67 -0
- package/dist/intelligence/session-threat-tracker.js +231 -0
- package/dist/intelligence/shadow-digest-cron.js +81 -0
- package/dist/intelligence/shadow-log.js +284 -0
- package/dist/intelligence/shell-ast.js +145 -0
- package/dist/intelligence/siem-forward.js +104 -0
- package/dist/intelligence/slack-digest.js +151 -0
- package/dist/intelligence/slack-override-loop.js +217 -0
- package/dist/intelligence/slack-routing.js +67 -0
- package/dist/intelligence/slack.js +900 -0
- package/dist/intelligence/sql-ast.js +31 -0
- package/dist/intelligence/team.js +1 -0
- package/dist/intelligence/telemetry.js +76 -0
- package/dist/intelligence/threshold-optimizer.js +75 -0
- package/dist/intelligence/token-budget.js +66 -0
- package/dist/intelligence/tool-guard.js +708 -0
- package/dist/intelligence/tool-manifest 2.js +74 -0
- package/dist/intelligence/tool-manifest.js +125 -0
- package/dist/intelligence/tools-analysis.js +857 -0
- package/dist/intelligence/tools-arch.js +152 -0
- package/dist/intelligence/tools-autonomy.js +495 -0
- package/dist/intelligence/tools-blast-radius.js +140 -0
- package/dist/intelligence/tools-browser.js +431 -0
- package/dist/intelligence/tools-change-timeline.js +154 -0
- package/dist/intelligence/tools-credentials.js +117 -0
- package/dist/intelligence/tools-datadog.js +233 -0
- package/dist/intelligence/tools-debug-sessions.js +209 -0
- package/dist/intelligence/tools-discovery.js +284 -0
- package/dist/intelligence/tools-infra.js +612 -0
- package/dist/intelligence/tools-intent.js +128 -0
- package/dist/intelligence/tools-memory.js +514 -0
- package/dist/intelligence/tools-runbook.js +951 -0
- package/dist/intelligence/tools-sessions.js +107 -0
- package/dist/intelligence/tools-state.js +232 -0
- package/dist/intelligence/tools-utility.js +430 -0
- package/dist/intelligence/tools-validate.js +215 -0
- package/dist/intelligence/tools.js +1 -0
- package/dist/intelligence/trace-context.js +11 -0
- package/dist/intelligence/unclassified-clusters.js +87 -0
- package/dist/intelligence/usage.js +195 -0
- package/dist/routes/active-authors.js +63 -0
- package/dist/routes/activity-feed.js +21 -0
- package/dist/routes/adr.js +117 -0
- package/dist/routes/agent-activity.js +184 -0
- package/dist/routes/agent-blunders.js +163 -0
- package/dist/routes/agents.js +175 -0
- package/dist/routes/api-keys.js +65 -0
- package/dist/routes/arch.js +75 -0
- package/dist/routes/audit-export.js +93 -0
- package/dist/routes/billing-dashboard.js +158 -0
- package/dist/routes/billing-outcome.js +77 -0
- package/dist/routes/calibration.js +305 -0
- package/dist/routes/ci-gate-history.js +20 -0
- package/dist/routes/ci-gate.js +232 -0
- package/dist/routes/ci.js +293 -0
- package/dist/routes/compliance-report.js +24 -0
- package/dist/routes/confidence.js +30 -0
- package/dist/routes/credentials.js +119 -0
- package/dist/routes/dashboard.js +1407 -0
- package/dist/routes/decision-memory.js +42 -0
- package/dist/routes/demo.js +844 -0
- package/dist/routes/device-auth-stub.js +173 -0
- package/dist/routes/explain-why.js +39 -0
- package/dist/routes/gate-analytics.js +213 -0
- package/dist/routes/gate.js +28 -0
- package/dist/routes/github-webhook.js +364 -0
- package/dist/routes/habituation.js +30 -0
- package/dist/routes/health-integrations.js +243 -0
- package/dist/routes/heartbeats.js +45 -0
- package/dist/routes/hitl.js +364 -0
- package/dist/routes/impact-report.js +645 -0
- package/dist/routes/incident-webhook.js +63 -0
- package/dist/routes/incidents.js +366 -0
- package/dist/routes/layers.js +62 -0
- package/dist/routes/license.js +187 -0
- package/dist/routes/oidc-issuer.js +30 -0
- package/dist/routes/onboarding.js +170 -0
- package/dist/routes/otel.js +67 -0
- package/dist/routes/otlp-receiver.js +179 -0
- package/dist/routes/overrides.js +241 -0
- package/dist/routes/pagerduty.js +258 -0
- package/dist/routes/policies.js +809 -0
- package/dist/routes/policy-nl.js +169 -0
- package/dist/routes/postmortem.js +102 -0
- package/dist/routes/pr-shadow.js +47 -0
- package/dist/routes/rbac.js +61 -0
- package/dist/routes/replay.js +17 -0
- package/dist/routes/risk-report.js +164 -0
- package/dist/routes/runbooks.js +125 -0
- package/dist/routes/safety-test.js +174 -0
- package/dist/routes/sdk.js +222 -0
- package/dist/routes/sensor.js +819 -0
- package/dist/routes/sentry.js +140 -0
- package/dist/routes/sessions.js +43 -0
- package/dist/routes/setup-ui.js +594 -0
- package/dist/routes/shadow-report.js +107 -0
- package/dist/routes/slack-routing.js +171 -0
- package/dist/routes/team-usage.js +71 -0
- package/dist/routes/telemetry.js +28 -0
- package/dist/routes/tenants.js +199 -0
- package/dist/routes/tickets.js +167 -0
- package/dist/routes/validate.js +13 -0
- package/dist/routes/war-room.js +113 -0
- package/dist/scripts/check-arch.js +22 -0
- package/dist/seeds/community-corpus.js +176 -0
- package/dist/seeds/corpus.js +1224 -0
- package/dist/sensor/action-ledger.js +327 -0
- package/dist/sensor/adr-store.js +140 -0
- package/dist/sensor/agent-blunder-store.js +370 -0
- package/dist/sensor/agent-context-store.js +225 -0
- package/dist/sensor/agent-memory-store.js +231 -0
- package/dist/sensor/audit-fetch.js +23 -0
- package/dist/sensor/audit-log.js +273 -0
- package/dist/sensor/buffer-schemas.js +225 -0
- package/dist/sensor/buffer.js +599 -0
- package/dist/sensor/bypass-tracker.js +93 -0
- package/dist/sensor/ci-gate-history.js +70 -0
- package/dist/sensor/cloud-auth.js +183 -0
- package/dist/sensor/commit-context-store.js +235 -0
- package/dist/sensor/docker-log-stream.js +164 -0
- package/dist/sensor/docker-monitor.js +122 -0
- package/dist/sensor/extended-buffer.js +46 -0
- package/dist/sensor/feedback-token.js +41 -0
- package/dist/sensor/file-lock.js +6 -0
- package/dist/sensor/fs-watcher.js +106 -0
- package/dist/sensor/gate-heartbeat.js +122 -0
- package/dist/sensor/git-suspect.js +136 -0
- package/dist/sensor/habituation-store.js +77 -0
- package/dist/sensor/heartbeat-monitor.js +133 -0
- package/dist/sensor/incident-store.js +340 -0
- package/dist/sensor/infra-normalizer.js +513 -0
- package/dist/sensor/ingest.js +339 -0
- package/dist/sensor/jest-reporter.js +52 -0
- package/dist/sensor/k8s-events.js +132 -0
- package/dist/sensor/layer2-store.js +111 -0
- package/dist/sensor/layer3-store.js +230 -0
- package/dist/sensor/layer4-store.js +147 -0
- package/dist/sensor/logger.js +13 -0
- package/dist/sensor/otel-exporter.js +161 -0
- package/dist/sensor/paths.js +71 -0
- package/dist/sensor/policy-history.js +147 -0
- package/dist/sensor/pr-shadow-store.js +83 -0
- package/dist/sensor/process-watcher.js +162 -0
- package/dist/sensor/rbac.js +92 -0
- package/dist/sensor/redact.js +114 -0
- package/dist/sensor/redis-store.js +191 -0
- package/dist/sensor/route-reachability.js +64 -0
- package/dist/sensor/security-utils.js +18 -0
- package/dist/sensor/service-graph.js +170 -0
- package/dist/sensor/service-topology.js +227 -0
- package/dist/sensor/session-history.js +74 -0
- package/dist/sensor/session-persist.js +38 -0
- package/dist/sensor/shadow-promote.js +122 -0
- package/dist/sensor/sourcemap.js +281 -0
- package/dist/sensor/sqlite-store.js +205 -0
- package/dist/sensor/sso.js +164 -0
- package/dist/sensor/vitest-reporter.js +65 -0
- package/dist/sensor/watcher.js +48 -0
- package/dist/storage/interfaces.js +0 -0
- package/dist/storage/pg/pg-action-ledger.js +138 -0
- package/dist/storage/pg/pg-approval-store.js +107 -0
- package/dist/storage/pg/pg-blunder-store.js +193 -0
- package/dist/storage/pg/pg-ci-gate-history.js +83 -0
- package/dist/storage/pg/pg-client.js +24 -0
- package/dist/storage/pg/pg-event-store.js +63 -0
- package/dist/storage/pg/pg-incident-store.js +190 -0
- package/dist/storage/pg/pg-migrations.js +26 -0
- package/dist/storage/pg/pg-override-corpus.js +447 -0
- package/dist/storage/pg/pg-shadow-log.js +129 -0
- package/dist/storage/sqlite/sqlite-action-ledger.js +18 -0
- package/dist/storage/sqlite/sqlite-approval-store.js +37 -0
- package/dist/storage/sqlite/sqlite-blunder-store.js +27 -0
- package/dist/storage/sqlite/sqlite-ci-gate-history.js +19 -0
- package/dist/storage/sqlite/sqlite-event-store.js +29 -0
- package/dist/storage/sqlite/sqlite-incident-store.js +34 -0
- package/dist/storage/sqlite/sqlite-override-corpus.js +75 -0
- package/dist/storage/sqlite/sqlite-shadow-log.js +36 -0
- package/dist/storage/store-factory.js +55 -0
- package/dist/storage/store-registry.js +31 -0
- package/dist/update-checker.js +107 -0
- package/dist/workers/autopilot-worker.js +28 -0
- package/dist/workers/notification-worker.js +28 -0
- package/dist/workers/queues.js +58 -0
- package/dist/workers/validation-worker.js +24 -0
- package/dist/workers/worker-registry.js +18 -0
- package/package.json +123 -0
- package/sdk/mergen-inject.js +260 -0
- package/sdk/node.js +313 -0
- package/sdk/vite-plugin.ts +57 -0
- package/sdk/webpack-plugin.js +106 -0
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { store } from "../sensor/buffer.js";
|
|
3
|
+
import { trackCall } from "./tools-state.js";
|
|
4
|
+
import {
|
|
5
|
+
startDebugSession,
|
|
6
|
+
checkpointSession,
|
|
7
|
+
endDebugSession,
|
|
8
|
+
getSession,
|
|
9
|
+
listActiveSessions,
|
|
10
|
+
captureSnapshot
|
|
11
|
+
} from "./debug-sessions.js";
|
|
12
|
+
function registerDebugSessionTools(server) {
|
|
13
|
+
server.registerTool(
|
|
14
|
+
"start_debug_session",
|
|
15
|
+
{
|
|
16
|
+
description: "\u26A1 FREE \xB7 Start an iterative debugging session. Fingerprints every current error/warning/network failure as a baseline. After each fix attempt, call checkpoint_debug_session to get a precise 3-way diff: \u2705 resolved | \u274C persisted | \u26A0\uFE0F new regressions. Closes the loop \u2014 no more manually describing what changed between iterations.",
|
|
17
|
+
inputSchema: {
|
|
18
|
+
hypothesis: z.string().min(10).max(500).describe('What you think is broken (e.g. "JWT token expires before refresh fires")'),
|
|
19
|
+
target_component: z.string().optional().describe('Optional component/file to focus on (e.g. "LoginForm", "auth.ts")')
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
async ({ hypothesis, target_component }) => {
|
|
23
|
+
trackCall("start_debug_session");
|
|
24
|
+
const errors = store.getLogs(200, "error");
|
|
25
|
+
const warns = store.getLogs(200, "warn");
|
|
26
|
+
const netFail = store.getNetwork(200).filter((n) => n.status >= 400 || n.status === 0 || n.error);
|
|
27
|
+
const baseline = captureSnapshot(errors, warns, netFail);
|
|
28
|
+
const session = startDebugSession(hypothesis, baseline, target_component);
|
|
29
|
+
const lines = [
|
|
30
|
+
"## \u{1F52C} Debug Session Started",
|
|
31
|
+
"",
|
|
32
|
+
`**Session ID:** \`${session.id}\``,
|
|
33
|
+
`**Hypothesis:** ${hypothesis}`,
|
|
34
|
+
...target_component ? [`**Target:** ${target_component}`] : [],
|
|
35
|
+
"",
|
|
36
|
+
"### Baseline Fingerprinted",
|
|
37
|
+
`| | Count |`,
|
|
38
|
+
`|---|---|`,
|
|
39
|
+
`| Errors | ${baseline.errors.length} |`,
|
|
40
|
+
`| Warnings | ${baseline.warnings.length} |`,
|
|
41
|
+
`| Network failures | ${baseline.networkFailures.length} |`
|
|
42
|
+
];
|
|
43
|
+
if (baseline.errors.length > 0) {
|
|
44
|
+
lines.push("", "**Errors to resolve:**", "```");
|
|
45
|
+
for (const e of baseline.errors.slice(0, 5))
|
|
46
|
+
lines.push(`[${e.level.toUpperCase()}] ${e.message.slice(0, 150)}`);
|
|
47
|
+
if (baseline.errors.length > 5) lines.push(`... +${baseline.errors.length - 5} more`);
|
|
48
|
+
lines.push("```");
|
|
49
|
+
} else {
|
|
50
|
+
lines.push("", "> \u2705 No errors at baseline \u2014 session will track any NEW errors that appear.");
|
|
51
|
+
}
|
|
52
|
+
lines.push(
|
|
53
|
+
"",
|
|
54
|
+
"### Workflow",
|
|
55
|
+
"1. Apply your fix to the code",
|
|
56
|
+
"2. Reproduce the scenario in the browser",
|
|
57
|
+
`3. Call \`checkpoint_debug_session\` with \`session_id: "${session.id}"\` + a short note`,
|
|
58
|
+
"4. See what resolved, what persisted, and any regressions",
|
|
59
|
+
`5. Repeat until clean, then call \`end_debug_session("${session.id}")\``
|
|
60
|
+
);
|
|
61
|
+
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
62
|
+
}
|
|
63
|
+
);
|
|
64
|
+
server.registerTool(
|
|
65
|
+
"checkpoint_debug_session",
|
|
66
|
+
{
|
|
67
|
+
description: "\u26A1 FREE \xB7 Record a fix attempt and see the exact diff vs baseline. Call this after every code change + browser reproduction \u2014 no credit cost. Returns: \u2705 resolved (gone) | \u274C persisted (still broken) | \u26A0\uFE0F new (regression). Use end_debug_session when satisfied.",
|
|
68
|
+
inputSchema: {
|
|
69
|
+
session_id: z.string().describe("Session ID from start_debug_session"),
|
|
70
|
+
note: z.string().max(300).optional().describe('What you just changed (e.g. "added null check before token read")')
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
async ({ session_id, note }) => {
|
|
74
|
+
trackCall("checkpoint_debug_session");
|
|
75
|
+
const session = getSession(session_id);
|
|
76
|
+
if (!session) {
|
|
77
|
+
const active = listActiveSessions().map((s2) => `"${s2.id.slice(0, 8)}\u2026" (${s2.description.slice(0, 40)})`).join(", ");
|
|
78
|
+
return {
|
|
79
|
+
content: [{ type: "text", text: `\u274C Session \`${session_id}\` not found.
|
|
80
|
+
Active: ${active || "none"}` }],
|
|
81
|
+
isError: true
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
const errors = store.getLogs(200, "error", session.baseline.capturedAt);
|
|
85
|
+
const warns = store.getLogs(200, "warn", session.baseline.capturedAt);
|
|
86
|
+
const netFail = store.getNetwork(200, void 0, session.baseline.capturedAt).filter((n) => n.status >= 400 || n.status === 0 || n.error);
|
|
87
|
+
const current = captureSnapshot(errors, warns, netFail);
|
|
88
|
+
const iterNote = note ?? `Fix attempt ${session.iterations.length + 1}`;
|
|
89
|
+
const result = checkpointSession(session_id, current, iterNote);
|
|
90
|
+
if (!result) return { content: [{ type: "text", text: "\u274C Session expired." }], isError: true };
|
|
91
|
+
const { diff, session: s } = result;
|
|
92
|
+
const lines = [
|
|
93
|
+
`## \u{1F52C} Checkpoint \u2014 Iteration ${s.iterations.length}`,
|
|
94
|
+
`**Fix applied:** ${iterNote}`,
|
|
95
|
+
"",
|
|
96
|
+
"### Diff vs Baseline",
|
|
97
|
+
""
|
|
98
|
+
];
|
|
99
|
+
if (diff.resolved.length > 0) {
|
|
100
|
+
lines.push(`\u2705 **Resolved (${diff.resolved.length}) \u2014 gone:**`);
|
|
101
|
+
diff.resolved.forEach((e) => lines.push(` - \`${e.message.slice(0, 120)}\``));
|
|
102
|
+
lines.push("");
|
|
103
|
+
}
|
|
104
|
+
if (diff.persisted.length > 0) {
|
|
105
|
+
lines.push(`\u274C **Persisted (${diff.persisted.length}) \u2014 fix didn't work:**`);
|
|
106
|
+
diff.persisted.forEach((e) => lines.push(` - \`${e.message.slice(0, 120)}\``));
|
|
107
|
+
lines.push("");
|
|
108
|
+
}
|
|
109
|
+
if (diff.newErrors.length > 0) {
|
|
110
|
+
lines.push(`\u26A0\uFE0F **New regressions (${diff.newErrors.length}):**`);
|
|
111
|
+
diff.newErrors.forEach((e) => lines.push(` - \`${e.message.slice(0, 120)}\``));
|
|
112
|
+
lines.push("");
|
|
113
|
+
}
|
|
114
|
+
if (diff.resolvedNetworkFailures.length > 0) {
|
|
115
|
+
lines.push(`\u2705 **Network failures fixed (${diff.resolvedNetworkFailures.length}):**`);
|
|
116
|
+
diff.resolvedNetworkFailures.forEach((n) => lines.push(` - \`${n.summary}\``));
|
|
117
|
+
lines.push("");
|
|
118
|
+
}
|
|
119
|
+
if (diff.newNetworkFailures.length > 0) {
|
|
120
|
+
lines.push(`\u26A0\uFE0F **New network failures (${diff.newNetworkFailures.length}):**`);
|
|
121
|
+
diff.newNetworkFailures.forEach((n) => lines.push(` - \`${n.summary}\``));
|
|
122
|
+
lines.push("");
|
|
123
|
+
}
|
|
124
|
+
if (!diff.resolved.length && !diff.persisted.length && !diff.newErrors.length && !diff.resolvedNetworkFailures.length && !diff.newNetworkFailures.length) {
|
|
125
|
+
lines.push("> \u26A0\uFE0F No events since session start. Reproduce the scenario in the browser first.");
|
|
126
|
+
}
|
|
127
|
+
lines.push("---");
|
|
128
|
+
if (diff.isFixed) {
|
|
129
|
+
lines.push(`\u2705 **All baseline errors resolved!** Call \`end_debug_session("${session_id}")\`.`);
|
|
130
|
+
} else {
|
|
131
|
+
const rem = diff.persisted.length + diff.newErrors.length;
|
|
132
|
+
lines.push(`\u274C **${rem} error(s) remain.** Apply another fix, reproduce, then checkpoint again.`);
|
|
133
|
+
lines.push(`> \u{1F4A1} \`reconstruct_context(since: ${session.baseline.capturedAt})\` for root-cause + fix.`);
|
|
134
|
+
}
|
|
135
|
+
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
136
|
+
}
|
|
137
|
+
);
|
|
138
|
+
server.registerTool(
|
|
139
|
+
"end_debug_session",
|
|
140
|
+
{
|
|
141
|
+
description: "\u26A1 FREE \xB7 Close a debugging session with a final resolved/persisted/new diff. Use when the bug is fixed or you are done. For mid-session progress checks without closing, use checkpoint_debug_session.",
|
|
142
|
+
inputSchema: {
|
|
143
|
+
session_id: z.string().describe("Session ID from start_debug_session")
|
|
144
|
+
}
|
|
145
|
+
},
|
|
146
|
+
async ({ session_id }) => {
|
|
147
|
+
trackCall("end_debug_session");
|
|
148
|
+
const session = getSession(session_id);
|
|
149
|
+
if (!session) {
|
|
150
|
+
const active = listActiveSessions().map((s2) => `"${s2.id.slice(0, 8)}\u2026"`).join(", ");
|
|
151
|
+
return {
|
|
152
|
+
content: [{ type: "text", text: `\u274C Session \`${session_id}\` not found. Active: ${active || "none"}` }],
|
|
153
|
+
isError: true
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
const errors = store.getLogs(200, "error", session.baseline.capturedAt);
|
|
157
|
+
const warns = store.getLogs(200, "warn", session.baseline.capturedAt);
|
|
158
|
+
const netFail = store.getNetwork(200, void 0, session.baseline.capturedAt).filter((n) => n.status >= 400 || n.status === 0 || n.error);
|
|
159
|
+
const current = captureSnapshot(errors, warns, netFail);
|
|
160
|
+
const result = endDebugSession(session_id, current);
|
|
161
|
+
if (!result) return { content: [{ type: "text", text: "\u274C Session already closed." }], isError: true };
|
|
162
|
+
const { session: s, diff } = result;
|
|
163
|
+
const duration = Math.round(((s.endedAt ?? Date.now()) - s.startedAt) / 1e3);
|
|
164
|
+
const lines = [
|
|
165
|
+
"## \u{1F52C} Debug Session Closed",
|
|
166
|
+
"",
|
|
167
|
+
`**Hypothesis:** ${s.description}`,
|
|
168
|
+
...s.targetComponent ? [`**Target:** ${s.targetComponent}`] : [],
|
|
169
|
+
`**Duration:** ${duration}s | **Iterations:** ${s.iterations.length}`,
|
|
170
|
+
"",
|
|
171
|
+
"### Final Diff vs Baseline",
|
|
172
|
+
""
|
|
173
|
+
];
|
|
174
|
+
if (diff.resolved.length > 0) {
|
|
175
|
+
lines.push(`\u2705 **Resolved (${diff.resolved.length}):**`);
|
|
176
|
+
diff.resolved.forEach((e) => lines.push(` - \`${e.message.slice(0, 120)}\``));
|
|
177
|
+
lines.push("");
|
|
178
|
+
}
|
|
179
|
+
if (diff.persisted.length > 0) {
|
|
180
|
+
lines.push(`\u274C **Still broken (${diff.persisted.length}):**`);
|
|
181
|
+
diff.persisted.forEach((e) => lines.push(` - \`${e.message.slice(0, 120)}\``));
|
|
182
|
+
lines.push("");
|
|
183
|
+
}
|
|
184
|
+
if (diff.newErrors.length > 0) {
|
|
185
|
+
lines.push(`\u26A0\uFE0F **New regressions (${diff.newErrors.length}):**`);
|
|
186
|
+
diff.newErrors.forEach((e) => lines.push(` - \`${e.message.slice(0, 120)}\``));
|
|
187
|
+
lines.push("");
|
|
188
|
+
}
|
|
189
|
+
if (diff.resolvedNetworkFailures.length > 0) {
|
|
190
|
+
lines.push(`\u2705 **Network failures fixed (${diff.resolvedNetworkFailures.length}):**`);
|
|
191
|
+
diff.resolvedNetworkFailures.forEach((n) => lines.push(` - \`${n.summary}\``));
|
|
192
|
+
lines.push("");
|
|
193
|
+
}
|
|
194
|
+
lines.push("---");
|
|
195
|
+
if (diff.isFixed) {
|
|
196
|
+
lines.push("\u2705 **Bug resolved.** All baseline errors gone, no regressions.");
|
|
197
|
+
} else if (diff.persisted.length > 0 || diff.newErrors.length > 0) {
|
|
198
|
+
const rem = diff.persisted.length + diff.newErrors.length;
|
|
199
|
+
lines.push(`\u26A0\uFE0F Closed with **${rem} unresolved error(s)**. Start a new session to continue.`);
|
|
200
|
+
} else {
|
|
201
|
+
lines.push("\u2139\uFE0F No events since session start \u2014 scenario may not have been reproduced.");
|
|
202
|
+
}
|
|
203
|
+
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
204
|
+
}
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
export {
|
|
208
|
+
registerDebugSessionTools
|
|
209
|
+
};
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { ALL_TOOLS } from "./tool-manifest.js";
|
|
3
|
+
import { trackCall } from "./tools-state.js";
|
|
4
|
+
import { store } from "../sensor/buffer.js";
|
|
5
|
+
import { serviceTopology } from "../sensor/service-topology.js";
|
|
6
|
+
function registerDiscoveryTools(server) {
|
|
7
|
+
server.registerTool(
|
|
8
|
+
"discover_repo_context",
|
|
9
|
+
{
|
|
10
|
+
description: "Phase 0 repository exploration \u2014 call this BEFORE writing any code. Returns: domain vocabulary, existing patterns, reusable utilities, testing conventions, and all registered MCP tools and REST routes. Read-only; makes no changes. Use the returned context to avoid duplicating logic that already exists.",
|
|
11
|
+
inputSchema: {
|
|
12
|
+
focus: z.enum(["all", "tools", "routes", "types", "testing", "utilities"]).optional().describe("Narrow the report to a specific area (default: all)")
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
async ({ focus = "all" }) => {
|
|
16
|
+
trackCall("discover_repo_context");
|
|
17
|
+
const sections = ["## Repository Discovery Report (Phase 0)", ""];
|
|
18
|
+
if (focus === "all" || focus === "tools") {
|
|
19
|
+
const byModule = /* @__PURE__ */ new Map();
|
|
20
|
+
for (const t of ALL_TOOLS) {
|
|
21
|
+
const group = byModule.get(t.module) ?? [];
|
|
22
|
+
group.push(t);
|
|
23
|
+
byModule.set(t.module, group);
|
|
24
|
+
}
|
|
25
|
+
sections.push("### Registered MCP Tools", "");
|
|
26
|
+
sections.push("Before adding a new tool, verify no existing tool already covers your need.", "");
|
|
27
|
+
for (const [mod, tools] of byModule) {
|
|
28
|
+
sections.push(`**${mod}**`);
|
|
29
|
+
for (const t of tools) {
|
|
30
|
+
sections.push(` - \`${t.name}\` (tier: ${t.tier})`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
sections.push("");
|
|
34
|
+
sections.push(
|
|
35
|
+
`**Pattern:** Register in \`intelligence/tool-manifest.ts\` + \`intelligence/tools-state.ts\` (KNOWN_TOOLS). Implement in \`intelligence/tools-<module>.ts\`. Export a \`registerXxxTools(server)\` function.`,
|
|
36
|
+
""
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
if (focus === "all" || focus === "routes") {
|
|
40
|
+
sections.push("### REST Route Conventions", "");
|
|
41
|
+
sections.push(
|
|
42
|
+
"Each route module exports a **factory function** (e.g. `createIncidentsRouter(): Router`).",
|
|
43
|
+
"The factory is imported in `app.ts` and mounted with `app.use(createXxxRouter())`.",
|
|
44
|
+
"Zod validates all request bodies. Return `{ ok: true, ... }` on success, `{ error: string }` on failure.",
|
|
45
|
+
"",
|
|
46
|
+
"**Existing route modules** (check before adding a new one):",
|
|
47
|
+
"`sensor`, `incidents`, `pagerduty`, `github-webhook`, `ci`, `sessions`, `postmortem`,",
|
|
48
|
+
"`calibration`, `dashboard`, `impact-report`, `shadow-report`, `rbac`, `overrides`,",
|
|
49
|
+
"`validate`, `license`, `api-keys`, `setup-ui`, `explain-why`, `war-room`,",
|
|
50
|
+
"`slack-routing`, `heartbeats`, `habituation`, `active-authors`, `agent-blunders`,",
|
|
51
|
+
"`telemetry`, `demo`, `sentry`, `otel`, `otlp-receiver`, `layers`, `billing-outcome`,",
|
|
52
|
+
"`tickets`, `incident-webhook`, `sdk`, `adr`, `confidence`",
|
|
53
|
+
""
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
if (focus === "all" || focus === "types") {
|
|
57
|
+
sections.push("### Domain Vocabulary (canonical type names)", "");
|
|
58
|
+
sections.push(
|
|
59
|
+
"Use these names exactly. Never use generic alternatives like `data`, `item`, `payload`.",
|
|
60
|
+
"",
|
|
61
|
+
"**Event types** (from `sensor/buffer-schemas.ts`):",
|
|
62
|
+
"`ConsoleEvent`, `NetworkEvent`, `ContextSnapshot`, `WebSocketEvent`, `SSEEvent`,",
|
|
63
|
+
"`DiagnosticEvent`, `TerminalOutputEvent`, `TestResultEvent`, `ProcessExitEvent`,",
|
|
64
|
+
"`CIEvent`, `DeploymentEvent`, `BackendSpanEvent`, `BrowserEvent`",
|
|
65
|
+
"",
|
|
66
|
+
"**Core concepts**:",
|
|
67
|
+
"`ToolEntry`, `ToolTier` (free|pro|all), `AdrRecord`, `ConfidenceReport`,",
|
|
68
|
+
"`RollbackStrategy`, `RollbackPlan`, `BlastRadiusReport`, `SessionSignal`",
|
|
69
|
+
"",
|
|
70
|
+
"**Key identifiers**: `pid` (hypothesis ID), `sessionId`, `traceId`, `spanId`, `buildSha`",
|
|
71
|
+
""
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
if (focus === "all" || focus === "testing") {
|
|
75
|
+
sections.push("### Testing Conventions", "");
|
|
76
|
+
sections.push(
|
|
77
|
+
"**Framework:** Vitest (`vitest run`)",
|
|
78
|
+
"**Test location:** Colocate `.test.ts` next to the implementation file, OR place in `src/__tests__/`.",
|
|
79
|
+
"**Coverage floors:** lines 80%, functions 80%, branches 75%.",
|
|
80
|
+
"**Import style:** use `.js` extension even for `.ts` source files (Node16 module resolution).",
|
|
81
|
+
"",
|
|
82
|
+
"**Required:** After adding an MCP tool, run `tool-manifest.test.ts` to verify consistency.",
|
|
83
|
+
"",
|
|
84
|
+
"**Mocking pattern:**",
|
|
85
|
+
"```typescript",
|
|
86
|
+
"vi.mock('../intelligence/license.js', async (importOriginal) => {",
|
|
87
|
+
" const actual = await importOriginal() as Record<string, unknown>;",
|
|
88
|
+
" return { ...actual, getActivePlanId: vi.fn(() => 'free') };",
|
|
89
|
+
"});",
|
|
90
|
+
"```",
|
|
91
|
+
"",
|
|
92
|
+
"**Arrange-Act-Assert structure** is expected in all test cases.",
|
|
93
|
+
""
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
if (focus === "all" || focus === "utilities") {
|
|
97
|
+
sections.push("### Reusable Utilities (check before writing a duplicate)", "");
|
|
98
|
+
sections.push(
|
|
99
|
+
"| Utility | Path | Purpose |",
|
|
100
|
+
"|---------|------|---------|",
|
|
101
|
+
"| `store` | `sensor/buffer.ts` | Ring buffer: getLogs, getNetwork, getContext, getSignals, push, clear |",
|
|
102
|
+
"| `trackCall(tool)` | `intelligence/tools-state.ts` | Increment MCP tool call counter |",
|
|
103
|
+
"| `withTierGate(tier, handler)` | `intelligence/tools-state.ts` | Enforce plan-tier access on a tool handler |",
|
|
104
|
+
"| `getTierForTool(name)` | `intelligence/tool-manifest.ts` | Lookup a tool's tier from the manifest |",
|
|
105
|
+
"| `adrStore` | `sensor/adr-store.ts` | List/get/add Architectural Decision Records |",
|
|
106
|
+
"| `incidentStore` | `sensor/incident-store.ts` | CRUD for open/acknowledged/resolved incidents |",
|
|
107
|
+
"| `logger` | `sensor/logger.ts` | Pino logger \u2014 use instead of console.log |",
|
|
108
|
+
"| `DATA_DIR`, `zeroRetentionMode()` | `sensor/paths.ts` | File paths and zero-retention guard |",
|
|
109
|
+
"| `executeRemediation(cmd)` | `intelligence/autonomy.ts` | Safe command execution (blocklist, audit, RBAC) |",
|
|
110
|
+
"| `deriveRollback(cmd)` | `intelligence/rollback.ts` | Derive inverse command for rollback |",
|
|
111
|
+
"| `generateRollbackPlan(intent)` | `intelligence/rollback.ts` | Pre-implementation rollback plan |",
|
|
112
|
+
""
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
sections.push("---");
|
|
116
|
+
sections.push("*This report is generated from live server state. Re-run after adding tools or routes.*");
|
|
117
|
+
return { content: [{ type: "text", text: sections.join("\n") }] };
|
|
118
|
+
}
|
|
119
|
+
);
|
|
120
|
+
server.registerTool(
|
|
121
|
+
"get_buffer_schema",
|
|
122
|
+
{
|
|
123
|
+
description: "Inspect the live event buffer without reading raw events \u2014 returns a structural summary: event types present, log levels, URL patterns, detected services, error patterns, and time range. Free to call; no credits consumed. Use this before `analyze_runtime` to understand what telemetry is available and calibrate how much context to request.",
|
|
124
|
+
inputSchema: {
|
|
125
|
+
include_samples: z.boolean().optional().describe("Include one sample message per error pattern (default: false).")
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
async ({ include_samples = false }) => {
|
|
129
|
+
trackCall("get_buffer_schema");
|
|
130
|
+
const logs = store.getLogs(500);
|
|
131
|
+
const network = store.getNetwork(500);
|
|
132
|
+
const ctx = store.getContext(20);
|
|
133
|
+
const terminal = store.getTerminalOutput(100);
|
|
134
|
+
const ci = store.getCIEvents(20);
|
|
135
|
+
const deploys = store.getDeployments(20);
|
|
136
|
+
const eventTypes = {};
|
|
137
|
+
if (logs.length) eventTypes["console"] = logs.length;
|
|
138
|
+
if (network.length) eventTypes["network"] = network.length;
|
|
139
|
+
if (ctx.length) eventTypes["context"] = ctx.length;
|
|
140
|
+
if (terminal.length) eventTypes["terminal"] = terminal.length;
|
|
141
|
+
if (ci.length) eventTypes["ci"] = ci.length;
|
|
142
|
+
if (deploys.length) eventTypes["deploy"] = deploys.length;
|
|
143
|
+
const totalEvents = Object.values(eventTypes).reduce((a, b) => a + b, 0);
|
|
144
|
+
const levelCounts = {};
|
|
145
|
+
for (const l of logs) {
|
|
146
|
+
const lv = l.level ?? "log";
|
|
147
|
+
levelCounts[lv] = (levelCounts[lv] ?? 0) + 1;
|
|
148
|
+
}
|
|
149
|
+
const urlPatterns = /* @__PURE__ */ new Set();
|
|
150
|
+
for (const n of network) {
|
|
151
|
+
try {
|
|
152
|
+
const u = new URL(n.url ?? "");
|
|
153
|
+
const parts = u.pathname.split("/").filter(Boolean);
|
|
154
|
+
urlPatterns.add("/" + (parts.slice(0, 2).join("/") || ""));
|
|
155
|
+
} catch {
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
const services = /* @__PURE__ */ new Set();
|
|
159
|
+
for (const c of ctx) {
|
|
160
|
+
if (c.service) services.add(c.service);
|
|
161
|
+
}
|
|
162
|
+
for (const l of logs) {
|
|
163
|
+
const m = String(l.args?.[0] ?? "").match(/^\[([a-z0-9_-]{2,24})\]/i);
|
|
164
|
+
if (m) services.add(m[1].toLowerCase());
|
|
165
|
+
}
|
|
166
|
+
const errorMsgs = logs.filter((l) => l.level === "error").map((l) => String(l.args?.[0] ?? ""));
|
|
167
|
+
const errorPatternMap = /* @__PURE__ */ new Map();
|
|
168
|
+
for (const msg of errorMsgs) {
|
|
169
|
+
const pat = msg.replace(/\d{3,}/g, "N").replace(/"[^"]{0,40}"/g, '"\u2026"').slice(0, 80);
|
|
170
|
+
if (!errorPatternMap.has(pat)) errorPatternMap.set(pat, msg);
|
|
171
|
+
}
|
|
172
|
+
const errorPatterns = [...errorPatternMap.keys()].slice(0, 10);
|
|
173
|
+
const allTs = [
|
|
174
|
+
...logs.map((l) => l.timestamp),
|
|
175
|
+
...network.map((n) => n.timestamp)
|
|
176
|
+
].filter(Boolean);
|
|
177
|
+
const minTs = allTs.length ? Math.min(...allTs) : null;
|
|
178
|
+
const maxTs = allTs.length ? Math.max(...allTs) : null;
|
|
179
|
+
const statusBuckets = {};
|
|
180
|
+
for (const n of network) {
|
|
181
|
+
const s = n.status ?? 0;
|
|
182
|
+
const bucket = s >= 500 ? "5xx" : s >= 400 ? "4xx" : s >= 300 ? "3xx" : s >= 200 ? "2xx" : "other";
|
|
183
|
+
statusBuckets[bucket] = (statusBuckets[bucket] ?? 0) + 1;
|
|
184
|
+
}
|
|
185
|
+
const lines = [
|
|
186
|
+
"## Buffer Schema",
|
|
187
|
+
"",
|
|
188
|
+
`**Total events:** ${totalEvents}`,
|
|
189
|
+
"",
|
|
190
|
+
"### Event Types",
|
|
191
|
+
...Object.entries(eventTypes).map(([k, v]) => `- \`${k}\`: ${v} events`),
|
|
192
|
+
"",
|
|
193
|
+
"### Log Levels",
|
|
194
|
+
Object.keys(levelCounts).length > 0 ? Object.entries(levelCounts).map(([k, v]) => `- \`${k}\`: ${v}`).join("\n") : "_No console events_",
|
|
195
|
+
"",
|
|
196
|
+
"### Network Status Distribution",
|
|
197
|
+
Object.keys(statusBuckets).length > 0 ? Object.entries(statusBuckets).map(([k, v]) => `- \`${k}\`: ${v}`).join("\n") : "_No network events_",
|
|
198
|
+
"",
|
|
199
|
+
"### URL Patterns (top path prefixes)",
|
|
200
|
+
[...urlPatterns].length > 0 ? [...urlPatterns].slice(0, 15).map((u) => `- \`${u}\``).join("\n") : "_No network events_",
|
|
201
|
+
"",
|
|
202
|
+
"### Detected Services",
|
|
203
|
+
[...services].length > 0 ? [...services].slice(0, 10).map((s) => `- \`${s}\``).join("\n") : "_No service identifiers detected_",
|
|
204
|
+
"",
|
|
205
|
+
"### Error Patterns",
|
|
206
|
+
errorPatterns.length > 0 ? errorPatterns.map((p, i) => {
|
|
207
|
+
const sample = include_samples ? `
|
|
208
|
+
_Sample: ${errorPatternMap.get(p)?.slice(0, 100)}_` : "";
|
|
209
|
+
return `${i + 1}. \`${p}\`${sample}`;
|
|
210
|
+
}).join("\n") : "_No errors in buffer_",
|
|
211
|
+
"",
|
|
212
|
+
"### Time Range",
|
|
213
|
+
minTs && maxTs ? `- Oldest: ${new Date(minTs).toISOString()}
|
|
214
|
+
- Newest: ${new Date(maxTs).toISOString()}
|
|
215
|
+
- Span: ${Math.round((maxTs - minTs) / 1e3)}s` : "_No timestamped events_",
|
|
216
|
+
"",
|
|
217
|
+
"---",
|
|
218
|
+
"_Call `analyze_runtime` to run full causal analysis, or `get_recent_logs` to read raw events._"
|
|
219
|
+
];
|
|
220
|
+
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
221
|
+
}
|
|
222
|
+
);
|
|
223
|
+
server.registerTool(
|
|
224
|
+
"get_behavior_map",
|
|
225
|
+
{
|
|
226
|
+
description: "Returns the living runtime behavior map of the system based on actual call traces. Shows service nodes, communication edges, latency stats, error rates, and critical paths. Use this to understand service connections and trace dependencies.",
|
|
227
|
+
inputSchema: {}
|
|
228
|
+
},
|
|
229
|
+
async () => {
|
|
230
|
+
trackCall("get_behavior_map");
|
|
231
|
+
const snap = serviceTopology.snapshot();
|
|
232
|
+
if (snap.nodes.length === 0) {
|
|
233
|
+
return {
|
|
234
|
+
content: [{
|
|
235
|
+
type: "text",
|
|
236
|
+
text: "## Living Behavior Map\n\nNo telemetry data available yet to build the map. Run your application and trigger network calls to build the topology."
|
|
237
|
+
}]
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
const lines = [
|
|
241
|
+
"## \u{1F310} Living Behavior Map (Behavior Memory)",
|
|
242
|
+
"",
|
|
243
|
+
`*Auto-generated topology based on live traces as of ${snap.capturedAt}*`,
|
|
244
|
+
"",
|
|
245
|
+
"### \u{1F5A5}\uFE0F Services / Nodes",
|
|
246
|
+
"| Service Name | Type | Average Latency | p99 Latency | Call Count | Error Count |",
|
|
247
|
+
"|---|---|---|---|---|---|",
|
|
248
|
+
...snap.nodes.map(
|
|
249
|
+
(n) => `| \`${n.name}\` | \`${n.type}\` | ${n.avgDurationMs}ms | ${n.p99DurationMs}ms | ${n.spanCount} | ${n.errorCount} |`
|
|
250
|
+
),
|
|
251
|
+
"",
|
|
252
|
+
"### \u{1F50C} Connections / Edges",
|
|
253
|
+
"| Caller | Receiver | Call Count | Error Count | Average Latency |",
|
|
254
|
+
"|---|---|---|---|---|",
|
|
255
|
+
...snap.edges.map(
|
|
256
|
+
(e) => `| \`${e.from}\` | \`${e.to}\` | ${e.callCount} | ${e.errorCount} | ${e.avgDurationMs}ms |`
|
|
257
|
+
),
|
|
258
|
+
"",
|
|
259
|
+
"### \u{1F4CA} Summary",
|
|
260
|
+
`- **Total Services**: ${snap.summary.totalServices}`,
|
|
261
|
+
`- **Total Edges**: ${snap.summary.totalEdges}`
|
|
262
|
+
];
|
|
263
|
+
if (snap.summary.errorHotspot) {
|
|
264
|
+
lines.push(`- \u26A0\uFE0F **Error Hotspot**: \`${snap.summary.errorHotspot}\` has the highest error rate.`);
|
|
265
|
+
}
|
|
266
|
+
if (snap.summary.slowestEdge) {
|
|
267
|
+
const { from, to, avgDurationMs } = snap.summary.slowestEdge;
|
|
268
|
+
lines.push(`- \u{1F422} **Slowest Connection**: \`${from}\` \u2192 \`${to}\` (Average: ${avgDurationMs}ms)`);
|
|
269
|
+
}
|
|
270
|
+
if (snap.summary.criticalPath && snap.summary.criticalPath.length > 0) {
|
|
271
|
+
lines.push(`- \u26D3\uFE0F **Critical Execution Path**: ${snap.summary.criticalPath.map((s) => `\`${s}\``).join(" \u2192 ")}`);
|
|
272
|
+
}
|
|
273
|
+
return {
|
|
274
|
+
content: [{
|
|
275
|
+
type: "text",
|
|
276
|
+
text: lines.join("\n")
|
|
277
|
+
}]
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
);
|
|
281
|
+
}
|
|
282
|
+
export {
|
|
283
|
+
registerDiscoveryTools
|
|
284
|
+
};
|