@danielblomma/cortex-mcp 2.2.1 → 2.2.3

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@danielblomma/cortex-mcp",
3
3
  "mcpName": "io.github.DanielBlomma/cortex",
4
- "version": "2.2.1",
4
+ "version": "2.2.3",
5
5
  "description": "Local, repo-scoped context platform for coding assistants. Semantic search, graph relationships, and architectural rule context.",
6
6
  "type": "module",
7
7
  "author": "Daniel Blomma",
@@ -64,7 +64,7 @@
64
64
  ],
65
65
  "scripts": {
66
66
  "pretest": "test -d scaffold/scripts/parsers/node_modules || npm --prefix scaffold/scripts/parsers install --no-fund --no-update-notifier --silent",
67
- "test": "node tests/context-regressions.test.mjs && node --test tests/ingest-units.test.mjs tests/ingest-parallel.test.mjs tests/ingest-worker-crash.test.mjs tests/javascript-parser.test.mjs tests/markdown-parser.test.mjs tests/sql-parser.test.mjs tests/config-parser.test.mjs tests/resources-parser.test.mjs tests/vbnet-parser.test.mjs tests/cpp-parser.test.mjs tests/dashboard.test.mjs tests/init-config.test.mjs tests/init-agents.test.mjs tests/multi-level.test.mjs tests/no-legacy-paths.test.mjs tests/tree-sitter-error-reporting.test.mjs tests/tree-sitter-body-cap.test.mjs tests/tree-sitter-exported.test.mjs tests/tree-sitter-robustness.test.mjs tests/bootstrapbench-stats.test.mjs tests/bootstrapbench-aggregate.test.mjs tests/bootstrapbench-cleanup.test.mjs tests/query-cli-shim.test.mjs",
67
+ "test": "node tests/context-regressions.test.mjs && node --test tests/ingest-units.test.mjs tests/ingest-parallel.test.mjs tests/ingest-worker-crash.test.mjs tests/javascript-parser.test.mjs tests/markdown-parser.test.mjs tests/sql-parser.test.mjs tests/config-parser.test.mjs tests/resources-parser.test.mjs tests/vbnet-parser.test.mjs tests/cpp-parser.test.mjs tests/dashboard.test.mjs tests/init-config.test.mjs tests/init-agents.test.mjs tests/multi-level.test.mjs tests/no-legacy-paths.test.mjs tests/tree-sitter-error-reporting.test.mjs tests/tree-sitter-body-cap.test.mjs tests/tree-sitter-exported.test.mjs tests/tree-sitter-robustness.test.mjs tests/bootstrapbench-run.test.mjs tests/bootstrapbench-stats.test.mjs tests/bootstrapbench-aggregate.test.mjs tests/bootstrapbench-cleanup.test.mjs tests/query-cli-shim.test.mjs",
68
68
  "release:sync-version": "node scripts/sync-release-version.mjs",
69
69
  "release:check-version-sync": "node scripts/sync-release-version.mjs --check",
70
70
  "prepublishOnly": "echo 'Ready to publish to npm'"
@@ -75,8 +75,12 @@ function buildRelationSearchSignals(data: ContextData): Map<string, string> {
75
75
  return new Map([...signalsByEntity.entries()].map(([id, parts]) => [id, parts.join("\n")]));
76
76
  }
77
77
 
78
- export function buildSearchEntities(data: ContextData, includeContent: boolean): SearchEntity[] {
79
- const entities: SearchEntity[] = [];
78
+ function buildSearchEntityIndexes(data: ContextData): {
79
+ fileRuleLinks: Map<string, string[]>;
80
+ relationSignals: Map<string, string>;
81
+ adrPathSet: Set<string>;
82
+ filePathById: Map<string, string>;
83
+ } {
80
84
  const fileRuleLinks = groupRuleLinks(data.relations);
81
85
  const relationSignals = buildRelationSearchSignals(data);
82
86
  const adrPathSet = new Set(
@@ -84,6 +88,15 @@ export function buildSearchEntities(data: ContextData, includeContent: boolean):
84
88
  .map((adr) => adr.path.trim().toLowerCase())
85
89
  .filter((adrPath) => adrPath.length > 0)
86
90
  );
91
+ const filePathById = new Map(
92
+ data.documents.filter((document) => document.kind === "CODE").map((document) => [document.id, document.path])
93
+ );
94
+
95
+ return { fileRuleLinks, relationSignals, adrPathSet, filePathById };
96
+ }
97
+
98
+ export function* iterateSearchEntities(data: ContextData, includeContent: boolean): Generator<SearchEntity> {
99
+ const { fileRuleLinks, relationSignals, adrPathSet, filePathById } = buildSearchEntityIndexes(data);
87
100
 
88
101
  for (const document of data.documents) {
89
102
  const normalizedPath = document.path.trim().toLowerCase();
@@ -91,7 +104,7 @@ export function buildSearchEntities(data: ContextData, includeContent: boolean):
91
104
  continue;
92
105
  }
93
106
 
94
- entities.push({
107
+ yield {
95
108
  id: document.id,
96
109
  entity_type: "File",
97
110
  kind: document.kind,
@@ -105,11 +118,11 @@ export function buildSearchEntities(data: ContextData, includeContent: boolean):
105
118
  snippet: document.excerpt,
106
119
  matched_rules: fileRuleLinks.get(document.id) ?? [],
107
120
  content: includeContent ? document.content : undefined
108
- });
121
+ };
109
122
  }
110
123
 
111
124
  for (const rule of data.rules) {
112
- entities.push({
125
+ yield {
113
126
  id: rule.id,
114
127
  entity_type: "Rule",
115
128
  kind: "RULE",
@@ -123,11 +136,11 @@ export function buildSearchEntities(data: ContextData, includeContent: boolean):
123
136
  snippet: rule.body.slice(0, 500),
124
137
  matched_rules: [rule.id],
125
138
  content: includeContent ? rule.body : undefined
126
- });
139
+ };
127
140
  }
128
141
 
129
142
  for (const adr of data.adrs) {
130
- entities.push({
143
+ yield {
131
144
  id: adr.id,
132
145
  entity_type: "ADR",
133
146
  kind: "ADR",
@@ -141,16 +154,12 @@ export function buildSearchEntities(data: ContextData, includeContent: boolean):
141
154
  snippet: adr.body.slice(0, 500),
142
155
  matched_rules: [],
143
156
  content: includeContent ? adr.body : undefined
144
- });
157
+ };
145
158
  }
146
159
 
147
- const filePathById = new Map(
148
- data.documents.filter((document) => document.kind === "CODE").map((document) => [document.id, document.path])
149
- );
150
-
151
160
  for (const chunk of data.chunks) {
152
161
  const filePath = filePathById.get(chunk.file_id) ?? "";
153
- entities.push({
162
+ yield {
154
163
  id: chunk.id,
155
164
  entity_type: "Chunk",
156
165
  kind: chunk.kind || "chunk",
@@ -164,11 +173,11 @@ export function buildSearchEntities(data: ContextData, includeContent: boolean):
164
173
  snippet: chunk.description || chunk.body.slice(0, 500),
165
174
  matched_rules: fileRuleLinks.get(chunk.file_id) ?? [],
166
175
  content: includeContent ? chunk.body : undefined
167
- });
176
+ };
168
177
  }
169
178
 
170
179
  for (const module of data.modules) {
171
- entities.push({
180
+ yield {
172
181
  id: module.id,
173
182
  entity_type: "Module",
174
183
  kind: "MODULE",
@@ -182,11 +191,11 @@ export function buildSearchEntities(data: ContextData, includeContent: boolean):
182
191
  snippet: (module.summary || "").slice(0, 500),
183
192
  matched_rules: [],
184
193
  content: includeContent ? module.summary : undefined
185
- });
194
+ };
186
195
  }
187
196
 
188
197
  for (const project of data.projects) {
189
- entities.push({
198
+ yield {
190
199
  id: project.id,
191
200
  entity_type: "Project",
192
201
  kind: project.kind.toUpperCase() || "PROJECT",
@@ -200,10 +209,12 @@ export function buildSearchEntities(data: ContextData, includeContent: boolean):
200
209
  snippet: (project.summary || "").slice(0, 500),
201
210
  matched_rules: [],
202
211
  content: includeContent ? project.summary : undefined
203
- });
212
+ };
204
213
  }
214
+ }
205
215
 
206
- return entities;
216
+ export function buildSearchEntities(data: ContextData, includeContent: boolean): SearchEntity[] {
217
+ return Array.from(iterateSearchEntities(data, includeContent));
207
218
  }
208
219
 
209
220
  export function buildChunkPartOfRelations(data: ContextData): RelationRecord[] {