homegraph 1.6.3 → 1.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.
@@ -9,6 +9,7 @@ exports.matchByFilePath = matchByFilePath;
9
9
  exports.sameLanguageFamily = sameLanguageFamily;
10
10
  exports.isKnownLanguageFamily = isKnownLanguageFamily;
11
11
  exports.crossesKnownFamily = crossesKnownFamily;
12
+ exports.matchTypeEdge = matchTypeEdge;
12
13
  exports.matchFunctionRef = matchFunctionRef;
13
14
  exports.matchByExactName = matchByExactName;
14
15
  exports.matchByQualifiedName = matchByQualifiedName;
@@ -193,7 +194,10 @@ function crossesKnownFamily(a, b) {
193
194
  * both-known filter so `.vue`/`.svelte` (own tag) importing `.ts` survives.
194
195
  */
195
196
  function applyLanguageGate(candidates, ref) {
196
- if (ref.referenceKind === 'references' || ref.referenceKind === 'function_ref') {
197
+ if (ref.referenceKind === 'references' ||
198
+ ref.referenceKind === 'function_ref' ||
199
+ ref.referenceKind === 'returns' ||
200
+ ref.referenceKind === 'type_of') {
197
201
  return candidates.filter((c) => sameLanguageFamily(c.language, ref.language));
198
202
  }
199
203
  if (ref.referenceKind === 'imports') {
@@ -201,6 +205,57 @@ function applyLanguageGate(candidates, ref) {
201
205
  }
202
206
  return candidates;
203
207
  }
208
+ /** Spec 0066 — targets for `returns` / `type_of` edges (type-as-node). */
209
+ const TYPE_EDGE_KINDS = new Set([
210
+ 'class',
211
+ 'interface',
212
+ 'type_alias',
213
+ 'enum',
214
+ 'struct',
215
+ 'protocol',
216
+ 'trait',
217
+ 'component',
218
+ ]);
219
+ /**
220
+ * Spec 0066: resolve a return/param type name to a unique type node.
221
+ * Ambiguous same-named types → no edge (wrong type hub is worse than none).
222
+ */
223
+ function matchTypeEdge(ref, context) {
224
+ if (ref.referenceKind !== 'returns' && ref.referenceKind !== 'type_of')
225
+ return null;
226
+ const simple = ref.referenceName.includes('.') || ref.referenceName.includes('::')
227
+ ? (ref.referenceName.split(/[.:]+/).filter(Boolean).pop() ?? ref.referenceName)
228
+ : ref.referenceName;
229
+ let candidates = context
230
+ .getNodesByName(simple)
231
+ .filter((n) => TYPE_EDGE_KINDS.has(n.kind) && n.id !== ref.fromNodeId);
232
+ candidates = applyLanguageGate(candidates, ref);
233
+ if (candidates.length === 0)
234
+ return null;
235
+ // Qualified exact: unique_id-style `A.B.Foo` / `A::Foo` against qualifiedName.
236
+ if (ref.referenceName.includes('.') || ref.referenceName.includes('::')) {
237
+ const qnHits = candidates.filter((n) => n.qualifiedName === ref.referenceName ||
238
+ n.qualifiedName.endsWith(`.${simple}`) ||
239
+ n.qualifiedName.endsWith(`::${simple}`));
240
+ if (qnHits.length === 1) {
241
+ return {
242
+ original: ref,
243
+ targetNodeId: qnHits[0].id,
244
+ confidence: 0.95,
245
+ resolvedBy: 'qualified-name',
246
+ };
247
+ }
248
+ }
249
+ const ordered = preferCallSiteFile(candidates, ref.filePath);
250
+ if (ordered.length !== 1)
251
+ return null;
252
+ return {
253
+ original: ref,
254
+ targetNodeId: ordered[0].id,
255
+ confidence: 0.9,
256
+ resolvedBy: 'exact-match',
257
+ };
258
+ }
204
259
  /**
205
260
  * Resolve a function-as-value reference (#756) — a function name used as a
206
261
  * callback/function-pointer value (`register(handler)`, `o->cb = handler`,
@@ -2078,6 +2133,10 @@ function matchReference(ref, context) {
2078
2133
  if (ref.referenceKind === 'function_ref') {
2079
2134
  return matchFunctionRef(ref, context);
2080
2135
  }
2136
+ // Spec 0066: returns / type_of — unique type node only; no fuzzy fallthrough.
2137
+ if (ref.referenceKind === 'returns' || ref.referenceKind === 'type_of') {
2138
+ return matchTypeEdge(ref, context);
2139
+ }
2081
2140
  // ArkTS chained UI attributes — emitted with a leading dot (`.titleStyle`,
2082
2141
  // `.width`) by the extractor — resolve ONLY to decorator-marked attribute
2083
2142
  // helpers: `@Extend`/`@Styles`/`@AnimatableExtend` functions (and global
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "homegraph",
3
- "version": "1.6.3",
3
+ "version": "1.6.4",
4
4
  "description": "Supercharge AI coding agents with semantic code intelligence — surgical context, fewer tool calls, faster answers. 100% local.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -25,6 +25,8 @@
25
25
  "test:node-matrix": "bash scripts/test-node-matrix.sh",
26
26
  "test:explore-routing": "node scripts/run-explore-routing.mjs",
27
27
  "eval": "npm run build && npx tsx test/evaluation/runner.ts",
28
+ "eval:peak-mem": "node --disable-warning=MODULE_TYPELESS_PACKAGE_JSON --experimental-strip-types test/evaluation/index-peak-mem.ts",
29
+ "soak:photos": "node test/harmony-callgraph-soak/run.mjs",
28
30
  "clean": "node -e \"const fs=require('fs');fs.rmSync('dist',{recursive:true,force:true})\""
29
31
  },
30
32
  "keywords": [