@danielblomma/cortex-mcp 2.1.1 → 2.2.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.
Files changed (150) hide show
  1. package/README.md +72 -24
  2. package/bin/cortex.mjs +50 -21
  3. package/mcp-registry-submission.json +63 -0
  4. package/package.json +19 -5
  5. package/scaffold/AGENTS.md +13 -9
  6. package/scaffold/CLAUDE.md +13 -9
  7. package/scaffold/docs/architecture.md +1 -1
  8. package/scaffold/mcp/build.mjs +92 -0
  9. package/scaffold/mcp/package.json +4 -4
  10. package/scaffold/mcp/src/cli/query.ts +455 -0
  11. package/scaffold/mcp/src/embed.ts +181 -77
  12. package/scaffold/mcp/src/embedScheduler.ts +509 -0
  13. package/scaffold/mcp/src/embeddings.ts +31 -30
  14. package/scaffold/mcp/src/graphCsv.ts +65 -0
  15. package/scaffold/mcp/src/jsonl.ts +69 -14
  16. package/scaffold/mcp/src/loadGraph.ts +276 -40
  17. package/scaffold/mcp/src/lruCache.ts +41 -0
  18. package/scaffold/mcp/src/searchCore.ts +1 -1
  19. package/scaffold/mcp/src/searchResults.ts +3 -3
  20. package/scaffold/mcp/src/types.ts +6 -1
  21. package/scaffold/mcp/tests/embed-scheduler.test.mjs +474 -0
  22. package/scaffold/mcp/tests/embedding-jsonl.test.mjs +39 -0
  23. package/scaffold/mcp/tests/graph-bulk-load.test.mjs +258 -0
  24. package/scaffold/mcp/tests/graph-csv.test.mjs +118 -0
  25. package/scaffold/mcp/tests/lru-cache.test.mjs +37 -0
  26. package/scaffold/mcp/tests/query-cli.test.mjs +115 -0
  27. package/scaffold/mcp/tests/vector-index.test.mjs +109 -0
  28. package/scaffold/mcp/tsconfig.json +3 -1
  29. package/scaffold/scripts/bootstrap.sh +37 -4
  30. package/scaffold/scripts/dashboard.mjs +1 -1
  31. package/scaffold/scripts/doctor.sh +9 -8
  32. package/scaffold/scripts/embed.sh +3 -2
  33. package/scaffold/scripts/ingest-parsers.mjs +387 -0
  34. package/scaffold/scripts/ingest-worker.mjs +52 -0
  35. package/scaffold/scripts/ingest.mjs +550 -378
  36. package/scaffold/scripts/load-ryu.sh +3 -2
  37. package/scaffold/scripts/memory-compile.mjs +5 -2
  38. package/scaffold/scripts/memory-lint.mjs +5 -2
  39. package/scaffold/scripts/parsers/csharp.mjs +2 -1
  40. package/scaffold/scripts/parsers/javascript/ast.mjs +160 -8
  41. package/scaffold/scripts/parsers/javascript/chunks.mjs +129 -22
  42. package/scaffold/scripts/parsers/javascript/imports.mjs +38 -4
  43. package/scaffold/scripts/parsers/vbnet.mjs +2 -1
  44. package/scaffold/scripts/status.sh +50 -14
  45. package/scaffold/scripts/parsers/node_modules/.package-lock.json +0 -56
  46. package/scaffold/scripts/parsers/node_modules/acorn/CHANGELOG.md +0 -972
  47. package/scaffold/scripts/parsers/node_modules/acorn/LICENSE +0 -21
  48. package/scaffold/scripts/parsers/node_modules/acorn/README.md +0 -301
  49. package/scaffold/scripts/parsers/node_modules/acorn/bin/acorn +0 -4
  50. package/scaffold/scripts/parsers/node_modules/acorn/dist/acorn.d.mts +0 -883
  51. package/scaffold/scripts/parsers/node_modules/acorn/dist/acorn.d.ts +0 -883
  52. package/scaffold/scripts/parsers/node_modules/acorn/dist/acorn.js +0 -6295
  53. package/scaffold/scripts/parsers/node_modules/acorn/dist/acorn.mjs +0 -6266
  54. package/scaffold/scripts/parsers/node_modules/acorn/dist/bin.js +0 -90
  55. package/scaffold/scripts/parsers/node_modules/acorn/package.json +0 -50
  56. package/scaffold/scripts/parsers/node_modules/acorn-typescript/CHANGELOG.md +0 -421
  57. package/scaffold/scripts/parsers/node_modules/acorn-typescript/LICENSE +0 -21
  58. package/scaffold/scripts/parsers/node_modules/acorn-typescript/README.md +0 -81
  59. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/error.d.ts +0 -103
  60. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/error.js +0 -78
  61. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/error.js.map +0 -1
  62. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/extentions/decorators.d.ts +0 -167
  63. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/extentions/decorators.js +0 -75
  64. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/extentions/decorators.js.map +0 -1
  65. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/extentions/import-assertions.d.ts +0 -177
  66. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/extentions/import-assertions.js +0 -56
  67. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/extentions/import-assertions.js.map +0 -1
  68. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/extentions/jsx/index.d.ts +0 -198
  69. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/extentions/jsx/index.js +0 -327
  70. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/extentions/jsx/index.js.map +0 -1
  71. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/extentions/jsx/xhtml.d.ts +0 -256
  72. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/extentions/jsx/xhtml.js +0 -256
  73. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/extentions/jsx/xhtml.js.map +0 -1
  74. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/index.d.ts +0 -472
  75. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/index.js +0 -1
  76. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/index.js.map +0 -1
  77. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/index.mjs +0 -1
  78. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/middleware.d.ts +0 -159
  79. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/middleware.js +0 -2
  80. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/middleware.js.map +0 -1
  81. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/parseutil.d.ts +0 -10
  82. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/parseutil.js +0 -38
  83. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/parseutil.js.map +0 -1
  84. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/scopeflags.d.ts +0 -12
  85. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/scopeflags.js +0 -29
  86. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/scopeflags.js.map +0 -1
  87. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/tokenType.d.ts +0 -2
  88. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/tokenType.js +0 -118
  89. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/tokenType.js.map +0 -1
  90. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/types.d.ts +0 -60
  91. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/types.js +0 -2
  92. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/types.js.map +0 -1
  93. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/whitespace.d.ts +0 -2
  94. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/whitespace.js +0 -19
  95. package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/whitespace.js.map +0 -1
  96. package/scaffold/scripts/parsers/node_modules/acorn-typescript/package.json +0 -53
  97. package/scaffold/scripts/parsers/node_modules/acorn-typescript/tsconfig.json +0 -19
  98. package/scaffold/scripts/parsers/node_modules/acorn-walk/CHANGELOG.md +0 -209
  99. package/scaffold/scripts/parsers/node_modules/acorn-walk/LICENSE +0 -21
  100. package/scaffold/scripts/parsers/node_modules/acorn-walk/README.md +0 -124
  101. package/scaffold/scripts/parsers/node_modules/acorn-walk/dist/walk.d.mts +0 -152
  102. package/scaffold/scripts/parsers/node_modules/acorn-walk/dist/walk.d.ts +0 -152
  103. package/scaffold/scripts/parsers/node_modules/acorn-walk/dist/walk.js +0 -485
  104. package/scaffold/scripts/parsers/node_modules/acorn-walk/dist/walk.mjs +0 -467
  105. package/scaffold/scripts/parsers/node_modules/acorn-walk/package.json +0 -50
  106. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/LICENSE +0 -24
  107. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/README.md +0 -23
  108. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-bash.wasm +0 -0
  109. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-c.wasm +0 -0
  110. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-c_sharp.wasm +0 -0
  111. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-cpp.wasm +0 -0
  112. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-css.wasm +0 -0
  113. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-dart.wasm +0 -0
  114. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-elisp.wasm +0 -0
  115. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-elixir.wasm +0 -0
  116. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-elm.wasm +0 -0
  117. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-embedded_template.wasm +0 -0
  118. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-go.wasm +0 -0
  119. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-html.wasm +0 -0
  120. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-java.wasm +0 -0
  121. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-javascript.wasm +0 -0
  122. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-json.wasm +0 -0
  123. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-kotlin.wasm +0 -0
  124. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-lua.wasm +0 -0
  125. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-objc.wasm +0 -0
  126. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-ocaml.wasm +0 -0
  127. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-php.wasm +0 -0
  128. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-python.wasm +0 -0
  129. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-ql.wasm +0 -0
  130. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-rescript.wasm +0 -0
  131. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-ruby.wasm +0 -0
  132. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-rust.wasm +0 -0
  133. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-scala.wasm +0 -0
  134. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-solidity.wasm +0 -0
  135. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-swift.wasm +0 -0
  136. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-systemrdl.wasm +0 -0
  137. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-tlaplus.wasm +0 -0
  138. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-toml.wasm +0 -0
  139. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-tsx.wasm +0 -0
  140. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-typescript.wasm +0 -0
  141. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-vue.wasm +0 -0
  142. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-yaml.wasm +0 -0
  143. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-zig.wasm +0 -0
  144. package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/package.json +0 -64
  145. package/scaffold/scripts/parsers/node_modules/web-tree-sitter/LICENSE +0 -21
  146. package/scaffold/scripts/parsers/node_modules/web-tree-sitter/README.md +0 -198
  147. package/scaffold/scripts/parsers/node_modules/web-tree-sitter/package.json +0 -37
  148. package/scaffold/scripts/parsers/node_modules/web-tree-sitter/tree-sitter-web.d.ts +0 -242
  149. package/scaffold/scripts/parsers/node_modules/web-tree-sitter/tree-sitter.js +0 -1
  150. package/scaffold/scripts/parsers/node_modules/web-tree-sitter/tree-sitter.wasm +0 -0
