@ttsc/graph 0.16.5 → 0.16.7
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 +22 -0
- package/lib/TtscGraphApplication.js +58 -22
- package/lib/TtscGraphApplication.js.map +1 -1
- package/lib/model/TtscGraphMemory.js +43 -4
- package/lib/model/TtscGraphMemory.js.map +1 -1
- package/lib/model/loadGraph.js +17 -17
- package/lib/server/accessAliases.js +53 -0
- package/lib/server/accessAliases.js.map +1 -0
- package/lib/server/createServer.js +1490 -657
- package/lib/server/createServer.js.map +1 -1
- package/lib/server/instructions.js +81 -21
- package/lib/server/instructions.js.map +1 -1
- package/lib/server/pathPolicy.js +35 -0
- package/lib/server/pathPolicy.js.map +1 -0
- package/lib/server/resultGuide.js +16 -0
- package/lib/server/resultGuide.js.map +1 -0
- package/lib/server/runDetails.js +474 -0
- package/lib/server/runDetails.js.map +1 -0
- package/lib/server/{runIndex.js → runEntrypoints.js} +92 -28
- package/lib/server/runEntrypoints.js.map +1 -0
- package/lib/server/runLookup.js +246 -0
- package/lib/server/runLookup.js.map +1 -0
- package/lib/server/runOverview.js +44 -27
- package/lib/server/runOverview.js.map +1 -1
- package/lib/server/runTour.js +737 -0
- package/lib/server/runTour.js.map +1 -0
- package/lib/server/runTrace.js +224 -43
- package/lib/server/runTrace.js.map +1 -1
- package/lib/structures/ITtscGraphDetails.js +3 -0
- package/lib/structures/ITtscGraphDetails.js.map +1 -0
- package/lib/structures/ITtscGraphEntrypoints.js +3 -0
- package/lib/structures/ITtscGraphEntrypoints.js.map +1 -0
- package/lib/structures/{ITtscGraphExpand.js → ITtscGraphEscape.js} +1 -1
- package/lib/structures/ITtscGraphEscape.js.map +1 -0
- package/lib/structures/ITtscGraphLookup.js +3 -0
- package/lib/structures/ITtscGraphLookup.js.map +1 -0
- package/lib/structures/{ITtscGraphIndex.js → ITtscGraphNext.js} +1 -1
- package/lib/structures/ITtscGraphNext.js.map +1 -0
- package/lib/structures/{ITtscGraphQuery.js → ITtscGraphTour.js} +1 -1
- package/lib/structures/ITtscGraphTour.js.map +1 -0
- package/lib/structures/index.js +6 -3
- package/lib/structures/index.js.map +1 -1
- package/package.json +2 -2
- package/src/TtscGraphApplication.ts +70 -30
- package/src/model/TtscGraphMemory.ts +46 -4
- package/src/server/accessAliases.ts +55 -0
- package/src/server/createServer.ts +4 -7
- package/src/server/instructions.ts +81 -21
- package/src/server/pathPolicy.ts +43 -0
- package/src/server/resultGuide.ts +20 -0
- package/src/server/runDetails.ts +553 -0
- package/src/server/{runIndex.ts → runEntrypoints.ts} +116 -36
- package/src/server/runLookup.ts +284 -0
- package/src/server/runOverview.ts +59 -31
- package/src/server/runTour.ts +881 -0
- package/src/server/runTrace.ts +299 -45
- package/src/structures/ITtscGraphApplication.ts +75 -56
- package/src/structures/ITtscGraphDecorator.ts +12 -14
- package/src/structures/ITtscGraphDetails.ts +197 -0
- package/src/structures/ITtscGraphEntrypoints.ts +149 -0
- package/src/structures/ITtscGraphEscape.ts +49 -0
- package/src/structures/ITtscGraphEvidence.ts +5 -8
- package/src/structures/ITtscGraphLookup.ts +82 -0
- package/src/structures/ITtscGraphNext.ts +23 -0
- package/src/structures/ITtscGraphNode.ts +10 -4
- package/src/structures/ITtscGraphOverview.ts +41 -18
- package/src/structures/ITtscGraphTour.ts +150 -0
- package/src/structures/ITtscGraphTrace.ts +93 -13
- package/src/structures/TtscGraphNodeKind.ts +2 -2
- package/src/structures/index.ts +6 -3
- package/lib/server/runExpand.js +0 -177
- package/lib/server/runExpand.js.map +0 -1
- package/lib/server/runIndex.js.map +0 -1
- package/lib/server/runQuery.js +0 -147
- package/lib/server/runQuery.js.map +0 -1
- package/lib/structures/ITtscGraphExpand.js.map +0 -1
- package/lib/structures/ITtscGraphIndex.js.map +0 -1
- package/lib/structures/ITtscGraphQuery.js.map +0 -1
- package/src/server/runExpand.ts +0 -186
- package/src/server/runQuery.ts +0 -150
- package/src/structures/ITtscGraphExpand.ts +0 -85
- package/src/structures/ITtscGraphIndex.ts +0 -100
- package/src/structures/ITtscGraphQuery.ts +0 -49
package/lib/server/runQuery.js
DELETED
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.runQuery = runQuery;
|
|
4
|
-
const runExpand_1 = require("./runExpand");
|
|
5
|
-
// One file should not crowd out the rest of the ranking, so cap hits per file.
|
|
6
|
-
const PER_FILE = 3;
|
|
7
|
-
const DEFAULT_LIMIT = 12;
|
|
8
|
-
/**
|
|
9
|
-
* Rank the graph's symbols against a natural query. Scoring blends exact and
|
|
10
|
-
* dotted-name matches, CamelCase/subword coverage, file-path terms, a prefix
|
|
11
|
-
* bonus, and dependency centrality, then dampens external, generated, and test
|
|
12
|
-
* nodes and caps per file so the result is a diverse, relevant shortlist rather
|
|
13
|
-
* than one file's roster.
|
|
14
|
-
*/
|
|
15
|
-
function runQuery(graph, props) {
|
|
16
|
-
const terms = subwords(props.query);
|
|
17
|
-
const queryLc = props.query.trim().toLowerCase();
|
|
18
|
-
if (terms.length === 0)
|
|
19
|
-
return { hits: [], next: { expand: [] } };
|
|
20
|
-
const scored = [];
|
|
21
|
-
for (const node of graph.nodes) {
|
|
22
|
-
if (node.kind === "file")
|
|
23
|
-
continue;
|
|
24
|
-
const score = scoreNode(graph, node, queryLc, terms);
|
|
25
|
-
if (score <= 0)
|
|
26
|
-
continue;
|
|
27
|
-
scored.push({
|
|
28
|
-
id: node.id,
|
|
29
|
-
name: node.qualifiedName ?? node.name,
|
|
30
|
-
kind: node.kind,
|
|
31
|
-
file: node.file,
|
|
32
|
-
line: node.evidence?.startLine,
|
|
33
|
-
score: Math.round(score),
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
scored.sort((a, b) => b.score - a.score);
|
|
37
|
-
// Diversity: keep at most PER_FILE hits per file while filling up to the limit.
|
|
38
|
-
const limit = Math.max(1, props.limit ?? DEFAULT_LIMIT);
|
|
39
|
-
const perFile = new Map();
|
|
40
|
-
const hits = [];
|
|
41
|
-
for (const hit of scored) {
|
|
42
|
-
const used = perFile.get(hit.file) ?? 0;
|
|
43
|
-
if (used >= PER_FILE)
|
|
44
|
-
continue;
|
|
45
|
-
perFile.set(hit.file, used + 1);
|
|
46
|
-
hits.push(hit);
|
|
47
|
-
if (hits.length >= limit)
|
|
48
|
-
break;
|
|
49
|
-
}
|
|
50
|
-
// Attach each kept hit's signature — only the shortlist, so the read cost is
|
|
51
|
-
// bounded — so the model can often answer from the query alone, no expand.
|
|
52
|
-
for (const hit of hits) {
|
|
53
|
-
const node = graph.node(hit.id);
|
|
54
|
-
if (node === undefined)
|
|
55
|
-
continue;
|
|
56
|
-
const sig = (0, runExpand_1.signatureOf)(graph.project, node);
|
|
57
|
-
if (sig !== undefined)
|
|
58
|
-
hit.signature = sig;
|
|
59
|
-
}
|
|
60
|
-
return { hits, next: { expand: hits.map((hit) => hit.id) } };
|
|
61
|
-
}
|
|
62
|
-
/** Score one node against the query; 0 means no match. */
|
|
63
|
-
function scoreNode(graph, node, queryLc, terms) {
|
|
64
|
-
const name = node.name.toLowerCase();
|
|
65
|
-
const qualified = (node.qualifiedName ?? node.name).toLowerCase();
|
|
66
|
-
const nameSubs = subwords(node.name);
|
|
67
|
-
const qualifiedSubs = subwords(node.qualifiedName ?? node.name);
|
|
68
|
-
const pathSubs = subwords(node.file);
|
|
69
|
-
let score = 0;
|
|
70
|
-
if (queryLc === name || queryLc === qualified) {
|
|
71
|
-
score += 100;
|
|
72
|
-
}
|
|
73
|
-
else if (qualified.includes(".") && queryLc.includes(qualified)) {
|
|
74
|
-
score += 85;
|
|
75
|
-
}
|
|
76
|
-
else if (queryLc.includes(".") && qualified.includes(queryLc)) {
|
|
77
|
-
score += 60;
|
|
78
|
-
}
|
|
79
|
-
let covered = 0;
|
|
80
|
-
for (const term of terms) {
|
|
81
|
-
if (nameSubs.includes(term)) {
|
|
82
|
-
score += 12;
|
|
83
|
-
covered++;
|
|
84
|
-
}
|
|
85
|
-
else if (qualifiedSubs.includes(term)) {
|
|
86
|
-
score += 8;
|
|
87
|
-
covered++;
|
|
88
|
-
}
|
|
89
|
-
else if (name.includes(term)) {
|
|
90
|
-
score += 5;
|
|
91
|
-
covered++;
|
|
92
|
-
}
|
|
93
|
-
else if (pathSubs.includes(term)) {
|
|
94
|
-
score += 3;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
// Every query term landed somewhere in the name: a strong whole-query match.
|
|
98
|
-
if (covered === terms.length)
|
|
99
|
-
score += 10;
|
|
100
|
-
if (name.startsWith(terms[0]))
|
|
101
|
-
score += 4;
|
|
102
|
-
if (score <= 0)
|
|
103
|
-
return 0;
|
|
104
|
-
// Centrality: a symbol the codebase leans on is a likelier target.
|
|
105
|
-
const fan = degree(graph, node.id);
|
|
106
|
-
score += Math.min(8, Math.log2(1 + fan) * 2);
|
|
107
|
-
// Dampen what is rarely the intended target.
|
|
108
|
-
if (node.external)
|
|
109
|
-
score *= 0.5;
|
|
110
|
-
if (node.ignored)
|
|
111
|
-
score *= 0.3;
|
|
112
|
-
if (isTestFile(node.file))
|
|
113
|
-
score *= 0.7;
|
|
114
|
-
return score;
|
|
115
|
-
}
|
|
116
|
-
/** Non-structural in+out degree (code dependency, not nesting). */
|
|
117
|
-
function degree(graph, id) {
|
|
118
|
-
let n = 0;
|
|
119
|
-
for (const edge of graph.outgoing(id))
|
|
120
|
-
if (!isStructural(edge.kind))
|
|
121
|
-
n++;
|
|
122
|
-
for (const edge of graph.incoming(id))
|
|
123
|
-
if (!isStructural(edge.kind))
|
|
124
|
-
n++;
|
|
125
|
-
return n;
|
|
126
|
-
}
|
|
127
|
-
function isStructural(kind) {
|
|
128
|
-
return kind === "contains" || kind === "exports" || kind === "imports";
|
|
129
|
-
}
|
|
130
|
-
function isTestFile(file) {
|
|
131
|
-
return (/(^|\/)(test|tests|__tests__|spec)\//.test(file) ||
|
|
132
|
-
/\.(test|spec)\.[cm]?tsx?$/.test(file));
|
|
133
|
-
}
|
|
134
|
-
/**
|
|
135
|
-
* Split an identifier or phrase into lowercase subword tokens: CamelCase,
|
|
136
|
-
* snake, dotted, and space boundaries all break, so `getHTTPResponse`,
|
|
137
|
-
* `find_by_id`, and `OrderService.create` tokenize the way a query would.
|
|
138
|
-
*/
|
|
139
|
-
function subwords(text) {
|
|
140
|
-
return text
|
|
141
|
-
.replace(/([a-z0-9])([A-Z])/g, "$1 $2")
|
|
142
|
-
.replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2")
|
|
143
|
-
.split(/[^a-zA-Z0-9]+/)
|
|
144
|
-
.filter((w) => w.length > 0)
|
|
145
|
-
.map((w) => w.toLowerCase());
|
|
146
|
-
}
|
|
147
|
-
//# sourceMappingURL=runQuery.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"runQuery.js","sourceRoot":"","sources":["../../src/server/runQuery.ts"],"names":[],"mappings":";;;AAGA,2CAA0C;AAE1C,+EAA+E;AAC/E,MAAM,QAAQ,GAAG,CAAC,CAAC;AACnB,MAAM,aAAa,GAAG,EAAE,CAAC;AAEzB;;;;;;GAMG;AACH,kBACE,KAAsB,EACtB,KAA6B;IAE7B,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACpC,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACjD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC;IAElE,MAAM,MAAM,GAA2B,EAAE,CAAC;IAC1C,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;QAC/B,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM;YAAE,SAAS;QACnC,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;QACrD,IAAI,KAAK,IAAI,CAAC;YAAE,SAAS;QACzB,MAAM,CAAC,IAAI,CAAC;YACV,EAAE,EAAE,IAAI,CAAC,EAAE;YACX,IAAI,EAAE,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,IAAI;YACrC,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,SAAS;YAC9B,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC;SACzB,CAAC,CAAC;IACL,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;IAEzC,gFAAgF;IAChF,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,IAAI,aAAa,CAAC,CAAC;IACxD,MAAM,OAAO,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC1C,MAAM,IAAI,GAA2B,EAAE,CAAC;IACxC,KAAK,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxC,IAAI,IAAI,IAAI,QAAQ;YAAE,SAAS;QAC/B,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,GAAG,CAAC,CAAC,CAAC;QAChC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACf,IAAI,IAAI,CAAC,MAAM,IAAI,KAAK;YAAE,MAAM;IAClC,CAAC;IAED,6EAA6E;IAC7E,2EAA2E;IAC3E,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChC,IAAI,IAAI,KAAK,SAAS;YAAE,SAAS;QACjC,MAAM,GAAG,GAAG,IAAA,uBAAW,EAAC,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QAC7C,IAAI,GAAG,KAAK,SAAS;YAAE,GAAG,CAAC,SAAS,GAAG,GAAG,CAAC;IAC7C,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;AAC/D,CAAC;AAED,0DAA0D;AAC1D,SAAS,SAAS,CAChB,KAAsB,EACtB,IAAoB,EACpB,OAAe,EACf,KAAe;IAEf,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;IACrC,MAAM,SAAS,GAAG,CAAC,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;IAClE,MAAM,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrC,MAAM,aAAa,GAAG,QAAQ,CAAC,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC;IAChE,MAAM,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAErC,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC9C,KAAK,IAAI,GAAG,CAAC;IACf,CAAC;SAAM,IAAI,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QAClE,KAAK,IAAI,EAAE,CAAC;IACd,CAAC;SAAM,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QAChE,KAAK,IAAI,EAAE,CAAC;IACd,CAAC;IAED,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YAC5B,KAAK,IAAI,EAAE,CAAC;YACZ,OAAO,EAAE,CAAC;QACZ,CAAC;aAAM,IAAI,aAAa,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACxC,KAAK,IAAI,CAAC,CAAC;YACX,OAAO,EAAE,CAAC;QACZ,CAAC;aAAM,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YAC/B,KAAK,IAAI,CAAC,CAAC;YACX,OAAO,EAAE,CAAC;QACZ,CAAC;aAAM,IAAI,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACnC,KAAK,IAAI,CAAC,CAAC;QACb,CAAC;IACH,CAAC;IACD,6EAA6E;IAC7E,IAAI,OAAO,KAAK,KAAK,CAAC,MAAM;QAAE,KAAK,IAAI,EAAE,CAAC;IAC1C,IAAI,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC;QAAE,KAAK,IAAI,CAAC,CAAC;IAE3C,IAAI,KAAK,IAAI,CAAC;QAAE,OAAO,CAAC,CAAC;IAEzB,mEAAmE;IACnE,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;IACnC,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;IAE7C,6CAA6C;IAC7C,IAAI,IAAI,CAAC,QAAQ;QAAE,KAAK,IAAI,GAAG,CAAC;IAChC,IAAI,IAAI,CAAC,OAAO;QAAE,KAAK,IAAI,GAAG,CAAC;IAC/B,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,KAAK,IAAI,GAAG,CAAC;IACxC,OAAO,KAAK,CAAC;AACf,CAAC;AAED,mEAAmE;AACnE,SAAS,MAAM,CAAC,KAAsB,EAAE,EAAU;IAChD,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;QAAE,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,CAAC,EAAE,CAAC;IACzE,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;QAAE,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,CAAC,EAAE,CAAC;IACzE,OAAO,CAAC,CAAC;AACX,CAAC;AAED,SAAS,YAAY,CAAC,IAAY;IAChC,OAAO,IAAI,KAAK,UAAU,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,SAAS,CAAC;AACzE,CAAC;AAED,SAAS,UAAU,CAAC,IAAY;IAC9B,OAAO,CACL,qCAAqC,CAAC,IAAI,CAAC,IAAI,CAAC;QAChD,2BAA2B,CAAC,IAAI,CAAC,IAAI,CAAC,CACvC,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAS,QAAQ,CAAC,IAAY;IAC5B,OAAO,IAAI;SACR,OAAO,CAAC,oBAAoB,EAAE,OAAO,CAAC;SACtC,OAAO,CAAC,uBAAuB,EAAE,OAAO,CAAC;SACzC,KAAK,CAAC,eAAe,CAAC;SACtB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;SAC3B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;AACjC,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ITtscGraphExpand.js","sourceRoot":"","sources":["../../src/structures/ITtscGraphExpand.ts"],"names":[],"mappings":""}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ITtscGraphIndex.js","sourceRoot":"","sources":["../../src/structures/ITtscGraphIndex.ts"],"names":[],"mappings":""}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ITtscGraphQuery.js","sourceRoot":"","sources":["../../src/structures/ITtscGraphQuery.ts"],"names":[],"mappings":""}
|
package/src/server/runExpand.ts
DELETED
|
@@ -1,186 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
|
|
4
|
-
import { TtscGraphMemory } from "../model/TtscGraphMemory";
|
|
5
|
-
import { ITtscGraphEdge } from "../structures/ITtscGraphEdge";
|
|
6
|
-
import { ITtscGraphExpand } from "../structures/ITtscGraphExpand";
|
|
7
|
-
import { ITtscGraphNode } from "../structures/ITtscGraphNode";
|
|
8
|
-
import { resolveGraphHandle } from "./resolveHandle";
|
|
9
|
-
|
|
10
|
-
// A whole declaration body can be large, so the full source is opt-in and capped
|
|
11
|
-
// when asked for; the default response carries only the declared shape.
|
|
12
|
-
const MAX_SOURCE_LINES = 200;
|
|
13
|
-
// A signature is the declaration head up to the body brace — a handful of lines.
|
|
14
|
-
const MAX_SIGNATURE_LINES = 6;
|
|
15
|
-
// Neighbor lists are a map, not a dump; keep them scannable.
|
|
16
|
-
const MAX_NEIGHBORS = 40;
|
|
17
|
-
// A container's outline can be long (a big class); keep it bounded.
|
|
18
|
-
const MAX_MEMBERS = 80;
|
|
19
|
-
// Structural relationships are navigation, not the dependency picture expand is for.
|
|
20
|
-
const STRUCTURAL_KINDS = new Set<string>(["contains", "exports", "imports"]);
|
|
21
|
-
// Kinds whose value is their member outline, not a source body.
|
|
22
|
-
const CONTAINER_KINDS = new Set<string>([
|
|
23
|
-
"class",
|
|
24
|
-
"interface",
|
|
25
|
-
"namespace",
|
|
26
|
-
"module",
|
|
27
|
-
"enum",
|
|
28
|
-
"file",
|
|
29
|
-
]);
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Resolve each handle to its declared shape — its signature, and for a
|
|
33
|
-
* container the outline of its members — and, only when asked, its full source
|
|
34
|
-
* body. This is the graph's edge over a plain file read: it answers from the
|
|
35
|
-
* resolved structure it already holds, so the agent reads compact shape, not
|
|
36
|
-
* inlined code, unless it explicitly needs a body's logic.
|
|
37
|
-
*/
|
|
38
|
-
export function runExpand(
|
|
39
|
-
graph: TtscGraphMemory,
|
|
40
|
-
props: ITtscGraphExpand.IProps,
|
|
41
|
-
): ITtscGraphExpand {
|
|
42
|
-
const wantSource = props.source === true;
|
|
43
|
-
const nodes: ITtscGraphExpand.INode[] = [];
|
|
44
|
-
const unknown: string[] = [];
|
|
45
|
-
for (const handle of props.handles) {
|
|
46
|
-
const resolved = resolveGraphHandle(graph, handle);
|
|
47
|
-
if (resolved.node === undefined) {
|
|
48
|
-
unknown.push(handle);
|
|
49
|
-
continue;
|
|
50
|
-
}
|
|
51
|
-
const node = resolved.node;
|
|
52
|
-
const expanded: ITtscGraphExpand.INode = {
|
|
53
|
-
id: node.id,
|
|
54
|
-
name: node.qualifiedName ?? node.name,
|
|
55
|
-
kind: node.kind,
|
|
56
|
-
file: node.file,
|
|
57
|
-
};
|
|
58
|
-
if (node.evidence?.startLine) expanded.line = node.evidence.startLine;
|
|
59
|
-
const sig = signatureOf(graph.project, node);
|
|
60
|
-
if (sig !== undefined) expanded.signature = sig;
|
|
61
|
-
if (CONTAINER_KINDS.has(node.kind)) {
|
|
62
|
-
const list = members(graph, node);
|
|
63
|
-
if (list.length > 0) expanded.members = list;
|
|
64
|
-
}
|
|
65
|
-
if (wantSource) {
|
|
66
|
-
const source = readSource(graph.project, node);
|
|
67
|
-
if (source !== undefined) {
|
|
68
|
-
expanded.source = source.text;
|
|
69
|
-
if (source.truncated) expanded.truncated = true;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
if (props.neighbors === true) {
|
|
73
|
-
expanded.dependsOn = refs(graph, graph.outgoing(node.id), "to");
|
|
74
|
-
expanded.dependedOnBy = refs(graph, graph.incoming(node.id), "from");
|
|
75
|
-
}
|
|
76
|
-
nodes.push(expanded);
|
|
77
|
-
}
|
|
78
|
-
return { nodes, unknown };
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/** The members a container owns (via `contains`), each with its own signature. */
|
|
82
|
-
function members(
|
|
83
|
-
graph: TtscGraphMemory,
|
|
84
|
-
node: ITtscGraphNode,
|
|
85
|
-
): ITtscGraphExpand.IMember[] {
|
|
86
|
-
const out: ITtscGraphExpand.IMember[] = [];
|
|
87
|
-
for (const edge of graph.outgoing(node.id)) {
|
|
88
|
-
if (edge.kind !== "contains") continue;
|
|
89
|
-
const member = graph.node(edge.to);
|
|
90
|
-
if (member === undefined) continue;
|
|
91
|
-
const m: ITtscGraphExpand.IMember = {
|
|
92
|
-
name: member.qualifiedName ?? member.name,
|
|
93
|
-
kind: member.kind,
|
|
94
|
-
};
|
|
95
|
-
if (member.evidence?.startLine) m.line = member.evidence.startLine;
|
|
96
|
-
const sig = signatureOf(graph.project, member);
|
|
97
|
-
if (sig !== undefined) m.signature = sig;
|
|
98
|
-
out.push(m);
|
|
99
|
-
if (out.length >= MAX_MEMBERS) break;
|
|
100
|
-
}
|
|
101
|
-
return out;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/** Map dependency edges to references on their far endpoint, dropping structure. */
|
|
105
|
-
function refs(
|
|
106
|
-
graph: TtscGraphMemory,
|
|
107
|
-
edges: readonly ITtscGraphEdge[],
|
|
108
|
-
end: "to" | "from",
|
|
109
|
-
): ITtscGraphExpand.IReference[] {
|
|
110
|
-
const out: ITtscGraphExpand.IReference[] = [];
|
|
111
|
-
for (const edge of edges) {
|
|
112
|
-
if (STRUCTURAL_KINDS.has(edge.kind)) continue;
|
|
113
|
-
const other = graph.node(end === "to" ? edge.to : edge.from);
|
|
114
|
-
if (other === undefined) continue;
|
|
115
|
-
out.push({
|
|
116
|
-
id: other.id,
|
|
117
|
-
name: other.qualifiedName ?? other.name,
|
|
118
|
-
kind: other.kind,
|
|
119
|
-
relation: edge.kind,
|
|
120
|
-
});
|
|
121
|
-
if (out.length >= MAX_NEIGHBORS) break;
|
|
122
|
-
}
|
|
123
|
-
return out;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/** Read a file's lines once, or undefined when it cannot be read. */
|
|
127
|
-
function fileLines(
|
|
128
|
-
project: string,
|
|
129
|
-
node: ITtscGraphNode,
|
|
130
|
-
): string[] | undefined {
|
|
131
|
-
if (node.evidence === undefined || node.file === "") return undefined;
|
|
132
|
-
try {
|
|
133
|
-
return fs
|
|
134
|
-
.readFileSync(path.join(project, node.file), "utf8")
|
|
135
|
-
.split(/\r?\n/);
|
|
136
|
-
} catch {
|
|
137
|
-
return undefined;
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* The declaration signature: the head of the declaration up to and including
|
|
143
|
-
* the line that opens its body (`{`), or the single declaration line when there
|
|
144
|
-
* is no brace, capped so a wrapped signature cannot run away.
|
|
145
|
-
*/
|
|
146
|
-
export function signatureOf(
|
|
147
|
-
project: string,
|
|
148
|
-
node: ITtscGraphNode,
|
|
149
|
-
): string | undefined {
|
|
150
|
-
const lines = fileLines(project, node);
|
|
151
|
-
const evidence = node.evidence;
|
|
152
|
-
if (lines === undefined || evidence === undefined) return undefined;
|
|
153
|
-
const start = Math.max(0, evidence.startLine - 1);
|
|
154
|
-
const out: string[] = [];
|
|
155
|
-
for (
|
|
156
|
-
let i = start;
|
|
157
|
-
i < lines.length && out.length < MAX_SIGNATURE_LINES;
|
|
158
|
-
i++
|
|
159
|
-
) {
|
|
160
|
-
const line = lines[i];
|
|
161
|
-
if (line === undefined) break;
|
|
162
|
-
out.push(line);
|
|
163
|
-
if (line.includes("{")) break;
|
|
164
|
-
}
|
|
165
|
-
const text = out.join("\n").trim();
|
|
166
|
-
return text === "" ? undefined : text;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
/** Slice a node's full declaration source from disk, capped at MAX_SOURCE_LINES. */
|
|
170
|
-
function readSource(
|
|
171
|
-
project: string,
|
|
172
|
-
node: ITtscGraphNode,
|
|
173
|
-
): { text: string; truncated: boolean } | undefined {
|
|
174
|
-
const lines = fileLines(project, node);
|
|
175
|
-
const evidence = node.evidence;
|
|
176
|
-
if (lines === undefined || evidence === undefined) return undefined;
|
|
177
|
-
const start = Math.max(0, evidence.startLine - 1);
|
|
178
|
-
const end = Math.min(evidence.endLine ?? evidence.startLine, lines.length);
|
|
179
|
-
let slice = lines.slice(start, Math.max(start + 1, end));
|
|
180
|
-
let truncated = false;
|
|
181
|
-
if (slice.length > MAX_SOURCE_LINES) {
|
|
182
|
-
slice = slice.slice(0, MAX_SOURCE_LINES);
|
|
183
|
-
truncated = true;
|
|
184
|
-
}
|
|
185
|
-
return { text: slice.join("\n"), truncated };
|
|
186
|
-
}
|
package/src/server/runQuery.ts
DELETED
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
import { TtscGraphMemory } from "../model/TtscGraphMemory";
|
|
2
|
-
import { ITtscGraphNode } from "../structures/ITtscGraphNode";
|
|
3
|
-
import { ITtscGraphQuery } from "../structures/ITtscGraphQuery";
|
|
4
|
-
import { signatureOf } from "./runExpand";
|
|
5
|
-
|
|
6
|
-
// One file should not crowd out the rest of the ranking, so cap hits per file.
|
|
7
|
-
const PER_FILE = 3;
|
|
8
|
-
const DEFAULT_LIMIT = 12;
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Rank the graph's symbols against a natural query. Scoring blends exact and
|
|
12
|
-
* dotted-name matches, CamelCase/subword coverage, file-path terms, a prefix
|
|
13
|
-
* bonus, and dependency centrality, then dampens external, generated, and test
|
|
14
|
-
* nodes and caps per file so the result is a diverse, relevant shortlist rather
|
|
15
|
-
* than one file's roster.
|
|
16
|
-
*/
|
|
17
|
-
export function runQuery(
|
|
18
|
-
graph: TtscGraphMemory,
|
|
19
|
-
props: ITtscGraphQuery.IProps,
|
|
20
|
-
): ITtscGraphQuery {
|
|
21
|
-
const terms = subwords(props.query);
|
|
22
|
-
const queryLc = props.query.trim().toLowerCase();
|
|
23
|
-
if (terms.length === 0) return { hits: [], next: { expand: [] } };
|
|
24
|
-
|
|
25
|
-
const scored: ITtscGraphQuery.IHit[] = [];
|
|
26
|
-
for (const node of graph.nodes) {
|
|
27
|
-
if (node.kind === "file") continue;
|
|
28
|
-
const score = scoreNode(graph, node, queryLc, terms);
|
|
29
|
-
if (score <= 0) continue;
|
|
30
|
-
scored.push({
|
|
31
|
-
id: node.id,
|
|
32
|
-
name: node.qualifiedName ?? node.name,
|
|
33
|
-
kind: node.kind,
|
|
34
|
-
file: node.file,
|
|
35
|
-
line: node.evidence?.startLine,
|
|
36
|
-
score: Math.round(score),
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
scored.sort((a, b) => b.score - a.score);
|
|
41
|
-
|
|
42
|
-
// Diversity: keep at most PER_FILE hits per file while filling up to the limit.
|
|
43
|
-
const limit = Math.max(1, props.limit ?? DEFAULT_LIMIT);
|
|
44
|
-
const perFile = new Map<string, number>();
|
|
45
|
-
const hits: ITtscGraphQuery.IHit[] = [];
|
|
46
|
-
for (const hit of scored) {
|
|
47
|
-
const used = perFile.get(hit.file) ?? 0;
|
|
48
|
-
if (used >= PER_FILE) continue;
|
|
49
|
-
perFile.set(hit.file, used + 1);
|
|
50
|
-
hits.push(hit);
|
|
51
|
-
if (hits.length >= limit) break;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// Attach each kept hit's signature — only the shortlist, so the read cost is
|
|
55
|
-
// bounded — so the model can often answer from the query alone, no expand.
|
|
56
|
-
for (const hit of hits) {
|
|
57
|
-
const node = graph.node(hit.id);
|
|
58
|
-
if (node === undefined) continue;
|
|
59
|
-
const sig = signatureOf(graph.project, node);
|
|
60
|
-
if (sig !== undefined) hit.signature = sig;
|
|
61
|
-
}
|
|
62
|
-
return { hits, next: { expand: hits.map((hit) => hit.id) } };
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/** Score one node against the query; 0 means no match. */
|
|
66
|
-
function scoreNode(
|
|
67
|
-
graph: TtscGraphMemory,
|
|
68
|
-
node: ITtscGraphNode,
|
|
69
|
-
queryLc: string,
|
|
70
|
-
terms: string[],
|
|
71
|
-
): number {
|
|
72
|
-
const name = node.name.toLowerCase();
|
|
73
|
-
const qualified = (node.qualifiedName ?? node.name).toLowerCase();
|
|
74
|
-
const nameSubs = subwords(node.name);
|
|
75
|
-
const qualifiedSubs = subwords(node.qualifiedName ?? node.name);
|
|
76
|
-
const pathSubs = subwords(node.file);
|
|
77
|
-
|
|
78
|
-
let score = 0;
|
|
79
|
-
if (queryLc === name || queryLc === qualified) {
|
|
80
|
-
score += 100;
|
|
81
|
-
} else if (qualified.includes(".") && queryLc.includes(qualified)) {
|
|
82
|
-
score += 85;
|
|
83
|
-
} else if (queryLc.includes(".") && qualified.includes(queryLc)) {
|
|
84
|
-
score += 60;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
let covered = 0;
|
|
88
|
-
for (const term of terms) {
|
|
89
|
-
if (nameSubs.includes(term)) {
|
|
90
|
-
score += 12;
|
|
91
|
-
covered++;
|
|
92
|
-
} else if (qualifiedSubs.includes(term)) {
|
|
93
|
-
score += 8;
|
|
94
|
-
covered++;
|
|
95
|
-
} else if (name.includes(term)) {
|
|
96
|
-
score += 5;
|
|
97
|
-
covered++;
|
|
98
|
-
} else if (pathSubs.includes(term)) {
|
|
99
|
-
score += 3;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
// Every query term landed somewhere in the name: a strong whole-query match.
|
|
103
|
-
if (covered === terms.length) score += 10;
|
|
104
|
-
if (name.startsWith(terms[0]!)) score += 4;
|
|
105
|
-
|
|
106
|
-
if (score <= 0) return 0;
|
|
107
|
-
|
|
108
|
-
// Centrality: a symbol the codebase leans on is a likelier target.
|
|
109
|
-
const fan = degree(graph, node.id);
|
|
110
|
-
score += Math.min(8, Math.log2(1 + fan) * 2);
|
|
111
|
-
|
|
112
|
-
// Dampen what is rarely the intended target.
|
|
113
|
-
if (node.external) score *= 0.5;
|
|
114
|
-
if (node.ignored) score *= 0.3;
|
|
115
|
-
if (isTestFile(node.file)) score *= 0.7;
|
|
116
|
-
return score;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
/** Non-structural in+out degree (code dependency, not nesting). */
|
|
120
|
-
function degree(graph: TtscGraphMemory, id: string): number {
|
|
121
|
-
let n = 0;
|
|
122
|
-
for (const edge of graph.outgoing(id)) if (!isStructural(edge.kind)) n++;
|
|
123
|
-
for (const edge of graph.incoming(id)) if (!isStructural(edge.kind)) n++;
|
|
124
|
-
return n;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
function isStructural(kind: string): boolean {
|
|
128
|
-
return kind === "contains" || kind === "exports" || kind === "imports";
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
function isTestFile(file: string): boolean {
|
|
132
|
-
return (
|
|
133
|
-
/(^|\/)(test|tests|__tests__|spec)\//.test(file) ||
|
|
134
|
-
/\.(test|spec)\.[cm]?tsx?$/.test(file)
|
|
135
|
-
);
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* Split an identifier or phrase into lowercase subword tokens: CamelCase,
|
|
140
|
-
* snake, dotted, and space boundaries all break, so `getHTTPResponse`,
|
|
141
|
-
* `find_by_id`, and `OrderService.create` tokenize the way a query would.
|
|
142
|
-
*/
|
|
143
|
-
function subwords(text: string): string[] {
|
|
144
|
-
return text
|
|
145
|
-
.replace(/([a-z0-9])([A-Z])/g, "$1 $2")
|
|
146
|
-
.replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2")
|
|
147
|
-
.split(/[^a-zA-Z0-9]+/)
|
|
148
|
-
.filter((w) => w.length > 0)
|
|
149
|
-
.map((w) => w.toLowerCase());
|
|
150
|
-
}
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The resolved nodes the `graph_expand` tool returns for a set of handles —
|
|
3
|
-
* their declared shape (signature, and a container's members), and only on
|
|
4
|
-
* request their full source body.
|
|
5
|
-
*/
|
|
6
|
-
export interface ITtscGraphExpand {
|
|
7
|
-
nodes: ITtscGraphExpand.INode[];
|
|
8
|
-
|
|
9
|
-
/** Handles that resolved to no node, or that were ambiguous. */
|
|
10
|
-
unknown: string[];
|
|
11
|
-
}
|
|
12
|
-
export namespace ITtscGraphExpand {
|
|
13
|
-
/** Which handles to expand, and how much of each to return. */
|
|
14
|
-
export interface IProps {
|
|
15
|
-
/**
|
|
16
|
-
* Node ids from another tool, or dotted symbol handles such as
|
|
17
|
-
* `OrderService.create`. Pass every handle you need in one call.
|
|
18
|
-
*/
|
|
19
|
-
handles: string[];
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Also list each node's direct dependencies and dependents (the symbols it
|
|
23
|
-
* uses and the symbols that use it).
|
|
24
|
-
*
|
|
25
|
-
* @default false
|
|
26
|
-
*/
|
|
27
|
-
neighbors?: boolean;
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Return the full declaration source body too. Off by default: expand
|
|
31
|
-
* returns the declared shape — a symbol's signature, and a class/interface/
|
|
32
|
-
* namespace's member outline — which is what you usually need and a
|
|
33
|
-
* fraction of the tokens. Turn this on only for the few leaf functions or
|
|
34
|
-
* methods whose actual control-flow logic you must read.
|
|
35
|
-
*
|
|
36
|
-
* @default false
|
|
37
|
-
*/
|
|
38
|
-
source?: boolean;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/** One expanded node: its declared shape, and on request its source. */
|
|
42
|
-
export interface INode {
|
|
43
|
-
id: string;
|
|
44
|
-
name: string;
|
|
45
|
-
kind: string;
|
|
46
|
-
file: string;
|
|
47
|
-
/** 1-based declaration line, when known. */
|
|
48
|
-
line?: number;
|
|
49
|
-
/** The declaration signature — its first line(s) up to the body. */
|
|
50
|
-
signature?: string;
|
|
51
|
-
/**
|
|
52
|
-
* For a class, interface, namespace, module, enum, or file: the symbols it
|
|
53
|
-
* contains, each with its own signature — the member outline a consumer
|
|
54
|
-
* reaches for, without the bodies.
|
|
55
|
-
*/
|
|
56
|
-
members?: IMember[];
|
|
57
|
-
/** The full declaration source — only when `source` was requested. */
|
|
58
|
-
source?: string;
|
|
59
|
-
/** True when `source` was cut at the line cap. */
|
|
60
|
-
truncated?: boolean;
|
|
61
|
-
/** Symbols this node uses (outgoing dependency edges). */
|
|
62
|
-
dependsOn?: IReference[];
|
|
63
|
-
/** Symbols that use this node (incoming dependency edges). */
|
|
64
|
-
dependedOnBy?: IReference[];
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/** One member of a container node, with its signature but not its body. */
|
|
68
|
-
export interface IMember {
|
|
69
|
-
name: string;
|
|
70
|
-
kind: string;
|
|
71
|
-
/** 1-based declaration line, when known. */
|
|
72
|
-
line?: number;
|
|
73
|
-
/** The member's declaration signature. */
|
|
74
|
-
signature?: string;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/** A dependency neighbor of an expanded node and the edge that links them. */
|
|
78
|
-
export interface IReference {
|
|
79
|
-
id: string;
|
|
80
|
-
name: string;
|
|
81
|
-
kind: string;
|
|
82
|
-
/** The edge kind connecting the two (`calls`, `type_ref`, …). */
|
|
83
|
-
relation: string;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
/** The compact source-free index returned by `graph_index` for a code question. */
|
|
2
|
-
export interface ITtscGraphIndex {
|
|
3
|
-
/** The original query the index was built for. */
|
|
4
|
-
query: string;
|
|
5
|
-
|
|
6
|
-
/** Ranked symbols relevant to the query. */
|
|
7
|
-
hits: ITtscGraphIndex.IHit[];
|
|
8
|
-
|
|
9
|
-
/** Code handles written directly in the query, resolved when possible. */
|
|
10
|
-
mentions: ITtscGraphIndex.IMention[];
|
|
11
|
-
|
|
12
|
-
/** Direct dependency context for the resolved mentions and highest hits. */
|
|
13
|
-
neighborhood: ITtscGraphIndex.INeighborhood[];
|
|
14
|
-
|
|
15
|
-
/** Follow-up handles for deeper graph calls. */
|
|
16
|
-
next: ITtscGraphIndex.INext;
|
|
17
|
-
|
|
18
|
-
/** True when result caps hid additional seeds or references. */
|
|
19
|
-
truncated?: boolean;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export namespace ITtscGraphIndex {
|
|
23
|
-
/**
|
|
24
|
-
* Ask the graph for the first index an agent should read before opening
|
|
25
|
-
* source: ranked symbols, exact mentioned handles, and nearby dependency
|
|
26
|
-
* edges.
|
|
27
|
-
*/
|
|
28
|
-
export interface IProps {
|
|
29
|
-
/**
|
|
30
|
-
* A natural code question or search phrase. Mix prose with code handles,
|
|
31
|
-
* for example `how Repository.find loads relations` or
|
|
32
|
-
* `SelectQueryBuilder.setFindOptions join aliases`.
|
|
33
|
-
*/
|
|
34
|
-
query: string;
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Maximum ranked hits to return.
|
|
38
|
-
*
|
|
39
|
-
* @default 8
|
|
40
|
-
*/
|
|
41
|
-
limit?: number;
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Maximum direct dependencies and dependents to return per indexed symbol.
|
|
45
|
-
*
|
|
46
|
-
* @default 4
|
|
47
|
-
*/
|
|
48
|
-
neighbors?: number;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/** A compact symbol coordinate, optionally with its declaration signature. */
|
|
52
|
-
export interface INode {
|
|
53
|
-
id: string;
|
|
54
|
-
name: string;
|
|
55
|
-
kind: string;
|
|
56
|
-
file: string;
|
|
57
|
-
/** 1-based declaration line, when known. */
|
|
58
|
-
line?: number;
|
|
59
|
-
/** Declaration head, included only for indexed symbols. */
|
|
60
|
-
signature?: string;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/** One ranked search hit. */
|
|
64
|
-
export interface IHit extends INode {
|
|
65
|
-
/** Relative relevance; higher is a better match. */
|
|
66
|
-
score: number;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/** A code handle written in the query, with its resolution status. */
|
|
70
|
-
export interface IMention {
|
|
71
|
-
handle: string;
|
|
72
|
-
node?: INode;
|
|
73
|
-
candidates?: INode[];
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/** Direct dependency context around one indexed symbol. */
|
|
77
|
-
export interface INeighborhood extends INode {
|
|
78
|
-
dependsOn: IReference[];
|
|
79
|
-
dependedOnBy: IReference[];
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/** One neighboring symbol and the relationship leading to it. */
|
|
83
|
-
export interface IReference {
|
|
84
|
-
id: string;
|
|
85
|
-
name: string;
|
|
86
|
-
kind: string;
|
|
87
|
-
file: string;
|
|
88
|
-
/** 1-based declaration line, when known. */
|
|
89
|
-
line?: number;
|
|
90
|
-
relation: string;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
/** Tool-call handles suggested by this first index. */
|
|
94
|
-
export interface INext {
|
|
95
|
-
/** Pass these ids to `graph_expand`, with `source: true` only when needed. */
|
|
96
|
-
expand: string[];
|
|
97
|
-
/** Pass these ids to `graph_trace` when following dependency flow. */
|
|
98
|
-
traceFrom: string[];
|
|
99
|
-
}
|
|
100
|
-
}
|