septum 0.1.1 → 0.1.3
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 +2 -0
- package/package.json +1 -1
- package/src/cli/templates/skill.ts +7 -4
- package/src/core/config/loader.ts +21 -8
- package/src/core/database/client.ts +1 -0
- package/src/core/database/repositories/dependency.repository.ts +70 -0
- package/src/core/database/repositories/file.repository.ts +7 -0
- package/src/core/database/repository.ts +13 -0
- package/src/core/discovery/topology-detector.ts +71 -3
- package/src/core/ingestion/pipeline.ts +98 -1
- package/src/core/parser/extractors/base.ts +1 -0
- package/src/core/parser/extractors/blade.ts +158 -0
- package/src/core/parser/extractors/laravel-semantic.ts +186 -27
- package/src/core/parser/extractors/registry.ts +21 -0
- package/src/core/parser/tree-sitter.ts +2 -0
- package/src/core/resolver/module-resolver.ts +30 -11
- package/src/core/resolver/path-resolver.ts +147 -0
- package/src/core/resolver/symbol-locator.ts +152 -14
- package/src/core/resolver/vertical-slice-tracer.ts +22 -7
- package/src/mcp/schemas.ts +216 -46
- package/src/mcp/server.ts +68 -24
- package/src/mcp/tools/check-boundary.ts +58 -8
- package/src/mcp/tools/get-domain-catalog.ts +31 -1
- package/src/mcp/tools/locate-symbol.ts +119 -3
- package/src/mcp/tools/trace-vertical-slice.ts +2 -1
- package/src/types/index.ts +4 -1
|
@@ -148,12 +148,109 @@ export class SymbolLocator {
|
|
|
148
148
|
const containers = this.repo.findContainers(simpleContainerName);
|
|
149
149
|
|
|
150
150
|
if (containers.length === 0) {
|
|
151
|
+
// Container not found directly: search for fuzzy container matches across the catalog
|
|
152
|
+
const allSymbols = this.repo.getAllSymbolsWithFiles();
|
|
153
|
+
const containerCandidates = allSymbols.filter((s) =>
|
|
154
|
+
["class", "interface", "trait", "enum", "struct"].includes(s.kind)
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
// Score containers by similarity
|
|
158
|
+
const scoredContainers = containerCandidates
|
|
159
|
+
.map((s) => {
|
|
160
|
+
const bare = s.name.includes("::")
|
|
161
|
+
? s.name.split("::")[0]
|
|
162
|
+
: s.name.split(/\\|\//).pop() || s.name;
|
|
163
|
+
const score = calculateSimilarity(simpleContainerName, bare);
|
|
164
|
+
return {
|
|
165
|
+
name: s.name,
|
|
166
|
+
bare,
|
|
167
|
+
kind: s.kind,
|
|
168
|
+
signature: s.signature,
|
|
169
|
+
line_start: s.line_start,
|
|
170
|
+
line_end: s.line_end,
|
|
171
|
+
file_path: s.file_path,
|
|
172
|
+
similarity_score: Math.round(score * 100) / 100,
|
|
173
|
+
};
|
|
174
|
+
})
|
|
175
|
+
.filter((c) => c.similarity_score >= 0.3)
|
|
176
|
+
.sort((a, b) => b.similarity_score - a.similarity_score);
|
|
177
|
+
|
|
178
|
+
// Deduplicate by name + file_path
|
|
179
|
+
const seenContainers = new Set<string>();
|
|
180
|
+
const uniqueContainers = scoredContainers.filter((c) => {
|
|
181
|
+
const key = `${c.name}@${c.file_path}`;
|
|
182
|
+
if (seenContainers.has(key)) return false;
|
|
183
|
+
seenContainers.add(key);
|
|
184
|
+
return true;
|
|
185
|
+
}).slice(0, 5);
|
|
186
|
+
|
|
187
|
+
// If a member was requested, prioritize methods within top fuzzy candidate containers
|
|
188
|
+
let memberSuggestions: SuggestionMatch[] = [];
|
|
189
|
+
if (memberName) {
|
|
190
|
+
const topCandidateFilePaths = new Set(uniqueContainers.map((c) => c.file_path));
|
|
191
|
+
|
|
192
|
+
const candidateMethods = allSymbols.filter(
|
|
193
|
+
(s) =>
|
|
194
|
+
(s.kind === "method" || s.kind === "function") &&
|
|
195
|
+
topCandidateFilePaths.has(s.file_path)
|
|
196
|
+
);
|
|
197
|
+
|
|
198
|
+
const methodsToScore =
|
|
199
|
+
candidateMethods.length > 0
|
|
200
|
+
? candidateMethods
|
|
201
|
+
: allSymbols
|
|
202
|
+
.filter(
|
|
203
|
+
(s) =>
|
|
204
|
+
(s.kind === "method" || s.kind === "function") &&
|
|
205
|
+
Math.abs(s.name.length - memberName.length) <= 8
|
|
206
|
+
)
|
|
207
|
+
.slice(0, 100);
|
|
208
|
+
|
|
209
|
+
memberSuggestions = methodsToScore
|
|
210
|
+
.map((s) => {
|
|
211
|
+
const bare = s.name.includes("::") ? s.name.split("::")[1] : s.name;
|
|
212
|
+
const score = calculateSimilarity(memberName, bare);
|
|
213
|
+
return {
|
|
214
|
+
name: s.name,
|
|
215
|
+
kind: s.kind,
|
|
216
|
+
signature: `${s.signature} (${s.file_path}:${s.line_start})`,
|
|
217
|
+
line_start: s.line_start,
|
|
218
|
+
line_end: s.line_end,
|
|
219
|
+
similarity_score: Math.round(score * 100) / 100,
|
|
220
|
+
file_path: s.file_path,
|
|
221
|
+
};
|
|
222
|
+
})
|
|
223
|
+
.filter((s) => s.similarity_score >= 0.35)
|
|
224
|
+
.sort((a, b) => b.similarity_score - a.similarity_score)
|
|
225
|
+
.slice(0, 5);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
const suggestions: SuggestionMatch[] = uniqueContainers.map((c) => ({
|
|
229
|
+
name: c.name,
|
|
230
|
+
kind: c.kind,
|
|
231
|
+
signature: `${c.signature || c.kind} (${c.file_path}:${c.line_start})`,
|
|
232
|
+
line_start: c.line_start,
|
|
233
|
+
line_end: c.line_end,
|
|
234
|
+
similarity_score: c.similarity_score,
|
|
235
|
+
file_path: c.file_path,
|
|
236
|
+
}));
|
|
237
|
+
|
|
238
|
+
// Combine container suggestions with member suggestions if available
|
|
239
|
+
const combinedSuggestions = [...suggestions, ...memberSuggestions]
|
|
240
|
+
.sort((a, b) => b.similarity_score - a.similarity_score)
|
|
241
|
+
.slice(0, 7);
|
|
242
|
+
|
|
243
|
+
const topSuggestion = combinedSuggestions.length > 0 ? combinedSuggestions[0].name : null;
|
|
244
|
+
const hint = topSuggestion
|
|
245
|
+
? ` Container '${containerQuery}' was not found. Did you mean '${topSuggestion}'?`
|
|
246
|
+
: ` Container '${containerQuery}' was not found in cataloged files.`;
|
|
247
|
+
|
|
151
248
|
return {
|
|
152
249
|
query: parsed.raw,
|
|
153
250
|
parsed,
|
|
154
251
|
found: false,
|
|
155
|
-
suggestions:
|
|
156
|
-
message:
|
|
252
|
+
suggestions: combinedSuggestions,
|
|
253
|
+
message: `${hint} Run 'septum ingest' if this file was recently added.`,
|
|
157
254
|
};
|
|
158
255
|
}
|
|
159
256
|
|
|
@@ -327,7 +424,9 @@ export class SymbolLocator {
|
|
|
327
424
|
const suggestions: SuggestionMatch[] = allSymbols
|
|
328
425
|
.map((s) => {
|
|
329
426
|
const bareName = s.name.includes("::") ? s.name.split("::")[1] : s.name;
|
|
330
|
-
const
|
|
427
|
+
const scoreBare = calculateSimilarity(targetName, bareName);
|
|
428
|
+
const scoreFull = calculateSimilarity(targetName, s.name);
|
|
429
|
+
const score = Math.max(scoreBare, scoreFull);
|
|
331
430
|
return {
|
|
332
431
|
name: s.name,
|
|
333
432
|
kind: s.kind,
|
|
@@ -335,9 +434,10 @@ export class SymbolLocator {
|
|
|
335
434
|
line_start: s.line_start,
|
|
336
435
|
line_end: s.line_end,
|
|
337
436
|
similarity_score: Math.round(score * 100) / 100,
|
|
437
|
+
file_path: s.file_path,
|
|
338
438
|
};
|
|
339
439
|
})
|
|
340
|
-
.filter((s) => s.similarity_score >= 0.
|
|
440
|
+
.filter((s) => s.similarity_score >= 0.3)
|
|
341
441
|
.sort((a, b) => b.similarity_score - a.similarity_score)
|
|
342
442
|
.slice(0, 5);
|
|
343
443
|
|
|
@@ -352,7 +452,9 @@ export class SymbolLocator {
|
|
|
352
452
|
}
|
|
353
453
|
|
|
354
454
|
/**
|
|
355
|
-
*
|
|
455
|
+
* Enhanced similarity matching:
|
|
456
|
+
* Combines Damerau-Levenshtein distance (handling typos & transpositions),
|
|
457
|
+
* prefix/suffix matching, substring inclusion, and token Jaccard similarity.
|
|
356
458
|
*/
|
|
357
459
|
export function calculateSimilarity(source: string, target: string): number {
|
|
358
460
|
const s1 = source.toLowerCase();
|
|
@@ -361,20 +463,43 @@ export function calculateSimilarity(source: string, target: string): number {
|
|
|
361
463
|
if (s1 === s2) return 1.0;
|
|
362
464
|
if (!s1 || !s2) return 0.0;
|
|
363
465
|
|
|
466
|
+
// Prefix bonus: highly relevant for autocomplete-style / partial searches
|
|
467
|
+
let prefixBonus = 0;
|
|
468
|
+
if (s2.startsWith(s1) || s1.startsWith(s2)) {
|
|
469
|
+
const minLen = Math.min(s1.length, s2.length);
|
|
470
|
+
const maxLen = Math.max(s1.length, s2.length);
|
|
471
|
+
prefixBonus = 0.25 * (minLen / maxLen);
|
|
472
|
+
}
|
|
473
|
+
|
|
364
474
|
// Substring inclusion bonus
|
|
475
|
+
let substringBonus = 0;
|
|
365
476
|
if (s2.includes(s1) || s1.includes(s2)) {
|
|
366
477
|
const minLen = Math.min(s1.length, s2.length);
|
|
367
478
|
const maxLen = Math.max(s1.length, s2.length);
|
|
368
|
-
|
|
479
|
+
substringBonus = 0.3 * (minLen / maxLen);
|
|
369
480
|
}
|
|
370
481
|
|
|
371
|
-
// Token-based matching (
|
|
372
|
-
const tokenize = (str: string) =>
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
482
|
+
// Token-based matching (CamelCase, snake_case, kebab-case, namespaces)
|
|
483
|
+
const tokenize = (str: string) =>
|
|
484
|
+
str
|
|
485
|
+
.replace(/([a-z0-9])([A-Z])/g, "$1 $2")
|
|
486
|
+
.toLowerCase()
|
|
487
|
+
.split(/[\s_\-\.\:\/\\]+/)
|
|
488
|
+
.filter((t) => t.length > 1);
|
|
489
|
+
|
|
490
|
+
const t1 = tokenize(source);
|
|
491
|
+
const t2 = tokenize(target);
|
|
492
|
+
let tokenBonus = 0;
|
|
493
|
+
if (t1.length > 0 && t2.length > 0) {
|
|
494
|
+
const sharedTokens = t1.filter((token) =>
|
|
495
|
+
t2.some((t) => t.includes(token) || token.includes(t))
|
|
496
|
+
);
|
|
497
|
+
const allUniqueTokens = new Set([...t1, ...t2]);
|
|
498
|
+
const jaccard = sharedTokens.length / (allUniqueTokens.size || 1);
|
|
499
|
+
tokenBonus = jaccard * 0.35;
|
|
500
|
+
}
|
|
377
501
|
|
|
502
|
+
// Damerau-Levenshtein Matrix
|
|
378
503
|
const len1 = s1.length;
|
|
379
504
|
const len2 = s2.length;
|
|
380
505
|
const matrix: number[][] = [];
|
|
@@ -389,11 +514,23 @@ export function calculateSimilarity(source: string, target: string): number {
|
|
|
389
514
|
for (let i = 1; i <= len1; i++) {
|
|
390
515
|
for (let j = 1; j <= len2; j++) {
|
|
391
516
|
const cost = s1[i - 1] === s2[j - 1] ? 0 : 1;
|
|
392
|
-
|
|
517
|
+
let minCost = Math.min(
|
|
393
518
|
matrix[i - 1][j] + 1, // deletion
|
|
394
519
|
matrix[i][j - 1] + 1, // insertion
|
|
395
520
|
matrix[i - 1][j - 1] + cost // substitution
|
|
396
521
|
);
|
|
522
|
+
|
|
523
|
+
// Transposition check (Damerau)
|
|
524
|
+
if (
|
|
525
|
+
i > 1 &&
|
|
526
|
+
j > 1 &&
|
|
527
|
+
s1[i - 1] === s2[j - 2] &&
|
|
528
|
+
s1[i - 2] === s2[j - 1]
|
|
529
|
+
) {
|
|
530
|
+
minCost = Math.min(minCost, matrix[i - 2][j - 2] + 1);
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
matrix[i][j] = minCost;
|
|
397
534
|
}
|
|
398
535
|
}
|
|
399
536
|
|
|
@@ -401,5 +538,6 @@ export function calculateSimilarity(source: string, target: string): number {
|
|
|
401
538
|
const maxLen = Math.max(len1, len2);
|
|
402
539
|
const rawSimilarity = 1.0 - distance / maxLen;
|
|
403
540
|
|
|
404
|
-
|
|
541
|
+
const totalScore = rawSimilarity + prefixBonus + substringBonus + tokenBonus;
|
|
542
|
+
return Math.min(1.0, Math.max(0.0, totalScore));
|
|
405
543
|
}
|
|
@@ -5,9 +5,11 @@ import type {
|
|
|
5
5
|
} from "../../types/index.ts";
|
|
6
6
|
import type { SeptumRepository } from "../database/repository.ts";
|
|
7
7
|
import { CallGraphTracer } from "./call-graph-tracer.ts";
|
|
8
|
+
import { SemanticSliceExtractorRegistry } from "../parser/extractors/registry.ts";
|
|
9
|
+
import { TopologyDetector } from "../discovery/topology-detector.ts";
|
|
8
10
|
|
|
9
11
|
export class VerticalSliceTracer {
|
|
10
|
-
constructor(private repo: SeptumRepository) {}
|
|
12
|
+
constructor(private repo: SeptumRepository, private projectRoot: string = process.cwd()) {}
|
|
11
13
|
|
|
12
14
|
/**
|
|
13
15
|
* Trace an end-to-end vertical slice from route/action/intent query.
|
|
@@ -25,16 +27,29 @@ export class VerticalSliceTracer {
|
|
|
25
27
|
const lowerTrimmed = trimmed.toLowerCase();
|
|
26
28
|
let allSlices = this.repo.getAllVerticalSlices();
|
|
27
29
|
|
|
28
|
-
// Lazy fallback: If no slices cataloged,
|
|
29
|
-
|
|
30
|
+
// Lazy on-demand fallback: If no slices cataloged, extract framework routes or trace call-graph
|
|
31
|
+
const hasCatalogData = typeof (this.repo as any).getAllDomains === "function" && this.repo.getAllDomains().length > 0;
|
|
32
|
+
if (allSlices.length === 0 && hasCatalogData) {
|
|
30
33
|
try {
|
|
31
|
-
const
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
34
|
+
const topology = TopologyDetector.detect(this.projectRoot);
|
|
35
|
+
const semanticSlices = SemanticSliceExtractorRegistry.extractAllSlicesSync(
|
|
36
|
+
this.projectRoot,
|
|
37
|
+
topology.framework
|
|
38
|
+
);
|
|
39
|
+
if (semanticSlices.length > 0) {
|
|
40
|
+
for (const s of semanticSlices) {
|
|
35
41
|
this.repo.upsertVerticalSlice(s);
|
|
36
42
|
}
|
|
37
43
|
allSlices = this.repo.getAllVerticalSlices();
|
|
44
|
+
} else {
|
|
45
|
+
const tracer = new CallGraphTracer(this.repo, this.projectRoot);
|
|
46
|
+
const traced = tracer.traceAllSlices();
|
|
47
|
+
if (traced.length > 0) {
|
|
48
|
+
for (const s of traced) {
|
|
49
|
+
this.repo.upsertVerticalSlice(s);
|
|
50
|
+
}
|
|
51
|
+
allSlices = this.repo.getAllVerticalSlices();
|
|
52
|
+
}
|
|
38
53
|
}
|
|
39
54
|
} catch (err: unknown) {
|
|
40
55
|
const msg = err instanceof Error ? err.message : String(err);
|
package/src/mcp/schemas.ts
CHANGED
|
@@ -1,68 +1,238 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
function withAliases(raw: unknown, aliases: Record<string, string>): unknown {
|
|
4
|
+
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) return raw;
|
|
5
|
+
const obj = { ...(raw as Record<string, unknown>) };
|
|
6
|
+
for (const [alias, target] of Object.entries(aliases)) {
|
|
7
|
+
if (obj[alias] !== undefined && obj[target] === undefined) {
|
|
8
|
+
obj[target] = obj[alias];
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
return obj;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function normalizeBoundaryArgs(raw: unknown): unknown {
|
|
15
|
+
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) return raw;
|
|
16
|
+
const obj = { ...(raw as Record<string, unknown>) };
|
|
17
|
+
const aliases: Record<string, string> = {
|
|
18
|
+
filePath: "file_path",
|
|
19
|
+
file: "file_path",
|
|
20
|
+
path: "file_path",
|
|
21
|
+
filePaths: "file_paths",
|
|
22
|
+
files: "file_paths",
|
|
23
|
+
paths: "file_paths",
|
|
24
|
+
proposedImports: "proposed_imports",
|
|
25
|
+
imports: "proposed_imports",
|
|
26
|
+
featureKey: "feature_key",
|
|
27
|
+
feature: "feature_key",
|
|
28
|
+
};
|
|
29
|
+
for (const [alias, target] of Object.entries(aliases)) {
|
|
30
|
+
if (obj[alias] !== undefined && obj[target] === undefined) {
|
|
31
|
+
obj[target] = obj[alias];
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
if (Array.isArray(obj.file_path) && !obj.file_paths) {
|
|
35
|
+
obj.file_paths = obj.file_path;
|
|
36
|
+
delete obj.file_path;
|
|
37
|
+
}
|
|
38
|
+
if (typeof obj.file_paths === "string" && !obj.file_path) {
|
|
39
|
+
obj.file_path = obj.file_paths;
|
|
40
|
+
delete obj.file_paths;
|
|
41
|
+
}
|
|
42
|
+
return obj;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export const GetDomainCatalogSchema = z.preprocess(
|
|
46
|
+
(args) =>
|
|
47
|
+
withAliases(args, {
|
|
48
|
+
domain_name: "domain",
|
|
49
|
+
domainName: "domain",
|
|
50
|
+
name: "domain",
|
|
51
|
+
archetype_filter: "archetype",
|
|
52
|
+
archetypeFilter: "archetype",
|
|
53
|
+
type: "archetype",
|
|
54
|
+
workspace: "workspace_path",
|
|
55
|
+
workspacePath: "workspace_path",
|
|
56
|
+
project_root: "workspace_path",
|
|
57
|
+
target_path: "workspace_path",
|
|
58
|
+
path: "workspace_path",
|
|
59
|
+
}),
|
|
60
|
+
z.object({
|
|
61
|
+
domain: z.string().optional(),
|
|
62
|
+
archetype: z.string().optional(),
|
|
63
|
+
workspace_path: z.string().optional(),
|
|
64
|
+
})
|
|
65
|
+
);
|
|
7
66
|
export type GetDomainCatalogArgs = z.infer<typeof GetDomainCatalogSchema>;
|
|
8
67
|
|
|
9
|
-
export const GetFeatureContextSchema = z.
|
|
10
|
-
|
|
11
|
-
|
|
68
|
+
export const GetFeatureContextSchema = z.preprocess(
|
|
69
|
+
(args) =>
|
|
70
|
+
withAliases(args, {
|
|
71
|
+
feature_key: "feature",
|
|
72
|
+
featureKey: "feature",
|
|
73
|
+
name: "feature",
|
|
74
|
+
workspace: "workspace_path",
|
|
75
|
+
workspacePath: "workspace_path",
|
|
76
|
+
}),
|
|
77
|
+
z.object({
|
|
78
|
+
feature: z.string().min(1, "feature is required"),
|
|
79
|
+
workspace_path: z.string().optional(),
|
|
80
|
+
})
|
|
81
|
+
);
|
|
12
82
|
export type GetFeatureContextArgs = z.infer<typeof GetFeatureContextSchema>;
|
|
13
83
|
|
|
14
|
-
export const LocateSymbolSchema = z.
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
84
|
+
export const LocateSymbolSchema = z.preprocess(
|
|
85
|
+
(args) =>
|
|
86
|
+
withAliases(args, {
|
|
87
|
+
symbol: "query",
|
|
88
|
+
name: "query",
|
|
89
|
+
symbol_name: "query",
|
|
90
|
+
symbolName: "query",
|
|
91
|
+
target: "query",
|
|
92
|
+
domain_name: "domain",
|
|
93
|
+
domainName: "domain",
|
|
94
|
+
max: "limit",
|
|
95
|
+
workspace: "workspace_path",
|
|
96
|
+
workspacePath: "workspace_path",
|
|
97
|
+
project_root: "workspace_path",
|
|
98
|
+
target_path: "workspace_path",
|
|
99
|
+
path: "workspace_path",
|
|
100
|
+
}),
|
|
101
|
+
z.object({
|
|
102
|
+
query: z.string().min(1, "query is required"),
|
|
103
|
+
domain: z.string().optional(),
|
|
104
|
+
limit: z.number().int().positive().optional().default(10),
|
|
105
|
+
workspace_path: z.string().optional(),
|
|
106
|
+
})
|
|
107
|
+
);
|
|
19
108
|
export type LocateSymbolArgs = z.infer<typeof LocateSymbolSchema>;
|
|
20
109
|
|
|
21
|
-
export const GetSymbolSchema = z.
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
110
|
+
export const GetSymbolSchema = z.preprocess(
|
|
111
|
+
(args) =>
|
|
112
|
+
withAliases(args, {
|
|
113
|
+
query: "symbol",
|
|
114
|
+
name: "symbol",
|
|
115
|
+
symbol_name: "symbol",
|
|
116
|
+
symbolName: "symbol",
|
|
117
|
+
target: "symbol",
|
|
118
|
+
domain_name: "domain",
|
|
119
|
+
domainName: "domain",
|
|
120
|
+
includeDependencies: "include_dependencies",
|
|
121
|
+
include_deps: "include_dependencies",
|
|
122
|
+
includeDeps: "include_dependencies",
|
|
123
|
+
dependencies: "include_dependencies",
|
|
124
|
+
deps: "include_dependencies",
|
|
125
|
+
}),
|
|
126
|
+
z.object({
|
|
127
|
+
symbol: z.string().min(1, "symbol is required"),
|
|
128
|
+
domain: z.string().optional(),
|
|
129
|
+
include_dependencies: z.boolean().optional().default(true),
|
|
130
|
+
})
|
|
131
|
+
);
|
|
26
132
|
export type GetSymbolArgs = z.infer<typeof GetSymbolSchema>;
|
|
27
133
|
|
|
28
|
-
export const GetSymbolImpactSchema = z.
|
|
29
|
-
|
|
30
|
-
|
|
134
|
+
export const GetSymbolImpactSchema = z.preprocess(
|
|
135
|
+
(args) =>
|
|
136
|
+
withAliases(args, {
|
|
137
|
+
query: "symbol",
|
|
138
|
+
name: "symbol",
|
|
139
|
+
symbol_name: "symbol",
|
|
140
|
+
symbolName: "symbol",
|
|
141
|
+
file_path: "symbol",
|
|
142
|
+
filePath: "symbol",
|
|
143
|
+
file: "symbol",
|
|
144
|
+
path: "symbol",
|
|
145
|
+
target: "symbol",
|
|
146
|
+
}),
|
|
147
|
+
z.object({
|
|
148
|
+
symbol: z.string().min(1, "symbol is required"),
|
|
149
|
+
})
|
|
150
|
+
);
|
|
31
151
|
export type GetSymbolImpactArgs = z.infer<typeof GetSymbolImpactSchema>;
|
|
32
152
|
|
|
33
|
-
export const TraceVerticalSliceSchema = z.
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
153
|
+
export const TraceVerticalSliceSchema = z.preprocess(
|
|
154
|
+
(args) =>
|
|
155
|
+
withAliases(args, {
|
|
156
|
+
route: "query",
|
|
157
|
+
uri: "query",
|
|
158
|
+
route_uri: "query",
|
|
159
|
+
routeUri: "query",
|
|
160
|
+
symbol: "query",
|
|
161
|
+
name: "query",
|
|
162
|
+
feature: "query",
|
|
163
|
+
feature_key: "query",
|
|
164
|
+
featureKey: "query",
|
|
165
|
+
maxDepth: "max_depth",
|
|
166
|
+
depth: "max_depth",
|
|
167
|
+
}),
|
|
168
|
+
z.object({
|
|
169
|
+
query: z.string().min(1, "query is required"),
|
|
170
|
+
max_depth: z.number().int().positive().optional().default(5),
|
|
171
|
+
})
|
|
172
|
+
);
|
|
37
173
|
export type TraceVerticalSliceArgs = z.infer<typeof TraceVerticalSliceSchema>;
|
|
38
174
|
|
|
39
|
-
export const CheckBoundarySchema = z.
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
175
|
+
export const CheckBoundarySchema = z.preprocess(
|
|
176
|
+
normalizeBoundaryArgs,
|
|
177
|
+
z.object({
|
|
178
|
+
file_path: z.string().optional(),
|
|
179
|
+
file_paths: z.array(z.string()).optional(),
|
|
180
|
+
proposed_imports: z.array(z.string()).default([]),
|
|
181
|
+
feature_key: z.string().optional(),
|
|
182
|
+
})
|
|
183
|
+
);
|
|
45
184
|
export type CheckBoundaryArgs = z.infer<typeof CheckBoundarySchema>;
|
|
46
185
|
|
|
47
|
-
export const GetSymbolHotspotsSchema = z.
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
186
|
+
export const GetSymbolHotspotsSchema = z.preprocess(
|
|
187
|
+
(args) =>
|
|
188
|
+
withAliases(args, {
|
|
189
|
+
domain_name: "domain",
|
|
190
|
+
domainName: "domain",
|
|
191
|
+
max: "limit",
|
|
192
|
+
}),
|
|
193
|
+
z.object({
|
|
194
|
+
domain: z.string().optional(),
|
|
195
|
+
limit: z.number().int().positive().optional().default(10),
|
|
196
|
+
})
|
|
197
|
+
);
|
|
51
198
|
export type GetSymbolHotspotsArgs = z.infer<typeof GetSymbolHotspotsSchema>;
|
|
52
199
|
|
|
53
|
-
export const RegisterDomainSchema = z.
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
200
|
+
export const RegisterDomainSchema = z.preprocess(
|
|
201
|
+
(args) =>
|
|
202
|
+
withAliases(args, {
|
|
203
|
+
domain: "name",
|
|
204
|
+
domain_name: "name",
|
|
205
|
+
domainName: "name",
|
|
206
|
+
root_path: "root",
|
|
207
|
+
rootPath: "root",
|
|
208
|
+
path: "root",
|
|
209
|
+
allowedDependencies: "allowed_dependencies",
|
|
210
|
+
allowed: "allowed_dependencies",
|
|
211
|
+
forbiddenDependencies: "forbidden_dependencies",
|
|
212
|
+
forbidden: "forbidden_dependencies",
|
|
213
|
+
archetype: "archetypes",
|
|
214
|
+
ingestNow: "ingest_now",
|
|
215
|
+
}),
|
|
216
|
+
z.object({
|
|
217
|
+
name: z.string().min(1, "Domain name is required"),
|
|
218
|
+
root: z.string().min(1, "Domain root path is required"),
|
|
219
|
+
description: z.string().optional(),
|
|
220
|
+
allowed_dependencies: z.array(z.string()).optional(),
|
|
221
|
+
forbidden_dependencies: z.array(z.string()).optional(),
|
|
222
|
+
archetypes: z.record(z.string()).optional(),
|
|
223
|
+
ingest_now: z.boolean().optional().default(false),
|
|
224
|
+
})
|
|
225
|
+
);
|
|
62
226
|
export type RegisterDomainArgs = z.infer<typeof RegisterDomainSchema>;
|
|
63
227
|
|
|
64
|
-
export const AutoDiscoverDomainsSchema = z.
|
|
65
|
-
|
|
66
|
-
|
|
228
|
+
export const AutoDiscoverDomainsSchema = z.preprocess(
|
|
229
|
+
(args) =>
|
|
230
|
+
withAliases(args, {
|
|
231
|
+
save: "persist",
|
|
232
|
+
}),
|
|
233
|
+
z.object({
|
|
234
|
+
persist: z.boolean().optional().default(true),
|
|
235
|
+
})
|
|
236
|
+
);
|
|
67
237
|
export type AutoDiscoverDomainsArgs = z.infer<typeof AutoDiscoverDomainsSchema>;
|
|
68
238
|
|