@@ -3,7 +3,8 @@ set -euo pipefail
3
3
 
4
4
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5
5
  REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
6
- MCP_DIR="$REPO_ROOT/.context/mcp"
6
+ CONTEXT_RUNTIME_DIR="$REPO_ROOT/.context/mcp"
7
+ MCP_DIR="$CONTEXT_RUNTIME_DIR"
7
8
 
8
9
  if [[ ! -f "$MCP_DIR/package.json" ]]; then
9
10
  echo "[graph-load] missing $MCP_DIR/package.json"
@@ -11,7 +12,7 @@ if [[ ! -f "$MCP_DIR/package.json" ]]; then
11
12
  fi
12
13
 
13
14
  if [[ ! -d "$MCP_DIR/node_modules" ]]; then
14
- echo "[graph-load] node_modules missing in .context/mcp/"
15
+ echo "[graph-load] node_modules missing in context runtime (.context/mcp compatibility path)"
15
16
  echo "[graph-load] run: cd .context/mcp && NPM_CONFIG_CACHE=$MCP_DIR/.npm-cache npm install"
16
17
  exit 1
17
18
  fi
@@ -1,11 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  import fs from "node:fs";
3
3
  import path from "node:path";
4
- import { fileURLToPath } from "node:url";
5
- import { parseFrontmatter, parseStringList } from "../mcp/dist/frontmatter.js";
4
+ import { fileURLToPath, pathToFileURL } from "node:url";
6
5
 
