dravix-agent 0.1.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/.claude/settings.example.json +30 -0
- package/ARCHITECTURE.md +410 -0
- package/LICENSE +21 -0
- package/README.md +153 -0
- package/ROADMAP.md +117 -0
- package/data/vulnkb.json +666 -0
- package/dist/bin/aegis.d.ts +3 -0
- package/dist/bin/aegis.d.ts.map +1 -0
- package/dist/bin/aegis.js +489 -0
- package/dist/bin/aegis.js.map +1 -0
- package/dist/cache.d.ts +9 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +146 -0
- package/dist/cache.js.map +1 -0
- package/dist/engines/ai-sinks.d.ts +52 -0
- package/dist/engines/ai-sinks.d.ts.map +1 -0
- package/dist/engines/ai-sinks.js +204 -0
- package/dist/engines/ai-sinks.js.map +1 -0
- package/dist/engines/eslint.d.ts +9 -0
- package/dist/engines/eslint.d.ts.map +1 -0
- package/dist/engines/eslint.js +245 -0
- package/dist/engines/eslint.js.map +1 -0
- package/dist/engines/joern.d.ts +3 -0
- package/dist/engines/joern.d.ts.map +1 -0
- package/dist/engines/joern.js +98 -0
- package/dist/engines/joern.js.map +1 -0
- package/dist/engines/js-sinks.d.ts +70 -0
- package/dist/engines/js-sinks.d.ts.map +1 -0
- package/dist/engines/js-sinks.js +370 -0
- package/dist/engines/js-sinks.js.map +1 -0
- package/dist/engines/llm-critic.d.ts +130 -0
- package/dist/engines/llm-critic.d.ts.map +1 -0
- package/dist/engines/llm-critic.js +551 -0
- package/dist/engines/llm-critic.js.map +1 -0
- package/dist/engines/pragma.d.ts +20 -0
- package/dist/engines/pragma.d.ts.map +1 -0
- package/dist/engines/pragma.js +83 -0
- package/dist/engines/pragma.js.map +1 -0
- package/dist/engines/property-test.d.ts +3 -0
- package/dist/engines/property-test.d.ts.map +1 -0
- package/dist/engines/property-test.js +134 -0
- package/dist/engines/property-test.js.map +1 -0
- package/dist/engines/pyright.d.ts +10 -0
- package/dist/engines/pyright.d.ts.map +1 -0
- package/dist/engines/pyright.js +143 -0
- package/dist/engines/pyright.js.map +1 -0
- package/dist/engines/pysa.d.ts +3 -0
- package/dist/engines/pysa.d.ts.map +1 -0
- package/dist/engines/pysa.js +83 -0
- package/dist/engines/pysa.js.map +1 -0
- package/dist/engines/python-sinks.d.ts +82 -0
- package/dist/engines/python-sinks.d.ts.map +1 -0
- package/dist/engines/python-sinks.js +459 -0
- package/dist/engines/python-sinks.js.map +1 -0
- package/dist/engines/registry.d.ts +26 -0
- package/dist/engines/registry.d.ts.map +1 -0
- package/dist/engines/registry.js +70 -0
- package/dist/engines/registry.js.map +1 -0
- package/dist/engines/secret-scan.d.ts +22 -0
- package/dist/engines/secret-scan.d.ts.map +1 -0
- package/dist/engines/secret-scan.js +179 -0
- package/dist/engines/secret-scan.js.map +1 -0
- package/dist/engines/semgrep.d.ts +10 -0
- package/dist/engines/semgrep.d.ts.map +1 -0
- package/dist/engines/semgrep.js +200 -0
- package/dist/engines/semgrep.js.map +1 -0
- package/dist/engines/treesitter.d.ts +18 -0
- package/dist/engines/treesitter.d.ts.map +1 -0
- package/dist/engines/treesitter.js +135 -0
- package/dist/engines/treesitter.js.map +1 -0
- package/dist/engines/tsc.d.ts +10 -0
- package/dist/engines/tsc.d.ts.map +1 -0
- package/dist/engines/tsc.js +142 -0
- package/dist/engines/tsc.js.map +1 -0
- package/dist/engines/types.d.ts +47 -0
- package/dist/engines/types.d.ts.map +1 -0
- package/dist/engines/types.js +27 -0
- package/dist/engines/types.js.map +1 -0
- package/dist/findings.d.ts +121 -0
- package/dist/findings.d.ts.map +1 -0
- package/dist/findings.js +98 -0
- package/dist/findings.js.map +1 -0
- package/dist/hooks/claude-code.d.ts +3 -0
- package/dist/hooks/claude-code.d.ts.map +1 -0
- package/dist/hooks/claude-code.js +187 -0
- package/dist/hooks/claude-code.js.map +1 -0
- package/dist/index/context.d.ts +127 -0
- package/dist/index/context.d.ts.map +1 -0
- package/dist/index/context.js +267 -0
- package/dist/index/context.js.map +1 -0
- package/dist/index/embeddings.d.ts +68 -0
- package/dist/index/embeddings.d.ts.map +1 -0
- package/dist/index/embeddings.js +570 -0
- package/dist/index/embeddings.js.map +1 -0
- package/dist/index/graph_routing.d.ts +36 -0
- package/dist/index/graph_routing.d.ts.map +1 -0
- package/dist/index/graph_routing.js +170 -0
- package/dist/index/graph_routing.js.map +1 -0
- package/dist/index/joern.d.ts +76 -0
- package/dist/index/joern.d.ts.map +1 -0
- package/dist/index/joern.js +782 -0
- package/dist/index/joern.js.map +1 -0
- package/dist/index/property-test.d.ts +88 -0
- package/dist/index/property-test.d.ts.map +1 -0
- package/dist/index/property-test.js +466 -0
- package/dist/index/property-test.js.map +1 -0
- package/dist/index/proto/scip.proto +897 -0
- package/dist/index/pysa.d.ts +91 -0
- package/dist/index/pysa.d.ts.map +1 -0
- package/dist/index/pysa.js +617 -0
- package/dist/index/pysa.js.map +1 -0
- package/dist/index/scip.d.ts +76 -0
- package/dist/index/scip.d.ts.map +1 -0
- package/dist/index/scip.js +541 -0
- package/dist/index/scip.js.map +1 -0
- package/dist/index/vulrag.d.ts +86 -0
- package/dist/index/vulrag.d.ts.map +1 -0
- package/dist/index/vulrag.js +242 -0
- package/dist/index/vulrag.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/install/claude-code.d.ts +31 -0
- package/dist/install/claude-code.d.ts.map +1 -0
- package/dist/install/claude-code.js +447 -0
- package/dist/install/claude-code.js.map +1 -0
- package/dist/lang.d.ts +5 -0
- package/dist/lang.d.ts.map +1 -0
- package/dist/lang.js +52 -0
- package/dist/lang.js.map +1 -0
- package/dist/learning/suppressions.d.ts +70 -0
- package/dist/learning/suppressions.d.ts.map +1 -0
- package/dist/learning/suppressions.js +179 -0
- package/dist/learning/suppressions.js.map +1 -0
- package/dist/mcp/server.d.ts +2 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +187 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/tools/explain.d.ts +58 -0
- package/dist/mcp/tools/explain.d.ts.map +1 -0
- package/dist/mcp/tools/explain.js +60 -0
- package/dist/mcp/tools/explain.js.map +1 -0
- package/dist/mcp/tools/precheck.d.ts +29 -0
- package/dist/mcp/tools/precheck.d.ts.map +1 -0
- package/dist/mcp/tools/precheck.js +42 -0
- package/dist/mcp/tools/precheck.js.map +1 -0
- package/dist/mcp/tools/validate.d.ts +73 -0
- package/dist/mcp/tools/validate.d.ts.map +1 -0
- package/dist/mcp/tools/validate.js +66 -0
- package/dist/mcp/tools/validate.js.map +1 -0
- package/dist/mcp/warm.d.ts +88 -0
- package/dist/mcp/warm.d.ts.map +1 -0
- package/dist/mcp/warm.js +331 -0
- package/dist/mcp/warm.js.map +1 -0
- package/dist/orchestrator.d.ts +46 -0
- package/dist/orchestrator.d.ts.map +1 -0
- package/dist/orchestrator.js +596 -0
- package/dist/orchestrator.js.map +1 -0
- package/dist/policy.d.ts +51 -0
- package/dist/policy.d.ts.map +1 -0
- package/dist/policy.js +201 -0
- package/dist/policy.js.map +1 -0
- package/dist/risk.d.ts +31 -0
- package/dist/risk.d.ts.map +1 -0
- package/dist/risk.js +92 -0
- package/dist/risk.js.map +1 -0
- package/dist/stats.d.ts +72 -0
- package/dist/stats.d.ts.map +1 -0
- package/dist/stats.js +217 -0
- package/dist/stats.js.map +1 -0
- package/dist/telemetry/collector.d.ts +10 -0
- package/dist/telemetry/collector.d.ts.map +1 -0
- package/dist/telemetry/collector.js +75 -0
- package/dist/telemetry/collector.js.map +1 -0
- package/dist/telemetry/consent.d.ts +9 -0
- package/dist/telemetry/consent.d.ts.map +1 -0
- package/dist/telemetry/consent.js +42 -0
- package/dist/telemetry/consent.js.map +1 -0
- package/dist/telemetry/installation.d.ts +2 -0
- package/dist/telemetry/installation.d.ts.map +1 -0
- package/dist/telemetry/installation.js +32 -0
- package/dist/telemetry/installation.js.map +1 -0
- package/dist/telemetry/sanitizer.d.ts +5 -0
- package/dist/telemetry/sanitizer.d.ts.map +1 -0
- package/dist/telemetry/sanitizer.js +60 -0
- package/dist/telemetry/sanitizer.js.map +1 -0
- package/dist/telemetry/types.d.ts +39 -0
- package/dist/telemetry/types.d.ts.map +1 -0
- package/dist/telemetry/types.js +4 -0
- package/dist/telemetry/types.js.map +1 -0
- package/dist/telemetry/uploader.d.ts +12 -0
- package/dist/telemetry/uploader.d.ts.map +1 -0
- package/dist/telemetry/uploader.js +92 -0
- package/dist/telemetry/uploader.js.map +1 -0
- package/dist/util/logger.d.ts +19 -0
- package/dist/util/logger.d.ts.map +1 -0
- package/dist/util/logger.js +58 -0
- package/dist/util/logger.js.map +1 -0
- package/dist/util/safe-paths.d.ts +8 -0
- package/dist/util/safe-paths.d.ts.map +1 -0
- package/dist/util/safe-paths.js +102 -0
- package/dist/util/safe-paths.js.map +1 -0
- package/dist/util/subprocess.d.ts +32 -0
- package/dist/util/subprocess.d.ts.map +1 -0
- package/dist/util/subprocess.js +137 -0
- package/dist/util/subprocess.js.map +1 -0
- package/package.json +93 -0
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `validate_edit` — authoritative gate (PostToolUse).
|
|
3
|
+
*
|
|
4
|
+
* Uses the MCP warm fast-path:
|
|
5
|
+
* 1. in-mem verdict LRU lookup (sub-millisecond on hit)
|
|
6
|
+
* 2. single-flight dedup for concurrent identical scans
|
|
7
|
+
* 3. fresh runGate() with precomputed engine availability
|
|
8
|
+
*/
|
|
9
|
+
import { z } from "zod";
|
|
10
|
+
export declare const validateEditInputSchema: z.ZodObject<{
|
|
11
|
+
file_path: z.ZodString;
|
|
12
|
+
content: z.ZodString;
|
|
13
|
+
project_root: z.ZodOptional<z.ZodString>;
|
|
14
|
+
/** Override engines (rare — for tests). */
|
|
15
|
+
engines: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
16
|
+
}, "strip", z.ZodTypeAny, {
|
|
17
|
+
file_path: string;
|
|
18
|
+
content: string;
|
|
19
|
+
project_root?: string | undefined;
|
|
20
|
+
engines?: string[] | undefined;
|
|
21
|
+
}, {
|
|
22
|
+
file_path: string;
|
|
23
|
+
content: string;
|
|
24
|
+
project_root?: string | undefined;
|
|
25
|
+
engines?: string[] | undefined;
|
|
26
|
+
}>;
|
|
27
|
+
export type ValidateEditInput = z.infer<typeof validateEditInputSchema>;
|
|
28
|
+
export interface ValidateEditOutput {
|
|
29
|
+
verdict: "allow" | "warn" | "block";
|
|
30
|
+
summary: string;
|
|
31
|
+
duration_ms: number;
|
|
32
|
+
truncated: boolean;
|
|
33
|
+
/** Origin of the verdict — "lru" = in-mem cache hit (sub-ms),
|
|
34
|
+
* "fresh" = full gate run. Useful for clients to display "cached" badges. */
|
|
35
|
+
cache_source: "lru" | "single-flight" | "fresh";
|
|
36
|
+
findings: Array<{
|
|
37
|
+
id: string;
|
|
38
|
+
engine: string;
|
|
39
|
+
rule_id: string;
|
|
40
|
+
file: string;
|
|
41
|
+
line?: number;
|
|
42
|
+
col?: number;
|
|
43
|
+
cwe?: string;
|
|
44
|
+
severity: string;
|
|
45
|
+
confidence: number;
|
|
46
|
+
message: string;
|
|
47
|
+
remediation?: string;
|
|
48
|
+
}>;
|
|
49
|
+
/** Phase-1 sidecar: cross-file evidence (definitions of imports + callers).
|
|
50
|
+
* Present iff a SCIP index exists for the project. */
|
|
51
|
+
project_context?: {
|
|
52
|
+
available: boolean;
|
|
53
|
+
languages: string[];
|
|
54
|
+
imported_definitions: Array<{
|
|
55
|
+
symbol: string;
|
|
56
|
+
kind: string;
|
|
57
|
+
file: string;
|
|
58
|
+
line: number;
|
|
59
|
+
snippet?: string;
|
|
60
|
+
}>;
|
|
61
|
+
callers: Array<{
|
|
62
|
+
symbol: string;
|
|
63
|
+
callers: Array<{
|
|
64
|
+
file: string;
|
|
65
|
+
line: number;
|
|
66
|
+
}>;
|
|
67
|
+
}>;
|
|
68
|
+
duration_ms: number;
|
|
69
|
+
};
|
|
70
|
+
remediation_prompt?: string;
|
|
71
|
+
}
|
|
72
|
+
export declare function runValidateEdit(input: ValidateEditInput): Promise<ValidateEditOutput>;
|
|
73
|
+
//# sourceMappingURL=validate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/validate.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,eAAO,MAAM,uBAAuB;;;;IAIlC,2CAA2C;;;;;;;;;;;;EAE3C,CAAC;AAEH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAExE,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB;iFAC6E;IAC7E,YAAY,EAAE,KAAK,GAAG,eAAe,GAAG,OAAO,CAAC;IAChD,QAAQ,EAAE,KAAK,CAAC;QACd,EAAE,EAAE,MAAM,CAAC;QACX,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,MAAM,CAAC;QACjB,UAAU,EAAE,MAAM,CAAC;QACnB,OAAO,EAAE,MAAM,CAAC;QAChB,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC,CAAC;IACH;0DACsD;IACtD,eAAe,CAAC,EAAE;QAChB,SAAS,EAAE,OAAO,CAAC;QACnB,SAAS,EAAE,MAAM,EAAE,CAAC;QACpB,oBAAoB,EAAE,KAAK,CAAC;YAC1B,MAAM,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAC;YAAC,OAAO,CAAC,EAAE,MAAM,CAAC;SAC5E,CAAC,CAAC;QACH,OAAO,EAAE,KAAK,CAAC;YACb,MAAM,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,KAAK,CAAC;gBAAE,IAAI,EAAE,MAAM,CAAC;gBAAC,IAAI,EAAE,MAAM,CAAA;aAAE,CAAC,CAAC;SAChE,CAAC,CAAC;QACH,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC;IACF,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,wBAAsB,eAAe,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAoC3F"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `validate_edit` — authoritative gate (PostToolUse).
|
|
3
|
+
*
|
|
4
|
+
* Uses the MCP warm fast-path:
|
|
5
|
+
* 1. in-mem verdict LRU lookup (sub-millisecond on hit)
|
|
6
|
+
* 2. single-flight dedup for concurrent identical scans
|
|
7
|
+
* 3. fresh runGate() with precomputed engine availability
|
|
8
|
+
*/
|
|
9
|
+
import { z } from "zod";
|
|
10
|
+
import { runGateFast } from "../warm.js";
|
|
11
|
+
export const validateEditInputSchema = z.object({
|
|
12
|
+
file_path: z.string().min(1),
|
|
13
|
+
content: z.string(),
|
|
14
|
+
project_root: z.string().optional(),
|
|
15
|
+
/** Override engines (rare — for tests). */
|
|
16
|
+
engines: z.array(z.string()).optional(),
|
|
17
|
+
});
|
|
18
|
+
export async function runValidateEdit(input) {
|
|
19
|
+
const { report, source } = await runGateFast({
|
|
20
|
+
filePath: input.file_path,
|
|
21
|
+
content: input.content,
|
|
22
|
+
...(input.project_root !== undefined ? { projectRoot: input.project_root } : {}),
|
|
23
|
+
});
|
|
24
|
+
const findings = report.findings.map((f) => ({
|
|
25
|
+
id: f.id,
|
|
26
|
+
engine: f.engine,
|
|
27
|
+
rule_id: f.rule_id,
|
|
28
|
+
file: f.file,
|
|
29
|
+
...(f.line !== undefined ? { line: f.line } : {}),
|
|
30
|
+
...(f.col !== undefined ? { col: f.col } : {}),
|
|
31
|
+
...(f.cwe !== undefined ? { cwe: f.cwe } : {}),
|
|
32
|
+
severity: f.severity,
|
|
33
|
+
confidence: f.confidence,
|
|
34
|
+
message: f.message,
|
|
35
|
+
...(f.remediation !== undefined ? { remediation: f.remediation } : {}),
|
|
36
|
+
}));
|
|
37
|
+
const out = {
|
|
38
|
+
verdict: report.decision.action,
|
|
39
|
+
summary: report.decision.summary,
|
|
40
|
+
duration_ms: report.durationMs,
|
|
41
|
+
truncated: report.truncated,
|
|
42
|
+
cache_source: source,
|
|
43
|
+
findings,
|
|
44
|
+
};
|
|
45
|
+
if (report.projectContext) {
|
|
46
|
+
out.project_context = report.projectContext;
|
|
47
|
+
}
|
|
48
|
+
if (report.decision.action === "block") {
|
|
49
|
+
out.remediation_prompt = formatRemediation(report.filePath, findings.slice(0, 5));
|
|
50
|
+
}
|
|
51
|
+
return out;
|
|
52
|
+
}
|
|
53
|
+
function formatRemediation(filePath, top) {
|
|
54
|
+
const lines = [];
|
|
55
|
+
lines.push(`The proposed write to ${filePath} was blocked by Aegis. Fix:`);
|
|
56
|
+
for (const f of top) {
|
|
57
|
+
const loc = f.line ? `:${f.line}` : "";
|
|
58
|
+
const cwe = f.cwe ? ` [${f.cwe}]` : "";
|
|
59
|
+
lines.push(`- ${f.engine}/${f.rule_id}${cwe} at ${f.file}${loc} — ${f.message}`);
|
|
60
|
+
if (f.remediation)
|
|
61
|
+
lines.push(` fix: ${f.remediation}`);
|
|
62
|
+
}
|
|
63
|
+
lines.push("Regenerate the file applying all the items above, then save again.");
|
|
64
|
+
return lines.join("\n");
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=validate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../../src/mcp/tools/validate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import type { Engine } from "../engines/types.js";
|
|
2
|
+
import { type GateInput, type GateReport } from "../orchestrator.js";
|
|
3
|
+
declare class VerdictLru {
|
|
4
|
+
private readonly cap;
|
|
5
|
+
private readonly ttlMs;
|
|
6
|
+
private readonly map;
|
|
7
|
+
private hits;
|
|
8
|
+
private misses;
|
|
9
|
+
private evictions;
|
|
10
|
+
constructor(cap: number, ttlMs: number);
|
|
11
|
+
get(key: string): GateReport | undefined;
|
|
12
|
+
put(key: string, report: GateReport): void;
|
|
13
|
+
size(): number;
|
|
14
|
+
stats(): {
|
|
15
|
+
hits: number;
|
|
16
|
+
misses: number;
|
|
17
|
+
evictions: number;
|
|
18
|
+
size: number;
|
|
19
|
+
cap: number;
|
|
20
|
+
};
|
|
21
|
+
clear(): void;
|
|
22
|
+
}
|
|
23
|
+
/** sha256 of the full input that determines verdict identity. Same key →
|
|
24
|
+
* same verdict iff our engines and policy haven't changed (we DON'T cache
|
|
25
|
+
* across policy edits — see notes at the call site). */
|
|
26
|
+
export declare function verdictCacheKey(input: GateInput, engineSetTag: string): string;
|
|
27
|
+
/** De-dup concurrent identical scans. Two agents calling ``validate_edit``
|
|
28
|
+
* with the same content at the same instant share ONE underlying gate
|
|
29
|
+
* run; the second callee awaits the same promise. Frees the system from
|
|
30
|
+
* O(N) LLM-critic calls under burst load. */
|
|
31
|
+
export declare function singleFlight(key: string, fn: () => Promise<GateReport>): Promise<GateReport>;
|
|
32
|
+
/** Probe every engine ONCE at boot. Subsequent runGate() calls can rely
|
|
33
|
+
* on this map instead of awaiting `e.available()` per engine per call. */
|
|
34
|
+
export declare function computeAvailability(): Promise<Map<string, boolean>>;
|
|
35
|
+
/** Get the precomputed availability snapshot. Returns null before
|
|
36
|
+
* ``warmAtBoot()`` completes. Callers SHOULD fall back to per-engine
|
|
37
|
+
* ``e.available()`` if null. */
|
|
38
|
+
export declare function availabilitySnapshot(): Map<string, boolean> | null;
|
|
39
|
+
/** Force a fresh probe (e.g. user just ran `pip install semgrep` mid-session). */
|
|
40
|
+
export declare function refreshAvailability(): Promise<Map<string, boolean>>;
|
|
41
|
+
interface WarmState {
|
|
42
|
+
warmedAt: number;
|
|
43
|
+
durationMs: number;
|
|
44
|
+
vulRagOk: boolean;
|
|
45
|
+
vulRagEntries: number;
|
|
46
|
+
engineCount: number;
|
|
47
|
+
engineAvailable: number;
|
|
48
|
+
claudeBin: string | null;
|
|
49
|
+
}
|
|
50
|
+
/** Eagerly load every subsystem that the hook path lazy-loads. Idempotent.
|
|
51
|
+
* Returns the cached state if already warmed. Concurrent callers share
|
|
52
|
+
* the same in-flight warm promise. */
|
|
53
|
+
export declare function warmAtBoot(): Promise<WarmState>;
|
|
54
|
+
/** Snapshot of warm state for ``aegis.health`` probe / debug. */
|
|
55
|
+
export declare function warmStateSnapshot(): WarmState | null;
|
|
56
|
+
/** Run the gate with full warm-path optimisation:
|
|
57
|
+
*
|
|
58
|
+
* 1. In-memory LRU lookup (returns in <0.2 ms when hit).
|
|
59
|
+
* 2. Single-flight dedup: if another call is in flight for the same key,
|
|
60
|
+
* wait for it instead of starting a parallel one.
|
|
61
|
+
* 3. Forward to ``runGate``, passing the warm availability snapshot so
|
|
62
|
+
* the orchestrator skips per-call ``e.available()`` awaits.
|
|
63
|
+
* 4. Store the resulting report in the LRU.
|
|
64
|
+
*
|
|
65
|
+
* Non-cacheable scans (``noCache: true``) bypass steps 1-2-4 — used by
|
|
66
|
+
* the precheck path which always wants fresh.
|
|
67
|
+
*/
|
|
68
|
+
export declare function runGateFast(input: GateInput): Promise<{
|
|
69
|
+
report: GateReport;
|
|
70
|
+
source: "lru" | "single-flight" | "fresh";
|
|
71
|
+
}>;
|
|
72
|
+
export declare function warmMetrics(): {
|
|
73
|
+
verdict_lru: ReturnType<VerdictLru["stats"]>;
|
|
74
|
+
inflight: number;
|
|
75
|
+
engine_set_tag: string;
|
|
76
|
+
warm: WarmState | null;
|
|
77
|
+
};
|
|
78
|
+
/** Reset all warm state. Tests only — production code must NOT call this. */
|
|
79
|
+
export declare function _resetWarmStateForTests(): void;
|
|
80
|
+
/** Expose internal hooks for unit tests. */
|
|
81
|
+
export declare const _testing: {
|
|
82
|
+
verdictLru: VerdictLru;
|
|
83
|
+
inflight: Map<string, Promise<GateReport>>;
|
|
84
|
+
ENGINE_SET_TAG: string;
|
|
85
|
+
engineSet: () => ReadonlyArray<Engine>;
|
|
86
|
+
};
|
|
87
|
+
export {};
|
|
88
|
+
//# sourceMappingURL=warm.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"warm.d.ts","sourceRoot":"","sources":["../../src/mcp/warm.ts"],"names":[],"mappings":"AAkCA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAGlD,OAAO,EAAW,KAAK,SAAS,EAAE,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AA6B9E,cAAM,UAAU;IACd,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAmC;IACvD,OAAO,CAAC,IAAI,CAAK;IACjB,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,SAAS,CAAK;gBAEV,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;IAKtC,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS;IAkBxC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI;IAW1C,IAAI,IAAI,MAAM;IAId,KAAK,IAAI;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE;IAUvF,KAAK,IAAI,IAAI;CAMd;AAID;;wDAEwD;AACxD,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAW9E;AAMD;;;6CAG6C;AAC7C,wBAAsB,YAAY,CAChC,GAAG,EAAE,MAAM,EACX,EAAE,EAAE,MAAM,OAAO,CAAC,UAAU,CAAC,GAC5B,OAAO,CAAC,UAAU,CAAC,CAYrB;AAMD;0EAC0E;AAC1E,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAiBzE;AAED;;gCAEgC;AAChC,wBAAgB,oBAAoB,IAAI,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAElE;AAED,kFAAkF;AAClF,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAEzE;AAID,UAAU,SAAS;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AA8BD;;sCAEsC;AACtC,wBAAsB,UAAU,IAAI,OAAO,CAAC,SAAS,CAAC,CA2DrD;AAED,iEAAiE;AACjE,wBAAgB,iBAAiB,IAAI,SAAS,GAAG,IAAI,CAEpD;AAYD;;;;;;;;;;;GAWG;AACH,wBAAsB,WAAW,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC;IAC3D,MAAM,EAAE,UAAU,CAAC;IACnB,MAAM,EAAE,KAAK,GAAG,eAAe,GAAG,OAAO,CAAC;CAC3C,CAAC,CA+BD;AAID,wBAAgB,WAAW,IAAI;IAC7B,WAAW,EAAE,UAAU,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC;IAC7C,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,SAAS,GAAG,IAAI,CAAC;CACxB,CAOA;AAID,6EAA6E;AAC7E,wBAAgB,uBAAuB,IAAI,IAAI,CAM9C;AAED,4CAA4C;AAC5C,eAAO,MAAM,QAAQ;;;;qBAIJ,aAAa,CAAC,MAAM,CAAC;CACrC,CAAC"}
|
package/dist/mcp/warm.js
ADDED
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Process-wide warm state for the MCP server.
|
|
3
|
+
*
|
|
4
|
+
* The aegis hook CLI pays full cold-start cost on every invocation
|
|
5
|
+
* (Vul-RAG KB embed, engine availability probes, LMDB open, claude
|
|
6
|
+
* binary discovery). For an interactive realtime gate this is
|
|
7
|
+
* unacceptable — a single fresh process is ~2-3 s before any actual
|
|
8
|
+
* scan work begins.
|
|
9
|
+
*
|
|
10
|
+
* The MCP server is long-running by design (stdio transport stays
|
|
11
|
+
* open for the entire IDE session). This module owns the state that
|
|
12
|
+
* needs to be hot from the very first tool call:
|
|
13
|
+
*
|
|
14
|
+
* - Vul-RAG: KB + embeddings loaded eagerly at boot.
|
|
15
|
+
* - SCIP indexer singleton: created (its real work is lazy
|
|
16
|
+
* per-project, but the singleton exists).
|
|
17
|
+
* - Claude binary discovery: ``which("claude")`` cached.
|
|
18
|
+
* - Per-engine availability map: computed once at boot, refreshed
|
|
19
|
+
* manually via ``refreshAvailability()`` if engines are
|
|
20
|
+
* installed during the session.
|
|
21
|
+
* - Verdict LRU keyed on (engine-set hash, sha256(content)): a
|
|
22
|
+
* sub-millisecond cache layer above LMDB. Hits return without
|
|
23
|
+
* touching disk.
|
|
24
|
+
* - Single-flight dedup: two concurrent identical scans share one
|
|
25
|
+
* in-flight ``runGate`` promise. Prevents N×LLM-critic blow-up
|
|
26
|
+
* when an agent fans out edits.
|
|
27
|
+
*
|
|
28
|
+
* The warm contract is opt-in — callers must `await warmAtBoot()`
|
|
29
|
+
* before the server's first tool call. ``server.ts`` does this
|
|
30
|
+
* before ``transport.connect()``.
|
|
31
|
+
*/
|
|
32
|
+
import { createHash } from "node:crypto";
|
|
33
|
+
import { ALL_ENGINES, ENGINES, STAGE2_ENGINES } from "../engines/registry.js";
|
|
34
|
+
import { getIndexer } from "../index/scip.js";
|
|
35
|
+
import { getVulRag } from "../index/vulrag.js";
|
|
36
|
+
import { runGate } from "../orchestrator.js";
|
|
37
|
+
import { getLogger } from "../util/logger.js";
|
|
38
|
+
import { which } from "../util/subprocess.js";
|
|
39
|
+
const log = getLogger("aegis.mcp.warm");
|
|
40
|
+
// ── Tunables ──────────────────────────────────────────────────────────────
|
|
41
|
+
/** Max verdicts retained in-process. 2k × ~5KB/verdict ≈ 10 MB worst case. */
|
|
42
|
+
const VERDICT_LRU_CAP = Number(process.env.AEGIS_MCP_VERDICT_LRU ?? 2000);
|
|
43
|
+
/** Soft time after which an in-mem verdict is re-validated against LMDB.
|
|
44
|
+
* Same content + same engine set → invariant verdict, so we can hold for
|
|
45
|
+
* a full coding session (8 h). */
|
|
46
|
+
const VERDICT_LRU_TTL_MS = Number(process.env.AEGIS_MCP_VERDICT_TTL_MS ?? 8 * 60 * 60 * 1000);
|
|
47
|
+
/** Per-call timeout for the boot warm-up of each subsystem. Vul-RAG
|
|
48
|
+
* embed of 60 entries on cold CPU is ~600 ms; SCIP indexer construction is
|
|
49
|
+
* trivial; ``which`` is <5 ms. 30 s is a generous upper bound that still
|
|
50
|
+
* fails fast if something is wedged. */
|
|
51
|
+
const WARM_PER_SUBSYSTEM_TIMEOUT_MS = 30_000;
|
|
52
|
+
class VerdictLru {
|
|
53
|
+
cap;
|
|
54
|
+
ttlMs;
|
|
55
|
+
map = new Map();
|
|
56
|
+
hits = 0;
|
|
57
|
+
misses = 0;
|
|
58
|
+
evictions = 0;
|
|
59
|
+
constructor(cap, ttlMs) {
|
|
60
|
+
this.cap = cap;
|
|
61
|
+
this.ttlMs = ttlMs;
|
|
62
|
+
}
|
|
63
|
+
get(key) {
|
|
64
|
+
const e = this.map.get(key);
|
|
65
|
+
if (!e) {
|
|
66
|
+
this.misses++;
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
if (Date.now() - e.storedAt > this.ttlMs) {
|
|
70
|
+
this.map.delete(key);
|
|
71
|
+
this.misses++;
|
|
72
|
+
return undefined;
|
|
73
|
+
}
|
|
74
|
+
// Move-to-end = recency bump.
|
|
75
|
+
this.map.delete(key);
|
|
76
|
+
this.map.set(key, e);
|
|
77
|
+
this.hits++;
|
|
78
|
+
return e.report;
|
|
79
|
+
}
|
|
80
|
+
put(key, report) {
|
|
81
|
+
if (this.map.has(key))
|
|
82
|
+
this.map.delete(key);
|
|
83
|
+
this.map.set(key, { report, storedAt: Date.now() });
|
|
84
|
+
while (this.map.size > this.cap) {
|
|
85
|
+
const oldest = this.map.keys().next().value;
|
|
86
|
+
if (oldest === undefined)
|
|
87
|
+
break;
|
|
88
|
+
this.map.delete(oldest);
|
|
89
|
+
this.evictions++;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
size() {
|
|
93
|
+
return this.map.size;
|
|
94
|
+
}
|
|
95
|
+
stats() {
|
|
96
|
+
return {
|
|
97
|
+
hits: this.hits,
|
|
98
|
+
misses: this.misses,
|
|
99
|
+
evictions: this.evictions,
|
|
100
|
+
size: this.map.size,
|
|
101
|
+
cap: this.cap,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
clear() {
|
|
105
|
+
this.map.clear();
|
|
106
|
+
this.hits = 0;
|
|
107
|
+
this.misses = 0;
|
|
108
|
+
this.evictions = 0;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
const verdictLru = new VerdictLru(VERDICT_LRU_CAP, VERDICT_LRU_TTL_MS);
|
|
112
|
+
/** sha256 of the full input that determines verdict identity. Same key →
|
|
113
|
+
* same verdict iff our engines and policy haven't changed (we DON'T cache
|
|
114
|
+
* across policy edits — see notes at the call site). */
|
|
115
|
+
export function verdictCacheKey(input, engineSetTag) {
|
|
116
|
+
const h = createHash("sha256");
|
|
117
|
+
h.update(engineSetTag);
|
|
118
|
+
h.update("\0");
|
|
119
|
+
h.update(input.filePath);
|
|
120
|
+
h.update("\0");
|
|
121
|
+
// projectRoot affects findings via policy + suppressions + SCIP context.
|
|
122
|
+
h.update(input.projectRoot ?? "");
|
|
123
|
+
h.update("\0");
|
|
124
|
+
h.update(input.content);
|
|
125
|
+
return h.digest("hex").slice(0, 32);
|
|
126
|
+
}
|
|
127
|
+
// ── Single-flight ─────────────────────────────────────────────────────────
|
|
128
|
+
const inflight = new Map();
|
|
129
|
+
/** De-dup concurrent identical scans. Two agents calling ``validate_edit``
|
|
130
|
+
* with the same content at the same instant share ONE underlying gate
|
|
131
|
+
* run; the second callee awaits the same promise. Frees the system from
|
|
132
|
+
* O(N) LLM-critic calls under burst load. */
|
|
133
|
+
export async function singleFlight(key, fn) {
|
|
134
|
+
const existing = inflight.get(key);
|
|
135
|
+
if (existing) {
|
|
136
|
+
return existing;
|
|
137
|
+
}
|
|
138
|
+
const p = fn().finally(() => {
|
|
139
|
+
// Detach AFTER resolution so a follow-up call that arrives 1ms later
|
|
140
|
+
// doesn't latch onto a not-yet-cleared entry expecting fresh data.
|
|
141
|
+
inflight.delete(key);
|
|
142
|
+
});
|
|
143
|
+
inflight.set(key, p);
|
|
144
|
+
return p;
|
|
145
|
+
}
|
|
146
|
+
// ── Engine availability map ───────────────────────────────────────────────
|
|
147
|
+
let _availabilityMap = null;
|
|
148
|
+
/** Probe every engine ONCE at boot. Subsequent runGate() calls can rely
|
|
149
|
+
* on this map instead of awaiting `e.available()` per engine per call. */
|
|
150
|
+
export async function computeAvailability() {
|
|
151
|
+
const m = new Map();
|
|
152
|
+
const checks = ALL_ENGINES.map(async (e) => {
|
|
153
|
+
try {
|
|
154
|
+
m.set(e.name, await e.available());
|
|
155
|
+
}
|
|
156
|
+
catch {
|
|
157
|
+
m.set(e.name, false);
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
await Promise.all(checks);
|
|
161
|
+
_availabilityMap = m;
|
|
162
|
+
log.info("availability probed", {
|
|
163
|
+
total: m.size,
|
|
164
|
+
available: [...m.entries()].filter(([, ok]) => ok).map(([n]) => n),
|
|
165
|
+
unavailable: [...m.entries()].filter(([, ok]) => !ok).map(([n]) => n),
|
|
166
|
+
});
|
|
167
|
+
return m;
|
|
168
|
+
}
|
|
169
|
+
/** Get the precomputed availability snapshot. Returns null before
|
|
170
|
+
* ``warmAtBoot()`` completes. Callers SHOULD fall back to per-engine
|
|
171
|
+
* ``e.available()`` if null. */
|
|
172
|
+
export function availabilitySnapshot() {
|
|
173
|
+
return _availabilityMap;
|
|
174
|
+
}
|
|
175
|
+
/** Force a fresh probe (e.g. user just ran `pip install semgrep` mid-session). */
|
|
176
|
+
export async function refreshAvailability() {
|
|
177
|
+
return computeAvailability();
|
|
178
|
+
}
|
|
179
|
+
let _warmState = null;
|
|
180
|
+
let _warmPromise = null;
|
|
181
|
+
/** Unique sentinel for timeout — using a Symbol avoids confusing the
|
|
182
|
+
* "step succeeded but returned null/undefined" case with "step timed out". */
|
|
183
|
+
const TIMEOUT_SENTINEL = Symbol("warm.timeout");
|
|
184
|
+
async function withDeadline(label, ms, fn) {
|
|
185
|
+
const deadline = new Promise((r) => setTimeout(() => r(TIMEOUT_SENTINEL), ms));
|
|
186
|
+
try {
|
|
187
|
+
const res = await Promise.race([fn(), deadline]);
|
|
188
|
+
if (res === TIMEOUT_SENTINEL) {
|
|
189
|
+
log.warn(`warm step timed out`, { step: label, timeoutMs: ms });
|
|
190
|
+
}
|
|
191
|
+
return res;
|
|
192
|
+
}
|
|
193
|
+
catch (err) {
|
|
194
|
+
log.warn(`warm step failed`, { step: label, err: String(err) });
|
|
195
|
+
return TIMEOUT_SENTINEL;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
/** Eagerly load every subsystem that the hook path lazy-loads. Idempotent.
|
|
199
|
+
* Returns the cached state if already warmed. Concurrent callers share
|
|
200
|
+
* the same in-flight warm promise. */
|
|
201
|
+
export async function warmAtBoot() {
|
|
202
|
+
if (_warmState)
|
|
203
|
+
return _warmState;
|
|
204
|
+
if (_warmPromise)
|
|
205
|
+
return _warmPromise;
|
|
206
|
+
const t0 = Date.now();
|
|
207
|
+
_warmPromise = (async () => {
|
|
208
|
+
log.info("warm-at-boot starting", {
|
|
209
|
+
stage1Engines: ENGINES.map((e) => e.name),
|
|
210
|
+
stage2Engines: STAGE2_ENGINES.map((e) => e.name),
|
|
211
|
+
});
|
|
212
|
+
// 1. Engine availability — parallel, fail-safe per engine inside.
|
|
213
|
+
const avail = await withDeadline("availability", WARM_PER_SUBSYSTEM_TIMEOUT_MS, () => computeAvailability());
|
|
214
|
+
const availMap = avail === TIMEOUT_SENTINEL ? new Map() : avail;
|
|
215
|
+
const availCount = [...availMap.values()].filter(Boolean).length;
|
|
216
|
+
// 2. Vul-RAG KB embed (this is the dominant cost — ~0.6-1.5 s cold).
|
|
217
|
+
let vulRagOk = false;
|
|
218
|
+
let vulRagEntries = 0;
|
|
219
|
+
await withDeadline("vulrag", WARM_PER_SUBSYSTEM_TIMEOUT_MS, async () => {
|
|
220
|
+
const rag = getVulRag();
|
|
221
|
+
vulRagOk = await rag.ensureLoaded();
|
|
222
|
+
vulRagEntries = rag.size;
|
|
223
|
+
return null;
|
|
224
|
+
});
|
|
225
|
+
// 3. SCIP indexer singleton — construction is cheap; per-project work
|
|
226
|
+
// is still lazy. We just want the singleton extant so the first
|
|
227
|
+
// runGate() doesn't pay a Map+Cache construction cost.
|
|
228
|
+
await withDeadline("scip-indexer", 2_000, async () => {
|
|
229
|
+
getIndexer();
|
|
230
|
+
return null;
|
|
231
|
+
});
|
|
232
|
+
// 4. Claude binary discovery — `which()` itself is cached, but the
|
|
233
|
+
// first lookup spawns a subprocess on Windows.
|
|
234
|
+
let claudeBin = null;
|
|
235
|
+
await withDeadline("claude-bin", 5_000, async () => {
|
|
236
|
+
claudeBin = await which("claude");
|
|
237
|
+
return null;
|
|
238
|
+
});
|
|
239
|
+
const state = {
|
|
240
|
+
warmedAt: Date.now(),
|
|
241
|
+
durationMs: Date.now() - t0,
|
|
242
|
+
vulRagOk,
|
|
243
|
+
vulRagEntries,
|
|
244
|
+
engineCount: ALL_ENGINES.length,
|
|
245
|
+
engineAvailable: availCount,
|
|
246
|
+
claudeBin,
|
|
247
|
+
};
|
|
248
|
+
_warmState = state;
|
|
249
|
+
log.info("warm-at-boot complete", { ...state });
|
|
250
|
+
return state;
|
|
251
|
+
})();
|
|
252
|
+
return _warmPromise;
|
|
253
|
+
}
|
|
254
|
+
/** Snapshot of warm state for ``aegis.health`` probe / debug. */
|
|
255
|
+
export function warmStateSnapshot() {
|
|
256
|
+
return _warmState;
|
|
257
|
+
}
|
|
258
|
+
// ── Gate fast-path ────────────────────────────────────────────────────────
|
|
259
|
+
/** Build a stable tag identifying the current engine set so the verdict
|
|
260
|
+
* cache invalidates correctly if an engine is added/removed between
|
|
261
|
+
* server restarts. Computed once per process. */
|
|
262
|
+
const ENGINE_SET_TAG = (() => {
|
|
263
|
+
const names = ALL_ENGINES.map((e) => e.name).sort();
|
|
264
|
+
return createHash("sha256").update(names.join("|")).digest("hex").slice(0, 12);
|
|
265
|
+
})();
|
|
266
|
+
/** Run the gate with full warm-path optimisation:
|
|
267
|
+
*
|
|
268
|
+
* 1. In-memory LRU lookup (returns in <0.2 ms when hit).
|
|
269
|
+
* 2. Single-flight dedup: if another call is in flight for the same key,
|
|
270
|
+
* wait for it instead of starting a parallel one.
|
|
271
|
+
* 3. Forward to ``runGate``, passing the warm availability snapshot so
|
|
272
|
+
* the orchestrator skips per-call ``e.available()`` awaits.
|
|
273
|
+
* 4. Store the resulting report in the LRU.
|
|
274
|
+
*
|
|
275
|
+
* Non-cacheable scans (``noCache: true``) bypass steps 1-2-4 — used by
|
|
276
|
+
* the precheck path which always wants fresh.
|
|
277
|
+
*/
|
|
278
|
+
export async function runGateFast(input) {
|
|
279
|
+
// Inject the warm availability snapshot into every gate call so the
|
|
280
|
+
// orchestrator doesn't await per-engine availability. If warmAtBoot
|
|
281
|
+
// hasn't completed yet (e.g. someone called runGateFast before await),
|
|
282
|
+
// the override is null and the orchestrator falls back to per-call probes.
|
|
283
|
+
const inputWithOverride = {
|
|
284
|
+
...input,
|
|
285
|
+
...(_availabilityMap ? { availabilityOverride: _availabilityMap } : {}),
|
|
286
|
+
};
|
|
287
|
+
if (input.noCache) {
|
|
288
|
+
const report = await runGate(inputWithOverride);
|
|
289
|
+
return { report, source: "fresh" };
|
|
290
|
+
}
|
|
291
|
+
const key = verdictCacheKey(input, ENGINE_SET_TAG);
|
|
292
|
+
const hit = verdictLru.get(key);
|
|
293
|
+
if (hit) {
|
|
294
|
+
return { report: hit, source: "lru" };
|
|
295
|
+
}
|
|
296
|
+
// Note on label correctness: we can't distinguish "original runner"
|
|
297
|
+
// from "joined an in-flight peer" from inside singleFlight() without
|
|
298
|
+
// a check-and-set racey lookup. We label "fresh" uniformly because
|
|
299
|
+
// the LRU put below STILL happens (idempotent — the joined caller
|
|
300
|
+
// re-puts the same report). Telemetry on actual single-flight hits
|
|
301
|
+
// is exposed via warmMetrics().inflight watermark.
|
|
302
|
+
const report = await singleFlight(key, async () => runGate(inputWithOverride));
|
|
303
|
+
verdictLru.put(key, report);
|
|
304
|
+
return { report, source: "fresh" };
|
|
305
|
+
}
|
|
306
|
+
// ── Metrics (for explain_health / debug) ──────────────────────────────────
|
|
307
|
+
export function warmMetrics() {
|
|
308
|
+
return {
|
|
309
|
+
verdict_lru: verdictLru.stats(),
|
|
310
|
+
inflight: inflight.size,
|
|
311
|
+
engine_set_tag: ENGINE_SET_TAG,
|
|
312
|
+
warm: _warmState,
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
// ── Test-only helpers ─────────────────────────────────────────────────────
|
|
316
|
+
/** Reset all warm state. Tests only — production code must NOT call this. */
|
|
317
|
+
export function _resetWarmStateForTests() {
|
|
318
|
+
_warmState = null;
|
|
319
|
+
_warmPromise = null;
|
|
320
|
+
_availabilityMap = null;
|
|
321
|
+
verdictLru.clear();
|
|
322
|
+
inflight.clear();
|
|
323
|
+
}
|
|
324
|
+
/** Expose internal hooks for unit tests. */
|
|
325
|
+
export const _testing = {
|
|
326
|
+
verdictLru,
|
|
327
|
+
inflight,
|
|
328
|
+
ENGINE_SET_TAG,
|
|
329
|
+
engineSet: () => ALL_ENGINES,
|
|
330
|
+
};
|
|
331
|
+
//# sourceMappingURL=warm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"warm.js","sourceRoot":"","sources":["../../src/mcp/warm.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { Engine, EngineRunResult } from "./engines/types.js";
|
|
2
|
+
import { Finding } from "./findings.js";
|
|
3
|
+
import { type ProjectContextBlock } from "./index/context.js";
|
|
4
|
+
import { Lang } from "./lang.js";
|
|
5
|
+
import { ActionDecision } from "./risk.js";
|
|
6
|
+
export interface GateInput {
|
|
7
|
+
filePath: string;
|
|
8
|
+
content: string;
|
|
9
|
+
projectRoot?: string;
|
|
10
|
+
/** Overall budget; default 5_000 ms. */
|
|
11
|
+
totalTimeoutMs?: number;
|
|
12
|
+
/** Override which engines run; default = all available. */
|
|
13
|
+
engines?: ReadonlyArray<Engine>;
|
|
14
|
+
/** Disable caching (tests). */
|
|
15
|
+
noCache?: boolean;
|
|
16
|
+
/** If false, the path safety check WILL NOT reject files that are
|
|
17
|
+
* outside ``projectRoot``. Used by the ad-hoc ``aegis scan`` CLI where
|
|
18
|
+
* the user explicitly chose the file. Hook path leaves it default (true). */
|
|
19
|
+
enforceContainment?: boolean;
|
|
20
|
+
/** Precomputed engine availability map. When supplied, the orchestrator
|
|
21
|
+
* SKIPS the per-call ``await e.available()`` round-trip — used by the
|
|
22
|
+
* MCP server warm path where availability is probed once at boot. Engines
|
|
23
|
+
* NOT present in the map fall back to per-call probing. Engines present
|
|
24
|
+
* with ``false`` are skipped without re-probing. */
|
|
25
|
+
availabilityOverride?: ReadonlyMap<string, boolean>;
|
|
26
|
+
}
|
|
27
|
+
export interface GateReport {
|
|
28
|
+
filePath: string;
|
|
29
|
+
lang: Lang;
|
|
30
|
+
decision: ActionDecision;
|
|
31
|
+
findings: Finding[];
|
|
32
|
+
engineResults: ReadonlyArray<EngineRunResult>;
|
|
33
|
+
durationMs: number;
|
|
34
|
+
truncated: boolean;
|
|
35
|
+
pathCheck: {
|
|
36
|
+
ok: true;
|
|
37
|
+
resolved: string;
|
|
38
|
+
} | {
|
|
39
|
+
ok: false;
|
|
40
|
+
reason: string;
|
|
41
|
+
};
|
|
42
|
+
/** Cross-file evidence assembled from the SCIP index, if available. */
|
|
43
|
+
projectContext?: ProjectContextBlock;
|
|
44
|
+
}
|
|
45
|
+
export declare function runGate(input: GateInput): Promise<GateReport>;
|
|
46
|
+
//# sourceMappingURL=orchestrator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orchestrator.d.ts","sourceRoot":"","sources":["../src/orchestrator.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,MAAM,EAAkB,eAAe,EAAW,MAAM,oBAAoB,CAAC;AAEtF,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAuB,KAAK,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAKnF,OAAO,EAAc,IAAI,EAAE,MAAM,WAAW,CAAC;AAG7C,OAAO,EAAE,cAAc,EAAU,MAAM,WAAW,CAAC;AAMnD,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wCAAwC;IACxC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,2DAA2D;IAC3D,OAAO,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAChC,+BAA+B;IAC/B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;iFAE6E;IAC7E,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B;;;;wDAIoD;IACpD,oBAAoB,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACrD;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,IAAI,CAAC;IACX,QAAQ,EAAE,cAAc,CAAC;IACzB,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,aAAa,EAAE,aAAa,CAAC,eAAe,CAAC,CAAC;IAC9C,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EACL;QAAE,EAAE,EAAE,IAAI,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAC9B;QAAE,EAAE,EAAE,KAAK,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAClC,uEAAuE;IACvE,cAAc,CAAC,EAAE,mBAAmB,CAAC;CACtC;AAqKD,wBAAsB,OAAO,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CA8WnE"}
|