@monoes/monograph 1.2.4 → 1.2.6
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/dist/src/pipeline/orchestrator.d.ts.map +1 -1
- package/dist/src/pipeline/orchestrator.js +29 -0
- package/dist/src/pipeline/orchestrator.js.map +1 -1
- package/dist/src/pipeline/phases/communities.d.ts.map +1 -1
- package/dist/src/pipeline/phases/communities.js +18 -1
- package/dist/src/pipeline/phases/communities.js.map +1 -1
- package/dist/src/pipeline/phases/tools.d.ts.map +1 -1
- package/dist/src/pipeline/phases/tools.js +14 -5
- package/dist/src/pipeline/phases/tools.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -2
- package/src/pipeline/orchestrator.ts +32 -0
- package/src/pipeline/phases/communities.ts +21 -1
- package/src/pipeline/phases/tools.ts +14 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@monoes/monograph",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.6",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Native TypeScript code intelligence engine for monomind",
|
|
6
6
|
"main": "dist/src/index.js",
|
|
@@ -46,7 +46,6 @@
|
|
|
46
46
|
"tree-sitter-vue": "^0.2.1"
|
|
47
47
|
},
|
|
48
48
|
"optionalDependencies": {
|
|
49
|
-
"@anthropic-ai/sdk": "^0.39.0",
|
|
50
49
|
"@huggingface/transformers": "^3.1.0"
|
|
51
50
|
},
|
|
52
51
|
"devDependencies": {
|
|
@@ -85,6 +85,38 @@ export async function buildAsync(repoPath: string, options: BuildOptions = {}):
|
|
|
85
85
|
|
|
86
86
|
const outputs = await runner.run(ctx);
|
|
87
87
|
|
|
88
|
+
// Every full build reuses the same DB in place (no truncate-on-open), and no
|
|
89
|
+
// phase ever deletes nodes for files that were renamed/deleted since the last
|
|
90
|
+
// build. Left unchecked, orphaned rows (and their FTS/edge fallout) accumulate
|
|
91
|
+
// forever across repeated rebuilds. Sweep them here, once, after scan knows the
|
|
92
|
+
// authoritative current file set.
|
|
93
|
+
const scanOut = outputs.get('scan') as { filePaths: string[] } | undefined;
|
|
94
|
+
if (scanOut) {
|
|
95
|
+
const liveFiles = new Set(scanOut.filePaths.map((f) => resolve(f)));
|
|
96
|
+
const staleFiles = (
|
|
97
|
+
db.prepare('SELECT DISTINCT file_path FROM nodes WHERE file_path IS NOT NULL').all() as { file_path: string }[]
|
|
98
|
+
)
|
|
99
|
+
.map((r) => r.file_path)
|
|
100
|
+
.filter((f) => !liveFiles.has(resolve(f)));
|
|
101
|
+
if (staleFiles.length > 0) {
|
|
102
|
+
const deleteStale = db.transaction((files: string[]) => {
|
|
103
|
+
// Edges FK-reference nodes with no ON DELETE CASCADE, and a stale node
|
|
104
|
+
// can be referenced from either side (another file's export pointing at
|
|
105
|
+
// it, or it importing another file) — clear both directions first.
|
|
106
|
+
const deleteEdges = db.prepare(`
|
|
107
|
+
DELETE FROM edges WHERE source_id IN (SELECT id FROM nodes WHERE file_path = ?)
|
|
108
|
+
OR target_id IN (SELECT id FROM nodes WHERE file_path = ?)
|
|
109
|
+
`);
|
|
110
|
+
const deleteNodesStmt = db.prepare('DELETE FROM nodes WHERE file_path = ?');
|
|
111
|
+
for (const f of files) {
|
|
112
|
+
deleteEdges.run(f, f);
|
|
113
|
+
deleteNodesStmt.run(f);
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
deleteStale(staleFiles);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
88
120
|
const hash = getCurrentCommitHash(resolve(repoPath));
|
|
89
121
|
if (hash) {
|
|
90
122
|
db.prepare("INSERT OR REPLACE INTO index_meta VALUES ('last_commit_hash', ?)").run(hash);
|
|
@@ -107,7 +107,7 @@ export function computeAllCohesionScores(
|
|
|
107
107
|
export const communitiesPhase: PipelinePhase<CommunitiesOutput> = {
|
|
108
108
|
name: 'communities',
|
|
109
109
|
deps: ['parse', 'cross-file', 'mro'],
|
|
110
|
-
async execute(
|
|
110
|
+
async execute(ctx, deps) {
|
|
111
111
|
const { resolvedEdges } = deps.get('cross-file') as CrossFileOutput;
|
|
112
112
|
const { allEdges } = deps.get('parse') as ParseOutput;
|
|
113
113
|
const allUsedEdges: MonographEdge[] = [...allEdges, ...resolvedEdges];
|
|
@@ -142,6 +142,26 @@ export const communitiesPhase: PipelinePhase<CommunitiesOutput> = {
|
|
|
142
142
|
// Compute all cohesion scores in one O(N+E) pass instead of O(K*(N+E))
|
|
143
143
|
const cohesionScores = computeAllCohesionScores(memberships, allUsedEdges);
|
|
144
144
|
|
|
145
|
+
// Persist community assignments to the DB
|
|
146
|
+
if (memberships.size > 0) {
|
|
147
|
+
const commSizes = new Map<number, number>();
|
|
148
|
+
for (const commId of memberships.values()) {
|
|
149
|
+
commSizes.set(commId, (commSizes.get(commId) ?? 0) + 1);
|
|
150
|
+
}
|
|
151
|
+
const updateNode = ctx.db.prepare('UPDATE nodes SET community_id = ? WHERE id = ?');
|
|
152
|
+
const upsertComm = ctx.db.prepare(
|
|
153
|
+
'INSERT OR REPLACE INTO communities (id, label, size, cohesion_score) VALUES (?, ?, ?, ?)',
|
|
154
|
+
);
|
|
155
|
+
ctx.db.transaction(() => {
|
|
156
|
+
for (const [nodeId, commId] of memberships) {
|
|
157
|
+
updateNode.run(commId, nodeId);
|
|
158
|
+
}
|
|
159
|
+
for (const [commId, label] of communityLabels) {
|
|
160
|
+
upsertComm.run(commId, label, commSizes.get(commId) ?? 0, cohesionScores.get(commId) ?? 0);
|
|
161
|
+
}
|
|
162
|
+
})();
|
|
163
|
+
}
|
|
164
|
+
|
|
145
165
|
return { memberships, communityLabels, cohesionScores };
|
|
146
166
|
},
|
|
147
167
|
};
|
|
@@ -124,17 +124,26 @@ export const toolsPhase: PipelinePhase<ToolsOutput> = {
|
|
|
124
124
|
return n.includes(lowerTool) || (n.length > 0 && lowerTool.includes(n));
|
|
125
125
|
});
|
|
126
126
|
|
|
127
|
-
if (matches.length
|
|
128
|
-
|
|
127
|
+
if (matches.length >= 1) {
|
|
128
|
+
// Pick best match: exact name > name contains tool > tool contains name
|
|
129
|
+
const scored = matches
|
|
130
|
+
.map(row => {
|
|
131
|
+
const n = row.name.toLowerCase().replace(/[_-]/g, '');
|
|
132
|
+
const score = n === lowerTool ? 3 : n.includes(lowerTool) ? 2 : 1;
|
|
133
|
+
return { row, score };
|
|
134
|
+
})
|
|
135
|
+
.sort((a, b) => b.score - a.score);
|
|
136
|
+
const { row: best, score } = scored[0];
|
|
137
|
+
const edgeId = makeId(toolNodeId, best.id, 'handles_tool');
|
|
129
138
|
handlesEdges.push({
|
|
130
139
|
id: edgeId,
|
|
131
140
|
sourceId: toolNodeId,
|
|
132
|
-
targetId:
|
|
141
|
+
targetId: best.id,
|
|
133
142
|
relation: 'HANDLES_TOOL',
|
|
134
143
|
confidence: 'EXTRACTED',
|
|
135
|
-
confidenceScore: 0.
|
|
144
|
+
confidenceScore: score === 3 ? 0.95 : 0.75,
|
|
136
145
|
});
|
|
137
|
-
def.handlerNodeId =
|
|
146
|
+
def.handlerNodeId = best.id;
|
|
138
147
|
}
|
|
139
148
|
}
|
|
140
149
|
|