7
6
  const __filename = fileURLToPath(import.meta.url);
8
7
  const __dirname = path.dirname(__filename);
8
+ const CONTEXT_RUNTIME_DIST = path.resolve(__dirname, "../mcp/dist");
9
+ const { parseFrontmatter, parseStringList } = await import(
10
+ pathToFileURL(path.join(CONTEXT_RUNTIME_DIST, "frontmatter.js")).href
11
+ );
9
12
 
10
13
  function normalizeForWsl(rawPath) {
11
14
  const m = rawPath.match(/^([A-Za-z]):[/\\](.*)/);
@@ -1,11 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  import fs from "node:fs";
3
3
  import path from "node:path";
4
- import { fileURLToPath } from "node:url";
5
- import { parseFrontmatter, parseStringList } from "../mcp/dist/frontmatter.js";
4
+ import { fileURLToPath, pathToFileURL } from "node:url";
6
5
 
7
6
  const __filename = fileURLToPath(import.meta.url);
8
7
  const __dirname = path.dirname(__filename);
8
+ const CONTEXT_RUNTIME_DIST = path.resolve(__dirname, "../mcp/dist");
9
+ const { parseFrontmatter, parseStringList } = await import(
10
+ pathToFileURL(path.join(CONTEXT_RUNTIME_DIST, "frontmatter.js")).href
11
+ );
9
12
 
10
13
  function normalizeForWsl(rawPath) {
11
14
  const m = rawPath.match(/^([A-Za-z]):[/\\](.*)/);
@@ -173,7 +173,8 @@ export function ensureCSharpParserPublished() {
173
173
  "-c", "Release",
174
174
  "-o", getPublishDir(),
175
175
  "--nologo",
176
- "-v", "quiet"
176
+ "-v", "quiet",
177
+ "/p:UseAppHost=false"
177
178
  ],
178
179
  { encoding: "utf8", timeout: 180000 }
179
180
  );
@@ -35,6 +35,8 @@ base.Class = (node, st, visit) => {
35
35
 
36
36
  const tsNodeHandlers = {
37
37
  TSAsExpression(node, st, visit) { visit(node.expression, st); },
38
+ TSSatisfiesExpression(node, st, visit) { visit(node.expression, st); },
39
+ TSTypeAssertion(node, st, visit) { visit(node.expression, st); },
38
40
  TSTypeAnnotation(node, st, visit) {
39
41
  if (node.typeAnnotation) {
40
42
  visit(node.typeAnnotation, st);
@@ -63,15 +65,80 @@ const tsNodeHandlers = {
63
65
  visit(node.typeParameters, st);
64
66
  }
65
67
  },
66
- TSInterfaceDeclaration() {},
67
- TSTypeAliasDeclaration() {},
68
- TSEnumDeclaration() {},
68
+ TSQualifiedName(node, st, visit) {
69
+ if (node.left) visit(node.left, st);
70
+ if (node.right) visit(node.right, st);
71
+ },
72
+ TSInterfaceDeclaration(node, st, visit) {
73
+ if (node.extends) {
74
+ for (const extendedType of node.extends) {
75
+ visit(extendedType, st);
76
+ }
77
+ }
78
+ if (node.body) {
79
+ visit(node.body, st);
80
+ }
81
+ },
82
+ TSInterfaceBody(node, st, visit) {
83
+ for (const member of node.body || []) {
84
+ visit(member, st);
85
+ }
86
+ },
87
+ TSTypeAliasDeclaration(node, st, visit) {
88
+ if (node.typeParameters) {
89
+ visit(node.typeParameters, st);
90
+ }
91
+ if (node.typeAnnotation) {
92
+ visit(node.typeAnnotation, st);
93
+ }
94
+ },
95
+ TSEnumDeclaration(node, st, visit) {
96
+ for (const member of node.members || []) {
97
+ visit(member, st);
98
+ }
99
+ },
100
+ TSEnumMember(node, st, visit) {
101
+ if (node.initializer) {
102
+ visit(node.initializer, st);
103
+ }
104
+ },
69
105
  TSModuleDeclaration() {},
70
106
  TSDeclareFunction() {},
71
- TSPropertySignature() {},
72
- TSMethodSignature() {},
73
- TSIndexSignature() {},
74
- TSTypeLiteral() {},
107
+ TSPropertySignature(node, st, visit) {
108
+ if (node.computed && node.key) {
109
+ visit(node.key, st);
110
+ }
111
+ if (node.typeAnnotation) {
112
+ visit(node.typeAnnotation, st);
113
+ }
114
+ },
115
+ TSMethodSignature(node, st, visit) {
116
+ if (node.computed && node.key) {
117
+ visit(node.key, st);
118
+ }
119
+ if (node.typeParameters) {
120
+ visit(node.typeParameters, st);
121
+ }
122
+ for (const param of node.params || []) {
123
+ visit(param, st);
124
+ }
125
+ if (node.returnType) {
126
+ visit(node.returnType, st);
127
+ }
128
+ },
129
+ TSIndexSignature(node, st, visit) {
130
+ for (const param of node.params || []) {
131
+ visit(param, st);
132
+ }
133
+ if (node.typeAnnotation) {
134
+ visit(node.typeAnnotation, st);
135
+ }
136
+ },
137
+ TSTypeLiteral(node, st, visit) {
138
+ for (const member of node.members || node.body || []) {
139
+ visit(member, st);
140
+ }
141
+ },
75
142
  TSUnionType(node, st, visit) {
76
143
  for (const typeNode of node.types || []) {
77
144
  visit(typeNode, st);
@@ -132,9 +199,94 @@ const tsNodeHandlers = {
132
199
  }
133
200
  },
134
201
  TSNonNullExpression(node, st, visit) { visit(node.expression, st); },
135
- TSInstantiationExpression(node, st, visit) { visit(node.expression, st); }
202
+ TSInstantiationExpression(node, st, visit) { visit(node.expression, st); },
203
+ JSXElement(node, st, visit) {
204
+ if (node.openingElement) {
205
+ visit(node.openingElement, st);
206
+ }
207
+ for (const child of node.children || []) {
208
+ visit(child, st);
209
+ }
210
+ if (node.closingElement) {
211
+ visit(node.closingElement, st);
212
+ }
213
+ },
214
+ JSXFragment(node, st, visit) {
215
+ if (node.openingFragment) {
216
+ visit(node.openingFragment, st);
217
+ }
218
+ for (const child of node.children || []) {
219
+ visit(child, st);
220
+ }
221
+ if (node.closingFragment) {
222
+ visit(node.closingFragment, st);
223
+ }
224
+ },
225
+ JSXOpeningElement(node, st, visit) {
226
+ if (node.name) {
227
+ visit(node.name, st);
228
+ }
229
+ for (const attribute of node.attributes || []) {
230
+ visit(attribute, st);
231
+ }
232
+ },
233
+ JSXClosingElement(node, st, visit) {
234
+ if (node.name) {
235
+ visit(node.name, st);
236
+ }
237
+ },
238
+ JSXAttribute(node, st, visit) {
239
+ if (node.value) {
240
+ visit(node.value, st);
241
+ }
242
+ },
243
+ JSXExpressionContainer(node, st, visit) {
244
+ if (node.expression && node.expression.type !== "JSXEmptyExpression") {
245
+ visit(node.expression, st);
246
+ }
247
+ },
248
+ JSXSpreadAttribute(node, st, visit) {
249
+ if (node.argument) {
250
+ visit(node.argument, st);
251
+ }
252
+ },
253
+ JSXMemberExpression(node, st, visit) {
254
+ if (node.object) {
255
+ visit(node.object, st);
256
+ }
257
+ },
258
+ JSXNamespacedName(node, st, visit) {
259
+ if (node.namespace) {
260
+ visit(node.namespace, st);
261
+ }
262
+ }
136
263
  };
137
264
 
265
+ for (const nodeType of [
266
+ "JSXClosingFragment",
267
+ "JSXEmptyExpression",
268
+ "JSXIdentifier",
269
+ "JSXOpeningFragment",
270
+ "JSXText",
271
+ "TSAnyKeyword",
272
+ "TSBigIntKeyword",
273
+ "TSBooleanKeyword",
274
+ "TSIntrinsicKeyword",
275
+ "TSNeverKeyword",
276
+ "TSNullKeyword",
277
+ "TSNumberKeyword",
278
+ "TSObjectKeyword",
279
+ "TSStringKeyword",
280
+ "TSSymbolKeyword",
281
+ "TSUndefinedKeyword",
282
+ "TSUnknownKeyword",
283
+ "TSVoidKeyword",
284
+ "TSThisType",
285
+ "TSLiteralType"
286
+ ]) {
287
+ tsNodeHandlers[nodeType] = () => {};
288
+ }
289
+
138
290
  Object.assign(base, tsNodeHandlers);
139
291
 
140
292
  export const WALK_BASE = base;
@@ -45,6 +45,18 @@ export function discoverChunks(ast, code, language = "javascript") {
45
45
  }
46
46
  },
47
47
 
48
+ TSInterfaceDeclaration(node) {
49
+ pushChunk(extractTypeDeclarationChunk(node, "interface", code));
50
+ },
51
+
52
+ TSTypeAliasDeclaration(node) {
53
+ pushChunk(extractTypeDeclarationChunk(node, "type", code));
54
+ },
55
+
56
+ TSEnumDeclaration(node) {
57
+ pushChunk(extractTypeDeclarationChunk(node, "enum", code));
58
+ },
59
+
48
60
  VariableDeclaration(node) {
49
61
  for (const declarator of node.declarations || []) {
50
62
  if (!declarator.id || declarator.id.type !== "Identifier" || !declarator.init) {
@@ -100,6 +112,15 @@ function collectExportedNames(ast) {
100
112
  exportedNames.add(node.declaration.id.name);
101
113
  }
102
114
 
115
+ if (
116
+ (node.declaration.type === "TSInterfaceDeclaration" ||
117
+ node.declaration.type === "TSTypeAliasDeclaration" ||
118
+ node.declaration.type === "TSEnumDeclaration") &&
119
+ node.declaration.id?.name
120
+ ) {
121
+ exportedNames.add(node.declaration.id.name);
122
+ }
123
+
103
124
  if (node.declaration.type === "VariableDeclaration") {
104
125
  for (const declarator of node.declaration.declarations || []) {
105
126
  if (declarator.id?.type === "Identifier") {
@@ -292,34 +313,120 @@ function extractClassMethods(classNode, code, language) {
292
313
  const className = classNode.id?.name || "UnknownClass";
293
314
 
294
315
  for (const member of classNode.body.body || []) {
295
- if (member.type !== "MethodDefinition" || member.key.type !== "Identifier") {
296
- continue;
297
- }
316
+ const methodChunk =
317
+ member.type === "MethodDefinition"
318
+ ? extractClassMethodChunk(member, className, code, language)
319
+ : extractClassFieldFunctionChunk(member, className, code, language);
298
320
 
299
- const params = (member.value.params || []).map(formatParameterName);
300
- const isStatic = member.static === true;
301
- const prefix = isStatic ? "static " : "";
302
- const bodyStart = findLeadingCommentStart(code, member);
303
-
304
- methods.push({
305
- name: `${className}.${member.key.name}`,
306
- kind: "method",
307
- signature: `${prefix}${member.key.name}(${params.join(", ")})`,
308
- body: code.slice(bodyStart, member.end),
309
- startLine: member.loc.start.line,
310
- endLine: member.loc.end.line,
311
- callNode: member.value.body,
312
- importNode: member,
313
- static: isStatic,
314
- async: member.value.async === true,
315
- generator: member.value.generator === true,
316
- language
317
- });
321
+ if (methodChunk) {
322
+ methods.push(methodChunk);
323
+ }
318
324
  }
319
325
 
320
326
  return methods;
321
327
  }
322
328
 
329
+ function extractClassMethodChunk(member, className, code, language) {
330
+ const methodName = getPropertyName(member.key, member.computed);
331
+ if (!methodName) {
332
+ return null;
333
+ }
334
+
335
+ const params = (member.value.params || []).map(formatParameterName);
336
+ const isStatic = member.static === true;
337
+ const prefix = isStatic ? "static " : "";
338
+ const bodyStart = findLeadingCommentStart(code, member);
339
+
340
+ return {
341
+ name: `${className}.${methodName}`,
342
+ kind: "method",
343
+ signature: `${prefix}${methodName}(${params.join(", ")})`,
344
+ body: code.slice(bodyStart, member.end),
345
+ startLine: member.loc.start.line,
346
+ endLine: member.loc.end.line,
347
+ callNode: member.value.body,
348
+ importNode: member,
349
+ static: isStatic,
350
+ async: member.value.async === true,
351
+ generator: member.value.generator === true,
352
+ language
353
+ };
354
+ }
355
+
356
+ function extractClassFieldFunctionChunk(member, className, code, language) {
357
+ if (member.type !== "PropertyDefinition" && member.type !== "FieldDefinition") {
358
+ return null;
359
+ }
360
+
361
+ const value = member.value;
362
+ const isFunctionField =
363
+ value?.type === "FunctionExpression" || value?.type === "ArrowFunctionExpression";
364
+ if (!isFunctionField) {
365
+ return null;
366
+ }
367
+
368
+ const fieldName = getPropertyName(member.key, member.computed);
369
+ if (!fieldName) {
370
+ return null;
371
+ }
372
+
373
+ const params = (value.params || []).map(formatParameterName);
374
+ const isStatic = member.static === true;
375
+ const prefix = isStatic ? "static " : "";
376
+ const bodyStart = findLeadingCommentStart(code, member);
377
+
378
+ return {
379
+ name: `${className}.${fieldName}`,
380
+ kind: "method",
381
+ signature: `${prefix}${fieldName}(${params.join(", ")})`,
382
+ body: code.slice(bodyStart, member.end),
383
+ startLine: member.loc.start.line,
384
+ endLine: member.loc.end.line,
385
+ callNode: value.body || value,
386
+ importNode: member,
387
+ static: isStatic,
388
+ async: value.async === true,
389
+ generator: value.generator === true,
390
+ field: true,
391
+ language
392
+ };
393
+ }
394
+
395
+ function extractTypeDeclarationChunk(node, kind, code) {
396
+ const name = node.id?.name;
397
+ if (!name) {
398
+ return null;
399
+ }
400
+
401
+ const bodyStart = findLeadingCommentStart(code, node);
402
+ return {
403
+ name,
404
+ kind,
405
+ signature: `${kind} ${name}`,
406
+ body: code.slice(bodyStart, node.end),
407
+ startLine: node.loc.start.line,
408
+ endLine: node.loc.end.line,
409
+ callNode: node,
410
+ importNode: node
411
+ };
412
+ }
413
+
414
+ function getPropertyName(key, computed = false) {
415
+ if (!key) {
416
+ return null;
417
+ }
418
+
419
+ if (!computed && key.type === "Identifier") {
420
+ return key.name;
421
+ }
422
+
423
+ if (key.type === "Literal" && typeof key.value === "string") {
424
+ return key.value;
425
+ }
426
+
427
+ return null;
428
+ }
429
+
323
430
  function findLeadingCommentStart(code, node) {
324
431
  let bodyStart = node.start;
325
432
  let lineStart = code.lastIndexOf("\n", node.start - 1) + 1;
@@ -103,16 +103,17 @@ function extractReferencedStaticImportSources(bodyNode, bindings) {
103
103
  fullAncestor(
104
104
  bodyNode,
105
105
  (node, state, ancestors) => {
106
- if (node.type !== "Identifier") {
106
+ const localName = getReferencedImportName(node, ancestors);
107
+ if (!localName) {
107
108
  return;
108
109
  }
109
110
 
110
- const source = importsByLocalName.get(node.name);
111
- if (!source || !isReferenceIdentifier(node, ancestors)) {
111
+ const source = importsByLocalName.get(localName);
112
+ if (!source) {
112
113
  return;
113
114
  }
114
115
 
115
- if (resolveIdentifier(node.name, ancestors, scopeGraph)) {
116
+ if (resolveIdentifier(localName, ancestors, scopeGraph)) {
116
117
  return;
117
118
  }
118
119
 
@@ -127,6 +128,39 @@ function extractReferencedStaticImportSources(bodyNode, bindings) {
127
128
  return [...sources].sort();
128
129
  }
129
130
 
131
+ function getReferencedImportName(node, ancestors) {
132
+ if (node.type === "Identifier") {
133
+ return isReferenceIdentifier(node, ancestors) ? node.name : null;
134
+ }
135
+
136
+ if (node.type !== "JSXIdentifier" || isIntrinsicJsxName(node.name)) {
137
+ return null;
138
+ }
139
+
140
+ const parent = ancestors[ancestors.length - 2] ?? null;
141
+ if (!parent) {
142
+ return null;
143
+ }
144
+
145
+ if (parent.type === "JSXOpeningElement" && parent.name === node) {
146
+ return node.name;
147
+ }
148
+
149
+ if (parent.type === "JSXMemberExpression" && parent.object === node) {
150
+ return node.name;
151
+ }
152
+
153
+ if (parent.type === "JSXNamespacedName" && parent.namespace === node) {
154
+ return node.name;
155
+ }
156
+
157
+ return null;
158
+ }
159
+
160
+ function isIntrinsicJsxName(name) {
161
+ return /^[a-z]/.test(name);
162
+ }
163
+
130
164
  function extractDynamicImports(bodyNode) {
131
165
  if (!bodyNode) {
132
166
  return [];
@@ -146,7 +146,8 @@ export function ensureVbNetParserPublished() {
146
146
  "-c", "Release",
147
147
  "-o", getPublishDir(),
148
148
  "--nologo",
149
- "-v", "quiet"
149
+ "-v", "quiet",
150
+ "/p:UseAppHost=false"
150
151
  ],
151
152
  { encoding: "utf8", timeout: 180000 }
152
153
  );
@@ -255,23 +255,59 @@ try {
255
255
  return raw.split(/\r?\n/)[0].trim();
256
256
  };
257
257
 
258
- const npmCache = path.join(cacheDir, "npm-cache");
259
- let latestRaw = "";
258
+ // The latest-version lookup is a network call; cache it for a day so
259
+ // repeated bootstraps/status checks stay fast and offline-friendly.
260
+ const fs = require("node:fs");
261
+ const versionCheckCache = path.join(cacheDir, "version-check.json");
262
+ const VERSION_CHECK_TTL_MS = 24 * 60 * 60 * 1000;
263
+ let latestVersion = null;
260
264
  try {
261
- latestRaw = execSync("npm view github:DanielBlomma/cortex version --json", {
262
- cwd: repoRoot,
263
- stdio: ["ignore", "pipe", "pipe"],
264
- encoding: "utf8",
265
- timeout: 2500,
266
- env: { ...process.env, NPM_CONFIG_CACHE: npmCache }
267
- }).trim();
268
- } catch (error) {
269
- console.log(`[status] cortex_update_check=unavailable (${summarizeError(error)})`);
270
- process.exit(0);
265
+ const cached = JSON.parse(fs.readFileSync(versionCheckCache, "utf8"));
266
+ const age = cached ? Date.now() - cached.checked_at : NaN;
267
+ if (
268
+ cached &&
269
+ typeof cached.latest === "string" &&
270
+ Number.isFinite(cached.checked_at) &&
271
+ age >= 0 &&
272
+ age < VERSION_CHECK_TTL_MS &&
273
+ parseVersion(cached.latest)
274
+ ) {
275
+ latestVersion = cached.latest;
276
+ }
277
+ } catch {
278
+ // No usable cache; fall through to the live lookup.
271
279
  }
272
280
 
273
- const parsedLatest = JSON.parse(latestRaw);
274
- const latestVersion = Array.isArray(parsedLatest) ? parsedLatest[parsedLatest.length - 1] : parsedLatest;
281
+ if (!latestVersion) {
282
+ const npmCache = path.join(cacheDir, "npm-cache");
283
+ let latestRaw = "";
284
+ try {
285
+ latestRaw = execSync("npm view github:DanielBlomma/cortex version --json", {
286
+ cwd: repoRoot,
287
+ stdio: ["ignore", "pipe", "pipe"],
288
+ encoding: "utf8",
289
+ timeout: 2500,
290
+ env: { ...process.env, NPM_CONFIG_CACHE: npmCache }
291
+ }).trim();
292
+ } catch (error) {
293
+ console.log(`[status] cortex_update_check=unavailable (${summarizeError(error)})`);
294
+ process.exit(0);
295
+ }
296
+
297
+ const parsedLatest = JSON.parse(latestRaw);
298
+ latestVersion = Array.isArray(parsedLatest) ? parsedLatest[parsedLatest.length - 1] : parsedLatest;
299
+ if (parseVersion(latestVersion)) {
300
+ try {
301
+ fs.mkdirSync(cacheDir, { recursive: true });
302
+ fs.writeFileSync(
303
+ versionCheckCache,
304
+ JSON.stringify({ checked_at: Date.now(), latest: latestVersion })
305
+ );
306
+ } catch {
307
+ // Cache write failures must never break status reporting.
308
+ }
309
+ }
310
+ }
275
311
 
276
312
  const localParsed = parseVersion(localVersion);
277
313
  const latestParsed = parseVersion(latestVersion);
@@ -1,56 +0,0 @@
1
- {
2
- "name": "parsers",
3
- "version": "1.0.0",
4
- "lockfileVersion": 3,
5
- "requires": true,
6
- "packages": {
7
- "node_modules/acorn": {
8
- "version": "8.16.0",
9
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz",
10
- "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==",
11
- "license": "MIT",
12
- "bin": {
13
- "acorn": "bin/acorn"
14
- },
15
- "engines": {
16
- "node": ">=0.4.0"
17
- }
18
- },
19
- "node_modules/acorn-typescript": {
20
- "version": "1.4.13",
21
- "resolved": "https://registry.npmjs.org/acorn-typescript/-/acorn-typescript-1.4.13.tgz",
22
- "integrity": "sha512-xsc9Xv0xlVfwp2o7sQ+GCQ1PgbkdcpWdTzrwXxO3xDMTAywVS3oXVOcOHuRjAPkS4P9b+yc/qNF15460v+jp4Q==",
23
- "license": "MIT",
24
- "peerDependencies": {
25
- "acorn": ">=8.9.0"
26
- }
27
- },
28
- "node_modules/acorn-walk": {
29
- "version": "8.3.5",
30
- "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.5.tgz",
31
- "integrity": "sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==",
32
- "license": "MIT",
33
- "dependencies": {
34
- "acorn": "^8.11.0"
35
- },
36
- "engines": {
37
- "node": ">=0.4.0"
38
- }
39
- },
40
- "node_modules/tree-sitter-wasms": {
41
- "version": "0.1.13",
42
- "resolved": "https://registry.npmjs.org/tree-sitter-wasms/-/tree-sitter-wasms-0.1.13.tgz",
43
- "integrity": "sha512-wT+cR6DwaIz80/vho3AvSF0N4txuNx/5bcRKoXouOfClpxh/qqrF4URNLQXbbt8MaAxeksZcZd1j8gcGjc+QxQ==",
44
- "license": "Unlicense",
45
- "dependencies": {
46
- "tree-sitter-wasms": "^0.1.11"
47
- }
48
- },
49
- "node_modules/web-tree-sitter": {
50
- "version": "0.22.6",
51
- "resolved": "https://registry.npmjs.org/web-tree-sitter/-/web-tree-sitter-0.22.6.tgz",
52
- "integrity": "sha512-hS87TH71Zd6mGAmYCvlgxeGDjqd9GTeqXNqTT+u0Gs51uIozNIaaq/kUAbV/Zf56jb2ZOyG8BxZs2GG9wbLi6Q==",
53
- "license": "MIT"
54
- }
55
- }
56
- }