ultracode 5.3.0 → 5.5.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/dist/chunks/analysis-tool-handlers-H2RXLDPX.js +817 -0
- package/dist/chunks/analysis-tool-handlers-RJZAR6VT.js +817 -0
- package/dist/chunks/analysis-tool-handlers-Z2RF24T7.js +13 -0
- package/dist/chunks/autodoc-tool-handlers-CV5JEQUA.js +1112 -0
- package/dist/chunks/autodoc-tool-handlers-EHTNCH6I.js +1112 -0
- package/dist/chunks/autodoc-tool-handlers-MECXQJ2K.js +138 -0
- package/dist/chunks/chaos-CO7TOBOJ.js +18 -0
- package/dist/chunks/chaos-VM2PXERO.js +1573 -0
- package/dist/chunks/chaos-W3XRVJ7K.js +1564 -0
- package/dist/chunks/chunk-6K37BWK5.js +439 -0
- package/dist/chunks/chunk-EALTCYHZ.js +10 -0
- package/dist/chunks/chunk-FTBE7VMY.js +316 -0
- package/dist/chunks/chunk-KBW6LRQP.js +322 -0
- package/dist/chunks/chunk-NKUHX4CU.js +5 -0
- package/dist/chunks/chunk-NZFF4DQ4.js +3179 -0
- package/dist/chunks/chunk-RGP5UVQ7.js +3179 -0
- package/dist/chunks/chunk-RMZXFGQZ.js +322 -0
- package/dist/chunks/chunk-UG44F23Y.js +316 -0
- package/dist/chunks/chunk-V2SCB5H5.js +4403 -0
- package/dist/chunks/chunk-V6JAQNM3.js +1 -0
- package/dist/chunks/chunk-XFGXM4CR.js +4403 -0
- package/dist/chunks/dev-agent-JVIGBMHQ.js +1 -0
- package/dist/chunks/dev-agent-TRVP5U6N.js +1624 -0
- package/dist/chunks/dev-agent-Y5G5WKQ4.js +1624 -0
- package/dist/chunks/graph-storage-factory-AYZ57YSL.js +13 -0
- package/dist/chunks/graph-storage-factory-GTAIJEI5.js +1 -0
- package/dist/chunks/graph-storage-factory-T2WO5QVG.js +13 -0
- package/dist/chunks/incremental-updater-KDIQGAUU.js +14 -0
- package/dist/chunks/incremental-updater-OJRSTO3Q.js +1 -0
- package/dist/chunks/incremental-updater-SBEBH7KF.js +14 -0
- package/dist/chunks/indexer-agent-H3QIEL3Z.js +21 -0
- package/dist/chunks/indexer-agent-KHF5JMV7.js +21 -0
- package/dist/chunks/indexer-agent-SHJD6Z77.js +1 -0
- package/dist/chunks/indexing-pipeline-J6Z4BHKF.js +1 -0
- package/dist/chunks/indexing-pipeline-OY3337QN.js +249 -0
- package/dist/chunks/indexing-pipeline-WCXIDMAP.js +249 -0
- package/dist/chunks/merge-agent-LSUBDJB2.js +2481 -0
- package/dist/chunks/merge-agent-MJEW3HWU.js +2481 -0
- package/dist/chunks/merge-agent-O45OXF33.js +11 -0
- package/dist/chunks/merge-tool-handlers-BDSVNQVZ.js +277 -0
- package/dist/chunks/merge-tool-handlers-HP7DRBXJ.js +1 -0
- package/dist/chunks/merge-tool-handlers-RUJAKE3D.js +277 -0
- package/dist/chunks/pattern-tool-handlers-L62W3CXR.js +1549 -0
- package/dist/chunks/pattern-tool-handlers-SAHX2CVW.js +13 -0
- package/dist/chunks/query-agent-3TWDFIMT.js +191 -0
- package/dist/chunks/query-agent-HXQ3BMMF.js +191 -0
- package/dist/chunks/query-agent-USMC2GNG.js +1 -0
- package/dist/chunks/semantic-agent-MQCAWIAB.js +6381 -0
- package/dist/chunks/semantic-agent-NDGR3NAK.js +6381 -0
- package/dist/chunks/semantic-agent-S4ZL6GZC.js +137 -0
- package/dist/index.js +17 -17
- package/dist/roslyn-addon/.build-hash +1 -1
- package/dist/roslyn-addon/ILGPU.Algorithms.dll +0 -0
- package/dist/roslyn-addon/ILGPU.dll +0 -0
- package/dist/roslyn-addon/UltraCode.CSharp.deps.json +35 -0
- package/dist/roslyn-addon/UltraCode.CSharp.dll +0 -0
- package/package.json +1 -1
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
import { getGraphStorage } from './chunk-V2SCB5H5.js';
|
|
2
|
+
import { existsSync, readFileSync, writeFileSync } from 'fs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
|
|
5
|
+
function extractReferences(content) {
|
|
6
|
+
const refs = [];
|
|
7
|
+
const fileLinePattern = /(?:`([^`]+\.(?:ts|js|tsx|jsx|py|go|rs|java|kt|swift|cpp|c|h)):(\d+)`|([a-zA-Z0-9_\-/.]+\.(?:ts|js|tsx|jsx|py|go|rs|java|kt|swift|cpp|c|h)):(\d+))/g;
|
|
8
|
+
let match;
|
|
9
|
+
while ((match = fileLinePattern.exec(content)) !== null) {
|
|
10
|
+
const filePath = match[1] || match[3];
|
|
11
|
+
const lineNum = match[2] || match[4];
|
|
12
|
+
if (filePath && lineNum) {
|
|
13
|
+
refs.push({
|
|
14
|
+
original: match[0],
|
|
15
|
+
filePath,
|
|
16
|
+
lineNumber: parseInt(lineNum, 10),
|
|
17
|
+
startIndex: match.index,
|
|
18
|
+
endIndex: match.index + match[0].length
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
const mdLinkPattern = /\[([^\]]+)\]\(([^)]+\.(?:ts|js|tsx|jsx|py|go|rs|java|kt|swift|cpp|c|h))(?:#L(\d+))?\)/g;
|
|
23
|
+
while ((match = mdLinkPattern.exec(content)) !== null) {
|
|
24
|
+
const mdFilePath = match[2];
|
|
25
|
+
if (mdFilePath) {
|
|
26
|
+
refs.push({
|
|
27
|
+
original: match[0],
|
|
28
|
+
filePath: mdFilePath,
|
|
29
|
+
lineNumber: match[3] ? parseInt(match[3], 10) : void 0,
|
|
30
|
+
startIndex: match.index,
|
|
31
|
+
endIndex: match.index + match[0].length
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return refs;
|
|
36
|
+
}
|
|
37
|
+
function extractSections(content) {
|
|
38
|
+
const lines = content.split("\n");
|
|
39
|
+
const sections = [];
|
|
40
|
+
let currentSection = null;
|
|
41
|
+
let contentLines = [];
|
|
42
|
+
for (let i = 0; i < lines.length; i++) {
|
|
43
|
+
const line = lines[i] ?? "";
|
|
44
|
+
const headerMatch = line.match(/^(#{1,6})\s+(.+)$/);
|
|
45
|
+
if (headerMatch?.[2]) {
|
|
46
|
+
if (currentSection) {
|
|
47
|
+
currentSection.content = contentLines.join("\n");
|
|
48
|
+
currentSection.endLine = i - 1;
|
|
49
|
+
sections.push(currentSection);
|
|
50
|
+
}
|
|
51
|
+
currentSection = {
|
|
52
|
+
title: headerMatch[2],
|
|
53
|
+
content: "",
|
|
54
|
+
startLine: i,
|
|
55
|
+
endLine: i,
|
|
56
|
+
relatedEntities: []
|
|
57
|
+
};
|
|
58
|
+
contentLines = [];
|
|
59
|
+
} else if (currentSection) {
|
|
60
|
+
contentLines.push(line);
|
|
61
|
+
const entityRefs = line.match(/`([A-Z][a-zA-Z0-9_]+)`/g);
|
|
62
|
+
if (entityRefs) {
|
|
63
|
+
for (const ref of entityRefs) {
|
|
64
|
+
const name = ref.slice(1, -1);
|
|
65
|
+
if (!currentSection.relatedEntities.includes(name)) {
|
|
66
|
+
currentSection.relatedEntities.push(name);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
if (currentSection) {
|
|
73
|
+
currentSection.content = contentLines.join("\n");
|
|
74
|
+
currentSection.endLine = lines.length - 1;
|
|
75
|
+
sections.push(currentSection);
|
|
76
|
+
}
|
|
77
|
+
return sections;
|
|
78
|
+
}
|
|
79
|
+
async function detectChanges(modulePath, existingDoc, currentEntities) {
|
|
80
|
+
const changes = [];
|
|
81
|
+
const refs = extractReferences(existingDoc);
|
|
82
|
+
const sections = extractSections(existingDoc);
|
|
83
|
+
const documentedEntities = /* @__PURE__ */ new Set();
|
|
84
|
+
for (const section of sections) {
|
|
85
|
+
for (const entity of section.relatedEntities) {
|
|
86
|
+
documentedEntities.add(entity);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
const entityPattern = /`([A-Z][a-zA-Z0-9_]+)`/g;
|
|
90
|
+
let match;
|
|
91
|
+
while ((match = entityPattern.exec(existingDoc)) !== null) {
|
|
92
|
+
if (match[1]) {
|
|
93
|
+
documentedEntities.add(match[1]);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
for (const entity of currentEntities) {
|
|
97
|
+
if (!documentedEntities.has(entity.name)) {
|
|
98
|
+
changes.push({
|
|
99
|
+
type: "added",
|
|
100
|
+
entityId: entity.id,
|
|
101
|
+
entityName: entity.name,
|
|
102
|
+
entityType: entity.type,
|
|
103
|
+
filePath: entity.filePath,
|
|
104
|
+
newLineNumber: entity.location?.start?.line,
|
|
105
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
const currentEntityNames = new Set(currentEntities.map((e) => e.name));
|
|
110
|
+
for (const docEntity of documentedEntities) {
|
|
111
|
+
if (!currentEntityNames.has(docEntity)) {
|
|
112
|
+
changes.push({
|
|
113
|
+
type: "deleted",
|
|
114
|
+
entityName: docEntity,
|
|
115
|
+
entityType: "unknown",
|
|
116
|
+
filePath: modulePath,
|
|
117
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
for (const ref of refs) {
|
|
122
|
+
if (ref.lineNumber && ref.entityName) {
|
|
123
|
+
const entity = currentEntities.find((e) => e.name === ref.entityName);
|
|
124
|
+
if (entity && entity.location?.start?.line !== ref.lineNumber) {
|
|
125
|
+
changes.push({
|
|
126
|
+
type: "moved",
|
|
127
|
+
entityId: entity.id,
|
|
128
|
+
entityName: entity.name,
|
|
129
|
+
entityType: entity.type,
|
|
130
|
+
filePath: entity.filePath,
|
|
131
|
+
oldLineNumber: ref.lineNumber,
|
|
132
|
+
newLineNumber: entity.location?.start?.line,
|
|
133
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return changes;
|
|
139
|
+
}
|
|
140
|
+
function updateReferences(content, changes) {
|
|
141
|
+
let updated = content;
|
|
142
|
+
const lineUpdates = /* @__PURE__ */ new Map();
|
|
143
|
+
for (const change of changes) {
|
|
144
|
+
if (change.type === "moved" && change.oldLineNumber && change.newLineNumber) {
|
|
145
|
+
const key = `${change.filePath}:${change.oldLineNumber}`;
|
|
146
|
+
lineUpdates.set(key, { old: change.oldLineNumber, new: change.newLineNumber });
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
const fileLinePattern = /(`[^`]+\.(?:ts|js|tsx|jsx)):(\d+)`/g;
|
|
150
|
+
updated = updated.replace(fileLinePattern, (match, filePart, lineNum) => {
|
|
151
|
+
const line = parseInt(lineNum, 10);
|
|
152
|
+
for (const [key, update] of lineUpdates) {
|
|
153
|
+
if (key.endsWith(`:${line}`)) {
|
|
154
|
+
return `${filePart}:${update.new}\``;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return match;
|
|
158
|
+
});
|
|
159
|
+
const mdLinkPattern = /(\[[^\]]+\]\([^)]+\.(?:ts|js|tsx|jsx))#L(\d+)\)/g;
|
|
160
|
+
updated = updated.replace(mdLinkPattern, (match, linkPart, lineNum) => {
|
|
161
|
+
const line = parseInt(lineNum, 10);
|
|
162
|
+
for (const [key, update] of lineUpdates) {
|
|
163
|
+
if (key.endsWith(`:${line}`)) {
|
|
164
|
+
return `${linkPart}#L${update.new})`;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
return match;
|
|
168
|
+
});
|
|
169
|
+
return updated;
|
|
170
|
+
}
|
|
171
|
+
function mergeWithExisting(existingContent, newContent, changes) {
|
|
172
|
+
const existingSections = extractSections(existingContent);
|
|
173
|
+
const newSections = extractSections(newContent);
|
|
174
|
+
const result = [];
|
|
175
|
+
const processedNewSections = /* @__PURE__ */ new Set();
|
|
176
|
+
for (const existingSection of existingSections) {
|
|
177
|
+
const newSection = newSections.find((s) => s.title === existingSection.title);
|
|
178
|
+
if (newSection) {
|
|
179
|
+
processedNewSections.add(newSection.title);
|
|
180
|
+
const addedEntities = changes.filter((c) => c.type === "added").map((c) => c.entityName);
|
|
181
|
+
if (addedEntities.length > 0 && existingSection.title.toLowerCase().includes("export")) {
|
|
182
|
+
result.push(`## ${existingSection.title}`);
|
|
183
|
+
result.push(existingSection.content);
|
|
184
|
+
result.push("");
|
|
185
|
+
result.push("### Added");
|
|
186
|
+
result.push("");
|
|
187
|
+
for (const entity of addedEntities) {
|
|
188
|
+
result.push(`- \`${entity}\` *(added ${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]})*`);
|
|
189
|
+
}
|
|
190
|
+
result.push("");
|
|
191
|
+
} else {
|
|
192
|
+
result.push(`## ${existingSection.title}`);
|
|
193
|
+
result.push(existingSection.content);
|
|
194
|
+
}
|
|
195
|
+
} else {
|
|
196
|
+
result.push(`## ${existingSection.title}`);
|
|
197
|
+
result.push(existingSection.content);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
for (const newSection of newSections) {
|
|
201
|
+
if (!processedNewSections.has(newSection.title)) {
|
|
202
|
+
const existsInOriginal = existingSections.some((s) => s.title === newSection.title);
|
|
203
|
+
if (!existsInOriginal) {
|
|
204
|
+
result.push("");
|
|
205
|
+
result.push(`## ${newSection.title}`);
|
|
206
|
+
result.push(newSection.content);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
return result.join("\n");
|
|
211
|
+
}
|
|
212
|
+
function markDeleted(content, deletedEntities) {
|
|
213
|
+
if (deletedEntities.length === 0) return content;
|
|
214
|
+
let updated = content;
|
|
215
|
+
if (!updated.includes("## Deprecated") && !updated.includes("## Deleted")) {
|
|
216
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
217
|
+
const deletedSection = ["", "## Deleted", "", "*The following items were removed from the codebase:*", ""];
|
|
218
|
+
for (const deleted of deletedEntities) {
|
|
219
|
+
deletedSection.push(`- ~~\`${deleted.entityName}\`~~ *(removed ${timestamp})*`);
|
|
220
|
+
}
|
|
221
|
+
deletedSection.push("");
|
|
222
|
+
updated += deletedSection.join("\n");
|
|
223
|
+
} else {
|
|
224
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
225
|
+
const insertPoint = updated.indexOf("## Deleted");
|
|
226
|
+
if (insertPoint !== -1) {
|
|
227
|
+
const afterHeader = updated.indexOf("\n\n", insertPoint) + 2;
|
|
228
|
+
const newItems = deletedEntities.map((d) => `- ~~\`${d.entityName}\`~~ *(removed ${timestamp})*`).join("\n");
|
|
229
|
+
updated = updated.slice(0, afterHeader) + newItems + "\n" + updated.slice(afterHeader);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
for (const deleted of deletedEntities) {
|
|
233
|
+
const pattern = new RegExp(`\`${deleted.entityName}\`(?![^~]*~~)`, "g");
|
|
234
|
+
updated = updated.replace(pattern, `~~\`${deleted.entityName}\`~~`);
|
|
235
|
+
}
|
|
236
|
+
return updated;
|
|
237
|
+
}
|
|
238
|
+
async function updateModuleDoc(modulePath, docPath, newContent, options = {}) {
|
|
239
|
+
const result = {
|
|
240
|
+
docPath,
|
|
241
|
+
updated: false,
|
|
242
|
+
changes: []
|
|
243
|
+
};
|
|
244
|
+
const docExists = existsSync(docPath);
|
|
245
|
+
if (!docExists) {
|
|
246
|
+
result.updated = true;
|
|
247
|
+
result.newContent = newContent;
|
|
248
|
+
result.changes.push({
|
|
249
|
+
type: "created_new",
|
|
250
|
+
description: "Created new documentation file"
|
|
251
|
+
});
|
|
252
|
+
return result;
|
|
253
|
+
}
|
|
254
|
+
const existingContent = readFileSync(docPath, "utf-8");
|
|
255
|
+
const storage = await getGraphStorage();
|
|
256
|
+
const currentEntities = await storage.searchEntitiesInDirectory(modulePath);
|
|
257
|
+
const changes = await detectChanges(modulePath, existingContent, currentEntities);
|
|
258
|
+
if (changes.length === 0) {
|
|
259
|
+
return result;
|
|
260
|
+
}
|
|
261
|
+
let updatedContent = existingContent;
|
|
262
|
+
const movedChanges = changes.filter((c) => c.type === "moved");
|
|
263
|
+
if (movedChanges.length > 0) {
|
|
264
|
+
updatedContent = updateReferences(updatedContent, movedChanges);
|
|
265
|
+
result.changes.push({
|
|
266
|
+
type: "reference_updated",
|
|
267
|
+
description: `Updated ${movedChanges.length} line/file references`
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
const addedChanges = changes.filter((c) => c.type === "added");
|
|
271
|
+
if (addedChanges.length > 0) {
|
|
272
|
+
updatedContent = mergeWithExisting(updatedContent, newContent, addedChanges);
|
|
273
|
+
result.changes.push({
|
|
274
|
+
type: "content_added",
|
|
275
|
+
description: `Added documentation for ${addedChanges.length} new entities: ${addedChanges.map((c) => c.entityName).join(", ")}`
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
const deletedChanges = changes.filter((c) => c.type === "deleted");
|
|
279
|
+
if (deletedChanges.length > 0) {
|
|
280
|
+
updatedContent = markDeleted(updatedContent, deletedChanges);
|
|
281
|
+
result.changes.push({
|
|
282
|
+
type: "content_marked_deleted",
|
|
283
|
+
description: `Marked ${deletedChanges.length} deleted entities: ${deletedChanges.map((c) => c.entityName).join(", ")}`
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
if (options.useLlm && options.llmEnhancer && addedChanges.length > 0) {
|
|
287
|
+
updatedContent = await options.llmEnhancer(updatedContent, addedChanges);
|
|
288
|
+
}
|
|
289
|
+
if (updatedContent !== existingContent) {
|
|
290
|
+
result.updated = true;
|
|
291
|
+
result.newContent = updatedContent;
|
|
292
|
+
}
|
|
293
|
+
return result;
|
|
294
|
+
}
|
|
295
|
+
async function updateAllModuleDocs(rootDir, options = {}) {
|
|
296
|
+
const results = [];
|
|
297
|
+
const { scanModules, generateModuleReadme } = await import('./doc-generator-RMUSNK3G.js');
|
|
298
|
+
const modules = await scanModules(rootDir);
|
|
299
|
+
for (const mod of modules) {
|
|
300
|
+
const docPath = path.join(mod.path, "AUTODOC.md");
|
|
301
|
+
const newContent = generateModuleReadme(mod);
|
|
302
|
+
const result = await updateModuleDoc(mod.path, docPath, newContent, {
|
|
303
|
+
useLlm: options.useLlm,
|
|
304
|
+
llmEnhancer: options.llmEnhancer
|
|
305
|
+
});
|
|
306
|
+
if (result.updated && !options.preview && result.newContent) {
|
|
307
|
+
writeFileSync(docPath, result.newContent, "utf-8");
|
|
308
|
+
}
|
|
309
|
+
results.push(result);
|
|
310
|
+
}
|
|
311
|
+
return results;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
export { detectChanges, extractReferences, extractSections, markDeleted, mergeWithExisting, updateAllModuleDocs, updateModuleDoc, updateReferences };
|
|
315
|
+
//# sourceMappingURL=chunk-FTBE7VMY.js.map
|
|
316
|
+
//# sourceMappingURL=chunk-FTBE7VMY.js.map
|
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
import { init_logging, log } from './chunk-VCCBEJQ5.js';
|
|
2
|
+
|
|
3
|
+
// src/core/di-container.ts
|
|
4
|
+
init_logging();
|
|
5
|
+
var DIContainer = class _DIContainer {
|
|
6
|
+
services = /* @__PURE__ */ new Map();
|
|
7
|
+
resolutionStack = /* @__PURE__ */ new Set();
|
|
8
|
+
disposed = false;
|
|
9
|
+
constructor() {
|
|
10
|
+
this.registerInstance("DIContainer", this);
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Register a service with factory function
|
|
14
|
+
*/
|
|
15
|
+
register(name, factory, lifetime = "singleton" /* SINGLETON */, dependencies = []) {
|
|
16
|
+
this.ensureNotDisposed();
|
|
17
|
+
if (this.services.has(name)) {
|
|
18
|
+
throw new Error(`Service '${name}' is already registered`);
|
|
19
|
+
}
|
|
20
|
+
const descriptor = {
|
|
21
|
+
name,
|
|
22
|
+
factory,
|
|
23
|
+
lifetime,
|
|
24
|
+
dependencies
|
|
25
|
+
};
|
|
26
|
+
this.services.set(name, descriptor);
|
|
27
|
+
log.i("DICONTAINER", "svc_registered", { name, lifetime });
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Register a singleton service (convenience method)
|
|
31
|
+
*/
|
|
32
|
+
registerSingleton(name, factory, dependencies = []) {
|
|
33
|
+
this.register(name, factory, "singleton" /* SINGLETON */, dependencies);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Register a transient service (convenience method)
|
|
37
|
+
*/
|
|
38
|
+
registerTransient(name, factory, dependencies = []) {
|
|
39
|
+
this.register(name, factory, "transient" /* TRANSIENT */, dependencies);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Register an existing instance as singleton
|
|
43
|
+
*/
|
|
44
|
+
registerInstance(name, instance) {
|
|
45
|
+
this.ensureNotDisposed();
|
|
46
|
+
if (this.services.has(name)) {
|
|
47
|
+
throw new Error(`Service '${name}' is already registered`);
|
|
48
|
+
}
|
|
49
|
+
const descriptor = {
|
|
50
|
+
name,
|
|
51
|
+
factory: () => instance,
|
|
52
|
+
lifetime: "singleton" /* SINGLETON */,
|
|
53
|
+
instance
|
|
54
|
+
};
|
|
55
|
+
this.services.set(name, descriptor);
|
|
56
|
+
log.i("DICONTAINER", "inst_registered", { name });
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Update an existing singleton instance (useful for project context switches)
|
|
60
|
+
*/
|
|
61
|
+
updateInstance(name, instance) {
|
|
62
|
+
this.ensureNotDisposed();
|
|
63
|
+
const descriptor = this.services.get(name);
|
|
64
|
+
if (!descriptor) {
|
|
65
|
+
this.registerInstance(name, instance);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
if (descriptor.lifetime !== "singleton" /* SINGLETON */) {
|
|
69
|
+
throw new Error(`Cannot update non-singleton service '${name}'`);
|
|
70
|
+
}
|
|
71
|
+
descriptor.instance = instance;
|
|
72
|
+
descriptor.factory = () => instance;
|
|
73
|
+
log.i("DICONTAINER", "inst_updated", { name });
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Register an agent factory
|
|
77
|
+
*/
|
|
78
|
+
registerAgent(agentType, factory, dependencies = []) {
|
|
79
|
+
const serviceName = `Agent:${agentType}`;
|
|
80
|
+
this.register(serviceName, factory, "singleton" /* SINGLETON */, dependencies);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Resolve a service by name with circular dependency detection
|
|
84
|
+
*/
|
|
85
|
+
async resolve(name) {
|
|
86
|
+
this.ensureNotDisposed();
|
|
87
|
+
const descriptor = this.services.get(name);
|
|
88
|
+
if (!descriptor) {
|
|
89
|
+
throw new Error(`Service '${name}' is not registered`);
|
|
90
|
+
}
|
|
91
|
+
if (this.resolutionStack.has(name)) {
|
|
92
|
+
const cycle = Array.from(this.resolutionStack).join(" -> ");
|
|
93
|
+
throw new Error(`Circular dependency detected: ${cycle} -> ${name}`);
|
|
94
|
+
}
|
|
95
|
+
if (descriptor.lifetime === "singleton" /* SINGLETON */ && descriptor.instance !== void 0) {
|
|
96
|
+
return descriptor.instance;
|
|
97
|
+
}
|
|
98
|
+
this.resolutionStack.add(name);
|
|
99
|
+
try {
|
|
100
|
+
const instance = await descriptor.factory(this);
|
|
101
|
+
if (descriptor.lifetime === "singleton" /* SINGLETON */) {
|
|
102
|
+
descriptor.instance = instance;
|
|
103
|
+
}
|
|
104
|
+
return instance;
|
|
105
|
+
} finally {
|
|
106
|
+
this.resolutionStack.delete(name);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Resolve an agent by type
|
|
111
|
+
*/
|
|
112
|
+
async resolveAgent(agentType) {
|
|
113
|
+
const serviceName = `Agent:${agentType}`;
|
|
114
|
+
return this.resolve(serviceName);
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Check if service is registered
|
|
118
|
+
*/
|
|
119
|
+
has(name) {
|
|
120
|
+
return this.services.has(name);
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Check if agent is registered
|
|
124
|
+
*/
|
|
125
|
+
hasAgent(agentType) {
|
|
126
|
+
return this.has(`Agent:${agentType}`);
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Get all registered service names
|
|
130
|
+
*/
|
|
131
|
+
getServiceNames() {
|
|
132
|
+
return Array.from(this.services.keys());
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Get all registered agent types
|
|
136
|
+
*/
|
|
137
|
+
getAgentTypes() {
|
|
138
|
+
const agentTypes = [];
|
|
139
|
+
for (const name of this.services.keys()) {
|
|
140
|
+
if (name.startsWith("Agent:")) {
|
|
141
|
+
agentTypes.push(name.slice(6));
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return agentTypes;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Get dependency graph for a service
|
|
148
|
+
*/
|
|
149
|
+
getDependencyGraph(name) {
|
|
150
|
+
const descriptor = this.services.get(name);
|
|
151
|
+
if (!descriptor) {
|
|
152
|
+
return [];
|
|
153
|
+
}
|
|
154
|
+
return descriptor.dependencies || [];
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Clear all transient instances (keep singletons)
|
|
158
|
+
*/
|
|
159
|
+
clearTransients() {
|
|
160
|
+
for (const descriptor of this.services.values()) {
|
|
161
|
+
if (descriptor.lifetime === "transient" /* TRANSIENT */) {
|
|
162
|
+
delete descriptor.instance;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
log.i("DICONTAINER", "transients_cleared");
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Clear cached agent instances (to force recreation with new context)
|
|
169
|
+
* Used when project context switches and agents need new SQLiteManager
|
|
170
|
+
*/
|
|
171
|
+
clearAgentInstances() {
|
|
172
|
+
let cleared = 0;
|
|
173
|
+
for (const [name, descriptor] of this.services) {
|
|
174
|
+
if (name.startsWith("Agent:") && descriptor.instance !== void 0) {
|
|
175
|
+
delete descriptor.instance;
|
|
176
|
+
cleared++;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
log.i("DICONTAINER", "agents_cleared", { count: cleared });
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Clear all registrations (useful for testing)
|
|
183
|
+
*/
|
|
184
|
+
clear() {
|
|
185
|
+
this.services.clear();
|
|
186
|
+
this.resolutionStack.clear();
|
|
187
|
+
this.disposed = false;
|
|
188
|
+
log.i("DICONTAINER", "container_cleared");
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Dispose all services and clear container
|
|
192
|
+
*/
|
|
193
|
+
async dispose() {
|
|
194
|
+
if (this.disposed) {
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
log.i("DICONTAINER", "disposing");
|
|
198
|
+
this.disposed = true;
|
|
199
|
+
const descriptors = Array.from(this.services.values()).reverse();
|
|
200
|
+
for (const descriptor of descriptors) {
|
|
201
|
+
if (descriptor.instance && this.isDisposable(descriptor.instance)) {
|
|
202
|
+
try {
|
|
203
|
+
await descriptor.instance.dispose();
|
|
204
|
+
log.i("DICONTAINER", "disposed_svc", { name: descriptor.name });
|
|
205
|
+
} catch (error) {
|
|
206
|
+
log.w("DICONTAINER", "dispose_fail", { name: descriptor.name, err: String(error) });
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
this.services.clear();
|
|
211
|
+
this.resolutionStack.clear();
|
|
212
|
+
log.i("DICONTAINER", "disposed");
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Check if object implements Disposable interface
|
|
216
|
+
*/
|
|
217
|
+
isDisposable(obj) {
|
|
218
|
+
return obj !== null && typeof obj === "object" && "dispose" in obj && typeof obj.dispose === "function";
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Ensure container is not disposed
|
|
222
|
+
*/
|
|
223
|
+
ensureNotDisposed() {
|
|
224
|
+
if (this.disposed) {
|
|
225
|
+
throw new Error("DIContainer has been disposed");
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Create a child container (scoped)
|
|
230
|
+
*/
|
|
231
|
+
createScope() {
|
|
232
|
+
const scope = new _DIContainer();
|
|
233
|
+
for (const [name, descriptor] of this.services) {
|
|
234
|
+
if (descriptor.lifetime === "singleton" /* SINGLETON */) {
|
|
235
|
+
scope.services.set(name, { ...descriptor, instance: void 0 });
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
return scope;
|
|
239
|
+
}
|
|
240
|
+
};
|
|
241
|
+
var globalContainer = null;
|
|
242
|
+
function getGlobalContainer() {
|
|
243
|
+
if (!globalContainer) {
|
|
244
|
+
globalContainer = new DIContainer();
|
|
245
|
+
}
|
|
246
|
+
return globalContainer;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// src/core/agent-registry.ts
|
|
250
|
+
init_logging();
|
|
251
|
+
async function registerAllAgents(container) {
|
|
252
|
+
log.i("AGENTREG", "registering_all");
|
|
253
|
+
container.registerAgent("dev" /* DEV */, async (_c) => {
|
|
254
|
+
const { DevAgent } = await import('./dev-agent-TRVP5U6N.js');
|
|
255
|
+
return new DevAgent();
|
|
256
|
+
});
|
|
257
|
+
container.registerAgent("semantic" /* SEMANTIC */, async (_c) => {
|
|
258
|
+
const { SemanticAgent } = await import('./semantic-agent-MQCAWIAB.js');
|
|
259
|
+
return new SemanticAgent();
|
|
260
|
+
});
|
|
261
|
+
container.registerAgent("dora" /* DORA */, async (_c) => {
|
|
262
|
+
const { DoraAgent } = await import('./dora-agent-NNYRSIBQ.js');
|
|
263
|
+
return new DoraAgent();
|
|
264
|
+
});
|
|
265
|
+
container.registerAgent("parser" /* PARSER */, async (_c) => {
|
|
266
|
+
const { ParserAgent } = await import('./parser-agent-FCJ2YDLD.js');
|
|
267
|
+
return new ParserAgent();
|
|
268
|
+
});
|
|
269
|
+
container.registerAgent("indexer" /* INDEXER */, async (_c) => {
|
|
270
|
+
const { IndexerAgent } = await import('./indexer-agent-H3QIEL3Z.js');
|
|
271
|
+
const agent = new IndexerAgent();
|
|
272
|
+
await agent.initialize();
|
|
273
|
+
return agent;
|
|
274
|
+
});
|
|
275
|
+
container.registerAgent("query" /* QUERY */, async (_c) => {
|
|
276
|
+
const { QueryAgent } = await import('./query-agent-3TWDFIMT.js');
|
|
277
|
+
return new QueryAgent();
|
|
278
|
+
});
|
|
279
|
+
container.registerAgent("merge" /* MERGE */, async (_c) => {
|
|
280
|
+
const { MergeAgent } = await import('./merge-agent-MJEW3HWU.js');
|
|
281
|
+
let repoPath = process.cwd();
|
|
282
|
+
let branchManager;
|
|
283
|
+
try {
|
|
284
|
+
const config = await _c.resolve("Config");
|
|
285
|
+
if (config?.directory) {
|
|
286
|
+
repoPath = config.directory;
|
|
287
|
+
}
|
|
288
|
+
} catch {
|
|
289
|
+
}
|
|
290
|
+
try {
|
|
291
|
+
branchManager = await _c.resolve("BranchManager");
|
|
292
|
+
} catch {
|
|
293
|
+
}
|
|
294
|
+
return new MergeAgent({
|
|
295
|
+
repoPath,
|
|
296
|
+
fastPathEnabled: true,
|
|
297
|
+
semanticMatchingEnabled: true,
|
|
298
|
+
semanticThreshold: 0.7,
|
|
299
|
+
autoResolveConflicts: false,
|
|
300
|
+
branchManager
|
|
301
|
+
});
|
|
302
|
+
});
|
|
303
|
+
log.i("AGENTREG", "all_registered");
|
|
304
|
+
}
|
|
305
|
+
async function getOrCreateAgent(container, conductor, agentType) {
|
|
306
|
+
const existing = conductor.getAgentsByType(agentType);
|
|
307
|
+
if (existing.length > 0) {
|
|
308
|
+
return existing[0];
|
|
309
|
+
}
|
|
310
|
+
if (!container.hasAgent(agentType)) {
|
|
311
|
+
throw new Error(`Agent ${agentType} is not registered in DI container`);
|
|
312
|
+
}
|
|
313
|
+
const agent = await container.resolveAgent(agentType);
|
|
314
|
+
await agent.initialize();
|
|
315
|
+
log.i("AGENTREG", "agent_init", { type: agentType });
|
|
316
|
+
conductor.register(agent);
|
|
317
|
+
return agent;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
export { getGlobalContainer, getOrCreateAgent, registerAllAgents };
|
|
321
|
+
//# sourceMappingURL=chunk-KBW6LRQP.js.map
|
|
322
|
+
//# sourceMappingURL=chunk-KBW6LRQP.js.map
|