@grec0/memory-bank-mcp 0.1.7 → 0.1.8
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.
|
@@ -302,7 +302,7 @@ export class IndexManager {
|
|
|
302
302
|
// Get all chunks for the project
|
|
303
303
|
const allChunks = await this.vectorStore.getAllChunks(projectId);
|
|
304
304
|
// Update docs incrementally based on changed files
|
|
305
|
-
docsGeneration = await this.projectKnowledgeService.updateDocuments(allChunks, changedFiles);
|
|
305
|
+
docsGeneration = await this.projectKnowledgeService.updateDocuments(projectId, allChunks, changedFiles);
|
|
306
306
|
console.error(`Docs updated: ${docsGeneration.documentsUpdated.length}`);
|
|
307
307
|
console.error(`Docs generated: ${docsGeneration.documentsGenerated.length}`);
|
|
308
308
|
console.error(`Reasoning tokens: ${docsGeneration.totalReasoningTokens}`);
|
|
@@ -133,7 +133,7 @@ Generate a markdown document tracking project documentation progress.`,
|
|
|
133
133
|
export class ProjectKnowledgeService {
|
|
134
134
|
client;
|
|
135
135
|
options;
|
|
136
|
-
|
|
136
|
+
metadataCacheByProject;
|
|
137
137
|
constructor(apiKey, options) {
|
|
138
138
|
if (!apiKey) {
|
|
139
139
|
throw new Error("OpenAI API key is required for Project Knowledge Service");
|
|
@@ -142,55 +142,72 @@ export class ProjectKnowledgeService {
|
|
|
142
142
|
this.options = {
|
|
143
143
|
model: options?.model || "gpt-5-mini",
|
|
144
144
|
reasoningEffort: options?.reasoningEffort || "medium",
|
|
145
|
-
|
|
145
|
+
storagePath: options?.storagePath || ".memorybank",
|
|
146
146
|
enableSummary: options?.enableSummary !== undefined ? options.enableSummary : true,
|
|
147
147
|
maxChunksPerDoc: options?.maxChunksPerDoc || 50,
|
|
148
148
|
};
|
|
149
|
-
this.
|
|
150
|
-
this.ensureDocsDirectory();
|
|
151
|
-
this.loadMetadata();
|
|
149
|
+
this.metadataCacheByProject = new Map();
|
|
152
150
|
}
|
|
153
151
|
/**
|
|
154
|
-
*
|
|
152
|
+
* Gets the docs path for a specific project
|
|
153
|
+
*/
|
|
154
|
+
getProjectDocsPath(projectId) {
|
|
155
|
+
return path.join(this.options.storagePath, "projects", projectId, "docs");
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Ensures the docs directory exists for a project
|
|
155
159
|
*/
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
+
ensureProjectDocsDirectory(projectId) {
|
|
161
|
+
const docsPath = this.getProjectDocsPath(projectId);
|
|
162
|
+
if (!fs.existsSync(docsPath)) {
|
|
163
|
+
fs.mkdirSync(docsPath, { recursive: true });
|
|
164
|
+
console.error(`Created project docs directory: ${docsPath}`);
|
|
160
165
|
}
|
|
166
|
+
return docsPath;
|
|
161
167
|
}
|
|
162
168
|
/**
|
|
163
|
-
* Loads metadata for
|
|
169
|
+
* Loads metadata for a specific project
|
|
164
170
|
*/
|
|
165
|
-
|
|
166
|
-
|
|
171
|
+
loadProjectMetadata(projectId) {
|
|
172
|
+
if (this.metadataCacheByProject.has(projectId)) {
|
|
173
|
+
return this.metadataCacheByProject.get(projectId);
|
|
174
|
+
}
|
|
175
|
+
const docsPath = this.getProjectDocsPath(projectId);
|
|
176
|
+
const metadataPath = path.join(docsPath, "metadata.json");
|
|
177
|
+
const cache = new Map();
|
|
167
178
|
try {
|
|
168
179
|
if (fs.existsSync(metadataPath)) {
|
|
169
180
|
const data = JSON.parse(fs.readFileSync(metadataPath, "utf-8"));
|
|
170
181
|
for (const [type, metadata] of Object.entries(data)) {
|
|
171
|
-
|
|
182
|
+
cache.set(type, metadata);
|
|
172
183
|
}
|
|
173
|
-
console.error(`Loaded metadata for ${
|
|
184
|
+
console.error(`Loaded metadata for ${cache.size} documents (project: ${projectId})`);
|
|
174
185
|
}
|
|
175
186
|
}
|
|
176
187
|
catch (error) {
|
|
177
|
-
console.error(`Warning: Could not load project docs metadata: ${error}`);
|
|
188
|
+
console.error(`Warning: Could not load project docs metadata for ${projectId}: ${error}`);
|
|
178
189
|
}
|
|
190
|
+
this.metadataCacheByProject.set(projectId, cache);
|
|
191
|
+
return cache;
|
|
179
192
|
}
|
|
180
193
|
/**
|
|
181
|
-
* Saves metadata for
|
|
194
|
+
* Saves metadata for a specific project
|
|
182
195
|
*/
|
|
183
|
-
|
|
184
|
-
const
|
|
196
|
+
saveProjectMetadata(projectId) {
|
|
197
|
+
const docsPath = this.ensureProjectDocsDirectory(projectId);
|
|
198
|
+
const metadataPath = path.join(docsPath, "metadata.json");
|
|
199
|
+
const cache = this.metadataCacheByProject.get(projectId);
|
|
200
|
+
if (!cache)
|
|
201
|
+
return;
|
|
185
202
|
try {
|
|
186
203
|
const data = {};
|
|
187
|
-
for (const [type, metadata] of
|
|
204
|
+
for (const [type, metadata] of cache) {
|
|
188
205
|
data[type] = metadata;
|
|
189
206
|
}
|
|
190
207
|
fs.writeFileSync(metadataPath, JSON.stringify(data, null, 2));
|
|
191
208
|
}
|
|
192
209
|
catch (error) {
|
|
193
|
-
console.error(`Warning: Could not save project docs metadata: ${error}`);
|
|
210
|
+
console.error(`Warning: Could not save project docs metadata for ${projectId}: ${error}`);
|
|
194
211
|
}
|
|
195
212
|
}
|
|
196
213
|
/**
|
|
@@ -315,18 +332,20 @@ ${chunk.content}
|
|
|
315
332
|
};
|
|
316
333
|
}
|
|
317
334
|
/**
|
|
318
|
-
* Generates a single document
|
|
335
|
+
* Generates a single document for a specific project
|
|
319
336
|
*/
|
|
320
|
-
async generateDocument(type, chunks, force = false, previousProgress) {
|
|
337
|
+
async generateDocument(projectId, type, chunks, force = false, previousProgress) {
|
|
321
338
|
const definition = DOC_DEFINITIONS[type];
|
|
322
339
|
const inputHash = this.hashChunks(chunks);
|
|
340
|
+
const docsPath = this.ensureProjectDocsDirectory(projectId);
|
|
341
|
+
const metadataCache = this.loadProjectMetadata(projectId);
|
|
323
342
|
// Check if regeneration is needed
|
|
324
|
-
const existingMetadata =
|
|
343
|
+
const existingMetadata = metadataCache.get(type);
|
|
325
344
|
if (!force && existingMetadata && existingMetadata.lastInputHash === inputHash) {
|
|
326
345
|
console.error(`Skipping ${type}: No changes detected`);
|
|
327
346
|
return null;
|
|
328
347
|
}
|
|
329
|
-
console.error(`Generating document: ${definition.title}`);
|
|
348
|
+
console.error(`Generating document: ${definition.title} (project: ${projectId})`);
|
|
330
349
|
console.error(` Input chunks: ${chunks.length}`);
|
|
331
350
|
// Prepare prompt
|
|
332
351
|
const chunksText = this.prepareChunksForPrompt(chunks, this.options.maxChunksPerDoc);
|
|
@@ -353,18 +372,18 @@ ${chunk.content}
|
|
|
353
372
|
},
|
|
354
373
|
};
|
|
355
374
|
// Save document
|
|
356
|
-
const docPath = path.join(
|
|
375
|
+
const docPath = path.join(docsPath, definition.filename);
|
|
357
376
|
fs.writeFileSync(docPath, doc.content);
|
|
358
377
|
// Update metadata
|
|
359
|
-
|
|
360
|
-
this.
|
|
378
|
+
metadataCache.set(type, doc.metadata);
|
|
379
|
+
this.saveProjectMetadata(projectId);
|
|
361
380
|
console.error(`Generated ${definition.title} (${result.reasoningTokens} reasoning + ${result.outputTokens} output tokens)`);
|
|
362
381
|
return doc;
|
|
363
382
|
}
|
|
364
383
|
/**
|
|
365
384
|
* Generates all project documents (in parallel for speed)
|
|
366
385
|
*/
|
|
367
|
-
async generateAllDocuments(chunks, force = false) {
|
|
386
|
+
async generateAllDocuments(projectId, chunks, force = false) {
|
|
368
387
|
const result = {
|
|
369
388
|
success: true,
|
|
370
389
|
documentsGenerated: [],
|
|
@@ -374,9 +393,11 @@ ${chunk.content}
|
|
|
374
393
|
totalOutputTokens: 0,
|
|
375
394
|
errors: [],
|
|
376
395
|
};
|
|
396
|
+
const docsPath = this.ensureProjectDocsDirectory(projectId);
|
|
397
|
+
const metadataCache = this.loadProjectMetadata(projectId);
|
|
377
398
|
// Get previous progress if exists (read before parallel generation)
|
|
378
399
|
let previousProgress;
|
|
379
|
-
const progressPath = path.join(
|
|
400
|
+
const progressPath = path.join(docsPath, "progress.md");
|
|
380
401
|
if (fs.existsSync(progressPath)) {
|
|
381
402
|
previousProgress = fs.readFileSync(progressPath, "utf-8");
|
|
382
403
|
}
|
|
@@ -393,15 +414,15 @@ ${chunk.content}
|
|
|
393
414
|
"activeContext",
|
|
394
415
|
"progress",
|
|
395
416
|
];
|
|
396
|
-
console.error(`\n🚀 Generating ${docTypes.length} documents in PARALLEL...`);
|
|
417
|
+
console.error(`\n🚀 Generating ${docTypes.length} documents in PARALLEL for project: ${projectId}...`);
|
|
397
418
|
// Generate all documents in parallel
|
|
398
419
|
const generationPromises = docTypes.map(async (docType) => {
|
|
399
420
|
try {
|
|
400
421
|
// For activeContext, use only recent chunks
|
|
401
422
|
const docChunks = docType === "activeContext" ? recentChunks : chunks;
|
|
402
|
-
const existingMetadata =
|
|
423
|
+
const existingMetadata = metadataCache.get(docType);
|
|
403
424
|
const isNew = !existingMetadata;
|
|
404
|
-
const doc = await this.generateDocument(docType, docChunks, force, docType === "progress" ? previousProgress : undefined);
|
|
425
|
+
const doc = await this.generateDocument(projectId, docType, docChunks, force, docType === "progress" ? previousProgress : undefined);
|
|
405
426
|
return { docType, doc, isNew, error: null };
|
|
406
427
|
}
|
|
407
428
|
catch (error) {
|
|
@@ -438,13 +459,15 @@ ${chunk.content}
|
|
|
438
459
|
/**
|
|
439
460
|
* Updates only documents affected by changes
|
|
440
461
|
*/
|
|
441
|
-
async updateDocuments(chunks, changedFiles) {
|
|
442
|
-
console.error(`updateDocuments called with ${chunks.length} chunks and ${changedFiles.length} changed files`);
|
|
462
|
+
async updateDocuments(projectId, chunks, changedFiles) {
|
|
463
|
+
console.error(`updateDocuments called for project ${projectId} with ${chunks.length} chunks and ${changedFiles.length} changed files`);
|
|
443
464
|
// Debug: show first chunk if exists
|
|
444
465
|
if (chunks.length > 0) {
|
|
445
466
|
const firstChunk = chunks[0];
|
|
446
467
|
console.error(`First chunk: ${firstChunk.file_path}, content length: ${firstChunk.content?.length || 0}`);
|
|
447
468
|
}
|
|
469
|
+
const docsPath = this.ensureProjectDocsDirectory(projectId);
|
|
470
|
+
const metadataCache = this.loadProjectMetadata(projectId);
|
|
448
471
|
// Determine which documents need updating based on changed files
|
|
449
472
|
const docsToUpdate = [];
|
|
450
473
|
// Always update activeContext and progress when there are changes
|
|
@@ -475,7 +498,7 @@ ${chunk.content}
|
|
|
475
498
|
};
|
|
476
499
|
// Get previous progress (read before parallel generation)
|
|
477
500
|
let previousProgress;
|
|
478
|
-
const progressPath = path.join(
|
|
501
|
+
const progressPath = path.join(docsPath, "progress.md");
|
|
479
502
|
if (fs.existsSync(progressPath)) {
|
|
480
503
|
previousProgress = fs.readFileSync(progressPath, "utf-8");
|
|
481
504
|
}
|
|
@@ -483,14 +506,14 @@ ${chunk.content}
|
|
|
483
506
|
const recentChunks = [...chunks]
|
|
484
507
|
.sort((a, b) => b.timestamp - a.timestamp)
|
|
485
508
|
.slice(0, Math.min(30, chunks.length));
|
|
486
|
-
console.error(`\n🚀 Updating ${docsToUpdate.length} documents in PARALLEL...`);
|
|
509
|
+
console.error(`\n🚀 Updating ${docsToUpdate.length} documents in PARALLEL for project: ${projectId}...`);
|
|
487
510
|
// Generate docs in parallel
|
|
488
511
|
const updatePromises = docsToUpdate.map(async (docType) => {
|
|
489
512
|
try {
|
|
490
513
|
const docChunks = docType === "activeContext" ? recentChunks : chunks;
|
|
491
|
-
const existingMetadata =
|
|
514
|
+
const existingMetadata = metadataCache.get(docType);
|
|
492
515
|
const isNew = !existingMetadata;
|
|
493
|
-
const doc = await this.generateDocument(docType, docChunks, true, // Force update for changed docs
|
|
516
|
+
const doc = await this.generateDocument(projectId, docType, docChunks, true, // Force update for changed docs
|
|
494
517
|
docType === "progress" ? previousProgress : undefined);
|
|
495
518
|
return { docType, doc, isNew, error: null };
|
|
496
519
|
}
|
|
@@ -535,16 +558,18 @@ ${chunk.content}
|
|
|
535
558
|
return result;
|
|
536
559
|
}
|
|
537
560
|
/**
|
|
538
|
-
* Reads a project document
|
|
561
|
+
* Reads a project document for a specific project
|
|
539
562
|
*/
|
|
540
|
-
getDocument(type) {
|
|
563
|
+
getDocument(projectId, type) {
|
|
541
564
|
const definition = DOC_DEFINITIONS[type];
|
|
542
|
-
const
|
|
565
|
+
const docsPath = this.getProjectDocsPath(projectId);
|
|
566
|
+
const docPath = path.join(docsPath, definition.filename);
|
|
543
567
|
if (!fs.existsSync(docPath)) {
|
|
544
568
|
return null;
|
|
545
569
|
}
|
|
546
570
|
const content = fs.readFileSync(docPath, "utf-8");
|
|
547
|
-
const
|
|
571
|
+
const metadataCache = this.loadProjectMetadata(projectId);
|
|
572
|
+
const metadata = metadataCache.get(type);
|
|
548
573
|
return {
|
|
549
574
|
type,
|
|
550
575
|
content,
|
|
@@ -558,12 +583,12 @@ ${chunk.content}
|
|
|
558
583
|
};
|
|
559
584
|
}
|
|
560
585
|
/**
|
|
561
|
-
* Reads all project documents
|
|
586
|
+
* Reads all project documents for a specific project
|
|
562
587
|
*/
|
|
563
|
-
getAllDocuments() {
|
|
588
|
+
getAllDocuments(projectId) {
|
|
564
589
|
const docs = [];
|
|
565
590
|
for (const type of Object.keys(DOC_DEFINITIONS)) {
|
|
566
|
-
const doc = this.getDocument(type);
|
|
591
|
+
const doc = this.getDocument(projectId, type);
|
|
567
592
|
if (doc) {
|
|
568
593
|
docs.push(doc);
|
|
569
594
|
}
|
|
@@ -573,8 +598,8 @@ ${chunk.content}
|
|
|
573
598
|
/**
|
|
574
599
|
* Gets a summary of all documents (useful for context loading)
|
|
575
600
|
*/
|
|
576
|
-
getDocumentsSummary() {
|
|
577
|
-
const docs = this.getAllDocuments();
|
|
601
|
+
getDocumentsSummary(projectId) {
|
|
602
|
+
const docs = this.getAllDocuments(projectId);
|
|
578
603
|
if (docs.length === 0) {
|
|
579
604
|
return "No project documentation has been generated yet. Use memorybank_generate_project_docs to generate documentation.";
|
|
580
605
|
}
|
|
@@ -594,21 +619,23 @@ ${chunk.content}
|
|
|
594
619
|
return summary;
|
|
595
620
|
}
|
|
596
621
|
/**
|
|
597
|
-
* Checks if documents exist
|
|
622
|
+
* Checks if documents exist for a project
|
|
598
623
|
*/
|
|
599
|
-
hasDocuments() {
|
|
600
|
-
|
|
624
|
+
hasDocuments(projectId) {
|
|
625
|
+
const metadataCache = this.loadProjectMetadata(projectId);
|
|
626
|
+
return metadataCache.size > 0;
|
|
601
627
|
}
|
|
602
628
|
/**
|
|
603
|
-
* Gets statistics about generated documents
|
|
629
|
+
* Gets statistics about generated documents for a project
|
|
604
630
|
*/
|
|
605
|
-
getStats() {
|
|
631
|
+
getStats(projectId) {
|
|
632
|
+
const metadataCache = this.loadProjectMetadata(projectId);
|
|
606
633
|
let totalReasoningTokens = 0;
|
|
607
634
|
let totalOutputTokens = 0;
|
|
608
635
|
let lastGenerated = 0;
|
|
609
636
|
const documents = {};
|
|
610
637
|
for (const type of Object.keys(DOC_DEFINITIONS)) {
|
|
611
|
-
const metadata =
|
|
638
|
+
const metadata = metadataCache.get(type);
|
|
612
639
|
documents[type] = {
|
|
613
640
|
exists: !!metadata,
|
|
614
641
|
lastGenerated: metadata ? new Date(metadata.lastGenerated) : undefined,
|
|
@@ -622,7 +649,7 @@ ${chunk.content}
|
|
|
622
649
|
}
|
|
623
650
|
}
|
|
624
651
|
return {
|
|
625
|
-
documentCount:
|
|
652
|
+
documentCount: metadataCache.size,
|
|
626
653
|
totalReasoningTokens,
|
|
627
654
|
totalOutputTokens,
|
|
628
655
|
lastGenerated: lastGenerated > 0 ? new Date(lastGenerated) : undefined,
|
|
@@ -632,13 +659,6 @@ ${chunk.content}
|
|
|
632
659
|
// ==========================================
|
|
633
660
|
// Project-specific document methods (for MCP Resources)
|
|
634
661
|
// ==========================================
|
|
635
|
-
/**
|
|
636
|
-
* Gets the docs path for a specific project
|
|
637
|
-
*/
|
|
638
|
-
getProjectDocsPath(projectId) {
|
|
639
|
-
const storagePath = process.env.MEMORYBANK_STORAGE_PATH || ".memorybank";
|
|
640
|
-
return path.join(storagePath, "projects", projectId, "docs");
|
|
641
|
-
}
|
|
642
662
|
/**
|
|
643
663
|
* Checks if a project's Memory Bank is initialized
|
|
644
664
|
*/
|
|
@@ -716,7 +736,7 @@ export function createProjectKnowledgeService() {
|
|
|
716
736
|
const options = {
|
|
717
737
|
model: process.env.MEMORYBANK_REASONING_MODEL || "gpt-5-mini",
|
|
718
738
|
reasoningEffort: process.env.MEMORYBANK_REASONING_EFFORT || "medium",
|
|
719
|
-
|
|
739
|
+
storagePath: storagePath,
|
|
720
740
|
enableSummary: true,
|
|
721
741
|
};
|
|
722
742
|
return new ProjectKnowledgeService(apiKey, options);
|
|
@@ -33,8 +33,9 @@ export async function generateProjectDocs(params, projectKnowledgeService, vecto
|
|
|
33
33
|
};
|
|
34
34
|
}
|
|
35
35
|
console.error(`Found ${chunks.length} code chunks to analyze`);
|
|
36
|
-
// Generate documents
|
|
37
|
-
const
|
|
36
|
+
// Generate documents - projectId is required
|
|
37
|
+
const projectId = params.projectId || "default";
|
|
38
|
+
const result = await projectKnowledgeService.generateAllDocuments(projectId, chunks, params.force || false);
|
|
38
39
|
// Calculate estimated cost (approximate rates for gpt-5-mini)
|
|
39
40
|
// Reasoning tokens are typically more expensive
|
|
40
41
|
const reasoningCostPer1K = 0.003; // $0.003 per 1K reasoning tokens
|
|
@@ -15,13 +15,14 @@ const VALID_DOC_TYPES = [
|
|
|
15
15
|
*/
|
|
16
16
|
export async function getProjectDocs(params, projectKnowledgeService) {
|
|
17
17
|
try {
|
|
18
|
+
const projectId = params.projectId;
|
|
18
19
|
const format = params.format || "full";
|
|
19
20
|
const requestedDoc = params.document?.toLowerCase();
|
|
20
|
-
// Check if any documents exist
|
|
21
|
-
if (!projectKnowledgeService.hasDocuments()) {
|
|
21
|
+
// Check if any documents exist for this project
|
|
22
|
+
if (!projectKnowledgeService.hasDocuments(projectId)) {
|
|
22
23
|
return {
|
|
23
24
|
success: false,
|
|
24
|
-
message:
|
|
25
|
+
message: `No project documentation has been generated for project "${projectId}" yet. Run memorybank_generate_project_docs first.`,
|
|
25
26
|
stats: {
|
|
26
27
|
documentCount: 0,
|
|
27
28
|
totalReasoningTokens: 0,
|
|
@@ -29,8 +30,8 @@ export async function getProjectDocs(params, projectKnowledgeService) {
|
|
|
29
30
|
},
|
|
30
31
|
};
|
|
31
32
|
}
|
|
32
|
-
// Get stats
|
|
33
|
-
const stats = projectKnowledgeService.getStats();
|
|
33
|
+
// Get stats for this project
|
|
34
|
+
const stats = projectKnowledgeService.getStats(projectId);
|
|
34
35
|
const statsResult = {
|
|
35
36
|
documentCount: stats.documentCount,
|
|
36
37
|
totalReasoningTokens: stats.totalReasoningTokens,
|
|
@@ -39,20 +40,20 @@ export async function getProjectDocs(params, projectKnowledgeService) {
|
|
|
39
40
|
};
|
|
40
41
|
// Handle summary request
|
|
41
42
|
if (requestedDoc === "summary" || format === "summary") {
|
|
42
|
-
const summary = projectKnowledgeService.getDocumentsSummary();
|
|
43
|
+
const summary = projectKnowledgeService.getDocumentsSummary(projectId);
|
|
43
44
|
return {
|
|
44
45
|
success: true,
|
|
45
|
-
message: `Retrieved summary of ${stats.documentCount} project documents.`,
|
|
46
|
+
message: `Retrieved summary of ${stats.documentCount} project documents for "${projectId}".`,
|
|
46
47
|
summary,
|
|
47
48
|
stats: statsResult,
|
|
48
49
|
};
|
|
49
50
|
}
|
|
50
51
|
// Handle "all" or no specific document
|
|
51
52
|
if (!requestedDoc || requestedDoc === "all") {
|
|
52
|
-
const documents = projectKnowledgeService.getAllDocuments();
|
|
53
|
+
const documents = projectKnowledgeService.getAllDocuments(projectId);
|
|
53
54
|
return {
|
|
54
55
|
success: true,
|
|
55
|
-
message: `Retrieved ${documents.length} project documents.`,
|
|
56
|
+
message: `Retrieved ${documents.length} project documents for "${projectId}".`,
|
|
56
57
|
documents,
|
|
57
58
|
stats: statsResult,
|
|
58
59
|
};
|
|
@@ -67,17 +68,17 @@ export async function getProjectDocs(params, projectKnowledgeService) {
|
|
|
67
68
|
stats: statsResult,
|
|
68
69
|
};
|
|
69
70
|
}
|
|
70
|
-
const document = projectKnowledgeService.getDocument(normalizedDoc);
|
|
71
|
+
const document = projectKnowledgeService.getDocument(projectId, normalizedDoc);
|
|
71
72
|
if (!document) {
|
|
72
73
|
return {
|
|
73
74
|
success: false,
|
|
74
|
-
message: `Document "${normalizedDoc}" has not been generated yet.`,
|
|
75
|
+
message: `Document "${normalizedDoc}" has not been generated yet for project "${projectId}".`,
|
|
75
76
|
stats: statsResult,
|
|
76
77
|
};
|
|
77
78
|
}
|
|
78
79
|
return {
|
|
79
80
|
success: true,
|
|
80
|
-
message: `Retrieved document: ${normalizedDoc}`,
|
|
81
|
+
message: `Retrieved document: ${normalizedDoc} for project "${projectId}"`,
|
|
81
82
|
documents: [document],
|
|
82
83
|
stats: statsResult,
|
|
83
84
|
};
|