@papyruslabsai/seshat-mcp 0.20.0 → 0.20.1
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 -0
- package/README.md +87 -0
- package/package.json +41 -48
- package/dist/bootstrap.d.ts +0 -29
- package/dist/bootstrap.js +0 -190
- package/dist/graph.d.ts +0 -42
- package/dist/graph.js +0 -272
- package/dist/index.d.ts +0 -9
- package/dist/loader.d.ts +0 -62
- package/dist/loader.js +0 -264
- package/dist/supabase.d.ts +0 -99
- package/dist/supabase.js +0 -132
- package/dist/tools/dbops.d.ts +0 -24
- package/dist/tools/dbops.js +0 -78
- package/dist/tools/diff.d.ts +0 -28
- package/dist/tools/diff.js +0 -604
- package/dist/tools/functors.d.ts +0 -150
- package/dist/tools/functors.js +0 -1727
- package/dist/tools/index.d.ts +0 -66
- package/dist/tools/index.js +0 -389
- package/dist/types.d.ts +0 -174
- package/dist/types.js +0 -8
package/dist/tools/index.d.ts
DELETED
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Semantic MCP Tool Implementations
|
|
3
|
-
*
|
|
4
|
-
* Each tool exposes a query or computation over the extracted code entity graph.
|
|
5
|
-
* Tools operate on the in-memory entity bundle loaded from .seshat/_bundle.json.
|
|
6
|
-
*
|
|
7
|
-
* Multi-project: when multiple projects are loaded, each tool accepts an optional
|
|
8
|
-
* `project` parameter. In multi-project mode, `project` is required.
|
|
9
|
-
*/
|
|
10
|
-
import type { JstfEntity, ProjectLoader } from '../types.js';
|
|
11
|
-
import { type CallGraph } from '../graph.js';
|
|
12
|
-
export { extractDbOps, tableContract, type DbOperation } from './dbops.js';
|
|
13
|
-
export declare function getGraph(project: string | undefined, loader: ProjectLoader): CallGraph;
|
|
14
|
-
/**
|
|
15
|
-
* Validate project param. Returns error string if invalid, null if OK.
|
|
16
|
-
* In single-project mode, project is optional (defaults to the only project).
|
|
17
|
-
* In multi-project mode, project is required.
|
|
18
|
-
*/
|
|
19
|
-
export declare function validateProject(project: string | undefined, loader: ProjectLoader): string | null;
|
|
20
|
-
export declare function entityName(e: JstfEntity): string;
|
|
21
|
-
export declare function entityLayer(e: JstfEntity): string;
|
|
22
|
-
export declare function entitySummary(e: JstfEntity): Record<string, unknown>;
|
|
23
|
-
export declare function normalizeConstraints(constraints: JstfEntity['constraints']): string[];
|
|
24
|
-
/**
|
|
25
|
-
* Deep search constraints — matches against raw constraint object fields too,
|
|
26
|
-
* not just normalized tags.
|
|
27
|
-
*/
|
|
28
|
-
export declare function constraintMatches(constraints: JstfEntity['constraints'], target: string): boolean;
|
|
29
|
-
export declare function queryEntities(args: {
|
|
30
|
-
project?: string;
|
|
31
|
-
query?: string;
|
|
32
|
-
layer?: string;
|
|
33
|
-
module?: string;
|
|
34
|
-
language?: string;
|
|
35
|
-
limit?: number;
|
|
36
|
-
}, loader: ProjectLoader): Promise<unknown>;
|
|
37
|
-
export declare function getEntity(args: {
|
|
38
|
-
id: string;
|
|
39
|
-
project?: string;
|
|
40
|
-
}, loader: ProjectLoader): unknown;
|
|
41
|
-
export declare function getDependencies(args: {
|
|
42
|
-
entity_id: string;
|
|
43
|
-
direction?: 'callers' | 'callees' | 'both';
|
|
44
|
-
depth?: number;
|
|
45
|
-
project?: string;
|
|
46
|
-
}, loader: ProjectLoader): unknown;
|
|
47
|
-
export declare function collectTransitive(adjacency: Map<string, Set<string>>, startId: string, maxDepth: number): string[];
|
|
48
|
-
export declare function getDataFlow(args: {
|
|
49
|
-
entity_id: string;
|
|
50
|
-
project?: string;
|
|
51
|
-
}, loader: ProjectLoader): unknown;
|
|
52
|
-
export declare function findByConstraint(args: {
|
|
53
|
-
constraint: string;
|
|
54
|
-
project?: string;
|
|
55
|
-
}, loader: ProjectLoader): unknown;
|
|
56
|
-
export declare function getBlastRadius(args: {
|
|
57
|
-
entity_ids: string[];
|
|
58
|
-
project?: string;
|
|
59
|
-
}, loader: ProjectLoader): unknown;
|
|
60
|
-
export declare function listModules(args: {
|
|
61
|
-
group_by?: 'layer' | 'module' | 'file' | 'language';
|
|
62
|
-
project?: string;
|
|
63
|
-
}, loader: ProjectLoader): unknown;
|
|
64
|
-
export declare function getTopology(args: {
|
|
65
|
-
project?: string;
|
|
66
|
-
} | undefined, loader: ProjectLoader): unknown;
|
package/dist/tools/index.js
DELETED
|
@@ -1,389 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Semantic MCP Tool Implementations
|
|
3
|
-
*
|
|
4
|
-
* Each tool exposes a query or computation over the extracted code entity graph.
|
|
5
|
-
* Tools operate on the in-memory entity bundle loaded from .seshat/_bundle.json.
|
|
6
|
-
*
|
|
7
|
-
* Multi-project: when multiple projects are loaded, each tool accepts an optional
|
|
8
|
-
* `project` parameter. In multi-project mode, `project` is required.
|
|
9
|
-
*/
|
|
10
|
-
import { buildCallGraph, computeBlastRadius } from '../graph.js';
|
|
11
|
-
export { extractDbOps, tableContract } from './dbops.js';
|
|
12
|
-
export function getGraph(project, loader) {
|
|
13
|
-
// Fast path: use pre-computed call graph edges cached on the snapshot row
|
|
14
|
-
// (avoids 3-10s CPU rebuild on first request for large codebases)
|
|
15
|
-
const precomputed = loader.getPrecomputedGraph?.();
|
|
16
|
-
if (precomputed)
|
|
17
|
-
return precomputed;
|
|
18
|
-
// Fallback for old snapshots (NULL call_graph_edges) or local file loaders
|
|
19
|
-
return buildCallGraph(loader.getEntities(project));
|
|
20
|
-
}
|
|
21
|
-
/**
|
|
22
|
-
* Validate project param. Returns error string if invalid, null if OK.
|
|
23
|
-
* In single-project mode, project is optional (defaults to the only project).
|
|
24
|
-
* In multi-project mode, project is required.
|
|
25
|
-
*/
|
|
26
|
-
export function validateProject(project, loader) {
|
|
27
|
-
if (!loader.isMultiProject())
|
|
28
|
-
return null; // single project, always OK
|
|
29
|
-
if (!project) {
|
|
30
|
-
return `Multiple projects loaded. You must specify a "project" parameter. Available: ${loader.getProjectNames().join(', ')}`;
|
|
31
|
-
}
|
|
32
|
-
if (!loader.hasProject(project)) {
|
|
33
|
-
return `Project "${project}" not found. Available: ${loader.getProjectNames().join(', ')}`;
|
|
34
|
-
}
|
|
35
|
-
return null;
|
|
36
|
-
}
|
|
37
|
-
// ─── Helper: Extract entity name from struct ─────────────────────
|
|
38
|
-
export function entityName(e) {
|
|
39
|
-
if (typeof e.struct === 'string')
|
|
40
|
-
return e.struct;
|
|
41
|
-
return e.struct?.name || e.id || 'anonymous';
|
|
42
|
-
}
|
|
43
|
-
export function entityLayer(e) {
|
|
44
|
-
// Use explicit layer if specific enough
|
|
45
|
-
const explicit = e.context?.layer?.toLowerCase();
|
|
46
|
-
if (explicit && explicit !== 'module' && explicit !== 'unknown')
|
|
47
|
-
return explicit;
|
|
48
|
-
// Infer from source file path (matches extract-and-generate.mjs logic)
|
|
49
|
-
const src = (e._sourceFile || e.context?.module || '').toLowerCase().replace(/\\/g, '/');
|
|
50
|
-
if (src.includes('/route') || src.includes('/api/'))
|
|
51
|
-
return 'route';
|
|
52
|
-
if (src.includes('/controller'))
|
|
53
|
-
return 'controller';
|
|
54
|
-
if (src.includes('/service'))
|
|
55
|
-
return 'service';
|
|
56
|
-
if (src.includes('/repo') || src.includes('/database') || src.includes('/db/'))
|
|
57
|
-
return 'repository';
|
|
58
|
-
if (src.includes('/util') || src.includes('/helper') || src.includes('/lib/'))
|
|
59
|
-
return 'utility';
|
|
60
|
-
if (src.includes('/hook'))
|
|
61
|
-
return 'hook';
|
|
62
|
-
if (src.includes('/component') || src.includes('/ui/'))
|
|
63
|
-
return 'component';
|
|
64
|
-
if (src.includes('/middleware'))
|
|
65
|
-
return 'middleware';
|
|
66
|
-
if (src.includes('/model') || src.includes('/entity'))
|
|
67
|
-
return 'model';
|
|
68
|
-
if (src.includes('/schema') || explicit === 'schema')
|
|
69
|
-
return 'schema';
|
|
70
|
-
if (src.includes('/test/') || src.includes('/tests/') || src.includes('/__tests__/') ||
|
|
71
|
-
src.includes('.test.') || src.includes('.spec.'))
|
|
72
|
-
return 'test';
|
|
73
|
-
return explicit || 'other';
|
|
74
|
-
}
|
|
75
|
-
export function entitySummary(e) {
|
|
76
|
-
const constraintTags = normalizeConstraints(e.constraints);
|
|
77
|
-
return {
|
|
78
|
-
id: e.id,
|
|
79
|
-
name: entityName(e),
|
|
80
|
-
...(e._project ? { project: e._project } : {}),
|
|
81
|
-
layer: entityLayer(e),
|
|
82
|
-
module: e.context?.module || null,
|
|
83
|
-
sourceFile: e._sourceFile || null,
|
|
84
|
-
line: e._sourceLine ?? undefined,
|
|
85
|
-
sourceLanguage: e._sourceLanguage || null,
|
|
86
|
-
async: typeof e.struct !== 'string' ? e.struct?.async : undefined,
|
|
87
|
-
exported: typeof e.struct !== 'string' ? e.struct?.exported : undefined,
|
|
88
|
-
constraints: constraintTags.length > 0 ? constraintTags : undefined,
|
|
89
|
-
callExpressions: Array.isArray(e.edges?.calls) ? e.edges.calls.length : 0,
|
|
90
|
-
uniqueCallees: Array.isArray(e.edges?.calls)
|
|
91
|
-
? new Set(e.edges.calls.map(c => c.target)).size
|
|
92
|
-
: 0,
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
export function normalizeConstraints(constraints) {
|
|
96
|
-
if (!constraints)
|
|
97
|
-
return [];
|
|
98
|
-
if (Array.isArray(constraints))
|
|
99
|
-
return constraints.map(String);
|
|
100
|
-
if (typeof constraints === 'object') {
|
|
101
|
-
const tags = [];
|
|
102
|
-
const c = constraints;
|
|
103
|
-
// Tag-based format: { security: ["AUTH", "VALIDATED"] }
|
|
104
|
-
if (c.security && Array.isArray(c.security))
|
|
105
|
-
tags.push(...c.security.map(String));
|
|
106
|
-
if (c.validation && Array.isArray(c.validation) && c.validation.length > 0) {
|
|
107
|
-
tags.push('VALIDATED');
|
|
108
|
-
}
|
|
109
|
-
// Property-based format: { purity: "pure"|"impure", immutable: true, sideEffects: [...] }
|
|
110
|
-
if (c.purity === 'pure')
|
|
111
|
-
tags.push('PURE');
|
|
112
|
-
if (c.purity === 'impure')
|
|
113
|
-
tags.push('IMPURE');
|
|
114
|
-
if (c.immutable)
|
|
115
|
-
tags.push('IMMUTABLE');
|
|
116
|
-
if (c.throws)
|
|
117
|
-
tags.push('THROWS');
|
|
118
|
-
if (Array.isArray(c.sideEffects)) {
|
|
119
|
-
for (const effect of c.sideEffects) {
|
|
120
|
-
if (typeof effect === 'string') {
|
|
121
|
-
if (effect === 'network')
|
|
122
|
-
tags.push('NETWORK_IO');
|
|
123
|
-
else if (effect === 'db' || effect === 'database')
|
|
124
|
-
tags.push('DB_ACCESS');
|
|
125
|
-
else if (effect === 'filesystem' || effect === 'fs')
|
|
126
|
-
tags.push('FS_ACCESS');
|
|
127
|
-
else
|
|
128
|
-
tags.push(effect.toUpperCase());
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
if (c.nullSafety)
|
|
133
|
-
tags.push('NULL_SAFE');
|
|
134
|
-
if (c.performance) {
|
|
135
|
-
const perf = c.performance;
|
|
136
|
-
if (perf.dbCalls)
|
|
137
|
-
tags.push('DB_ACCESS');
|
|
138
|
-
if (perf.apiCalls)
|
|
139
|
-
tags.push('NETWORK_IO');
|
|
140
|
-
}
|
|
141
|
-
return tags;
|
|
142
|
-
}
|
|
143
|
-
return [];
|
|
144
|
-
}
|
|
145
|
-
/**
|
|
146
|
-
* Deep search constraints — matches against raw constraint object fields too,
|
|
147
|
-
* not just normalized tags.
|
|
148
|
-
*/
|
|
149
|
-
export function constraintMatches(constraints, target) {
|
|
150
|
-
// First check normalized tags
|
|
151
|
-
const tags = normalizeConstraints(constraints);
|
|
152
|
-
if (tags.some((t) => t.toUpperCase().includes(target.toUpperCase())))
|
|
153
|
-
return true;
|
|
154
|
-
// Also search raw constraint values for substring match
|
|
155
|
-
if (constraints && typeof constraints === 'object' && !Array.isArray(constraints)) {
|
|
156
|
-
const str = JSON.stringify(constraints).toLowerCase();
|
|
157
|
-
if (str.includes(target.toLowerCase()))
|
|
158
|
-
return true;
|
|
159
|
-
}
|
|
160
|
-
return false;
|
|
161
|
-
}
|
|
162
|
-
// ─── Tool: query_entities ─────────────────────────────────────────
|
|
163
|
-
export async function queryEntities(args, loader) {
|
|
164
|
-
const apiKey = process.env.SESHAT_API_KEY;
|
|
165
|
-
if (!apiKey) {
|
|
166
|
-
return { error: 'SESHAT_API_KEY environment variable is missing. You must provide an API key to use Ptah Cloud tools.' };
|
|
167
|
-
}
|
|
168
|
-
// We are hardcoding the project_hash to 'seshat-fabric' for this local test,
|
|
169
|
-
// but in production the MCP would pass args.project or read from the manifest.
|
|
170
|
-
const project_hash = args.project || 'seshat-fabric';
|
|
171
|
-
try {
|
|
172
|
-
const res = await fetch('http://localhost:3001/api/mcp/execute', {
|
|
173
|
-
method: 'POST',
|
|
174
|
-
headers: {
|
|
175
|
-
'Content-Type': 'application/json',
|
|
176
|
-
'x-api-key': apiKey
|
|
177
|
-
},
|
|
178
|
-
body: JSON.stringify({
|
|
179
|
-
tool: 'query_entities',
|
|
180
|
-
project_hash: project_hash,
|
|
181
|
-
args
|
|
182
|
-
})
|
|
183
|
-
});
|
|
184
|
-
if (!res.ok) {
|
|
185
|
-
const errorText = await res.text();
|
|
186
|
-
return { error: `Cloud API Error (${res.status}): ${errorText}` };
|
|
187
|
-
}
|
|
188
|
-
return await res.json();
|
|
189
|
-
}
|
|
190
|
-
catch (error) {
|
|
191
|
-
return { error: `Failed to connect to Ptah Cloud: ${error.message}` };
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
// ─── Tool: get_entity ─────────────────────────────────────────────
|
|
195
|
-
export function getEntity(args, loader) {
|
|
196
|
-
const projErr = validateProject(args.project, loader);
|
|
197
|
-
if (projErr)
|
|
198
|
-
return { error: projErr };
|
|
199
|
-
const entity = loader.getEntityById(args.id, args.project) || loader.getEntityByName(args.id, args.project);
|
|
200
|
-
if (!entity) {
|
|
201
|
-
return { error: `Entity not found: ${args.id}` };
|
|
202
|
-
}
|
|
203
|
-
return {
|
|
204
|
-
id: entity.id,
|
|
205
|
-
name: entityName(entity),
|
|
206
|
-
...(entity._project ? { project: entity._project } : {}),
|
|
207
|
-
sourceFile: entity._sourceFile,
|
|
208
|
-
sourceLanguage: entity._sourceLanguage,
|
|
209
|
-
structure: entity.struct,
|
|
210
|
-
call_graph: entity.edges,
|
|
211
|
-
data_flow: entity.data,
|
|
212
|
-
constraints: entity.constraints,
|
|
213
|
-
context: entity.context,
|
|
214
|
-
ownership: entity.ownership,
|
|
215
|
-
type_info: entity.traits,
|
|
216
|
-
runtime: entity.runtime,
|
|
217
|
-
logic: entity.semantics,
|
|
218
|
-
};
|
|
219
|
-
}
|
|
220
|
-
// ─── Tool: get_dependencies ───────────────────────────────────────
|
|
221
|
-
export function getDependencies(args, loader) {
|
|
222
|
-
const projErr = validateProject(args.project, loader);
|
|
223
|
-
if (projErr)
|
|
224
|
-
return { error: projErr };
|
|
225
|
-
const { entity_id, direction = 'both', depth = 2 } = args;
|
|
226
|
-
const g = getGraph(args.project, loader);
|
|
227
|
-
const entity = loader.getEntityById(entity_id, args.project) || loader.getEntityByName(entity_id, args.project);
|
|
228
|
-
if (!entity) {
|
|
229
|
-
return { error: `Entity not found: ${entity_id}` };
|
|
230
|
-
}
|
|
231
|
-
const id = entity.id;
|
|
232
|
-
const result = {
|
|
233
|
-
entity: { id, name: entityName(entity) },
|
|
234
|
-
};
|
|
235
|
-
if (direction === 'callers' || direction === 'both') {
|
|
236
|
-
const callerIds = collectTransitive(g.callers, id, depth);
|
|
237
|
-
result.callers = callerIds.map(cId => {
|
|
238
|
-
const e = g.entityById.get(cId);
|
|
239
|
-
return e ? entitySummary(e) : { id: cId };
|
|
240
|
-
});
|
|
241
|
-
}
|
|
242
|
-
if (direction === 'callees' || direction === 'both') {
|
|
243
|
-
const calleeIds = collectTransitive(g.callees, id, depth);
|
|
244
|
-
result.callees = calleeIds.map(cId => {
|
|
245
|
-
const e = g.entityById.get(cId);
|
|
246
|
-
return e ? entitySummary(e) : { id: cId };
|
|
247
|
-
});
|
|
248
|
-
}
|
|
249
|
-
// Also include direct imports
|
|
250
|
-
if (entity.edges?.imports) {
|
|
251
|
-
result.imports = entity.edges.imports;
|
|
252
|
-
}
|
|
253
|
-
return result;
|
|
254
|
-
}
|
|
255
|
-
export function collectTransitive(adjacency, startId, maxDepth) {
|
|
256
|
-
const visited = new Set();
|
|
257
|
-
const queue = [[startId, 0]];
|
|
258
|
-
visited.add(startId);
|
|
259
|
-
while (queue.length > 0) {
|
|
260
|
-
const [current, d] = queue.shift();
|
|
261
|
-
if (d >= maxDepth)
|
|
262
|
-
continue;
|
|
263
|
-
const neighbors = adjacency.get(current);
|
|
264
|
-
if (!neighbors)
|
|
265
|
-
continue;
|
|
266
|
-
for (const neighbor of neighbors) {
|
|
267
|
-
if (!visited.has(neighbor)) {
|
|
268
|
-
visited.add(neighbor);
|
|
269
|
-
queue.push([neighbor, d + 1]);
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
visited.delete(startId); // Don't include the start entity itself
|
|
274
|
-
return [...visited];
|
|
275
|
-
}
|
|
276
|
-
// ─── Tool: get_data_flow ──────────────────────────────────────────
|
|
277
|
-
export function getDataFlow(args, loader) {
|
|
278
|
-
const projErr = validateProject(args.project, loader);
|
|
279
|
-
if (projErr)
|
|
280
|
-
return { error: projErr };
|
|
281
|
-
const entity = loader.getEntityById(args.entity_id, args.project) || loader.getEntityByName(args.entity_id, args.project);
|
|
282
|
-
if (!entity) {
|
|
283
|
-
return { error: `Entity not found: ${args.entity_id}` };
|
|
284
|
-
}
|
|
285
|
-
return {
|
|
286
|
-
entity: { id: entity.id, name: entityName(entity) },
|
|
287
|
-
inputs: entity.data?.inputs || entity.data?.sources || [],
|
|
288
|
-
outputs: entity.data?.outputs || entity.data?.returns || [],
|
|
289
|
-
mutations: entity.data?.mutations || [],
|
|
290
|
-
};
|
|
291
|
-
}
|
|
292
|
-
// ─── Tool: find_by_constraint ─────────────────────────────────────
|
|
293
|
-
export function findByConstraint(args, loader) {
|
|
294
|
-
const projErr = validateProject(args.project, loader);
|
|
295
|
-
if (projErr)
|
|
296
|
-
return { error: projErr };
|
|
297
|
-
const target = args.constraint;
|
|
298
|
-
const results = loader.getEntities(args.project).filter((e) => constraintMatches(e.constraints, target));
|
|
299
|
-
return {
|
|
300
|
-
constraint: args.constraint,
|
|
301
|
-
total: results.length,
|
|
302
|
-
entities: results.slice(0, 100).map(entitySummary),
|
|
303
|
-
};
|
|
304
|
-
}
|
|
305
|
-
// ─── Tool: get_blast_radius ───────────────────────────────────────
|
|
306
|
-
export function getBlastRadius(args, loader) {
|
|
307
|
-
const projErr = validateProject(args.project, loader);
|
|
308
|
-
if (projErr)
|
|
309
|
-
return { error: projErr };
|
|
310
|
-
const g = getGraph(args.project, loader);
|
|
311
|
-
// Resolve names to IDs
|
|
312
|
-
const resolvedIds = new Set();
|
|
313
|
-
const notFound = [];
|
|
314
|
-
for (const nameOrId of args.entity_ids) {
|
|
315
|
-
const entity = loader.getEntityById(nameOrId, args.project) || loader.getEntityByName(nameOrId, args.project);
|
|
316
|
-
if (entity) {
|
|
317
|
-
resolvedIds.add(entity.id);
|
|
318
|
-
}
|
|
319
|
-
else {
|
|
320
|
-
notFound.push(nameOrId);
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
if (resolvedIds.size === 0) {
|
|
324
|
-
return { error: `No entities found for: ${args.entity_ids.join(', ')}` };
|
|
325
|
-
}
|
|
326
|
-
const result = computeBlastRadius(g, resolvedIds);
|
|
327
|
-
return {
|
|
328
|
-
changed: [...resolvedIds],
|
|
329
|
-
totalAffected: result.affected.length,
|
|
330
|
-
ancestors: result.ancestors.length,
|
|
331
|
-
descendants: result.descendants.length,
|
|
332
|
-
affected: result.affected.slice(0, 100).map(id => {
|
|
333
|
-
const e = g.entityById.get(id);
|
|
334
|
-
return {
|
|
335
|
-
...(e ? entitySummary(e) : { id }),
|
|
336
|
-
depth: result.depthMap[id],
|
|
337
|
-
};
|
|
338
|
-
}),
|
|
339
|
-
...(notFound.length > 0 ? { notFound } : {}),
|
|
340
|
-
};
|
|
341
|
-
}
|
|
342
|
-
// ─── Tool: list_modules ───────────────────────────────────────────
|
|
343
|
-
export function listModules(args, loader) {
|
|
344
|
-
const projErr = validateProject(args.project, loader);
|
|
345
|
-
if (projErr)
|
|
346
|
-
return { error: projErr };
|
|
347
|
-
const { group_by = 'layer' } = args;
|
|
348
|
-
const entities = loader.getEntities(args.project);
|
|
349
|
-
const groups = new Map();
|
|
350
|
-
for (const e of entities) {
|
|
351
|
-
let key;
|
|
352
|
-
switch (group_by) {
|
|
353
|
-
case 'layer':
|
|
354
|
-
key = entityLayer(e);
|
|
355
|
-
break;
|
|
356
|
-
case 'module':
|
|
357
|
-
key = e.context?.module || 'unknown';
|
|
358
|
-
break;
|
|
359
|
-
case 'file':
|
|
360
|
-
key = e._sourceFile || 'unknown';
|
|
361
|
-
break;
|
|
362
|
-
case 'language':
|
|
363
|
-
key = e._sourceLanguage || 'unknown';
|
|
364
|
-
break;
|
|
365
|
-
default:
|
|
366
|
-
key = entityLayer(e);
|
|
367
|
-
}
|
|
368
|
-
groups.set(key, (groups.get(key) || 0) + 1);
|
|
369
|
-
}
|
|
370
|
-
// Sort by count descending
|
|
371
|
-
const sorted = [...groups.entries()].sort((a, b) => b[1] - a[1]);
|
|
372
|
-
return {
|
|
373
|
-
groupBy: group_by,
|
|
374
|
-
totalEntities: entities.length,
|
|
375
|
-
groupCount: sorted.length,
|
|
376
|
-
groups: Object.fromEntries(sorted),
|
|
377
|
-
};
|
|
378
|
-
}
|
|
379
|
-
// ─── Tool: get_topology ───────────────────────────────────────────
|
|
380
|
-
export function getTopology(args, loader) {
|
|
381
|
-
const projErr = validateProject(args?.project, loader);
|
|
382
|
-
if (projErr)
|
|
383
|
-
return { error: projErr };
|
|
384
|
-
const topology = loader.getTopology(args?.project);
|
|
385
|
-
if (!topology) {
|
|
386
|
-
return { error: 'No topology data found. The _topology.json file may not have been generated.' };
|
|
387
|
-
}
|
|
388
|
-
return topology;
|
|
389
|
-
}
|
package/dist/types.d.ts
DELETED
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Code Entity — the core unit of analysis
|
|
3
|
-
*
|
|
4
|
-
* Each entity represents a code unit (function, class, module, schema)
|
|
5
|
-
* with extracted properties: structure, call graph, data flow, constraints,
|
|
6
|
-
* context, ownership, type info, runtime, and logic.
|
|
7
|
-
*/
|
|
8
|
-
export interface JstfEntity {
|
|
9
|
-
id: string;
|
|
10
|
-
_jstfFilename?: string;
|
|
11
|
-
_sourceFile?: string | null;
|
|
12
|
-
_sourceLanguage?: string;
|
|
13
|
-
_project?: string;
|
|
14
|
-
_sourceLocation?: {
|
|
15
|
-
startLine: number;
|
|
16
|
-
endLine: number;
|
|
17
|
-
};
|
|
18
|
-
/** Structure: function shape, signature, modifiers */
|
|
19
|
-
struct?: {
|
|
20
|
-
name?: string;
|
|
21
|
-
type?: string;
|
|
22
|
-
async?: boolean;
|
|
23
|
-
exported?: boolean;
|
|
24
|
-
params?: Array<{
|
|
25
|
-
name: string;
|
|
26
|
-
type?: string;
|
|
27
|
-
}>;
|
|
28
|
-
returnType?: string;
|
|
29
|
-
[key: string]: unknown;
|
|
30
|
-
} | string;
|
|
31
|
-
/** Call graph: dependencies, imports, callers */
|
|
32
|
-
edges?: {
|
|
33
|
-
calls?: Array<{
|
|
34
|
-
target: string;
|
|
35
|
-
type?: string;
|
|
36
|
-
}>;
|
|
37
|
-
imports?: Array<{
|
|
38
|
-
module: string;
|
|
39
|
-
bindings?: string[];
|
|
40
|
-
}>;
|
|
41
|
-
calledBy?: Array<{
|
|
42
|
-
source: string;
|
|
43
|
-
type?: string;
|
|
44
|
-
}>;
|
|
45
|
-
[key: string]: unknown;
|
|
46
|
-
};
|
|
47
|
-
/** Data flow: inputs, outputs, mutations */
|
|
48
|
-
data?: {
|
|
49
|
-
inputs?: Array<{
|
|
50
|
-
name: string;
|
|
51
|
-
source?: string;
|
|
52
|
-
untrusted?: boolean;
|
|
53
|
-
}>;
|
|
54
|
-
outputs?: Array<{
|
|
55
|
-
name: string;
|
|
56
|
-
destination?: string;
|
|
57
|
-
}>;
|
|
58
|
-
mutations?: Array<{
|
|
59
|
-
target: string;
|
|
60
|
-
operation?: string;
|
|
61
|
-
}>;
|
|
62
|
-
tables?: string[];
|
|
63
|
-
sources?: unknown[];
|
|
64
|
-
returns?: unknown[];
|
|
65
|
-
[key: string]: unknown;
|
|
66
|
-
};
|
|
67
|
-
/** Constraints: behavioral contracts, validation, purity */
|
|
68
|
-
constraints?: {
|
|
69
|
-
security?: string[];
|
|
70
|
-
performance?: Record<string, unknown>;
|
|
71
|
-
validation?: Array<{
|
|
72
|
-
field: string;
|
|
73
|
-
rule: string;
|
|
74
|
-
}>;
|
|
75
|
-
auth?: string[] | 'none';
|
|
76
|
-
authRequired?: boolean;
|
|
77
|
-
purity?: string;
|
|
78
|
-
throws?: boolean;
|
|
79
|
-
sideEffects?: string[];
|
|
80
|
-
errorHandling?: {
|
|
81
|
-
tryCatch?: boolean;
|
|
82
|
-
catchClause?: boolean;
|
|
83
|
-
finally?: boolean;
|
|
84
|
-
errorBoundary?: boolean;
|
|
85
|
-
};
|
|
86
|
-
[key: string]: unknown;
|
|
87
|
-
} | string[];
|
|
88
|
-
/** Context: architectural position, visibility, layer */
|
|
89
|
-
context?: {
|
|
90
|
-
layer?: string;
|
|
91
|
-
layerSource?: string;
|
|
92
|
-
module?: string;
|
|
93
|
-
path?: string;
|
|
94
|
-
exposure?: string;
|
|
95
|
-
visibility?: string;
|
|
96
|
-
traffic?: string;
|
|
97
|
-
criticality?: string;
|
|
98
|
-
[key: string]: unknown;
|
|
99
|
-
};
|
|
100
|
-
/** Ownership: memory management, lifetimes, borrowing (Rust/C++) */
|
|
101
|
-
ownership?: Record<string, unknown>;
|
|
102
|
-
/** Type info: type capabilities, bounds, markers */
|
|
103
|
-
traits?: string[] | {
|
|
104
|
-
self?: {
|
|
105
|
-
asyncContext?: boolean;
|
|
106
|
-
fallible?: boolean;
|
|
107
|
-
[key: string]: unknown;
|
|
108
|
-
};
|
|
109
|
-
params?: Record<string, {
|
|
110
|
-
bounds?: string[];
|
|
111
|
-
markers?: string[];
|
|
112
|
-
}>;
|
|
113
|
-
[key: string]: unknown;
|
|
114
|
-
};
|
|
115
|
-
/** Runtime: async model, platform, framework */
|
|
116
|
-
runtime?: {
|
|
117
|
-
async?: string;
|
|
118
|
-
framework?: string;
|
|
119
|
-
platform?: string;
|
|
120
|
-
[key: string]: unknown;
|
|
121
|
-
};
|
|
122
|
-
/** Logic: operational content, normalized logic tree */
|
|
123
|
-
semantics?: unknown[];
|
|
124
|
-
[key: string]: unknown;
|
|
125
|
-
}
|
|
126
|
-
export interface JstfBundle {
|
|
127
|
-
$schema: string;
|
|
128
|
-
extractedAt: string;
|
|
129
|
-
source: string;
|
|
130
|
-
files: number;
|
|
131
|
-
languages: string[];
|
|
132
|
-
entityCount: number;
|
|
133
|
-
entities: JstfEntity[];
|
|
134
|
-
}
|
|
135
|
-
export interface Topology {
|
|
136
|
-
stats: {
|
|
137
|
-
plugins: number;
|
|
138
|
-
routes: number;
|
|
139
|
-
tables: number;
|
|
140
|
-
authRequired: number;
|
|
141
|
-
};
|
|
142
|
-
[key: string]: unknown;
|
|
143
|
-
}
|
|
144
|
-
export interface Manifest {
|
|
145
|
-
projectName: string;
|
|
146
|
-
commitSha: string;
|
|
147
|
-
extractedAt: string;
|
|
148
|
-
entityCount: number;
|
|
149
|
-
languages: string[];
|
|
150
|
-
layers: Record<string, number>;
|
|
151
|
-
}
|
|
152
|
-
export interface ProjectInfo {
|
|
153
|
-
name: string;
|
|
154
|
-
path: string;
|
|
155
|
-
entityCount: number;
|
|
156
|
-
languages: string[];
|
|
157
|
-
commitSha: string;
|
|
158
|
-
extractedAt: string;
|
|
159
|
-
layers: Record<string, number>;
|
|
160
|
-
}
|
|
161
|
-
export interface ProjectLoader {
|
|
162
|
-
getEntities(project?: string): JstfEntity[];
|
|
163
|
-
getTopology(project?: string): Topology | null;
|
|
164
|
-
getManifest(project?: string): Manifest | null;
|
|
165
|
-
getEntityById(id: string, project?: string): JstfEntity | undefined;
|
|
166
|
-
getEntityByName(name: string, project?: string): JstfEntity | undefined;
|
|
167
|
-
getProjectNames(): string[];
|
|
168
|
-
getProjectInfo(): ProjectInfo[];
|
|
169
|
-
isMultiProject(): boolean;
|
|
170
|
-
isLoaded(): boolean;
|
|
171
|
-
hasProject(name: string): boolean;
|
|
172
|
-
registerVirtualEntity(entity: JstfEntity, project?: string): void;
|
|
173
|
-
totalEntities(): number;
|
|
174
|
-
}
|
package/dist/types.js
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Code Entity — the core unit of analysis
|
|
3
|
-
*
|
|
4
|
-
* Each entity represents a code unit (function, class, module, schema)
|
|
5
|
-
* with extracted properties: structure, call graph, data flow, constraints,
|
|
6
|
-
* context, ownership, type info, runtime, and logic.
|
|
7
|
-
*/
|
|
8
|
-
export {};
|