@danielblomma/cortex-mcp 0.4.2 → 0.6.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +64 -16
- package/bin/cortex.mjs +32 -60
- package/package.json +17 -3
- package/scaffold/.context/ontology.cypher +47 -0
- package/scaffold/.githooks/post-commit +14 -0
- package/scaffold/.githooks/post-rewrite +23 -0
- package/scaffold/mcp/package-lock.json +19 -23
- package/scaffold/mcp/package.json +3 -1
- package/scaffold/mcp/src/contextEntities.ts +311 -0
- package/scaffold/mcp/src/defaults.ts +6 -0
- package/scaffold/mcp/src/embed.ts +163 -37
- package/scaffold/mcp/src/frontmatter.ts +39 -0
- package/scaffold/mcp/src/graph.ts +330 -109
- package/scaffold/mcp/src/graphMetrics.ts +12 -0
- package/scaffold/mcp/src/impactPresentation.ts +202 -0
- package/scaffold/mcp/src/impactRanking.ts +237 -0
- package/scaffold/mcp/src/impactResponse.ts +47 -0
- package/scaffold/mcp/src/impactResults.ts +173 -0
- package/scaffold/mcp/src/impactSeed.ts +33 -0
- package/scaffold/mcp/src/impactTraversal.ts +83 -0
- package/scaffold/mcp/src/jsonl.ts +34 -0
- package/scaffold/mcp/src/loadGraph.ts +345 -86
- package/scaffold/mcp/src/paths.ts +24 -2
- package/scaffold/mcp/src/presets.ts +137 -0
- package/scaffold/mcp/src/relatedResponse.ts +30 -0
- package/scaffold/mcp/src/relatedTraversal.ts +101 -0
- package/scaffold/mcp/src/rules.ts +27 -0
- package/scaffold/mcp/src/search.ts +191 -355
- package/scaffold/mcp/src/searchCore.ts +274 -0
- package/scaffold/mcp/src/searchResults.ts +133 -0
- package/scaffold/mcp/src/server.ts +95 -3
- package/scaffold/mcp/src/types.ts +99 -3
- package/scaffold/scripts/context.sh +12 -46
- package/scaffold/scripts/dashboard.mjs +797 -0
- package/scaffold/scripts/dashboard.sh +13 -0
- package/scaffold/scripts/ingest.mjs +2219 -59
- package/scaffold/scripts/install-git-hooks.sh +3 -1
- package/scaffold/scripts/memory-compile.mjs +232 -0
- package/scaffold/scripts/memory-compile.sh +20 -0
- package/scaffold/scripts/memory-lint.mjs +375 -0
- package/scaffold/scripts/memory-lint.sh +20 -0
- package/scaffold/scripts/parsers/config.mjs +178 -0
- package/scaffold/scripts/parsers/cpp.mjs +316 -0
- package/scaffold/scripts/parsers/dotnet/VbNetParser/Program.cs +374 -0
- package/scaffold/scripts/parsers/dotnet/VbNetParser/VbNetParser.csproj +13 -0
- package/scaffold/scripts/parsers/javascript/ast.mjs +61 -0
- package/scaffold/scripts/parsers/javascript/calls.mjs +53 -0
- package/scaffold/scripts/parsers/javascript/chunks.mjs +388 -0
- package/scaffold/scripts/parsers/javascript/imports.mjs +162 -0
- package/scaffold/scripts/parsers/javascript/patterns.mjs +82 -0
- package/scaffold/scripts/parsers/javascript/scope-analysis.mjs +3 -0
- package/scaffold/scripts/parsers/javascript/scope-builder.mjs +305 -0
- package/scaffold/scripts/parsers/javascript/scope-resolver.mjs +82 -0
- package/scaffold/scripts/parsers/javascript.mjs +27 -350
- package/scaffold/scripts/parsers/resources.mjs +166 -0
- package/scaffold/scripts/parsers/sql.mjs +137 -0
- package/scaffold/scripts/parsers/vbnet.mjs +143 -0
- package/scaffold/scripts/status.sh +15 -8
- package/scaffold/scripts/capture-note.sh +0 -55
- package/scaffold/scripts/plan-state-engine.cjs +0 -310
- package/scaffold/scripts/plan-state.sh +0 -71
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import type { ImpactParams, RelatedParams, SearchParams } from "./types.js";
|
|
2
|
+
|
|
3
|
+
export type ResponsePreset = "full" | "compact" | "minimal";
|
|
4
|
+
|
|
5
|
+
type ImpactPresetOptions = {
|
|
6
|
+
includeScores: boolean;
|
|
7
|
+
includeReasons: boolean;
|
|
8
|
+
verbosePaths: boolean;
|
|
9
|
+
maxPathHopsShown: number;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
type SearchPresetOptions = {
|
|
13
|
+
includeScores: boolean;
|
|
14
|
+
includeMatchedRules: boolean;
|
|
15
|
+
includeContent: boolean;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
type RelatedPresetOptions = {
|
|
19
|
+
includeEdges: boolean;
|
|
20
|
+
includeEntityMetadata: boolean;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
function resolvePresetOptions<TDefaults extends Record<string, boolean | number | string>>(
|
|
24
|
+
responsePreset: ResponsePreset | undefined,
|
|
25
|
+
presetDefaultsByMode: Record<ResponsePreset, TDefaults>,
|
|
26
|
+
explicitOverrides: Partial<TDefaults>
|
|
27
|
+
): TDefaults & { responsePreset: ResponsePreset } {
|
|
28
|
+
const resolvedPreset = responsePreset ?? "full";
|
|
29
|
+
const presetDefaults = presetDefaultsByMode[resolvedPreset];
|
|
30
|
+
|
|
31
|
+
return {
|
|
32
|
+
responsePreset: resolvedPreset,
|
|
33
|
+
...presetDefaults,
|
|
34
|
+
...Object.fromEntries(
|
|
35
|
+
Object.entries(explicitOverrides).filter(([, value]) => value !== undefined)
|
|
36
|
+
)
|
|
37
|
+
} as TDefaults & { responsePreset: ResponsePreset };
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function resolveImpactResponsePreset(parsed: ImpactParams): {
|
|
41
|
+
responsePreset: ResponsePreset;
|
|
42
|
+
includeScores: boolean;
|
|
43
|
+
includeReasons: boolean;
|
|
44
|
+
verbosePaths: boolean;
|
|
45
|
+
maxPathHopsShown: number;
|
|
46
|
+
} {
|
|
47
|
+
return resolvePresetOptions<ImpactPresetOptions>(
|
|
48
|
+
parsed.response_preset,
|
|
49
|
+
{
|
|
50
|
+
full: {
|
|
51
|
+
includeScores: true,
|
|
52
|
+
includeReasons: true,
|
|
53
|
+
verbosePaths: true,
|
|
54
|
+
maxPathHopsShown: 2
|
|
55
|
+
},
|
|
56
|
+
compact: {
|
|
57
|
+
includeScores: false,
|
|
58
|
+
includeReasons: true,
|
|
59
|
+
verbosePaths: false,
|
|
60
|
+
maxPathHopsShown: 2
|
|
61
|
+
},
|
|
62
|
+
minimal: {
|
|
63
|
+
includeScores: false,
|
|
64
|
+
includeReasons: false,
|
|
65
|
+
verbosePaths: false,
|
|
66
|
+
maxPathHopsShown: 1
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
includeScores: parsed.include_scores,
|
|
71
|
+
includeReasons: parsed.include_reasons,
|
|
72
|
+
verbosePaths: parsed.verbose_paths,
|
|
73
|
+
maxPathHopsShown: parsed.max_path_hops_shown
|
|
74
|
+
}
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function resolveSearchResponsePreset(parsed: SearchParams): {
|
|
79
|
+
responsePreset: ResponsePreset;
|
|
80
|
+
includeScores: boolean;
|
|
81
|
+
includeMatchedRules: boolean;
|
|
82
|
+
includeContent: boolean;
|
|
83
|
+
} {
|
|
84
|
+
return resolvePresetOptions<SearchPresetOptions>(
|
|
85
|
+
parsed.response_preset,
|
|
86
|
+
{
|
|
87
|
+
full: {
|
|
88
|
+
includeScores: true,
|
|
89
|
+
includeMatchedRules: true,
|
|
90
|
+
includeContent: false
|
|
91
|
+
},
|
|
92
|
+
compact: {
|
|
93
|
+
includeScores: false,
|
|
94
|
+
includeMatchedRules: true,
|
|
95
|
+
includeContent: false
|
|
96
|
+
},
|
|
97
|
+
minimal: {
|
|
98
|
+
includeScores: false,
|
|
99
|
+
includeMatchedRules: false,
|
|
100
|
+
includeContent: false
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
includeScores: parsed.include_scores,
|
|
105
|
+
includeMatchedRules: parsed.include_matched_rules,
|
|
106
|
+
includeContent: parsed.include_content
|
|
107
|
+
}
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export function resolveRelatedResponsePreset(parsed: RelatedParams): {
|
|
112
|
+
responsePreset: ResponsePreset;
|
|
113
|
+
includeEdges: boolean;
|
|
114
|
+
includeEntityMetadata: boolean;
|
|
115
|
+
} {
|
|
116
|
+
return resolvePresetOptions<RelatedPresetOptions>(
|
|
117
|
+
parsed.response_preset,
|
|
118
|
+
{
|
|
119
|
+
full: {
|
|
120
|
+
includeEdges: true,
|
|
121
|
+
includeEntityMetadata: true
|
|
122
|
+
},
|
|
123
|
+
compact: {
|
|
124
|
+
includeEdges: false,
|
|
125
|
+
includeEntityMetadata: true
|
|
126
|
+
},
|
|
127
|
+
minimal: {
|
|
128
|
+
includeEdges: false,
|
|
129
|
+
includeEntityMetadata: false
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
includeEdges: parsed.include_edges,
|
|
134
|
+
includeEntityMetadata: parsed.include_entity_metadata
|
|
135
|
+
}
|
|
136
|
+
);
|
|
137
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { RelatedParams, ToolPayload } from "./types.js";
|
|
2
|
+
|
|
3
|
+
export function buildRelatedResponseMeta(params: {
|
|
4
|
+
parsed: RelatedParams;
|
|
5
|
+
responsePreset: "full" | "compact" | "minimal";
|
|
6
|
+
includeEdges: boolean;
|
|
7
|
+
includeEntityMetadata: boolean;
|
|
8
|
+
contextSource: string;
|
|
9
|
+
}): ToolPayload {
|
|
10
|
+
return {
|
|
11
|
+
entity_id: params.parsed.entity_id,
|
|
12
|
+
depth: params.parsed.depth,
|
|
13
|
+
response_preset: params.responsePreset,
|
|
14
|
+
include_edges: params.includeEdges,
|
|
15
|
+
include_entity_metadata: params.includeEntityMetadata,
|
|
16
|
+
context_source: params.contextSource
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function buildEmptyRelatedResponse(params: {
|
|
21
|
+
meta: ToolPayload;
|
|
22
|
+
warning: string;
|
|
23
|
+
}): ToolPayload {
|
|
24
|
+
return {
|
|
25
|
+
...params.meta,
|
|
26
|
+
related: [],
|
|
27
|
+
edges: [],
|
|
28
|
+
warning: params.warning
|
|
29
|
+
};
|
|
30
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import type { JsonObject, RelationRecord } from "./types.js";
|
|
2
|
+
|
|
3
|
+
export function traverseRelatedGraph(params: {
|
|
4
|
+
entityId: string;
|
|
5
|
+
relations: RelationRecord[];
|
|
6
|
+
depth: number;
|
|
7
|
+
catalog: Map<string, JsonObject>;
|
|
8
|
+
includeEntityMetadata: boolean;
|
|
9
|
+
}): {
|
|
10
|
+
related: JsonObject[];
|
|
11
|
+
traversedEdges: JsonObject[];
|
|
12
|
+
} {
|
|
13
|
+
const outgoing = new Map<string, RelationRecord[]>();
|
|
14
|
+
const incoming = new Map<string, RelationRecord[]>();
|
|
15
|
+
|
|
16
|
+
for (const relation of params.relations) {
|
|
17
|
+
const outList = outgoing.get(relation.from) ?? [];
|
|
18
|
+
outList.push(relation);
|
|
19
|
+
outgoing.set(relation.from, outList);
|
|
20
|
+
|
|
21
|
+
const inList = incoming.get(relation.to) ?? [];
|
|
22
|
+
inList.push(relation);
|
|
23
|
+
incoming.set(relation.to, inList);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const seen = new Set<string>([params.entityId]);
|
|
27
|
+
const queue: Array<{ id: string; hop: number }> = [{ id: params.entityId, hop: 0 }];
|
|
28
|
+
const related: JsonObject[] = [];
|
|
29
|
+
const traversedEdges: JsonObject[] = [];
|
|
30
|
+
const traversedEdgeKeys = new Set<string>();
|
|
31
|
+
|
|
32
|
+
while (queue.length > 0) {
|
|
33
|
+
const current = queue.shift() as { id: string; hop: number };
|
|
34
|
+
if (current.hop >= params.depth) {
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const neighbors = [
|
|
39
|
+
...(outgoing.get(current.id) ?? []).map((edge) => ({
|
|
40
|
+
edge,
|
|
41
|
+
next: edge.to,
|
|
42
|
+
direction: "outgoing"
|
|
43
|
+
})),
|
|
44
|
+
...(incoming.get(current.id) ?? []).map((edge) => ({
|
|
45
|
+
edge,
|
|
46
|
+
next: edge.from,
|
|
47
|
+
direction: "incoming"
|
|
48
|
+
}))
|
|
49
|
+
];
|
|
50
|
+
|
|
51
|
+
for (const neighbor of neighbors) {
|
|
52
|
+
const target = neighbor.next;
|
|
53
|
+
if (!seen.has(target)) {
|
|
54
|
+
seen.add(target);
|
|
55
|
+
queue.push({ id: target, hop: current.hop + 1 });
|
|
56
|
+
|
|
57
|
+
const entity = params.catalog.get(target) ?? {
|
|
58
|
+
id: target,
|
|
59
|
+
type: "Unknown",
|
|
60
|
+
label: target,
|
|
61
|
+
status: "unknown",
|
|
62
|
+
source_of_truth: false
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
related.push(
|
|
66
|
+
params.includeEntityMetadata
|
|
67
|
+
? {
|
|
68
|
+
...entity,
|
|
69
|
+
hops: current.hop + 1,
|
|
70
|
+
via_relation: neighbor.edge.relation,
|
|
71
|
+
direction: neighbor.direction
|
|
72
|
+
}
|
|
73
|
+
: {
|
|
74
|
+
id: entity.id,
|
|
75
|
+
type: entity.type,
|
|
76
|
+
label: entity.label,
|
|
77
|
+
hops: current.hop + 1,
|
|
78
|
+
via_relation: neighbor.edge.relation,
|
|
79
|
+
direction: neighbor.direction
|
|
80
|
+
}
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const edgeKey = `${neighbor.edge.from}|${neighbor.edge.relation}|${neighbor.edge.to}|${neighbor.edge.note}`;
|
|
85
|
+
if (!traversedEdgeKeys.has(edgeKey)) {
|
|
86
|
+
traversedEdgeKeys.add(edgeKey);
|
|
87
|
+
traversedEdges.push({
|
|
88
|
+
from: neighbor.edge.from,
|
|
89
|
+
to: neighbor.edge.to,
|
|
90
|
+
relation: neighbor.edge.relation,
|
|
91
|
+
note: neighbor.edge.note
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return {
|
|
98
|
+
related,
|
|
99
|
+
traversedEdges
|
|
100
|
+
};
|
|
101
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { loadContextData } from "./graph.js";
|
|
2
|
+
import type { RulesParams, ToolPayload } from "./types.js";
|
|
3
|
+
|
|
4
|
+
export async function runContextRules(parsed: RulesParams): Promise<ToolPayload> {
|
|
5
|
+
const data = await loadContextData();
|
|
6
|
+
|
|
7
|
+
const rules = data.rules
|
|
8
|
+
.filter((rule) => parsed.include_inactive || rule.status === "active")
|
|
9
|
+
.filter((rule) => !parsed.scope || rule.scope === parsed.scope || rule.scope === "global")
|
|
10
|
+
.sort((a, b) => b.priority - a.priority)
|
|
11
|
+
.map((rule) => ({
|
|
12
|
+
id: rule.id,
|
|
13
|
+
title: rule.title,
|
|
14
|
+
description: rule.body,
|
|
15
|
+
priority: rule.priority,
|
|
16
|
+
scope: rule.scope,
|
|
17
|
+
status: rule.status
|
|
18
|
+
}));
|
|
19
|
+
|
|
20
|
+
return {
|
|
21
|
+
scope: parsed.scope ?? "global",
|
|
22
|
+
count: rules.length,
|
|
23
|
+
context_source: data.source,
|
|
24
|
+
warning: data.warning,
|
|
25
|
+
rules
|
|
26
|
+
};
|
|
27
|
+
}
|