purecontext-mcp 1.1.7 → 1.2.0
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/AGENT_INSTRUCTIONS.md +393 -0
- package/AGENT_INSTRUCTIONS_SHORT.md +53 -0
- package/AST-SEARCH.md +274 -0
- package/CHANGELOG.md +62 -0
- package/CODE-INTELLIGENCE.md +369 -0
- package/HEALTH-DASHBOARDS.md +241 -0
- package/README.md +7 -0
- package/REFACTORING-SAFELY.md +279 -0
- package/UNDERSTANDING-RELATIONSHIPS.md +240 -0
- package/USER-GUIDE.md +14 -0
- package/VISUALIZING-CODE.md +199 -0
- package/WORKFLOW-TECH-DEBT.md +286 -0
- package/dist/core/db/dep-store.d.ts +75 -0
- package/dist/core/db/dep-store.d.ts.map +1 -1
- package/dist/core/db/dep-store.js +277 -0
- package/dist/core/db/dep-store.js.map +1 -1
- package/dist/core/db/schema.d.ts.map +1 -1
- package/dist/core/db/schema.js +12 -0
- package/dist/core/db/schema.js.map +1 -1
- package/dist/core/index-manager.js +1 -1
- package/dist/core/index-manager.js.map +1 -1
- package/dist/core/token-tracker.d.ts +0 -9
- package/dist/core/token-tracker.d.ts.map +1 -1
- package/dist/core/token-tracker.js +0 -21
- package/dist/core/token-tracker.js.map +1 -1
- package/dist/core/types.d.ts +5 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/graph/diagram-renderer.d.ts +83 -0
- package/dist/graph/diagram-renderer.d.ts.map +1 -0
- package/dist/graph/diagram-renderer.js +294 -0
- package/dist/graph/diagram-renderer.js.map +1 -0
- package/dist/graph/graph-traversal.d.ts +92 -0
- package/dist/graph/graph-traversal.d.ts.map +1 -1
- package/dist/graph/graph-traversal.js +440 -2
- package/dist/graph/graph-traversal.js.map +1 -1
- package/dist/server/http-server.d.ts.map +1 -1
- package/dist/server/http-server.js +30 -1
- package/dist/server/http-server.js.map +1 -1
- package/dist/server/mcp-server.d.ts.map +1 -1
- package/dist/server/mcp-server.js +145 -0
- package/dist/server/mcp-server.js.map +1 -1
- package/dist/server/tools/_meta.d.ts +0 -2
- package/dist/server/tools/_meta.d.ts.map +1 -1
- package/dist/server/tools/_meta.js +1 -4
- package/dist/server/tools/_meta.js.map +1 -1
- package/dist/server/tools/check-delete-safe.d.ts +50 -0
- package/dist/server/tools/check-delete-safe.d.ts.map +1 -0
- package/dist/server/tools/check-delete-safe.js +308 -0
- package/dist/server/tools/check-delete-safe.js.map +1 -0
- package/dist/server/tools/check-move-safe.d.ts +44 -0
- package/dist/server/tools/check-move-safe.d.ts.map +1 -0
- package/dist/server/tools/check-move-safe.js +266 -0
- package/dist/server/tools/check-move-safe.js.map +1 -0
- package/dist/server/tools/check-rename-safe.d.ts +48 -0
- package/dist/server/tools/check-rename-safe.d.ts.map +1 -0
- package/dist/server/tools/check-rename-safe.js +218 -0
- package/dist/server/tools/check-rename-safe.js.map +1 -0
- package/dist/server/tools/diff-health-radar.d.ts +44 -0
- package/dist/server/tools/diff-health-radar.d.ts.map +1 -0
- package/dist/server/tools/diff-health-radar.js +192 -0
- package/dist/server/tools/diff-health-radar.js.map +1 -0
- package/dist/server/tools/find-cycles.d.ts +31 -0
- package/dist/server/tools/find-cycles.d.ts.map +1 -0
- package/dist/server/tools/find-cycles.js +85 -0
- package/dist/server/tools/find-cycles.js.map +1 -0
- package/dist/server/tools/find-implementations.d.ts +47 -0
- package/dist/server/tools/find-implementations.d.ts.map +1 -0
- package/dist/server/tools/find-implementations.js +167 -0
- package/dist/server/tools/find-implementations.js.map +1 -0
- package/dist/server/tools/find-untested-symbols.d.ts +52 -0
- package/dist/server/tools/find-untested-symbols.d.ts.map +1 -0
- package/dist/server/tools/find-untested-symbols.js +308 -0
- package/dist/server/tools/find-untested-symbols.js.map +1 -0
- package/dist/server/tools/get-architecture-snapshot.d.ts +43 -0
- package/dist/server/tools/get-architecture-snapshot.d.ts.map +1 -0
- package/dist/server/tools/get-architecture-snapshot.js +292 -0
- package/dist/server/tools/get-architecture-snapshot.js.map +1 -0
- package/dist/server/tools/get-call-hierarchy.d.ts +43 -0
- package/dist/server/tools/get-call-hierarchy.d.ts.map +1 -0
- package/dist/server/tools/get-call-hierarchy.js +119 -0
- package/dist/server/tools/get-call-hierarchy.js.map +1 -0
- package/dist/server/tools/get-class-hierarchy.d.ts +36 -0
- package/dist/server/tools/get-class-hierarchy.d.ts.map +1 -0
- package/dist/server/tools/get-class-hierarchy.js +125 -0
- package/dist/server/tools/get-class-hierarchy.js.map +1 -0
- package/dist/server/tools/get-complexity-hotspots.d.ts +50 -0
- package/dist/server/tools/get-complexity-hotspots.d.ts.map +1 -0
- package/dist/server/tools/get-complexity-hotspots.js +282 -0
- package/dist/server/tools/get-complexity-hotspots.js.map +1 -0
- package/dist/server/tools/get-coupling-map.d.ts +39 -0
- package/dist/server/tools/get-coupling-map.d.ts.map +1 -0
- package/dist/server/tools/get-coupling-map.js +107 -0
- package/dist/server/tools/get-coupling-map.js.map +1 -0
- package/dist/server/tools/get-debt-report.d.ts +44 -0
- package/dist/server/tools/get-debt-report.d.ts.map +1 -0
- package/dist/server/tools/get-debt-report.js +606 -0
- package/dist/server/tools/get-debt-report.js.map +1 -0
- package/dist/server/tools/get-entry-points.d.ts +79 -0
- package/dist/server/tools/get-entry-points.d.ts.map +1 -0
- package/dist/server/tools/get-entry-points.js +362 -0
- package/dist/server/tools/get-entry-points.js.map +1 -0
- package/dist/server/tools/get-public-api.d.ts +53 -0
- package/dist/server/tools/get-public-api.d.ts.map +1 -0
- package/dist/server/tools/get-public-api.js +218 -0
- package/dist/server/tools/get-public-api.js.map +1 -0
- package/dist/server/tools/get-savings-stats.d.ts.map +1 -1
- package/dist/server/tools/get-savings-stats.js +1 -3
- package/dist/server/tools/get-savings-stats.js.map +1 -1
- package/dist/server/tools/get-test-coverage-map.d.ts +66 -0
- package/dist/server/tools/get-test-coverage-map.d.ts.map +1 -0
- package/dist/server/tools/get-test-coverage-map.js +588 -0
- package/dist/server/tools/get-test-coverage-map.js.map +1 -0
- package/dist/server/tools/get-todos.d.ts +51 -0
- package/dist/server/tools/get-todos.d.ts.map +1 -0
- package/dist/server/tools/get-todos.js +180 -0
- package/dist/server/tools/get-todos.js.map +1 -0
- package/dist/server/tools/get-type-graph.d.ts +73 -0
- package/dist/server/tools/get-type-graph.d.ts.map +1 -0
- package/dist/server/tools/get-type-graph.js +437 -0
- package/dist/server/tools/get-type-graph.js.map +1 -0
- package/dist/server/tools/health-radar.d.ts +50 -0
- package/dist/server/tools/health-radar.d.ts.map +1 -0
- package/dist/server/tools/health-radar.js +426 -0
- package/dist/server/tools/health-radar.js.map +1 -0
- package/dist/server/tools/plan-refactoring.d.ts +74 -0
- package/dist/server/tools/plan-refactoring.d.ts.map +1 -0
- package/dist/server/tools/plan-refactoring.js +644 -0
- package/dist/server/tools/plan-refactoring.js.map +1 -0
- package/dist/server/tools/render-call-graph.d.ts +40 -0
- package/dist/server/tools/render-call-graph.d.ts.map +1 -0
- package/dist/server/tools/render-call-graph.js +215 -0
- package/dist/server/tools/render-call-graph.js.map +1 -0
- package/dist/server/tools/render-class-hierarchy.d.ts +42 -0
- package/dist/server/tools/render-class-hierarchy.d.ts.map +1 -0
- package/dist/server/tools/render-class-hierarchy.js +265 -0
- package/dist/server/tools/render-class-hierarchy.js.map +1 -0
- package/dist/server/tools/render-dep-matrix.d.ts +38 -0
- package/dist/server/tools/render-dep-matrix.d.ts.map +1 -0
- package/dist/server/tools/render-dep-matrix.js +186 -0
- package/dist/server/tools/render-dep-matrix.js.map +1 -0
- package/dist/server/tools/render-diagram.d.ts +47 -0
- package/dist/server/tools/render-diagram.d.ts.map +1 -0
- package/dist/server/tools/render-diagram.js +266 -0
- package/dist/server/tools/render-diagram.js.map +1 -0
- package/dist/server/tools/render-import-graph.d.ts +41 -0
- package/dist/server/tools/render-import-graph.d.ts.map +1 -0
- package/dist/server/tools/render-import-graph.js +158 -0
- package/dist/server/tools/render-import-graph.js.map +1 -0
- package/dist/server/tools/search-ast.d.ts +55 -0
- package/dist/server/tools/search-ast.d.ts.map +1 -0
- package/dist/server/tools/search-ast.js +279 -0
- package/dist/server/tools/search-ast.js.map +1 -0
- package/dist/server/tools/search-by-complexity.d.ts +92 -0
- package/dist/server/tools/search-by-complexity.d.ts.map +1 -0
- package/dist/server/tools/search-by-complexity.js +268 -0
- package/dist/server/tools/search-by-complexity.js.map +1 -0
- package/dist/server/tools/search-by-decorator.d.ts +48 -0
- package/dist/server/tools/search-by-decorator.d.ts.map +1 -0
- package/dist/server/tools/search-by-decorator.js +518 -0
- package/dist/server/tools/search-by-decorator.js.map +1 -0
- package/dist/server/tools/search-by-signature.d.ts +56 -0
- package/dist/server/tools/search-by-signature.d.ts.map +1 -0
- package/dist/server/tools/search-by-signature.js +200 -0
- package/dist/server/tools/search-by-signature.js.map +1 -0
- package/dist/ui/assets/BlastRadius-QdgESOL8.js +1 -0
- package/dist/ui/assets/{DependencyGraph-CDtBHM0U.js → DependencyGraph-BSMhzwWV.js} +6 -6
- package/dist/ui/assets/{NotFound-Cdt6X8pl.js → NotFound-CipFP_s1.js} +1 -1
- package/dist/ui/assets/RepoDetail-Dfp5z5Kq.js +1 -0
- package/dist/ui/assets/{RepoList-B9LaZvob.js → RepoList-BKtST3hB.js} +1 -1
- package/dist/ui/assets/{Search-CLqv2KGV.js → Search-DzhGDViy.js} +1 -1
- package/dist/ui/assets/{SymbolView-BlbDR1DU.js → SymbolView-ryVEwAHG.js} +1 -1
- package/dist/ui/assets/{index-DADf5y_L.css → index-Ny8gn9F0.css} +1 -1
- package/dist/ui/assets/{index-i3Q1XbEh.js → index-nX2chMqi.js} +6 -6
- package/dist/ui/assets/{useSearch-mbMk6-M1.js → useSearch-BnBCRKui.js} +1 -1
- package/dist/ui/index.html +2 -2
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/docs/dev/jcodemunch-gap-analysis.md +198 -0
- package/package.json +9 -1
- package/user-manual.md +2466 -0
- package/dist/ui/assets/BlastRadius-BDZWhEk-.js +0 -1
- package/dist/ui/assets/RepoDetail-M6WaYbZ3.js +0 -1
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* check-delete-safe.ts
|
|
3
|
+
*
|
|
4
|
+
* MCP tool: check_delete_safe
|
|
5
|
+
*
|
|
6
|
+
* Pre-flight check for deleting a symbol or file. Returns a binary verdict
|
|
7
|
+
* and all live references that would break — so an agent can decide whether
|
|
8
|
+
* deletion is safe without manually interpreting find_references output.
|
|
9
|
+
*
|
|
10
|
+
* Safety rules:
|
|
11
|
+
* safe: false — if any live (non-test) references exist in the repo
|
|
12
|
+
* safe: false — if symbol is exported AND includeExternalRisk: true
|
|
13
|
+
* (exported symbols may be consumed by external npm packages)
|
|
14
|
+
* safe: false — if symbol is detected as an entry point
|
|
15
|
+
* safe: true — zero live refs, not exported (or external risk ignored),
|
|
16
|
+
* and not an entry point
|
|
17
|
+
*
|
|
18
|
+
* Modes:
|
|
19
|
+
* symbolId — check a single named symbol
|
|
20
|
+
* filePath — check all symbols in a file (aggregate verdict)
|
|
21
|
+
*
|
|
22
|
+
* Risk kinds:
|
|
23
|
+
* 'live-reference' — production code that imports or calls the symbol
|
|
24
|
+
* 'exported-symbol' — symbol is exported (potential external consumers)
|
|
25
|
+
* 'entry-point' — symbol is a route handler, main function, or framework default
|
|
26
|
+
* 'test-subject' — test file references the symbol (informational, not a hard block)
|
|
27
|
+
*/
|
|
28
|
+
import { z } from 'zod';
|
|
29
|
+
import { openDatabase, getRepo } from '../../core/db/schema.js';
|
|
30
|
+
import { getSymbolById } from '../../core/db/symbol-store.js';
|
|
31
|
+
import { getAllFilesWithContent } from '../../core/db/file-store.js';
|
|
32
|
+
import { buildMeta } from './_meta.js';
|
|
33
|
+
export const name = 'check_delete_safe';
|
|
34
|
+
export const description = 'Pre-flight check for deleting a symbol or file. Returns a verdict and all live ' +
|
|
35
|
+
'references that would break if the symbol were removed. ' +
|
|
36
|
+
'safe: false when live references exist, the symbol is exported (external consumers), ' +
|
|
37
|
+
'or the symbol is an entry point (route handler, main export). ' +
|
|
38
|
+
'Supports two modes: symbolId (single symbol) or filePath (all symbols in a file). ' +
|
|
39
|
+
'Use search_symbols or get_file_outline to find a symbolId first.';
|
|
40
|
+
export const inputSchema = {
|
|
41
|
+
repoId: z
|
|
42
|
+
.string()
|
|
43
|
+
.describe('Repo ID from index_folder or resolve_repo'),
|
|
44
|
+
symbolId: z
|
|
45
|
+
.string()
|
|
46
|
+
.optional()
|
|
47
|
+
.describe('Symbol ID of the symbol to check. Mutually exclusive with filePath. ' +
|
|
48
|
+
'Use search_symbols to find the symbolId.'),
|
|
49
|
+
filePath: z
|
|
50
|
+
.string()
|
|
51
|
+
.optional()
|
|
52
|
+
.describe('File path relative to the repo root — checks all symbols in the file and ' +
|
|
53
|
+
'produces an aggregate verdict. Mutually exclusive with symbolId.'),
|
|
54
|
+
includeExternalRisk: z
|
|
55
|
+
.boolean()
|
|
56
|
+
.optional()
|
|
57
|
+
.describe('Warn when a symbol is exported but has no internal references ' +
|
|
58
|
+
'(may be consumed by external npm packages). Default true. ' +
|
|
59
|
+
'Set false to suppress this warning.'),
|
|
60
|
+
};
|
|
61
|
+
// ─── Helpers ──────────────────────────────────────────────────────────────────
|
|
62
|
+
function escapeRegex(str) {
|
|
63
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Return true when a file path looks like a test file.
|
|
67
|
+
* Matches: *.test.ts, *.spec.ts, /__tests__/, /test/, /tests/
|
|
68
|
+
*/
|
|
69
|
+
function isTestFile(filePath) {
|
|
70
|
+
const p = filePath.replace(/\\/g, '/');
|
|
71
|
+
return (/\.test\.[jt]sx?$/.test(p) ||
|
|
72
|
+
/\.spec\.[jt]sx?$/.test(p) ||
|
|
73
|
+
/\/__tests__\//.test(p) ||
|
|
74
|
+
/\/tests?\//.test(p));
|
|
75
|
+
}
|
|
76
|
+
/** Return true when the signature contains the `export` keyword. */
|
|
77
|
+
function isExportedSignature(signature) {
|
|
78
|
+
return /\bexport\b/.test(signature);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Heuristic entry-point detection.
|
|
82
|
+
* A symbol is considered an entry point when:
|
|
83
|
+
* - its name is one of the well-known entry names (main, default, handler, index)
|
|
84
|
+
* - its signature contains a route/controller decorator
|
|
85
|
+
* - it is a default export from an index file
|
|
86
|
+
*/
|
|
87
|
+
function isEntryPointSymbol(name, signature, filePath) {
|
|
88
|
+
if (['main', 'default', 'handler', 'index'].includes(name))
|
|
89
|
+
return true;
|
|
90
|
+
if (/@(Get|Post|Put|Delete|Patch|Route|Controller)\b/.test(signature))
|
|
91
|
+
return true;
|
|
92
|
+
const fp = filePath.replace(/\\/g, '/');
|
|
93
|
+
if (/\/index\.[jt]sx?$/.test(fp) && /\bdefault\b/.test(signature))
|
|
94
|
+
return true;
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Scan all cached file contents for references to `symbolName`.
|
|
99
|
+
* The definition file is excluded (deleting the symbol removes its definition too).
|
|
100
|
+
* References found in test files are tagged 'test-subject'; all others 'live-reference'.
|
|
101
|
+
*/
|
|
102
|
+
function findRisksForSymbol(symbolName, definitionFilePath, files) {
|
|
103
|
+
const pattern = new RegExp(`\\b${escapeRegex(symbolName)}\\b`);
|
|
104
|
+
const risks = [];
|
|
105
|
+
let liveReferenceCount = 0;
|
|
106
|
+
for (const { path, rawContent } of files) {
|
|
107
|
+
if (!rawContent)
|
|
108
|
+
continue;
|
|
109
|
+
if (path === definitionFilePath)
|
|
110
|
+
continue;
|
|
111
|
+
const text = rawContent.toString('utf8');
|
|
112
|
+
const lines = text.split('\n');
|
|
113
|
+
const test = isTestFile(path);
|
|
114
|
+
for (let i = 0; i < lines.length; i++) {
|
|
115
|
+
const line = lines[i];
|
|
116
|
+
if (!pattern.test(line))
|
|
117
|
+
continue;
|
|
118
|
+
const context = line.trim().length > 120 ? line.trim().slice(0, 120) : line.trim();
|
|
119
|
+
if (test) {
|
|
120
|
+
risks.push({
|
|
121
|
+
kind: 'test-subject',
|
|
122
|
+
filePath: path,
|
|
123
|
+
line: i + 1,
|
|
124
|
+
detail: `Test file references "${symbolName}": ${context}`,
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
liveReferenceCount++;
|
|
129
|
+
risks.push({
|
|
130
|
+
kind: 'live-reference',
|
|
131
|
+
filePath: path,
|
|
132
|
+
line: i + 1,
|
|
133
|
+
detail: context,
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return { risks, liveReferenceCount };
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Run the full safety check for one symbol and return aggregated risk data.
|
|
142
|
+
*/
|
|
143
|
+
function checkOneSymbol(symbolName, symbolFilePath, symbolSignature, includeExternalRisk, files) {
|
|
144
|
+
const { risks, liveReferenceCount } = findRisksForSymbol(symbolName, symbolFilePath, files);
|
|
145
|
+
const exported = isExportedSignature(symbolSignature);
|
|
146
|
+
const entryPoint = isEntryPointSymbol(symbolName, symbolSignature, symbolFilePath);
|
|
147
|
+
if (exported && includeExternalRisk) {
|
|
148
|
+
risks.push({
|
|
149
|
+
kind: 'exported-symbol',
|
|
150
|
+
filePath: symbolFilePath,
|
|
151
|
+
detail: `"${symbolName}" is exported and may be consumed by external packages. ` +
|
|
152
|
+
`No internal references were found.`,
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
if (entryPoint) {
|
|
156
|
+
risks.push({
|
|
157
|
+
kind: 'entry-point',
|
|
158
|
+
filePath: symbolFilePath,
|
|
159
|
+
detail: `"${symbolName}" appears to be an entry point (route handler, main export, or framework default).`,
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
return { risks, liveReferenceCount, isExported: exported, isEntryPoint: entryPoint };
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Build a human-readable verdict sentence from aggregated risk data.
|
|
166
|
+
*/
|
|
167
|
+
function buildVerdict(safe, liveReferenceCount, isExported, isEntryPoint, risks) {
|
|
168
|
+
if (safe) {
|
|
169
|
+
const testCount = risks.filter((r) => r.kind === 'test-subject').length;
|
|
170
|
+
const testNote = testCount > 0 ? ` (${testCount} test reference${testCount > 1 ? 's' : ''} will also break).` : '.';
|
|
171
|
+
return `Safe to delete: no live references found${testNote}`;
|
|
172
|
+
}
|
|
173
|
+
const parts = [];
|
|
174
|
+
if (liveReferenceCount > 0) {
|
|
175
|
+
const fileSet = new Set(risks.filter((r) => r.kind === 'live-reference').map((r) => r.filePath));
|
|
176
|
+
parts.push(`${liveReferenceCount} live reference${liveReferenceCount > 1 ? 's' : ''} in ${fileSet.size} file${fileSet.size > 1 ? 's' : ''}`);
|
|
177
|
+
}
|
|
178
|
+
if (isExported) {
|
|
179
|
+
parts.push('symbol is exported (external consumers possible)');
|
|
180
|
+
}
|
|
181
|
+
if (isEntryPoint) {
|
|
182
|
+
parts.push('symbol is an entry point');
|
|
183
|
+
}
|
|
184
|
+
return `Unsafe to delete: ${parts.join('; ')}.`;
|
|
185
|
+
}
|
|
186
|
+
// ─── Handler ──────────────────────────────────────────────────────────────────
|
|
187
|
+
export async function handler(args) {
|
|
188
|
+
const t0 = Date.now();
|
|
189
|
+
const { repoId, symbolId, filePath, includeExternalRisk = true } = args;
|
|
190
|
+
if (!symbolId && !filePath) {
|
|
191
|
+
return {
|
|
192
|
+
content: [
|
|
193
|
+
{
|
|
194
|
+
type: 'text',
|
|
195
|
+
text: JSON.stringify({
|
|
196
|
+
error: 'Provide either symbolId or filePath.',
|
|
197
|
+
}),
|
|
198
|
+
},
|
|
199
|
+
],
|
|
200
|
+
isError: true,
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
const db = openDatabase(repoId);
|
|
204
|
+
try {
|
|
205
|
+
const repo = getRepo(db, repoId);
|
|
206
|
+
if (!repo) {
|
|
207
|
+
return {
|
|
208
|
+
content: [
|
|
209
|
+
{
|
|
210
|
+
type: 'text',
|
|
211
|
+
text: JSON.stringify({
|
|
212
|
+
error: `Repo "${repoId}" not found. Run index_folder first.`,
|
|
213
|
+
}),
|
|
214
|
+
},
|
|
215
|
+
],
|
|
216
|
+
isError: true,
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
const files = getAllFilesWithContent(db, repoId);
|
|
220
|
+
// ── symbolId mode ──────────────────────────────────────────────────────────
|
|
221
|
+
if (symbolId) {
|
|
222
|
+
const symbol = getSymbolById(db, repoId, symbolId);
|
|
223
|
+
if (!symbol) {
|
|
224
|
+
return {
|
|
225
|
+
content: [
|
|
226
|
+
{
|
|
227
|
+
type: 'text',
|
|
228
|
+
text: JSON.stringify({
|
|
229
|
+
error: `Symbol "${symbolId}" not found in repo "${repoId}".`,
|
|
230
|
+
}),
|
|
231
|
+
},
|
|
232
|
+
],
|
|
233
|
+
isError: true,
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
const { risks, liveReferenceCount, isExported, isEntryPoint } = checkOneSymbol(symbol.name, symbol.filePath, symbol.signature, includeExternalRisk, files);
|
|
237
|
+
const safe = liveReferenceCount === 0 &&
|
|
238
|
+
(!isExported || !includeExternalRisk) &&
|
|
239
|
+
!isEntryPoint;
|
|
240
|
+
const verdict = buildVerdict(safe, liveReferenceCount, isExported, isEntryPoint, risks);
|
|
241
|
+
const responseText = JSON.stringify(risks);
|
|
242
|
+
const output = {
|
|
243
|
+
safe,
|
|
244
|
+
verdict,
|
|
245
|
+
risks,
|
|
246
|
+
liveReferenceCount,
|
|
247
|
+
isExported,
|
|
248
|
+
isEntryPoint,
|
|
249
|
+
_tokenEstimate: Math.ceil(responseText.length / 4),
|
|
250
|
+
_meta: buildMeta({ timingMs: Date.now() - t0 }),
|
|
251
|
+
};
|
|
252
|
+
return { content: [{ type: 'text', text: JSON.stringify(output, null, 2) }] };
|
|
253
|
+
}
|
|
254
|
+
// ── filePath mode ──────────────────────────────────────────────────────────
|
|
255
|
+
const targetFilePath = filePath;
|
|
256
|
+
const symbolRows = db
|
|
257
|
+
.prepare('SELECT id, name, kind, file_path, signature FROM symbols WHERE repo_id = ? AND file_path = ?')
|
|
258
|
+
.all(repoId, targetFilePath);
|
|
259
|
+
if (symbolRows.length === 0) {
|
|
260
|
+
return {
|
|
261
|
+
content: [
|
|
262
|
+
{
|
|
263
|
+
type: 'text',
|
|
264
|
+
text: JSON.stringify({
|
|
265
|
+
error: `No symbols found for file "${targetFilePath}" in repo "${repoId}". ` +
|
|
266
|
+
'Check the file path is relative to the repo root and the file is indexed.',
|
|
267
|
+
}),
|
|
268
|
+
},
|
|
269
|
+
],
|
|
270
|
+
isError: true,
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
// Aggregate results across all symbols in the file
|
|
274
|
+
const allRisks = [];
|
|
275
|
+
let totalLiveRefCount = 0;
|
|
276
|
+
let anyExported = false;
|
|
277
|
+
let anyEntryPoint = false;
|
|
278
|
+
for (const row of symbolRows) {
|
|
279
|
+
const { risks, liveReferenceCount, isExported, isEntryPoint } = checkOneSymbol(row.name, row.file_path, row.signature, includeExternalRisk, files);
|
|
280
|
+
allRisks.push(...risks);
|
|
281
|
+
totalLiveRefCount += liveReferenceCount;
|
|
282
|
+
if (isExported)
|
|
283
|
+
anyExported = true;
|
|
284
|
+
if (isEntryPoint)
|
|
285
|
+
anyEntryPoint = true;
|
|
286
|
+
}
|
|
287
|
+
const safe = totalLiveRefCount === 0 &&
|
|
288
|
+
(!anyExported || !includeExternalRisk) &&
|
|
289
|
+
!anyEntryPoint;
|
|
290
|
+
const verdict = buildVerdict(safe, totalLiveRefCount, anyExported, anyEntryPoint, allRisks);
|
|
291
|
+
const responseText = JSON.stringify(allRisks);
|
|
292
|
+
const output = {
|
|
293
|
+
safe,
|
|
294
|
+
verdict,
|
|
295
|
+
risks: allRisks,
|
|
296
|
+
liveReferenceCount: totalLiveRefCount,
|
|
297
|
+
isExported: anyExported,
|
|
298
|
+
isEntryPoint: anyEntryPoint,
|
|
299
|
+
_tokenEstimate: Math.ceil(responseText.length / 4),
|
|
300
|
+
_meta: buildMeta({ timingMs: Date.now() - t0 }),
|
|
301
|
+
};
|
|
302
|
+
return { content: [{ type: 'text', text: JSON.stringify(output, null, 2) }] };
|
|
303
|
+
}
|
|
304
|
+
finally {
|
|
305
|
+
db.close();
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
//# sourceMappingURL=check-delete-safe.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-delete-safe.js","sourceRoot":"","sources":["../../../src/server/tools/check-delete-safe.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC9D,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAIvC,MAAM,CAAC,MAAM,IAAI,GAAG,mBAAmB,CAAC;AAExC,MAAM,CAAC,MAAM,WAAW,GACtB,iFAAiF;IACjF,0DAA0D;IAC1D,uFAAuF;IACvF,gEAAgE;IAChE,oFAAoF;IACpF,kEAAkE,CAAC;AAErE,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,MAAM,EAAE,CAAC;SACN,MAAM,EAAE;SACR,QAAQ,CAAC,2CAA2C,CAAC;IACxD,QAAQ,EAAE,CAAC;SACR,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CACP,sEAAsE;QACtE,0CAA0C,CAC3C;IACH,QAAQ,EAAE,CAAC;SACR,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CACP,2EAA2E;QAC3E,kEAAkE,CACnE;IACH,mBAAmB,EAAE,CAAC;SACnB,OAAO,EAAE;SACT,QAAQ,EAAE;SACV,QAAQ,CACP,gEAAgE;QAChE,4DAA4D;QAC5D,qCAAqC,CACtC;CACJ,CAAC;AAmCF,iFAAiF;AAEjF,SAAS,WAAW,CAAC,GAAW;IAC9B,OAAO,GAAG,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;AACpD,CAAC;AAED;;;GAGG;AACH,SAAS,UAAU,CAAC,QAAgB;IAClC,MAAM,CAAC,GAAG,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IACvC,OAAO,CACL,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC;QAC1B,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC;QAC1B,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC;QACvB,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,CACrB,CAAC;AACJ,CAAC;AAED,oEAAoE;AACpE,SAAS,mBAAmB,CAAC,SAAiB;IAC5C,OAAO,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;AACtC,CAAC;AAED;;;;;;GAMG;AACH,SAAS,kBAAkB,CAAC,IAAY,EAAE,SAAiB,EAAE,QAAgB;IAC3E,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACxE,IAAI,iDAAiD,CAAC,IAAI,CAAC,SAAS,CAAC;QAAE,OAAO,IAAI,CAAC;IACnF,MAAM,EAAE,GAAG,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IACxC,IAAI,mBAAmB,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC;QAAE,OAAO,IAAI,CAAC;IAC/E,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;GAIG;AACH,SAAS,kBAAkB,CACzB,UAAkB,EAClB,kBAA0B,EAC1B,KAAkB;IAElB,MAAM,OAAO,GAAG,IAAI,MAAM,CAAC,MAAM,WAAW,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;IAC/D,MAAM,KAAK,GAAiB,EAAE,CAAC;IAC/B,IAAI,kBAAkB,GAAG,CAAC,CAAC;IAE3B,KAAK,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,KAAK,EAAE,CAAC;QACzC,IAAI,CAAC,UAAU;YAAE,SAAS;QAC1B,IAAI,IAAI,KAAK,kBAAkB;YAAE,SAAS;QAE1C,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACzC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC/B,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;QAE9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAE,CAAC;YACvB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;gBAAE,SAAS;YAElC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YAEnF,IAAI,IAAI,EAAE,CAAC;gBACT,KAAK,CAAC,IAAI,CAAC;oBACT,IAAI,EAAE,cAAc;oBACpB,QAAQ,EAAE,IAAI;oBACd,IAAI,EAAE,CAAC,GAAG,CAAC;oBACX,MAAM,EAAE,yBAAyB,UAAU,MAAM,OAAO,EAAE;iBAC3D,CAAC,CAAC;YACL,CAAC;iBAAM,CAAC;gBACN,kBAAkB,EAAE,CAAC;gBACrB,KAAK,CAAC,IAAI,CAAC;oBACT,IAAI,EAAE,gBAAgB;oBACtB,QAAQ,EAAE,IAAI;oBACd,IAAI,EAAE,CAAC,GAAG,CAAC;oBACX,MAAM,EAAE,OAAO;iBAChB,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,kBAAkB,EAAE,CAAC;AACvC,CAAC;AAED;;GAEG;AACH,SAAS,cAAc,CACrB,UAAkB,EAClB,cAAsB,EACtB,eAAuB,EACvB,mBAA4B,EAC5B,KAAkB;IAOlB,MAAM,EAAE,KAAK,EAAE,kBAAkB,EAAE,GAAG,kBAAkB,CAAC,UAAU,EAAE,cAAc,EAAE,KAAK,CAAC,CAAC;IAE5F,MAAM,QAAQ,GAAG,mBAAmB,CAAC,eAAe,CAAC,CAAC;IACtD,MAAM,UAAU,GAAG,kBAAkB,CAAC,UAAU,EAAE,eAAe,EAAE,cAAc,CAAC,CAAC;IAEnF,IAAI,QAAQ,IAAI,mBAAmB,EAAE,CAAC;QACpC,KAAK,CAAC,IAAI,CAAC;YACT,IAAI,EAAE,iBAAiB;YACvB,QAAQ,EAAE,cAAc;YACxB,MAAM,EACJ,IAAI,UAAU,0DAA0D;gBACxE,oCAAoC;SACvC,CAAC,CAAC;IACL,CAAC;IAED,IAAI,UAAU,EAAE,CAAC;QACf,KAAK,CAAC,IAAI,CAAC;YACT,IAAI,EAAE,aAAa;YACnB,QAAQ,EAAE,cAAc;YACxB,MAAM,EAAE,IAAI,UAAU,oFAAoF;SAC3G,CAAC,CAAC;IACL,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,kBAAkB,EAAE,UAAU,EAAE,QAAQ,EAAE,YAAY,EAAE,UAAU,EAAE,CAAC;AACvF,CAAC;AAED;;GAEG;AACH,SAAS,YAAY,CACnB,IAAa,EACb,kBAA0B,EAC1B,UAAmB,EACnB,YAAqB,EACrB,KAAmB;IAEnB,IAAI,IAAI,EAAE,CAAC;QACT,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,cAAc,CAAC,CAAC,MAAM,CAAC;QACxE,MAAM,QAAQ,GAAG,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,SAAS,kBAAkB,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,oBAAoB,CAAC,CAAC,CAAC,GAAG,CAAC;QACpH,OAAO,2CAA2C,QAAQ,EAAE,CAAC;IAC/D,CAAC;IAED,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,IAAI,kBAAkB,GAAG,CAAC,EAAE,CAAC;QAC3B,MAAM,OAAO,GAAG,IAAI,GAAG,CACrB,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,gBAAgB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CACxE,CAAC;QACF,KAAK,CAAC,IAAI,CACR,GAAG,kBAAkB,kBAAkB,kBAAkB,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,OAAO,OAAO,CAAC,IAAI,QAAQ,OAAO,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CACjI,CAAC;IACJ,CAAC;IAED,IAAI,UAAU,EAAE,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,kDAAkD,CAAC,CAAC;IACjE,CAAC;IAED,IAAI,YAAY,EAAE,CAAC;QACjB,KAAK,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;IACzC,CAAC;IAED,OAAO,qBAAqB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;AAClD,CAAC;AAED,iFAAiF;AAEjF,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,IAK7B;IACC,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACtB,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,mBAAmB,GAAG,IAAI,EAAE,GAAG,IAAI,CAAC;IAExE,IAAI,CAAC,QAAQ,IAAI,CAAC,QAAQ,EAAE,CAAC;QAC3B,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;wBACnB,KAAK,EAAE,sCAAsC;qBAC9C,CAAC;iBACH;aACF;YACD,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;IAED,MAAM,EAAE,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;IAEhC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,OAAO,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;QACjC,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;4BACnB,KAAK,EAAE,SAAS,MAAM,sCAAsC;yBAC7D,CAAC;qBACH;iBACF;gBACD,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;QAED,MAAM,KAAK,GAAG,sBAAsB,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;QAEjD,8EAA8E;QAE9E,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,MAAM,GAAG,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;YACnD,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,OAAO;oBACL,OAAO,EAAE;wBACP;4BACE,IAAI,EAAE,MAAM;4BACZ,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gCACnB,KAAK,EAAE,WAAW,QAAQ,wBAAwB,MAAM,IAAI;6BAC7D,CAAC;yBACH;qBACF;oBACD,OAAO,EAAE,IAAI;iBACd,CAAC;YACJ,CAAC;YAED,MAAM,EAAE,KAAK,EAAE,kBAAkB,EAAE,UAAU,EAAE,YAAY,EAAE,GAAG,cAAc,CAC5E,MAAM,CAAC,IAAI,EACX,MAAM,CAAC,QAAQ,EACf,MAAM,CAAC,SAAS,EAChB,mBAAmB,EACnB,KAAK,CACN,CAAC;YAEF,MAAM,IAAI,GACR,kBAAkB,KAAK,CAAC;gBACxB,CAAC,CAAC,UAAU,IAAI,CAAC,mBAAmB,CAAC;gBACrC,CAAC,YAAY,CAAC;YAEhB,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,EAAE,kBAAkB,EAAE,UAAU,EAAE,YAAY,EAAE,KAAK,CAAC,CAAC;YAExF,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;YAC3C,MAAM,MAAM,GAA0B;gBACpC,IAAI;gBACJ,OAAO;gBACP,KAAK;gBACL,kBAAkB;gBAClB,UAAU;gBACV,YAAY;gBACZ,cAAc,EAAE,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC;gBAClD,KAAK,EAAE,SAAS,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC;aAChD,CAAC;YAEF,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;QAChF,CAAC;QAED,8EAA8E;QAE9E,MAAM,cAAc,GAAG,QAAS,CAAC;QAEjC,MAAM,UAAU,GAAG,EAAE;aAClB,OAAO,CACN,8FAA8F,CAC/F;aACA,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;QAE/B,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC5B,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;4BACnB,KAAK,EAAE,8BAA8B,cAAc,cAAc,MAAM,KAAK;gCAC1E,2EAA2E;yBAC9E,CAAC;qBACH;iBACF;gBACD,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;QAED,mDAAmD;QACnD,MAAM,QAAQ,GAAiB,EAAE,CAAC;QAClC,IAAI,iBAAiB,GAAG,CAAC,CAAC;QAC1B,IAAI,WAAW,GAAG,KAAK,CAAC;QACxB,IAAI,aAAa,GAAG,KAAK,CAAC;QAE1B,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;YAC7B,MAAM,EAAE,KAAK,EAAE,kBAAkB,EAAE,UAAU,EAAE,YAAY,EAAE,GAAG,cAAc,CAC5E,GAAG,CAAC,IAAI,EACR,GAAG,CAAC,SAAS,EACb,GAAG,CAAC,SAAS,EACb,mBAAmB,EACnB,KAAK,CACN,CAAC;YACF,QAAQ,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC;YACxB,iBAAiB,IAAI,kBAAkB,CAAC;YACxC,IAAI,UAAU;gBAAE,WAAW,GAAG,IAAI,CAAC;YACnC,IAAI,YAAY;gBAAE,aAAa,GAAG,IAAI,CAAC;QACzC,CAAC;QAED,MAAM,IAAI,GACR,iBAAiB,KAAK,CAAC;YACvB,CAAC,CAAC,WAAW,IAAI,CAAC,mBAAmB,CAAC;YACtC,CAAC,aAAa,CAAC;QAEjB,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,EAAE,iBAAiB,EAAE,WAAW,EAAE,aAAa,EAAE,QAAQ,CAAC,CAAC;QAE5F,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QAC9C,MAAM,MAAM,GAA0B;YACpC,IAAI;YACJ,OAAO;YACP,KAAK,EAAE,QAAQ;YACf,kBAAkB,EAAE,iBAAiB;YACrC,UAAU,EAAE,WAAW;YACvB,YAAY,EAAE,aAAa;YAC3B,cAAc,EAAE,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC;YAClD,KAAK,EAAE,SAAS,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC;SAChD,CAAC;QAEF,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IAChF,CAAC;YAAS,CAAC;QACT,EAAE,CAAC,KAAK,EAAE,CAAC;IACb,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* check-move-safe.ts
|
|
3
|
+
*
|
|
4
|
+
* MCP tool: check_move_safe
|
|
5
|
+
*
|
|
6
|
+
* Pre-flight check for moving a file to a new location. Returns:
|
|
7
|
+
* - All import statements that need updating (importUpdates), with exact
|
|
8
|
+
* current and new paths, plus the line number of each import.
|
|
9
|
+
* - Whether the move would introduce import cycles at the new location
|
|
10
|
+
* (wouldIntroduceCycles).
|
|
11
|
+
*
|
|
12
|
+
* Safety definition:
|
|
13
|
+
* safe: false — if the move would place the file in an existing import cycle
|
|
14
|
+
* (the cycle moves with the file to its new location).
|
|
15
|
+
* safe: true — if all affected imports can be updated mechanically and the
|
|
16
|
+
* new location has no cycle involvement.
|
|
17
|
+
*
|
|
18
|
+
* Note: all moves are mechanically doable — the only hard blocker is cycle
|
|
19
|
+
* risk. `importUpdates` is the primary output: an exact checklist of the
|
|
20
|
+
* import statements that must be updated after the move.
|
|
21
|
+
*/
|
|
22
|
+
import { z } from 'zod';
|
|
23
|
+
import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
|
|
24
|
+
export declare const name = "check_move_safe";
|
|
25
|
+
export declare const description: string;
|
|
26
|
+
export declare const inputSchema: {
|
|
27
|
+
repoId: z.ZodString;
|
|
28
|
+
filePath: z.ZodString;
|
|
29
|
+
newFilePath: z.ZodString;
|
|
30
|
+
checkCycles: z.ZodOptional<z.ZodBoolean>;
|
|
31
|
+
};
|
|
32
|
+
export interface ImportUpdate {
|
|
33
|
+
importerFilePath: string;
|
|
34
|
+
currentImportPath: string;
|
|
35
|
+
newImportPath: string;
|
|
36
|
+
line: number;
|
|
37
|
+
}
|
|
38
|
+
export declare function handler(args: {
|
|
39
|
+
repoId: string;
|
|
40
|
+
filePath: string;
|
|
41
|
+
newFilePath: string;
|
|
42
|
+
checkCycles?: boolean;
|
|
43
|
+
}): Promise<CallToolResult>;
|
|
44
|
+
//# sourceMappingURL=check-move-safe.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-move-safe.d.ts","sourceRoot":"","sources":["../../../src/server/tools/check-move-safe.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAOxB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAGzE,eAAO,MAAM,IAAI,oBAAoB,CAAC;AAEtC,eAAO,MAAM,WAAW,QAM0D,CAAC;AAEnF,eAAO,MAAM,WAAW;;;;;CAevB,CAAC;AAIF,MAAM,WAAW,YAAY;IAC3B,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;CACd;AAyJD,wBAAsB,OAAO,CAAC,IAAI,EAAE;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,GAAG,OAAO,CAAC,cAAc,CAAC,CA2H1B"}
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* check-move-safe.ts
|
|
3
|
+
*
|
|
4
|
+
* MCP tool: check_move_safe
|
|
5
|
+
*
|
|
6
|
+
* Pre-flight check for moving a file to a new location. Returns:
|
|
7
|
+
* - All import statements that need updating (importUpdates), with exact
|
|
8
|
+
* current and new paths, plus the line number of each import.
|
|
9
|
+
* - Whether the move would introduce import cycles at the new location
|
|
10
|
+
* (wouldIntroduceCycles).
|
|
11
|
+
*
|
|
12
|
+
* Safety definition:
|
|
13
|
+
* safe: false — if the move would place the file in an existing import cycle
|
|
14
|
+
* (the cycle moves with the file to its new location).
|
|
15
|
+
* safe: true — if all affected imports can be updated mechanically and the
|
|
16
|
+
* new location has no cycle involvement.
|
|
17
|
+
*
|
|
18
|
+
* Note: all moves are mechanically doable — the only hard blocker is cycle
|
|
19
|
+
* risk. `importUpdates` is the primary output: an exact checklist of the
|
|
20
|
+
* import statements that must be updated after the move.
|
|
21
|
+
*/
|
|
22
|
+
import { z } from 'zod';
|
|
23
|
+
import { dirname, extname, relative, sep } from 'path';
|
|
24
|
+
import { openDatabase, getRepo } from '../../core/db/schema.js';
|
|
25
|
+
import { getFileContent } from '../../core/db/file-store.js';
|
|
26
|
+
import { getImportersOf, getAllDepEdges } from '../../core/db/dep-store.js';
|
|
27
|
+
import { buildMeta } from './_meta.js';
|
|
28
|
+
export const name = 'check_move_safe';
|
|
29
|
+
export const description = 'Pre-flight check for moving a file to a new location. Returns a checklist of ' +
|
|
30
|
+
'import statements that need updating (importUpdates) plus cycle-risk analysis ' +
|
|
31
|
+
'(wouldIntroduceCycles). ' +
|
|
32
|
+
'safe: false only when the move would place the file inside an existing import cycle. ' +
|
|
33
|
+
'All moves are mechanically doable — importUpdates gives you the exact edits needed. ' +
|
|
34
|
+
'Use find_importers to preview which files depend on a module before moving it.';
|
|
35
|
+
export const inputSchema = {
|
|
36
|
+
repoId: z.string().describe('Repo ID from index_folder or resolve_repo'),
|
|
37
|
+
filePath: z
|
|
38
|
+
.string()
|
|
39
|
+
.describe('Current file path relative to the repo root (e.g. "src/utils/hash.ts")'),
|
|
40
|
+
newFilePath: z
|
|
41
|
+
.string()
|
|
42
|
+
.describe('Proposed new location relative to the repo root (e.g. "src/core/hash.ts")'),
|
|
43
|
+
checkCycles: z
|
|
44
|
+
.boolean()
|
|
45
|
+
.optional()
|
|
46
|
+
.describe('Simulate the move in the dependency graph and detect any import cycles ' +
|
|
47
|
+
'that would involve the new location. Default true.'),
|
|
48
|
+
};
|
|
49
|
+
// ─── Helpers ──────────────────────────────────────────────────────────────────
|
|
50
|
+
/** Normalize path separators to forward slashes. */
|
|
51
|
+
function normalizeSep(p) {
|
|
52
|
+
return p.split(sep).join('/');
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Compute the new import specifier from `importerFilePath` to `newTargetPath`,
|
|
56
|
+
* preserving whether the original specifier had a file extension.
|
|
57
|
+
*
|
|
58
|
+
* Examples:
|
|
59
|
+
* importerFilePath = 'src/main.ts', newTargetPath = 'src/core/hash.ts',
|
|
60
|
+
* currentSpecifier = './utils/hash'
|
|
61
|
+
* → './core/hash' (no extension, matching original)
|
|
62
|
+
*
|
|
63
|
+
* importerFilePath = 'src/deep/nested/consumer.ts', newTargetPath = 'src/deep/parser.ts',
|
|
64
|
+
* currentSpecifier = '../../lib/parser'
|
|
65
|
+
* → '../parser'
|
|
66
|
+
*/
|
|
67
|
+
function computeNewImportPath(importerFilePath, newTargetPath, currentSpecifier) {
|
|
68
|
+
const importerDir = dirname(importerFilePath);
|
|
69
|
+
const rawRelative = normalizeSep(relative(normalizeSep(importerDir), normalizeSep(newTargetPath)));
|
|
70
|
+
// Add './' prefix when the path doesn't start with '../'
|
|
71
|
+
const withPrefix = rawRelative.startsWith('../') ? rawRelative : `./${rawRelative}`;
|
|
72
|
+
// Match extension presence from the original specifier
|
|
73
|
+
if (!extname(currentSpecifier)) {
|
|
74
|
+
// Original had no extension → strip extension from computed path
|
|
75
|
+
const ext = extname(withPrefix);
|
|
76
|
+
return ext ? withPrefix.slice(0, -ext.length) : withPrefix;
|
|
77
|
+
}
|
|
78
|
+
return withPrefix;
|
|
79
|
+
}
|
|
80
|
+
/** Find the 1-based line number of the first import containing `specifier`. */
|
|
81
|
+
function findImportLine(content, specifier) {
|
|
82
|
+
if (!content)
|
|
83
|
+
return 0;
|
|
84
|
+
const text = content.toString('utf8');
|
|
85
|
+
const lines = text.split('\n');
|
|
86
|
+
// Match the raw specifier surrounded by any quote character
|
|
87
|
+
const escaped = specifier.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
88
|
+
const re = new RegExp(`['"\`]${escaped}['"\`]`);
|
|
89
|
+
for (let i = 0; i < lines.length; i++) {
|
|
90
|
+
if (re.test(lines[i]))
|
|
91
|
+
return i + 1;
|
|
92
|
+
}
|
|
93
|
+
return 0;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Get the import specifier used by `importerFile` when importing `targetFile`.
|
|
97
|
+
* Returns the first matching edge's specifier, or an empty string if not found.
|
|
98
|
+
*/
|
|
99
|
+
function getSpecifier(db, repoId, importerFile, targetFile) {
|
|
100
|
+
const row = db
|
|
101
|
+
.prepare(`SELECT specifier FROM dep_edges
|
|
102
|
+
WHERE repo_id = ? AND source_file = ? AND target_file = ?
|
|
103
|
+
LIMIT 1`)
|
|
104
|
+
.get(repoId, importerFile, targetFile);
|
|
105
|
+
return row?.specifier ?? '';
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Detect all import cycles in a modified dependency graph where `oldPath` has
|
|
109
|
+
* been renamed to `newPath`. Returns cycles that involve `newPath`.
|
|
110
|
+
*
|
|
111
|
+
* Uses the same DFS algorithm as findImportCycles: each cycle is reported
|
|
112
|
+
* exactly once, rooted at its lexicographically smallest file.
|
|
113
|
+
*/
|
|
114
|
+
function detectCyclesAfterMove(edges, oldPath, newPath, maxCycles = 20) {
|
|
115
|
+
// Build adjacency list with oldPath renamed to newPath
|
|
116
|
+
const adj = new Map();
|
|
117
|
+
for (const edge of edges) {
|
|
118
|
+
if (edge.sourceFile === edge.targetFile)
|
|
119
|
+
continue;
|
|
120
|
+
const src = edge.sourceFile === oldPath ? newPath : edge.sourceFile;
|
|
121
|
+
const tgt = edge.targetFile === oldPath ? newPath : edge.targetFile;
|
|
122
|
+
if (src === tgt)
|
|
123
|
+
continue;
|
|
124
|
+
const srcList = adj.get(src) ?? [];
|
|
125
|
+
if (!srcList.includes(tgt))
|
|
126
|
+
srcList.push(tgt);
|
|
127
|
+
adj.set(src, srcList);
|
|
128
|
+
if (!adj.has(tgt))
|
|
129
|
+
adj.set(tgt, []);
|
|
130
|
+
}
|
|
131
|
+
for (const v of adj.values())
|
|
132
|
+
v.sort();
|
|
133
|
+
const found = [];
|
|
134
|
+
const cap = maxCycles + 1;
|
|
135
|
+
const nodes = [...adj.keys()].sort();
|
|
136
|
+
function dfs(start, path, pathSet) {
|
|
137
|
+
if (found.length >= cap)
|
|
138
|
+
return;
|
|
139
|
+
const cur = path[path.length - 1];
|
|
140
|
+
for (const next of adj.get(cur) ?? []) {
|
|
141
|
+
if (found.length >= cap)
|
|
142
|
+
return;
|
|
143
|
+
if (next === start && path.length >= 2) {
|
|
144
|
+
found.push([...path]);
|
|
145
|
+
}
|
|
146
|
+
else if (!pathSet.has(next) && next > start) {
|
|
147
|
+
pathSet.add(next);
|
|
148
|
+
path.push(next);
|
|
149
|
+
dfs(start, path, pathSet);
|
|
150
|
+
path.pop();
|
|
151
|
+
pathSet.delete(next);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
for (const node of nodes) {
|
|
156
|
+
if (found.length >= cap)
|
|
157
|
+
break;
|
|
158
|
+
dfs(node, [node], new Set([node]));
|
|
159
|
+
}
|
|
160
|
+
// Return only cycles that involve the new (moved) path, capped at maxCycles
|
|
161
|
+
return found.filter((c) => c.includes(newPath)).slice(0, maxCycles);
|
|
162
|
+
}
|
|
163
|
+
// ─── Handler ──────────────────────────────────────────────────────────────────
|
|
164
|
+
export async function handler(args) {
|
|
165
|
+
const t0 = Date.now();
|
|
166
|
+
const { repoId, filePath, newFilePath, checkCycles = true } = args;
|
|
167
|
+
// Normalize separators so the paths match what's stored in the DB
|
|
168
|
+
const normalizedFilePath = normalizeSep(filePath);
|
|
169
|
+
const normalizedNewFilePath = normalizeSep(newFilePath);
|
|
170
|
+
if (normalizedFilePath === normalizedNewFilePath) {
|
|
171
|
+
const output = {
|
|
172
|
+
safe: true,
|
|
173
|
+
verdict: 'Safe to move: source and destination paths are the same (no-op).',
|
|
174
|
+
filePath: normalizedFilePath,
|
|
175
|
+
newFilePath: normalizedNewFilePath,
|
|
176
|
+
importUpdates: [],
|
|
177
|
+
importUpdateCount: 0,
|
|
178
|
+
newCycles: [],
|
|
179
|
+
wouldIntroduceCycles: false,
|
|
180
|
+
_tokenEstimate: 0,
|
|
181
|
+
_meta: buildMeta({ timingMs: Date.now() - t0 }),
|
|
182
|
+
};
|
|
183
|
+
return { content: [{ type: 'text', text: JSON.stringify(output, null, 2) }] };
|
|
184
|
+
}
|
|
185
|
+
const db = openDatabase(repoId);
|
|
186
|
+
try {
|
|
187
|
+
const repo = getRepo(db, repoId);
|
|
188
|
+
if (!repo) {
|
|
189
|
+
return {
|
|
190
|
+
content: [
|
|
191
|
+
{
|
|
192
|
+
type: 'text',
|
|
193
|
+
text: JSON.stringify({
|
|
194
|
+
error: `Repo "${repoId}" not found. Run index_folder first.`,
|
|
195
|
+
}),
|
|
196
|
+
},
|
|
197
|
+
],
|
|
198
|
+
isError: true,
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
// ── 1. Find all direct importers ──────────────────────────────────────────
|
|
202
|
+
const importerFiles = getImportersOf(db, repoId, normalizedFilePath);
|
|
203
|
+
// ── 2. Build ImportUpdate list ────────────────────────────────────────────
|
|
204
|
+
const importUpdates = [];
|
|
205
|
+
for (const importerFilePath of importerFiles) {
|
|
206
|
+
const specifier = getSpecifier(db, repoId, importerFilePath, normalizedFilePath);
|
|
207
|
+
if (!specifier)
|
|
208
|
+
continue; // edge without specifier — skip
|
|
209
|
+
const newImportPath = computeNewImportPath(importerFilePath, normalizedNewFilePath, specifier);
|
|
210
|
+
const content = getFileContent(db, repoId, importerFilePath);
|
|
211
|
+
const line = findImportLine(content, specifier);
|
|
212
|
+
importUpdates.push({
|
|
213
|
+
importerFilePath,
|
|
214
|
+
currentImportPath: specifier,
|
|
215
|
+
newImportPath,
|
|
216
|
+
line,
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
// Sort by importer path for deterministic output
|
|
220
|
+
importUpdates.sort((a, b) => a.importerFilePath.localeCompare(b.importerFilePath));
|
|
221
|
+
// ── 3. Cycle detection ────────────────────────────────────────────────────
|
|
222
|
+
let newCycles = [];
|
|
223
|
+
if (checkCycles) {
|
|
224
|
+
const allEdges = getAllDepEdges(db, repoId);
|
|
225
|
+
newCycles = detectCyclesAfterMove(allEdges, normalizedFilePath, normalizedNewFilePath);
|
|
226
|
+
}
|
|
227
|
+
const wouldIntroduceCycles = newCycles.length > 0;
|
|
228
|
+
// ── 4. Verdict ────────────────────────────────────────────────────────────
|
|
229
|
+
const safe = !wouldIntroduceCycles;
|
|
230
|
+
let verdict;
|
|
231
|
+
if (safe) {
|
|
232
|
+
const count = importUpdates.length;
|
|
233
|
+
if (count === 0) {
|
|
234
|
+
verdict = 'Safe to move: no importers found. No import statements need updating.';
|
|
235
|
+
}
|
|
236
|
+
else {
|
|
237
|
+
verdict =
|
|
238
|
+
`Safe to move: ${count} import statement${count !== 1 ? 's' : ''} will need updating across ` +
|
|
239
|
+
`${new Set(importUpdates.map((u) => u.importerFilePath)).size} file${importUpdates.length !== 1 ? 's' : ''}. No cycles.`;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
else {
|
|
243
|
+
verdict =
|
|
244
|
+
`Move introduces ${newCycles.length} import cycle${newCycles.length !== 1 ? 's' : ''} at the new location. ` +
|
|
245
|
+
`${importUpdates.length} import statement${importUpdates.length !== 1 ? 's' : ''} also need updating.`;
|
|
246
|
+
}
|
|
247
|
+
const responseText = JSON.stringify({ importUpdates, newCycles });
|
|
248
|
+
const output = {
|
|
249
|
+
safe,
|
|
250
|
+
verdict,
|
|
251
|
+
filePath: normalizedFilePath,
|
|
252
|
+
newFilePath: normalizedNewFilePath,
|
|
253
|
+
importUpdates,
|
|
254
|
+
importUpdateCount: importUpdates.length,
|
|
255
|
+
newCycles,
|
|
256
|
+
wouldIntroduceCycles,
|
|
257
|
+
_tokenEstimate: Math.ceil(responseText.length / 4),
|
|
258
|
+
_meta: buildMeta({ timingMs: Date.now() - t0 }),
|
|
259
|
+
};
|
|
260
|
+
return { content: [{ type: 'text', text: JSON.stringify(output, null, 2) }] };
|
|
261
|
+
}
|
|
262
|
+
finally {
|
|
263
|
+
db.close();
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
//# sourceMappingURL=check-move-safe.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-move-safe.js","sourceRoot":"","sources":["../../../src/server/tools/check-move-safe.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,MAAM,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5E,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAKvC,MAAM,CAAC,MAAM,IAAI,GAAG,iBAAiB,CAAC;AAEtC,MAAM,CAAC,MAAM,WAAW,GACtB,+EAA+E;IAC/E,gFAAgF;IAChF,0BAA0B;IAC1B,uFAAuF;IACvF,sFAAsF;IACtF,gFAAgF,CAAC;AAEnF,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,2CAA2C,CAAC;IACxE,QAAQ,EAAE,CAAC;SACR,MAAM,EAAE;SACR,QAAQ,CAAC,wEAAwE,CAAC;IACrF,WAAW,EAAE,CAAC;SACX,MAAM,EAAE;SACR,QAAQ,CAAC,2EAA2E,CAAC;IACxF,WAAW,EAAE,CAAC;SACX,OAAO,EAAE;SACT,QAAQ,EAAE;SACV,QAAQ,CACP,yEAAyE;QACzE,oDAAoD,CACrD;CACJ,CAAC;AAwBF,iFAAiF;AAEjF,oDAAoD;AACpD,SAAS,YAAY,CAAC,CAAS;IAC7B,OAAO,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAChC,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,SAAS,oBAAoB,CAC3B,gBAAwB,EACxB,aAAqB,EACrB,gBAAwB;IAExB,MAAM,WAAW,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAC9C,MAAM,WAAW,GAAG,YAAY,CAAC,QAAQ,CAAC,YAAY,CAAC,WAAW,CAAC,EAAE,YAAY,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;IAEnG,yDAAyD;IACzD,MAAM,UAAU,GAAG,WAAW,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,WAAW,EAAE,CAAC;IAEpF,uDAAuD;IACvD,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAAE,CAAC;QAC/B,iEAAiE;QACjE,MAAM,GAAG,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;QAChC,OAAO,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC;IAC7D,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,+EAA+E;AAC/E,SAAS,cAAc,CAAC,OAAsB,EAAE,SAAiB;IAC/D,IAAI,CAAC,OAAO;QAAE,OAAO,CAAC,CAAC;IACvB,MAAM,IAAI,GAAG,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACtC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC/B,4DAA4D;IAC5D,MAAM,OAAO,GAAG,SAAS,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;IACjE,MAAM,EAAE,GAAG,IAAI,MAAM,CAAC,SAAS,OAAO,QAAQ,CAAC,CAAC;IAEhD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,IAAI,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC;YAAE,OAAO,CAAC,GAAG,CAAC,CAAC;IACvC,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED;;;GAGG;AACH,SAAS,YAAY,CACnB,EAAqB,EACrB,MAAc,EACd,YAAoB,EACpB,UAAkB;IAElB,MAAM,GAAG,GAAG,EAAE;SACX,OAAO,CACN;;eAES,CACV;SACA,GAAG,CAAC,MAAM,EAAE,YAAY,EAAE,UAAU,CAAC,CAAC;IACzC,OAAO,GAAG,EAAE,SAAS,IAAI,EAAE,CAAC;AAC9B,CAAC;AAED;;;;;;GAMG;AACH,SAAS,qBAAqB,CAC5B,KAAgB,EAChB,OAAe,EACf,OAAe,EACf,SAAS,GAAG,EAAE;IAEd,uDAAuD;IACvD,MAAM,GAAG,GAAG,IAAI,GAAG,EAAoB,CAAC;IAExC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,UAAU,KAAK,IAAI,CAAC,UAAU;YAAE,SAAS;QAClD,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC;QACpE,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC;QACpE,IAAI,GAAG,KAAK,GAAG;YAAE,SAAS;QAE1B,MAAM,OAAO,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;QACnC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC;YAAE,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC9C,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QACtB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IACtC,CAAC;IAED,KAAK,MAAM,CAAC,IAAI,GAAG,CAAC,MAAM,EAAE;QAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAEvC,MAAM,KAAK,GAAe,EAAE,CAAC;IAC7B,MAAM,GAAG,GAAG,SAAS,GAAG,CAAC,CAAC;IAC1B,MAAM,KAAK,GAAG,CAAC,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAErC,SAAS,GAAG,CAAC,KAAa,EAAE,IAAc,EAAE,OAAoB;QAC9D,IAAI,KAAK,CAAC,MAAM,IAAI,GAAG;YAAE,OAAO;QAChC,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAE,CAAC;QACnC,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC;YACtC,IAAI,KAAK,CAAC,MAAM,IAAI,GAAG;gBAAE,OAAO;YAChC,IAAI,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;gBACvC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;YACxB,CAAC;iBAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,KAAK,EAAE,CAAC;gBAC9C,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;gBAClB,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAChB,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;gBAC1B,IAAI,CAAC,GAAG,EAAE,CAAC;gBACX,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YACvB,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,KAAK,CAAC,MAAM,IAAI,GAAG;YAAE,MAAM;QAC/B,GAAG,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,EAAE,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACrC,CAAC;IAED,4EAA4E;IAC5E,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;AACtE,CAAC;AAED,iFAAiF;AAEjF,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,IAK7B;IACC,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACtB,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,GAAG,IAAI,EAAE,GAAG,IAAI,CAAC;IAEnE,kEAAkE;IAClE,MAAM,kBAAkB,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;IAClD,MAAM,qBAAqB,GAAG,YAAY,CAAC,WAAW,CAAC,CAAC;IAExD,IAAI,kBAAkB,KAAK,qBAAqB,EAAE,CAAC;QACjD,MAAM,MAAM,GAAwB;YAClC,IAAI,EAAE,IAAI;YACV,OAAO,EAAE,kEAAkE;YAC3E,QAAQ,EAAE,kBAAkB;YAC5B,WAAW,EAAE,qBAAqB;YAClC,aAAa,EAAE,EAAE;YACjB,iBAAiB,EAAE,CAAC;YACpB,SAAS,EAAE,EAAE;YACb,oBAAoB,EAAE,KAAK;YAC3B,cAAc,EAAE,CAAC;YACjB,KAAK,EAAE,SAAS,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC;SAChD,CAAC;QACF,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IAChF,CAAC;IAED,MAAM,EAAE,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;IAEhC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,OAAO,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;QACjC,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;4BACnB,KAAK,EAAE,SAAS,MAAM,sCAAsC;yBAC7D,CAAC;qBACH;iBACF;gBACD,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;QAED,6EAA6E;QAE7E,MAAM,aAAa,GAAG,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,kBAAkB,CAAC,CAAC;QAErE,6EAA6E;QAE7E,MAAM,aAAa,GAAmB,EAAE,CAAC;QAEzC,KAAK,MAAM,gBAAgB,IAAI,aAAa,EAAE,CAAC;YAC7C,MAAM,SAAS,GAAG,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,gBAAgB,EAAE,kBAAkB,CAAC,CAAC;YACjF,IAAI,CAAC,SAAS;gBAAE,SAAS,CAAC,gCAAgC;YAE1D,MAAM,aAAa,GAAG,oBAAoB,CACxC,gBAAgB,EAChB,qBAAqB,EACrB,SAAS,CACV,CAAC;YAEF,MAAM,OAAO,GAAG,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,gBAAgB,CAAC,CAAC;YAC7D,MAAM,IAAI,GAAG,cAAc,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;YAEhD,aAAa,CAAC,IAAI,CAAC;gBACjB,gBAAgB;gBAChB,iBAAiB,EAAE,SAAS;gBAC5B,aAAa;gBACb,IAAI;aACL,CAAC,CAAC;QACL,CAAC;QAED,iDAAiD;QACjD,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,gBAAgB,CAAC,aAAa,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC;QAEnF,6EAA6E;QAE7E,IAAI,SAAS,GAAe,EAAE,CAAC;QAE/B,IAAI,WAAW,EAAE,CAAC;YAChB,MAAM,QAAQ,GAAG,cAAc,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;YAC5C,SAAS,GAAG,qBAAqB,CAAC,QAAQ,EAAE,kBAAkB,EAAE,qBAAqB,CAAC,CAAC;QACzF,CAAC;QAED,MAAM,oBAAoB,GAAG,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC;QAElD,6EAA6E;QAE7E,MAAM,IAAI,GAAG,CAAC,oBAAoB,CAAC;QAEnC,IAAI,OAAe,CAAC;QACpB,IAAI,IAAI,EAAE,CAAC;YACT,MAAM,KAAK,GAAG,aAAa,CAAC,MAAM,CAAC;YACnC,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;gBAChB,OAAO,GAAG,uEAAuE,CAAC;YACpF,CAAC;iBAAM,CAAC;gBACN,OAAO;oBACL,iBAAiB,KAAK,oBAAoB,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,6BAA6B;wBAC7F,GAAG,IAAI,GAAG,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,IAAI,QAAQ,aAAa,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,cAAc,CAAC;YAC7H,CAAC;QACH,CAAC;aAAM,CAAC;YACN,OAAO;gBACL,mBAAmB,SAAS,CAAC,MAAM,gBAAgB,SAAS,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,wBAAwB;oBAC5G,GAAG,aAAa,CAAC,MAAM,oBAAoB,aAAa,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,sBAAsB,CAAC;QAC3G,CAAC;QAED,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,aAAa,EAAE,SAAS,EAAE,CAAC,CAAC;QAClE,MAAM,MAAM,GAAwB;YAClC,IAAI;YACJ,OAAO;YACP,QAAQ,EAAE,kBAAkB;YAC5B,WAAW,EAAE,qBAAqB;YAClC,aAAa;YACb,iBAAiB,EAAE,aAAa,CAAC,MAAM;YACvC,SAAS;YACT,oBAAoB;YACpB,cAAc,EAAE,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC;YAClD,KAAK,EAAE,SAAS,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC;SAChD,CAAC;QAEF,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IAChF,CAAC;YAAS,CAAC;QACT,EAAE,CAAC,KAAK,EAAE,CAAC;IACb,CAAC;AACH,CAAC"}
|