@ttsc/graph 0.16.4 → 0.16.5
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/LICENSE +21 -21
- package/README.md +24 -53
- package/lib/TtscGraphApplication.js +46 -0
- package/lib/TtscGraphApplication.js.map +1 -0
- package/lib/index.js +31 -108
- package/lib/index.js.map +1 -1
- package/lib/model/TtscGraphMemory.js +185 -0
- package/lib/model/TtscGraphMemory.js.map +1 -0
- package/lib/model/loadGraph.js +418 -0
- package/lib/model/loadGraph.js.map +1 -0
- package/lib/reduce.js +101 -0
- package/lib/reduce.js.map +1 -0
- package/lib/resolveGraphBinary.js +42 -0
- package/lib/resolveGraphBinary.js.map +1 -0
- package/lib/server/createServer.js +1227 -0
- package/lib/server/createServer.js.map +1 -0
- package/lib/server/instructions.js +32 -0
- package/lib/server/instructions.js.map +1 -0
- package/lib/server/resolveHandle.js +25 -0
- package/lib/server/resolveHandle.js.map +1 -0
- package/lib/server/runExpand.js +177 -0
- package/lib/server/runExpand.js.map +1 -0
- package/lib/server/runIndex.js +146 -0
- package/lib/server/runIndex.js.map +1 -0
- package/lib/server/runOverview.js +150 -0
- package/lib/server/runOverview.js.map +1 -0
- package/lib/server/runQuery.js +147 -0
- package/lib/server/runQuery.js.map +1 -0
- package/lib/server/runTrace.js +219 -0
- package/lib/server/runTrace.js.map +1 -0
- package/lib/server/startServer.js +21 -0
- package/lib/server/startServer.js.map +1 -0
- package/lib/structures/ITtscGraphApplication.js +3 -0
- package/lib/structures/ITtscGraphApplication.js.map +1 -0
- package/lib/structures/ITtscGraphDecorator.js +3 -0
- package/lib/structures/ITtscGraphDecorator.js.map +1 -0
- package/lib/structures/ITtscGraphDiagnostic.js +3 -0
- package/lib/structures/ITtscGraphDiagnostic.js.map +1 -0
- package/lib/structures/ITtscGraphDump.js +3 -0
- package/lib/structures/ITtscGraphDump.js.map +1 -0
- package/lib/structures/ITtscGraphEdge.js +3 -0
- package/lib/structures/ITtscGraphEdge.js.map +1 -0
- package/lib/structures/ITtscGraphEvidence.js +3 -0
- package/lib/structures/ITtscGraphEvidence.js.map +1 -0
- package/lib/structures/ITtscGraphExpand.js +3 -0
- package/lib/structures/ITtscGraphExpand.js.map +1 -0
- package/lib/structures/ITtscGraphIndex.js +3 -0
- package/lib/structures/ITtscGraphIndex.js.map +1 -0
- package/lib/structures/ITtscGraphNode.js +3 -0
- package/lib/structures/ITtscGraphNode.js.map +1 -0
- package/lib/structures/ITtscGraphOverview.js +3 -0
- package/lib/structures/ITtscGraphOverview.js.map +1 -0
- package/lib/structures/ITtscGraphQuery.js +3 -0
- package/lib/structures/ITtscGraphQuery.js.map +1 -0
- package/lib/structures/ITtscGraphTrace.js +3 -0
- package/lib/structures/ITtscGraphTrace.js.map +1 -0
- package/lib/structures/TtscGraphEdgeKind.js +3 -0
- package/lib/structures/TtscGraphEdgeKind.js.map +1 -0
- package/lib/structures/TtscGraphNodeKind.js +3 -0
- package/lib/structures/TtscGraphNodeKind.js.map +1 -0
- package/lib/structures/TtscGraphNodeModifier.js +3 -0
- package/lib/structures/TtscGraphNodeModifier.js.map +1 -0
- package/lib/structures/index.js +37 -0
- package/lib/structures/index.js.map +1 -0
- package/lib/view.js +140 -0
- package/lib/view.js.map +1 -0
- package/lib/viewer/index.html +123 -0
- package/lib/viewer/viewer.js +4610 -0
- package/package.json +17 -4
- package/src/TtscGraphApplication.ts +57 -0
- package/src/index.ts +40 -126
- package/src/model/TtscGraphMemory.ts +204 -0
- package/src/model/loadGraph.ts +85 -0
- package/src/reduce.ts +165 -0
- package/src/resolveGraphBinary.ts +40 -0
- package/src/server/createServer.ts +104 -0
- package/src/server/instructions.ts +28 -0
- package/src/server/resolveHandle.ts +34 -0
- package/src/server/runExpand.ts +186 -0
- package/src/server/runIndex.ts +181 -0
- package/src/server/runOverview.ts +154 -0
- package/src/server/runQuery.ts +150 -0
- package/src/server/runTrace.ts +233 -0
- package/src/server/startServer.ts +25 -0
- package/src/structures/ITtscGraphApplication.ts +68 -0
- package/src/structures/ITtscGraphDecorator.ts +33 -0
- package/src/structures/ITtscGraphDiagnostic.ts +34 -0
- package/src/structures/ITtscGraphDump.ts +35 -0
- package/src/structures/ITtscGraphEdge.ts +24 -0
- package/src/structures/ITtscGraphEvidence.ts +29 -0
- package/src/structures/ITtscGraphExpand.ts +85 -0
- package/src/structures/ITtscGraphIndex.ts +100 -0
- package/src/structures/ITtscGraphNode.ts +64 -0
- package/src/structures/ITtscGraphOverview.ts +79 -0
- package/src/structures/ITtscGraphQuery.ts +49 -0
- package/src/structures/ITtscGraphTrace.ts +97 -0
- package/src/structures/TtscGraphEdgeKind.ts +23 -0
- package/src/structures/TtscGraphNodeKind.ts +26 -0
- package/src/structures/TtscGraphNodeModifier.ts +19 -0
- package/src/structures/index.ts +21 -0
- package/src/view.ts +155 -0
- package/src/viewer/index.html +123 -0
- package/src/viewer/main.ts +209 -0
- package/lib/bin.d.ts +0 -2
- package/lib/diagnostics.d.ts +0 -23
- package/lib/diagnostics.js +0 -84
- package/lib/diagnostics.js.map +0 -1
- package/lib/index.d.ts +0 -29
- package/src/diagnostics.ts +0 -93
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import { TtscGraphMemory } from "../model/TtscGraphMemory";
|
|
2
|
+
import { ITtscGraphNode } from "../structures/ITtscGraphNode";
|
|
3
|
+
import { ITtscGraphTrace } from "../structures/ITtscGraphTrace";
|
|
4
|
+
import { resolveGraphHandle } from "./resolveHandle";
|
|
5
|
+
import { signatureOf } from "./runExpand";
|
|
6
|
+
|
|
7
|
+
const DEFAULT_DEPTH = 6;
|
|
8
|
+
const DEFAULT_MAX_NODES = 60;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Breadth-first trace along the dependency graph. Structural
|
|
12
|
+
* (contains/exports/imports) edges are excluded so the path is real call/type
|
|
13
|
+
* flow; forward walks callees, reverse and impact walk callers. Impact
|
|
14
|
+
* additionally tags each reached node's role so the blast radius on the public
|
|
15
|
+
* surface is legible.
|
|
16
|
+
*/
|
|
17
|
+
export function runTrace(
|
|
18
|
+
graph: TtscGraphMemory,
|
|
19
|
+
props: ITtscGraphTrace.IProps,
|
|
20
|
+
): ITtscGraphTrace {
|
|
21
|
+
const direction = props.direction ?? "forward";
|
|
22
|
+
const maxDepth = Math.max(1, props.maxDepth ?? DEFAULT_DEPTH);
|
|
23
|
+
const maxNodes = Math.max(1, props.maxNodes ?? DEFAULT_MAX_NODES);
|
|
24
|
+
const reverse = direction === "reverse" || direction === "impact";
|
|
25
|
+
// Only an impact trace tags reached nodes with their public-surface role; for
|
|
26
|
+
// forward/reverse the role is noise.
|
|
27
|
+
const withRoles = direction === "impact";
|
|
28
|
+
|
|
29
|
+
const start = resolveGraphHandle(graph, props.from);
|
|
30
|
+
if (start.candidates) {
|
|
31
|
+
return {
|
|
32
|
+
direction,
|
|
33
|
+
hops: [],
|
|
34
|
+
reached: [],
|
|
35
|
+
truncated: false,
|
|
36
|
+
candidates: start.candidates.map((n) => summary(n)),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
if (start.node === undefined) {
|
|
40
|
+
return { direction, hops: [], reached: [], truncated: false };
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Path mode: with `to`, return the dependency path from `from` to `to` — the
|
|
44
|
+
// one-call answer for "how does A reach B" — instead of an open-ended trace.
|
|
45
|
+
if (props.to !== undefined && props.to !== "") {
|
|
46
|
+
const base = { direction: "path", hops: [], reached: [], truncated: false };
|
|
47
|
+
const target = resolveGraphHandle(graph, props.to);
|
|
48
|
+
if (target.candidates) {
|
|
49
|
+
return {
|
|
50
|
+
...base,
|
|
51
|
+
start: summary(start.node),
|
|
52
|
+
candidates: target.candidates.map((n) => summary(n)),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
if (target.node === undefined) {
|
|
56
|
+
return { ...base, start: summary(start.node) };
|
|
57
|
+
}
|
|
58
|
+
const found = findPath(
|
|
59
|
+
graph,
|
|
60
|
+
start.node.id,
|
|
61
|
+
target.node.id,
|
|
62
|
+
Math.max(1, props.maxDepth ?? 12),
|
|
63
|
+
);
|
|
64
|
+
return {
|
|
65
|
+
...base,
|
|
66
|
+
start: summary(start.node),
|
|
67
|
+
target: summary(target.node),
|
|
68
|
+
hops: found?.hops ?? [],
|
|
69
|
+
path: (found?.path ?? []).map((node, i) => {
|
|
70
|
+
const node_ = summary(node, i);
|
|
71
|
+
const sig = signatureOf(graph.project, node);
|
|
72
|
+
if (sig !== undefined) node_.signature = sig;
|
|
73
|
+
return node_;
|
|
74
|
+
}),
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const hops: ITtscGraphTrace.IHop[] = [];
|
|
79
|
+
const reached = new Map<string, ITtscGraphTrace.INode>();
|
|
80
|
+
const visited = new Set<string>([start.node.id]);
|
|
81
|
+
let queue: Array<{ id: string; depth: number }> = [
|
|
82
|
+
{ id: start.node.id, depth: 0 },
|
|
83
|
+
];
|
|
84
|
+
let truncated = false;
|
|
85
|
+
|
|
86
|
+
while (queue.length > 0) {
|
|
87
|
+
const next: Array<{ id: string; depth: number }> = [];
|
|
88
|
+
for (const { id, depth } of queue) {
|
|
89
|
+
if (depth >= maxDepth) {
|
|
90
|
+
truncated = true;
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
const edges = reverse ? graph.incoming(id) : graph.outgoing(id);
|
|
94
|
+
for (const edge of edges) {
|
|
95
|
+
if (!traversable(edge.kind)) continue;
|
|
96
|
+
const otherId = reverse ? edge.from : edge.to;
|
|
97
|
+
const other = graph.node(otherId);
|
|
98
|
+
if (other === undefined || other.kind === "file") continue;
|
|
99
|
+
const hop = {
|
|
100
|
+
from: edge.from,
|
|
101
|
+
to: edge.to,
|
|
102
|
+
kind: edge.kind,
|
|
103
|
+
depth: depth + 1,
|
|
104
|
+
};
|
|
105
|
+
// A back-edge to the start or an already-reached node: record the hop;
|
|
106
|
+
// its endpoints are already represented.
|
|
107
|
+
if (visited.has(otherId)) {
|
|
108
|
+
hops.push(hop);
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
// A new node past the cap is left unrepresented, so drop its hop too —
|
|
112
|
+
// every hop's endpoints stay resolvable in `reached`/`start`.
|
|
113
|
+
if (reached.size >= maxNodes) {
|
|
114
|
+
truncated = true;
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
visited.add(otherId);
|
|
118
|
+
reached.set(otherId, summary(other, depth + 1, withRoles));
|
|
119
|
+
next.push({ id: otherId, depth: depth + 1 });
|
|
120
|
+
hops.push(hop);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
queue = next;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return {
|
|
127
|
+
start: summary(start.node),
|
|
128
|
+
direction,
|
|
129
|
+
hops,
|
|
130
|
+
reached: [...reached.values()],
|
|
131
|
+
truncated,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* The shortest dependency path from `startId` to `targetId` over real (non-
|
|
137
|
+
* structural) forward edges, breadth-first, or null when `targetId` is not
|
|
138
|
+
* reachable within maxDepth. Returns the nodes in order and the hops between.
|
|
139
|
+
*/
|
|
140
|
+
function findPath(
|
|
141
|
+
graph: TtscGraphMemory,
|
|
142
|
+
startId: string,
|
|
143
|
+
targetId: string,
|
|
144
|
+
maxDepth: number,
|
|
145
|
+
): { path: ITtscGraphNode[]; hops: ITtscGraphTrace.IHop[] } | null {
|
|
146
|
+
const startNode = graph.node(startId);
|
|
147
|
+
if (startNode === undefined) return null;
|
|
148
|
+
if (startId === targetId) return { path: [startNode], hops: [] };
|
|
149
|
+
const parent = new Map<string, { via: string; kind: string }>();
|
|
150
|
+
const visited = new Set<string>([startId]);
|
|
151
|
+
let queue: Array<{ id: string; depth: number }> = [{ id: startId, depth: 0 }];
|
|
152
|
+
while (queue.length > 0) {
|
|
153
|
+
const next: Array<{ id: string; depth: number }> = [];
|
|
154
|
+
for (const { id, depth } of queue) {
|
|
155
|
+
if (depth >= maxDepth) continue;
|
|
156
|
+
for (const edge of graph.outgoing(id)) {
|
|
157
|
+
if (!traversable(edge.kind)) continue;
|
|
158
|
+
const otherId = edge.to;
|
|
159
|
+
if (visited.has(otherId)) continue;
|
|
160
|
+
const other = graph.node(otherId);
|
|
161
|
+
if (other === undefined || other.kind === "file") continue;
|
|
162
|
+
visited.add(otherId);
|
|
163
|
+
parent.set(otherId, { via: id, kind: edge.kind });
|
|
164
|
+
if (otherId === targetId) {
|
|
165
|
+
const ids: string[] = [otherId];
|
|
166
|
+
let cur = otherId;
|
|
167
|
+
while (cur !== startId) {
|
|
168
|
+
const p = parent.get(cur);
|
|
169
|
+
if (p === undefined) break;
|
|
170
|
+
ids.unshift(p.via);
|
|
171
|
+
cur = p.via;
|
|
172
|
+
}
|
|
173
|
+
const path: ITtscGraphNode[] = [];
|
|
174
|
+
for (const nid of ids) {
|
|
175
|
+
const n = graph.node(nid);
|
|
176
|
+
if (n !== undefined) path.push(n);
|
|
177
|
+
}
|
|
178
|
+
const hops: ITtscGraphTrace.IHop[] = [];
|
|
179
|
+
for (let i = 1; i < path.length; i++) {
|
|
180
|
+
const node = path[i]!;
|
|
181
|
+
hops.push({
|
|
182
|
+
from: path[i - 1]!.id,
|
|
183
|
+
to: node.id,
|
|
184
|
+
kind: parent.get(node.id)?.kind ?? "calls",
|
|
185
|
+
depth: i,
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
return { path, hops };
|
|
189
|
+
}
|
|
190
|
+
next.push({ id: otherId, depth: depth + 1 });
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
queue = next;
|
|
194
|
+
}
|
|
195
|
+
return null;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Summarize a node for a trace result. With `withRoles`, tag the public-surface
|
|
200
|
+
* roles (exported / test) an impact trace reports; other directions omit them.
|
|
201
|
+
*/
|
|
202
|
+
function summary(
|
|
203
|
+
node: ITtscGraphNode,
|
|
204
|
+
depth?: number,
|
|
205
|
+
withRoles = false,
|
|
206
|
+
): ITtscGraphTrace.INode {
|
|
207
|
+
const out: ITtscGraphTrace.INode = {
|
|
208
|
+
id: node.id,
|
|
209
|
+
name: node.qualifiedName ?? node.name,
|
|
210
|
+
kind: node.kind,
|
|
211
|
+
file: node.file,
|
|
212
|
+
};
|
|
213
|
+
if (depth !== undefined) out.depth = depth;
|
|
214
|
+
if (withRoles) {
|
|
215
|
+
const roles: string[] = [];
|
|
216
|
+
if (node.exported) roles.push("exported");
|
|
217
|
+
if (isTestFile(node.file)) roles.push("test");
|
|
218
|
+
if (roles.length > 0) out.roles = roles;
|
|
219
|
+
}
|
|
220
|
+
return out;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/** An edge the trace should follow: a real dependency, not a structural edge. */
|
|
224
|
+
function traversable(kind: string): boolean {
|
|
225
|
+
return kind !== "contains" && kind !== "exports" && kind !== "imports";
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
function isTestFile(file: string): boolean {
|
|
229
|
+
return (
|
|
230
|
+
/(^|\/)(test|tests|__tests__|spec)\//.test(file) ||
|
|
231
|
+
/\.(test|spec)\.[cm]?tsx?$/.test(file)
|
|
232
|
+
);
|
|
233
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
2
|
+
|
|
3
|
+
import { TtscGraphMemory } from "../model/TtscGraphMemory";
|
|
4
|
+
import { loadGraph } from "../model/loadGraph";
|
|
5
|
+
import { createServer } from "./createServer";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Serve the graph tools over MCP on stdio. The server answers the MCP handshake
|
|
9
|
+
* immediately and builds the resident graph on the first tool call, so a large
|
|
10
|
+
* project cannot make the client give up before tools are advertised.
|
|
11
|
+
*/
|
|
12
|
+
export async function startServer(options: {
|
|
13
|
+
cwd?: string;
|
|
14
|
+
tsconfig?: string;
|
|
15
|
+
/** Server version reported in the MCP handshake. */
|
|
16
|
+
version: string;
|
|
17
|
+
}): Promise<void> {
|
|
18
|
+
let graph: TtscGraphMemory | undefined;
|
|
19
|
+
const server = createServer(() => {
|
|
20
|
+
graph ??= loadGraph({ cwd: options.cwd, tsconfig: options.tsconfig });
|
|
21
|
+
return graph;
|
|
22
|
+
}, options.version);
|
|
23
|
+
const transport = new StdioServerTransport();
|
|
24
|
+
await server.connect(transport);
|
|
25
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { ITtscGraphExpand } from "./ITtscGraphExpand";
|
|
2
|
+
import { ITtscGraphIndex } from "./ITtscGraphIndex";
|
|
3
|
+
import { ITtscGraphOverview } from "./ITtscGraphOverview";
|
|
4
|
+
import { ITtscGraphQuery } from "./ITtscGraphQuery";
|
|
5
|
+
import { ITtscGraphTrace } from "./ITtscGraphTrace";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* The MCP tool surface of `@ttsc/graph`, as a typed application.
|
|
9
|
+
*
|
|
10
|
+
* Each method is one MCP tool; its name is the tool name and its parameter
|
|
11
|
+
* object becomes the tool's JSON schema once `typia.llm.controller` reflects
|
|
12
|
+
* this interface. `TtscGraphApplication` implements it over the resident
|
|
13
|
+
* graph.
|
|
14
|
+
*/
|
|
15
|
+
export interface ITtscGraphApplication {
|
|
16
|
+
/**
|
|
17
|
+
* The first source-free index for a code question: ranked symbols, exact code
|
|
18
|
+
* handles mentioned in the query, declaration signatures, and direct
|
|
19
|
+
* dependency context. Use this before reading source.
|
|
20
|
+
*
|
|
21
|
+
* @param props The natural code question or search phrase
|
|
22
|
+
* @returns Compact graph coordinates and dependency context
|
|
23
|
+
*/
|
|
24
|
+
graph_index(props: ITtscGraphIndex.IProps): ITtscGraphIndex;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* The project's architecture — folder layers, dependency hotspots, and the
|
|
28
|
+
* public API. Call first to orient on an unfamiliar codebase.
|
|
29
|
+
*
|
|
30
|
+
* @param props Which facet to project
|
|
31
|
+
* @returns The requested architecture facets
|
|
32
|
+
*/
|
|
33
|
+
graph_overview(props: ITtscGraphOverview.IProps): ITtscGraphOverview;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* The declared shape of the given symbols: each one's signature, and for a
|
|
37
|
+
* class/interface/namespace its members. Handles may be ids or dotted symbol
|
|
38
|
+
* names. Set `source: true` to also read a specific body, `neighbors: true`
|
|
39
|
+
* to list what it uses and what uses it.
|
|
40
|
+
*
|
|
41
|
+
* @param props The handles to expand
|
|
42
|
+
* @returns The resolved nodes, and any handles that did not resolve
|
|
43
|
+
*/
|
|
44
|
+
graph_expand(props: ITtscGraphExpand.IProps): ITtscGraphExpand;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Find any symbol — class, function, method, or field — by name or
|
|
48
|
+
* description. Each hit comes with its signature, so the query alone often
|
|
49
|
+
* answers the question, and `next.expand` gives handles for source
|
|
50
|
+
* follow-up.
|
|
51
|
+
*
|
|
52
|
+
* @param props The query and result cap
|
|
53
|
+
* @returns Ranked hits with handles
|
|
54
|
+
*/
|
|
55
|
+
graph_query(props: ITtscGraphQuery.IProps): ITtscGraphQuery;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Follow dependency flow from a symbol: `forward` to what it uses, `reverse`
|
|
59
|
+
* to what uses it, or `impact` to the public API and tests a change reaches.
|
|
60
|
+
* Give `from`/`to` as ids or dotted names to get the path between two symbols
|
|
61
|
+
* in one call — how A reaches B.
|
|
62
|
+
*
|
|
63
|
+
* @param props The start, optional target, direction, and bounds
|
|
64
|
+
* @returns The ordered hops and reached nodes, or candidates for an ambiguous
|
|
65
|
+
* start
|
|
66
|
+
*/
|
|
67
|
+
graph_trace(props: ITtscGraphTrace.IProps): ITtscGraphTrace;
|
|
68
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A decorator as written on a declaration, carried on the decorated
|
|
3
|
+
* {@link ITtscGraphNode}'s `decorators`. The graph reports the decorator
|
|
4
|
+
* faithfully rather than interpreting any framework's convention: the `name` is
|
|
5
|
+
* the decorator as written (`Controller`, `Get`, `TypedRoute.Get`, …) and the
|
|
6
|
+
* statically resolvable `arguments` are preserved, so a consumer can apply its
|
|
7
|
+
* own meaning without re-parsing source.
|
|
8
|
+
*/
|
|
9
|
+
export interface ITtscGraphDecorator {
|
|
10
|
+
/**
|
|
11
|
+
* The decorator name as written, qualified through its access path —
|
|
12
|
+
* `Controller`, `Get`, `TypedRoute.Get`, `MessagePattern`.
|
|
13
|
+
*/
|
|
14
|
+
name: string;
|
|
15
|
+
|
|
16
|
+
/** The call arguments, in source order. Empty for a bare decorator. */
|
|
17
|
+
arguments: ITtscGraphDecorator.IArgument[];
|
|
18
|
+
}
|
|
19
|
+
export namespace ITtscGraphDecorator {
|
|
20
|
+
/**
|
|
21
|
+
* One argument of an {@link ITtscGraphDecorator}. `text` is always the source
|
|
22
|
+
* of the argument expression; `literal` is set only when the argument is a
|
|
23
|
+
* string, number, or boolean literal the producer could resolve statically,
|
|
24
|
+
* so a consumer can use it without evaluating code.
|
|
25
|
+
*/
|
|
26
|
+
export interface IArgument {
|
|
27
|
+
/** The argument expression's source text. */
|
|
28
|
+
text: string;
|
|
29
|
+
|
|
30
|
+
/** The statically-resolved literal value, when the argument is a literal. */
|
|
31
|
+
literal?: string | number | boolean;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A compiler or plugin diagnostic, fused onto the graph so an edit-triage query
|
|
3
|
+
* can name the owning symbol of an error.
|
|
4
|
+
*
|
|
5
|
+
* The TypeScript semantic pass contributes numeric-coded `tsc` diagnostics;
|
|
6
|
+
* `@ttsc/lint` rules and transform plugins (typia, nestia, …) contribute
|
|
7
|
+
* `plugin`/`lint` findings whose `code` is a string. `node` is set when the
|
|
8
|
+
* finding's position was attributed to a graph node.
|
|
9
|
+
*/
|
|
10
|
+
export interface ITtscGraphDiagnostic {
|
|
11
|
+
/** Project-relative path of the file the diagnostic is reported in. */
|
|
12
|
+
file: string;
|
|
13
|
+
|
|
14
|
+
/** 1-based line of the diagnostic. */
|
|
15
|
+
line: number;
|
|
16
|
+
|
|
17
|
+
/** 1-based column of the diagnostic, when known. */
|
|
18
|
+
column?: number;
|
|
19
|
+
|
|
20
|
+
/** Numeric `tsc` code, or string rule id for a lint/plugin finding. */
|
|
21
|
+
code: number | string;
|
|
22
|
+
|
|
23
|
+
/** The human-readable diagnostic message. */
|
|
24
|
+
message: string;
|
|
25
|
+
|
|
26
|
+
/** Severity, when the producer distinguishes it. */
|
|
27
|
+
severity?: "error" | "warning" | "info" | "hint";
|
|
28
|
+
|
|
29
|
+
/** Which lane produced the diagnostic. */
|
|
30
|
+
origin?: "tsc" | "plugin" | "lint";
|
|
31
|
+
|
|
32
|
+
/** Node id the diagnostic was fused onto, when resolved. */
|
|
33
|
+
node?: string;
|
|
34
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { ITtscGraphDiagnostic } from "./ITtscGraphDiagnostic";
|
|
2
|
+
import { ITtscGraphEdge } from "./ITtscGraphEdge";
|
|
3
|
+
import { ITtscGraphNode } from "./ITtscGraphNode";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The whole-graph export `ttscgraph dump` writes and the MCP server loads — the
|
|
7
|
+
* wire contract between the Go fact-builder and the TypeScript graph engine.
|
|
8
|
+
*
|
|
9
|
+
* It is the complete graph with none of the per-response caps the MCP tools
|
|
10
|
+
* apply: every node and edge the build resolved. The server parses it once at
|
|
11
|
+
* startup (typia-validated) into an in-memory resident graph and answers every
|
|
12
|
+
* tool call from that warm model; the bundled 3D viewer reduces the same dump.
|
|
13
|
+
*
|
|
14
|
+
* Paths in `project` and `tsconfig` are absolute; `file` fields on nodes,
|
|
15
|
+
* edges, and diagnostics are project-relative.
|
|
16
|
+
*/
|
|
17
|
+
export interface ITtscGraphDump {
|
|
18
|
+
/** Absolute path of the project root the graph was built for. */
|
|
19
|
+
project: string;
|
|
20
|
+
|
|
21
|
+
/** The tsconfig the program was loaded from, relative to `project`. */
|
|
22
|
+
tsconfig: string;
|
|
23
|
+
|
|
24
|
+
/** Every node the build recorded. */
|
|
25
|
+
nodes: ITtscGraphNode[];
|
|
26
|
+
|
|
27
|
+
/** Every edge the build resolved. */
|
|
28
|
+
edges: ITtscGraphEdge[];
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Fused compiler and plugin diagnostics, when diagnostics were collected.
|
|
32
|
+
* Absent when the dump was built without a diagnostics pass.
|
|
33
|
+
*/
|
|
34
|
+
diagnostics?: ITtscGraphDiagnostic[];
|
|
35
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { ITtscGraphEvidence } from "./ITtscGraphEvidence";
|
|
2
|
+
import { TtscGraphEdgeKind } from "./TtscGraphEdgeKind";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* A directed relationship from one {@link ITtscGraphNode} to another, both named
|
|
6
|
+
* by `id`. The triple `(from, to, kind)` is unique; a repeated relationship
|
|
7
|
+
* keeps the first source-order evidence.
|
|
8
|
+
*
|
|
9
|
+
* Every edge is resolved by the compiler, so there is no per-edge trust flag to
|
|
10
|
+
* carry — the whole graph is checker-resolved fact.
|
|
11
|
+
*/
|
|
12
|
+
export interface ITtscGraphEdge {
|
|
13
|
+
/** Node id the relationship originates from. */
|
|
14
|
+
from: string;
|
|
15
|
+
|
|
16
|
+
/** Node id the relationship points to. */
|
|
17
|
+
to: string;
|
|
18
|
+
|
|
19
|
+
/** The relationship kind. */
|
|
20
|
+
kind: TtscGraphEdgeKind;
|
|
21
|
+
|
|
22
|
+
/** The source expression that produced the edge, for display and expansion. */
|
|
23
|
+
evidence?: ITtscGraphEvidence;
|
|
24
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A source location that grounds a node or edge in real code — the declaration
|
|
3
|
+
* span for a node, or the expression that produced an edge.
|
|
4
|
+
*
|
|
5
|
+
* Evidence is display and grounding only; it is never identity. A node's id is
|
|
6
|
+
* position-invariant (see {@link ITtscGraphNode}), so an edit that shifts a span
|
|
7
|
+
* does not re-key anything. `startLine`/`startCol` are 1-based. `text` is an
|
|
8
|
+
* optional short excerpt the producer may include so a consumer can show the
|
|
9
|
+
* evidence without a file read.
|
|
10
|
+
*/
|
|
11
|
+
export interface ITtscGraphEvidence {
|
|
12
|
+
/** Project-relative path of the file the span lives in. */
|
|
13
|
+
file: string;
|
|
14
|
+
|
|
15
|
+
/** 1-based line where the span starts. */
|
|
16
|
+
startLine: number;
|
|
17
|
+
|
|
18
|
+
/** 1-based column where the span starts, when known. */
|
|
19
|
+
startCol?: number;
|
|
20
|
+
|
|
21
|
+
/** 1-based line where the span ends, when it differs from `startLine`. */
|
|
22
|
+
endLine?: number;
|
|
23
|
+
|
|
24
|
+
/** 1-based column where the span ends, when known. */
|
|
25
|
+
endCol?: number;
|
|
26
|
+
|
|
27
|
+
/** A short source excerpt of the span, when the producer inlines one. */
|
|
28
|
+
text?: string;
|
|
29
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
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
|
+
}
|