@elizaos/plugin-knowledge 1.5.12 → 1.5.13
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/index.d.ts +14 -1
- package/dist/index.js +176 -86
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
|
-
import { logger as
|
|
2
|
+
import { logger as logger11 } from "@elizaos/core";
|
|
3
3
|
|
|
4
4
|
// src/service.ts
|
|
5
5
|
import {
|
|
@@ -3033,8 +3033,97 @@ var knowledgeProvider = {
|
|
|
3033
3033
|
}
|
|
3034
3034
|
};
|
|
3035
3035
|
|
|
3036
|
+
// src/documents-provider.ts
|
|
3037
|
+
import { addHeader as addHeader2, logger as logger8, MemoryType as MemoryType3 } from "@elizaos/core";
|
|
3038
|
+
var documentsProvider = {
|
|
3039
|
+
name: "AVAILABLE_DOCUMENTS",
|
|
3040
|
+
description: "List of documents available in the knowledge base. Shows which documents the agent can reference and retrieve information from.",
|
|
3041
|
+
dynamic: false,
|
|
3042
|
+
// Static provider - doesn't change based on the message
|
|
3043
|
+
get: async (runtime) => {
|
|
3044
|
+
try {
|
|
3045
|
+
const knowledgeService = runtime.getService("knowledge");
|
|
3046
|
+
if (!knowledgeService) {
|
|
3047
|
+
logger8.warn("Knowledge service not available for documents provider");
|
|
3048
|
+
return {
|
|
3049
|
+
data: { documents: [] },
|
|
3050
|
+
values: { documents: "" },
|
|
3051
|
+
text: ""
|
|
3052
|
+
};
|
|
3053
|
+
}
|
|
3054
|
+
const allMemories = await knowledgeService.getMemories({
|
|
3055
|
+
tableName: "documents",
|
|
3056
|
+
roomId: runtime.agentId,
|
|
3057
|
+
count: 100
|
|
3058
|
+
// Limit to 100 documents to avoid context overflow
|
|
3059
|
+
});
|
|
3060
|
+
const documents = allMemories.filter(
|
|
3061
|
+
(memory) => memory.metadata?.type === MemoryType3.DOCUMENT
|
|
3062
|
+
);
|
|
3063
|
+
if (!documents || documents.length === 0) {
|
|
3064
|
+
return {
|
|
3065
|
+
data: { documents: [] },
|
|
3066
|
+
values: { documents: "" },
|
|
3067
|
+
text: ""
|
|
3068
|
+
};
|
|
3069
|
+
}
|
|
3070
|
+
const documentsList = documents.map((doc, index) => {
|
|
3071
|
+
const metadata = doc.metadata;
|
|
3072
|
+
const filename = metadata?.filename || metadata?.title || `Document ${index + 1}`;
|
|
3073
|
+
const fileType = metadata?.fileExt || metadata?.fileType || "unknown";
|
|
3074
|
+
const source = metadata?.source || "upload";
|
|
3075
|
+
const fileSize = metadata?.fileSize;
|
|
3076
|
+
const parts = [filename];
|
|
3077
|
+
if (fileType && fileType !== "unknown") {
|
|
3078
|
+
parts.push(fileType);
|
|
3079
|
+
}
|
|
3080
|
+
if (fileSize) {
|
|
3081
|
+
const sizeKB = Math.round(fileSize / 1024);
|
|
3082
|
+
if (sizeKB > 1024) {
|
|
3083
|
+
parts.push(`${Math.round(sizeKB / 1024)}MB`);
|
|
3084
|
+
} else {
|
|
3085
|
+
parts.push(`${sizeKB}KB`);
|
|
3086
|
+
}
|
|
3087
|
+
}
|
|
3088
|
+
if (source && source !== "upload") {
|
|
3089
|
+
parts.push(`from ${source}`);
|
|
3090
|
+
}
|
|
3091
|
+
return parts.join(" - ");
|
|
3092
|
+
}).join("\n");
|
|
3093
|
+
const documentsText = addHeader2(
|
|
3094
|
+
"# Available Documents",
|
|
3095
|
+
`${documents.length} document(s) in knowledge base:
|
|
3096
|
+
${documentsList}`
|
|
3097
|
+
);
|
|
3098
|
+
return {
|
|
3099
|
+
data: {
|
|
3100
|
+
documents: documents.map((doc) => ({
|
|
3101
|
+
id: doc.id,
|
|
3102
|
+
filename: doc.metadata?.filename || doc.metadata?.title,
|
|
3103
|
+
fileType: doc.metadata?.fileType || doc.metadata?.fileExt,
|
|
3104
|
+
source: doc.metadata?.source
|
|
3105
|
+
})),
|
|
3106
|
+
count: documents.length
|
|
3107
|
+
},
|
|
3108
|
+
values: {
|
|
3109
|
+
documentsCount: documents.length,
|
|
3110
|
+
documents: documentsList
|
|
3111
|
+
},
|
|
3112
|
+
text: documentsText
|
|
3113
|
+
};
|
|
3114
|
+
} catch (error) {
|
|
3115
|
+
logger8.error("Error in documents provider:", error.message);
|
|
3116
|
+
return {
|
|
3117
|
+
data: { documents: [], error: error.message },
|
|
3118
|
+
values: { documents: "" },
|
|
3119
|
+
text: ""
|
|
3120
|
+
};
|
|
3121
|
+
}
|
|
3122
|
+
}
|
|
3123
|
+
};
|
|
3124
|
+
|
|
3036
3125
|
// src/tests.ts
|
|
3037
|
-
import { MemoryType as
|
|
3126
|
+
import { MemoryType as MemoryType4, ModelType as ModelType3 } from "@elizaos/core";
|
|
3038
3127
|
import { Buffer as Buffer3 } from "buffer";
|
|
3039
3128
|
import * as fs2 from "fs";
|
|
3040
3129
|
import * as path2 from "path";
|
|
@@ -3159,9 +3248,9 @@ function createMockRuntime(overrides) {
|
|
|
3159
3248
|
const results = Array.from(memories.values()).filter((m) => {
|
|
3160
3249
|
if (params.roomId && m.roomId !== params.roomId) return false;
|
|
3161
3250
|
if (params.entityId && m.entityId !== params.entityId) return false;
|
|
3162
|
-
if (params.tableName === "knowledge" && m.metadata?.type !==
|
|
3251
|
+
if (params.tableName === "knowledge" && m.metadata?.type !== MemoryType4.FRAGMENT)
|
|
3163
3252
|
return false;
|
|
3164
|
-
if (params.tableName === "documents" && m.metadata?.type !==
|
|
3253
|
+
if (params.tableName === "documents" && m.metadata?.type !== MemoryType4.DOCUMENT)
|
|
3165
3254
|
return false;
|
|
3166
3255
|
return true;
|
|
3167
3256
|
});
|
|
@@ -3175,7 +3264,7 @@ function createMockRuntime(overrides) {
|
|
|
3175
3264
|
},
|
|
3176
3265
|
async searchMemories(params) {
|
|
3177
3266
|
const fragments = Array.from(memories.values()).filter(
|
|
3178
|
-
(m) => m.metadata?.type ===
|
|
3267
|
+
(m) => m.metadata?.type === MemoryType4.FRAGMENT
|
|
3179
3268
|
);
|
|
3180
3269
|
return fragments.map((f) => ({
|
|
3181
3270
|
...f,
|
|
@@ -3547,7 +3636,7 @@ var KnowledgeTestSuite = class {
|
|
|
3547
3636
|
if (!memory.id) {
|
|
3548
3637
|
throw new Error("Document memory should have an ID");
|
|
3549
3638
|
}
|
|
3550
|
-
if (memory.metadata?.type !==
|
|
3639
|
+
if (memory.metadata?.type !== MemoryType4.DOCUMENT) {
|
|
3551
3640
|
throw new Error("Document memory should have DOCUMENT type");
|
|
3552
3641
|
}
|
|
3553
3642
|
if (memory.content.text !== params.text) {
|
|
@@ -3920,7 +4009,7 @@ var KnowledgeTestSuite = class {
|
|
|
3920
4009
|
var tests_default = new KnowledgeTestSuite();
|
|
3921
4010
|
|
|
3922
4011
|
// src/actions.ts
|
|
3923
|
-
import { logger as
|
|
4012
|
+
import { logger as logger9, stringToUuid } from "@elizaos/core";
|
|
3924
4013
|
import * as fs3 from "fs";
|
|
3925
4014
|
import * as path3 from "path";
|
|
3926
4015
|
var processKnowledgeAction = {
|
|
@@ -3978,7 +4067,7 @@ var processKnowledgeAction = {
|
|
|
3978
4067
|
const hasPath = pathPattern.test(text);
|
|
3979
4068
|
const service = runtime.getService(KnowledgeService.serviceType);
|
|
3980
4069
|
if (!service) {
|
|
3981
|
-
|
|
4070
|
+
logger9.warn("Knowledge service not available for PROCESS_KNOWLEDGE action");
|
|
3982
4071
|
return false;
|
|
3983
4072
|
}
|
|
3984
4073
|
return hasKeyword || hasPath;
|
|
@@ -4056,7 +4145,7 @@ var processKnowledgeAction = {
|
|
|
4056
4145
|
await callback(response);
|
|
4057
4146
|
}
|
|
4058
4147
|
} catch (error) {
|
|
4059
|
-
|
|
4148
|
+
logger9.error({ error }, "Error in PROCESS_KNOWLEDGE action");
|
|
4060
4149
|
const errorResponse = {
|
|
4061
4150
|
text: `I encountered an error while processing the knowledge: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
4062
4151
|
};
|
|
@@ -4147,7 +4236,7 @@ ${formattedResults}`
|
|
|
4147
4236
|
await callback(response);
|
|
4148
4237
|
}
|
|
4149
4238
|
} catch (error) {
|
|
4150
|
-
|
|
4239
|
+
logger9.error({ error }, "Error in SEARCH_KNOWLEDGE action");
|
|
4151
4240
|
const errorResponse = {
|
|
4152
4241
|
text: `I encountered an error while searching the knowledge base: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
4153
4242
|
};
|
|
@@ -4160,7 +4249,7 @@ ${formattedResults}`
|
|
|
4160
4249
|
var knowledgeActions = [processKnowledgeAction, searchKnowledgeAction];
|
|
4161
4250
|
|
|
4162
4251
|
// src/routes.ts
|
|
4163
|
-
import { MemoryType as
|
|
4252
|
+
import { MemoryType as MemoryType5, createUniqueUuid as createUniqueUuid2, logger as logger10, ModelType as ModelType4 } from "@elizaos/core";
|
|
4164
4253
|
import fs4 from "fs";
|
|
4165
4254
|
import path4 from "path";
|
|
4166
4255
|
import multer from "multer";
|
|
@@ -4211,7 +4300,7 @@ var cleanupFile = (filePath) => {
|
|
|
4211
4300
|
try {
|
|
4212
4301
|
fs4.unlinkSync(filePath);
|
|
4213
4302
|
} catch (error) {
|
|
4214
|
-
|
|
4303
|
+
logger10.error({ error }, `Error cleaning up file ${filePath}`);
|
|
4215
4304
|
}
|
|
4216
4305
|
}
|
|
4217
4306
|
};
|
|
@@ -4238,15 +4327,15 @@ async function uploadKnowledgeHandler(req, res, runtime) {
|
|
|
4238
4327
|
}
|
|
4239
4328
|
const invalidFiles = files.filter((file) => {
|
|
4240
4329
|
if (file.size === 0) {
|
|
4241
|
-
|
|
4330
|
+
logger10.warn(`File ${file.originalname} is empty`);
|
|
4242
4331
|
return true;
|
|
4243
4332
|
}
|
|
4244
4333
|
if (!file.originalname || file.originalname.trim() === "") {
|
|
4245
|
-
|
|
4334
|
+
logger10.warn(`File has no name`);
|
|
4246
4335
|
return true;
|
|
4247
4336
|
}
|
|
4248
4337
|
if (!file.path) {
|
|
4249
|
-
|
|
4338
|
+
logger10.warn(`File ${file.originalname} has no path`);
|
|
4250
4339
|
return true;
|
|
4251
4340
|
}
|
|
4252
4341
|
return false;
|
|
@@ -4263,7 +4352,7 @@ async function uploadKnowledgeHandler(req, res, runtime) {
|
|
|
4263
4352
|
}
|
|
4264
4353
|
const agentId = req.body.agentId || req.query.agentId;
|
|
4265
4354
|
if (!agentId) {
|
|
4266
|
-
|
|
4355
|
+
logger10.error("[Document Processor] \u274C No agent ID provided in upload request");
|
|
4267
4356
|
return sendError(
|
|
4268
4357
|
res,
|
|
4269
4358
|
400,
|
|
@@ -4272,11 +4361,11 @@ async function uploadKnowledgeHandler(req, res, runtime) {
|
|
|
4272
4361
|
);
|
|
4273
4362
|
}
|
|
4274
4363
|
const worldId = req.body.worldId || agentId;
|
|
4275
|
-
|
|
4364
|
+
logger10.info(`[Document Processor] \u{1F4E4} Processing file upload for agent: ${agentId}`);
|
|
4276
4365
|
const processingPromises = files.map(async (file, index) => {
|
|
4277
4366
|
const originalFilename = file.originalname;
|
|
4278
4367
|
const filePath = file.path;
|
|
4279
|
-
|
|
4368
|
+
logger10.debug(
|
|
4280
4369
|
`[Document Processor] \u{1F4C4} Processing file: ${originalFilename} (agent: ${agentId})`
|
|
4281
4370
|
);
|
|
4282
4371
|
try {
|
|
@@ -4311,7 +4400,7 @@ async function uploadKnowledgeHandler(req, res, runtime) {
|
|
|
4311
4400
|
status: "success"
|
|
4312
4401
|
};
|
|
4313
4402
|
} catch (fileError) {
|
|
4314
|
-
|
|
4403
|
+
logger10.error(
|
|
4315
4404
|
`[Document Processor] \u274C Error processing file ${file.originalname}:`,
|
|
4316
4405
|
fileError
|
|
4317
4406
|
);
|
|
@@ -4334,7 +4423,7 @@ async function uploadKnowledgeHandler(req, res, runtime) {
|
|
|
4334
4423
|
}
|
|
4335
4424
|
const agentId = req.body.agentId || req.query.agentId;
|
|
4336
4425
|
if (!agentId) {
|
|
4337
|
-
|
|
4426
|
+
logger10.error("[Document Processor] \u274C No agent ID provided in URL request");
|
|
4338
4427
|
return sendError(
|
|
4339
4428
|
res,
|
|
4340
4429
|
400,
|
|
@@ -4342,7 +4431,7 @@ async function uploadKnowledgeHandler(req, res, runtime) {
|
|
|
4342
4431
|
"Agent ID is required for uploading knowledge from URLs"
|
|
4343
4432
|
);
|
|
4344
4433
|
}
|
|
4345
|
-
|
|
4434
|
+
logger10.info(`[Document Processor] \u{1F4E4} Processing URL upload for agent: ${agentId}`);
|
|
4346
4435
|
const processingPromises = fileUrls.map(async (fileUrl) => {
|
|
4347
4436
|
try {
|
|
4348
4437
|
const normalizedUrl = normalizeS3Url(fileUrl);
|
|
@@ -4350,7 +4439,7 @@ async function uploadKnowledgeHandler(req, res, runtime) {
|
|
|
4350
4439
|
const pathSegments = urlObject.pathname.split("/");
|
|
4351
4440
|
const encodedFilename = pathSegments[pathSegments.length - 1] || "document.pdf";
|
|
4352
4441
|
const originalFilename = decodeURIComponent(encodedFilename);
|
|
4353
|
-
|
|
4442
|
+
logger10.debug(`[Document Processor] \u{1F310} Fetching content from URL: ${fileUrl}`);
|
|
4354
4443
|
const { content, contentType: fetchedContentType } = await fetchUrlContent(fileUrl);
|
|
4355
4444
|
let contentType = fetchedContentType;
|
|
4356
4445
|
if (contentType === "application/octet-stream") {
|
|
@@ -4390,7 +4479,7 @@ async function uploadKnowledgeHandler(req, res, runtime) {
|
|
|
4390
4479
|
url: normalizedUrl
|
|
4391
4480
|
}
|
|
4392
4481
|
};
|
|
4393
|
-
|
|
4482
|
+
logger10.debug(
|
|
4394
4483
|
`[Document Processor] \u{1F4C4} Processing knowledge from URL: ${originalFilename} (type: ${contentType})`
|
|
4395
4484
|
);
|
|
4396
4485
|
const result = await service.addKnowledge(addKnowledgeOpts);
|
|
@@ -4405,7 +4494,7 @@ async function uploadKnowledgeHandler(req, res, runtime) {
|
|
|
4405
4494
|
status: "success"
|
|
4406
4495
|
};
|
|
4407
4496
|
} catch (urlError) {
|
|
4408
|
-
|
|
4497
|
+
logger10.error(`[Document Processor] \u274C Error processing URL ${fileUrl}:`, urlError);
|
|
4409
4498
|
return {
|
|
4410
4499
|
fileUrl,
|
|
4411
4500
|
status: "error_processing",
|
|
@@ -4417,7 +4506,7 @@ async function uploadKnowledgeHandler(req, res, runtime) {
|
|
|
4417
4506
|
sendSuccess(res, results);
|
|
4418
4507
|
}
|
|
4419
4508
|
} catch (error) {
|
|
4420
|
-
|
|
4509
|
+
logger10.error({ error }, "[Document Processor] \u274C Error processing knowledge");
|
|
4421
4510
|
if (hasUploadedFiles) {
|
|
4422
4511
|
cleanupFiles(req.files);
|
|
4423
4512
|
}
|
|
@@ -4456,7 +4545,7 @@ async function getKnowledgeDocumentsHandler(req, res, runtime) {
|
|
|
4456
4545
|
// Or if the URL is stored in the metadata (check if it exists)
|
|
4457
4546
|
memory.metadata && "url" in memory.metadata && typeof memory.metadata.url === "string" && normalizedRequestUrls.includes(normalizeS3Url(memory.metadata.url))
|
|
4458
4547
|
);
|
|
4459
|
-
|
|
4548
|
+
logger10.debug(
|
|
4460
4549
|
`[Document Processor] \u{1F50D} Filtered documents by URLs: ${fileUrls.length} URLs, found ${filteredMemories.length} matching documents`
|
|
4461
4550
|
);
|
|
4462
4551
|
}
|
|
@@ -4471,12 +4560,12 @@ async function getKnowledgeDocumentsHandler(req, res, runtime) {
|
|
|
4471
4560
|
totalRequested: fileUrls ? fileUrls.length : 0
|
|
4472
4561
|
});
|
|
4473
4562
|
} catch (error) {
|
|
4474
|
-
|
|
4563
|
+
logger10.error({ error }, "[Document Processor] \u274C Error retrieving documents");
|
|
4475
4564
|
sendError(res, 500, "RETRIEVAL_ERROR", "Failed to retrieve documents", error.message);
|
|
4476
4565
|
}
|
|
4477
4566
|
}
|
|
4478
4567
|
async function deleteKnowledgeDocumentHandler(req, res, runtime) {
|
|
4479
|
-
|
|
4568
|
+
logger10.debug(`[Document Processor] \u{1F5D1}\uFE0F DELETE request for document: ${req.params.knowledgeId}`);
|
|
4480
4569
|
const service = runtime.getService(KnowledgeService.serviceType);
|
|
4481
4570
|
if (!service) {
|
|
4482
4571
|
return sendError(
|
|
@@ -4488,22 +4577,22 @@ async function deleteKnowledgeDocumentHandler(req, res, runtime) {
|
|
|
4488
4577
|
}
|
|
4489
4578
|
const knowledgeId = req.params.knowledgeId;
|
|
4490
4579
|
if (!knowledgeId || knowledgeId.length < 36) {
|
|
4491
|
-
|
|
4580
|
+
logger10.error(`[Document Processor] \u274C Invalid knowledge ID format: ${knowledgeId}`);
|
|
4492
4581
|
return sendError(res, 400, "INVALID_ID", "Invalid Knowledge ID format");
|
|
4493
4582
|
}
|
|
4494
4583
|
try {
|
|
4495
4584
|
const typedKnowledgeId = knowledgeId;
|
|
4496
|
-
|
|
4585
|
+
logger10.debug(`[Document Processor] \u{1F5D1}\uFE0F Deleting document: ${typedKnowledgeId}`);
|
|
4497
4586
|
await service.deleteMemory(typedKnowledgeId);
|
|
4498
|
-
|
|
4587
|
+
logger10.info(`[Document Processor] \u2705 Successfully deleted document: ${typedKnowledgeId}`);
|
|
4499
4588
|
sendSuccess(res, null, 204);
|
|
4500
4589
|
} catch (error) {
|
|
4501
|
-
|
|
4590
|
+
logger10.error({ error }, `[Document Processor] \u274C Error deleting document ${knowledgeId}`);
|
|
4502
4591
|
sendError(res, 500, "DELETE_ERROR", "Failed to delete document", error.message);
|
|
4503
4592
|
}
|
|
4504
4593
|
}
|
|
4505
4594
|
async function getKnowledgeByIdHandler(req, res, runtime) {
|
|
4506
|
-
|
|
4595
|
+
logger10.debug(`[Document Processor] \u{1F50D} GET request for document: ${req.params.knowledgeId}`);
|
|
4507
4596
|
const service = runtime.getService(KnowledgeService.serviceType);
|
|
4508
4597
|
if (!service) {
|
|
4509
4598
|
return sendError(
|
|
@@ -4515,11 +4604,11 @@ async function getKnowledgeByIdHandler(req, res, runtime) {
|
|
|
4515
4604
|
}
|
|
4516
4605
|
const knowledgeId = req.params.knowledgeId;
|
|
4517
4606
|
if (!knowledgeId || knowledgeId.length < 36) {
|
|
4518
|
-
|
|
4607
|
+
logger10.error(`[Document Processor] \u274C Invalid knowledge ID format: ${knowledgeId}`);
|
|
4519
4608
|
return sendError(res, 400, "INVALID_ID", "Invalid Knowledge ID format");
|
|
4520
4609
|
}
|
|
4521
4610
|
try {
|
|
4522
|
-
|
|
4611
|
+
logger10.debug(`[Document Processor] \u{1F50D} Retrieving document: ${knowledgeId}`);
|
|
4523
4612
|
const agentId = req.query.agentId;
|
|
4524
4613
|
const memories = await service.getMemories({
|
|
4525
4614
|
tableName: "documents",
|
|
@@ -4536,20 +4625,20 @@ async function getKnowledgeByIdHandler(req, res, runtime) {
|
|
|
4536
4625
|
};
|
|
4537
4626
|
sendSuccess(res, { document: cleanDocument });
|
|
4538
4627
|
} catch (error) {
|
|
4539
|
-
|
|
4628
|
+
logger10.error({ error }, `[Document Processor] \u274C Error retrieving document ${knowledgeId}`);
|
|
4540
4629
|
sendError(res, 500, "RETRIEVAL_ERROR", "Failed to retrieve document", error.message);
|
|
4541
4630
|
}
|
|
4542
4631
|
}
|
|
4543
4632
|
async function knowledgePanelHandler(req, res, runtime) {
|
|
4544
4633
|
const agentId = runtime.agentId;
|
|
4545
|
-
|
|
4634
|
+
logger10.debug(`[Document Processor] \u{1F310} Serving knowledge panel for agent ${agentId}`);
|
|
4546
4635
|
const requestPath = req.originalUrl || req.url || req.path;
|
|
4547
4636
|
const pluginBasePath = requestPath.replace(/\/display.*$/, "");
|
|
4548
|
-
|
|
4637
|
+
logger10.debug(`[Document Processor] \u{1F310} Plugin base path: ${pluginBasePath}`);
|
|
4549
4638
|
try {
|
|
4550
4639
|
const currentDir = path4.dirname(new URL(import.meta.url).pathname);
|
|
4551
4640
|
const frontendPath = path4.join(currentDir, "../dist/index.html");
|
|
4552
|
-
|
|
4641
|
+
logger10.debug(`[Document Processor] \u{1F310} Looking for frontend at: ${frontendPath}`);
|
|
4553
4642
|
if (fs4.existsSync(frontendPath)) {
|
|
4554
4643
|
const html = await fs4.promises.readFile(frontendPath, "utf8");
|
|
4555
4644
|
let injectedHtml = html.replace(
|
|
@@ -4585,10 +4674,10 @@ async function knowledgePanelHandler(req, res, runtime) {
|
|
|
4585
4674
|
}
|
|
4586
4675
|
}
|
|
4587
4676
|
} catch (manifestError) {
|
|
4588
|
-
|
|
4677
|
+
logger10.error({ error: manifestError }, "[Document Processor] \u274C Error reading manifest");
|
|
4589
4678
|
}
|
|
4590
4679
|
}
|
|
4591
|
-
|
|
4680
|
+
logger10.debug(`[Document Processor] \u{1F310} Using fallback with CSS: ${cssFile}, JS: ${jsFile}`);
|
|
4592
4681
|
const html = `
|
|
4593
4682
|
<!DOCTYPE html>
|
|
4594
4683
|
<html lang="en">
|
|
@@ -4622,14 +4711,14 @@ async function knowledgePanelHandler(req, res, runtime) {
|
|
|
4622
4711
|
res.end(html);
|
|
4623
4712
|
}
|
|
4624
4713
|
} catch (error) {
|
|
4625
|
-
|
|
4714
|
+
logger10.error({ error }, "[Document Processor] \u274C Error serving frontend");
|
|
4626
4715
|
sendError(res, 500, "FRONTEND_ERROR", "Failed to load knowledge panel", error.message);
|
|
4627
4716
|
}
|
|
4628
4717
|
}
|
|
4629
4718
|
async function frontendAssetHandler(req, res, runtime) {
|
|
4630
4719
|
try {
|
|
4631
4720
|
const fullPath = req.originalUrl || req.url || req.path;
|
|
4632
|
-
|
|
4721
|
+
logger10.debug(`[Document Processor] \u{1F310} Asset request: ${fullPath}`);
|
|
4633
4722
|
const currentDir = path4.dirname(new URL(import.meta.url).pathname);
|
|
4634
4723
|
const assetsMarker = "/assets/";
|
|
4635
4724
|
const assetsStartIndex = fullPath.lastIndexOf(assetsMarker);
|
|
@@ -4650,7 +4739,7 @@ async function frontendAssetHandler(req, res, runtime) {
|
|
|
4650
4739
|
);
|
|
4651
4740
|
}
|
|
4652
4741
|
const assetPath = path4.join(currentDir, "../dist/assets", assetName);
|
|
4653
|
-
|
|
4742
|
+
logger10.debug(`[Document Processor] \u{1F310} Serving asset: ${assetPath}`);
|
|
4654
4743
|
if (fs4.existsSync(assetPath)) {
|
|
4655
4744
|
const fileStream = fs4.createReadStream(assetPath);
|
|
4656
4745
|
let contentType = "application/octet-stream";
|
|
@@ -4665,7 +4754,7 @@ async function frontendAssetHandler(req, res, runtime) {
|
|
|
4665
4754
|
sendError(res, 404, "NOT_FOUND", `Asset not found: ${req.url}`);
|
|
4666
4755
|
}
|
|
4667
4756
|
} catch (error) {
|
|
4668
|
-
|
|
4757
|
+
logger10.error({ error }, `[Document Processor] \u274C Error serving asset ${req.url}`);
|
|
4669
4758
|
sendError(res, 500, "ASSET_ERROR", `Failed to load asset ${req.url}`, error.message);
|
|
4670
4759
|
}
|
|
4671
4760
|
}
|
|
@@ -4726,7 +4815,7 @@ async function getKnowledgeChunksHandler(req, res, runtime) {
|
|
|
4726
4815
|
}
|
|
4727
4816
|
});
|
|
4728
4817
|
} catch (error) {
|
|
4729
|
-
|
|
4818
|
+
logger10.error({ error }, "[Document Processor] \u274C Error retrieving chunks");
|
|
4730
4819
|
sendError(res, 500, "RETRIEVAL_ERROR", "Failed to retrieve knowledge chunks", error.message);
|
|
4731
4820
|
}
|
|
4732
4821
|
}
|
|
@@ -4748,14 +4837,14 @@ async function searchKnowledgeHandler(req, res, runtime) {
|
|
|
4748
4837
|
return sendError(res, 400, "INVALID_QUERY", "Search query cannot be empty");
|
|
4749
4838
|
}
|
|
4750
4839
|
if (req.query.threshold && (parsedThreshold < 0 || parsedThreshold > 1)) {
|
|
4751
|
-
|
|
4840
|
+
logger10.debug(
|
|
4752
4841
|
`[Document Processor] \u{1F50D} Threshold value ${parsedThreshold} was clamped to ${matchThreshold}`
|
|
4753
4842
|
);
|
|
4754
4843
|
}
|
|
4755
4844
|
if (req.query.limit && (parsedLimit < 1 || parsedLimit > 100)) {
|
|
4756
|
-
|
|
4845
|
+
logger10.debug(`[Document Processor] \u{1F50D} Limit value ${parsedLimit} was clamped to ${limit}`);
|
|
4757
4846
|
}
|
|
4758
|
-
|
|
4847
|
+
logger10.debug(
|
|
4759
4848
|
`[Document Processor] \u{1F50D} Searching: "${searchText}" (threshold: ${matchThreshold}, limit: ${limit})`
|
|
4760
4849
|
);
|
|
4761
4850
|
const embedding = await runtime.useModel(ModelType4.TEXT_EMBEDDING, {
|
|
@@ -4782,7 +4871,7 @@ async function searchKnowledgeHandler(req, res, runtime) {
|
|
|
4782
4871
|
documentFilename = document.metadata.filename || documentFilename;
|
|
4783
4872
|
}
|
|
4784
4873
|
} catch (e) {
|
|
4785
|
-
|
|
4874
|
+
logger10.debug(`Could not fetch document ${documentId} for fragment`);
|
|
4786
4875
|
}
|
|
4787
4876
|
}
|
|
4788
4877
|
return {
|
|
@@ -4797,7 +4886,7 @@ async function searchKnowledgeHandler(req, res, runtime) {
|
|
|
4797
4886
|
};
|
|
4798
4887
|
})
|
|
4799
4888
|
);
|
|
4800
|
-
|
|
4889
|
+
logger10.info(
|
|
4801
4890
|
`[Document Processor] \u{1F50D} Found ${enhancedResults.length} results for: "${searchText}"`
|
|
4802
4891
|
);
|
|
4803
4892
|
sendSuccess(res, {
|
|
@@ -4807,7 +4896,7 @@ async function searchKnowledgeHandler(req, res, runtime) {
|
|
|
4807
4896
|
count: enhancedResults.length
|
|
4808
4897
|
});
|
|
4809
4898
|
} catch (error) {
|
|
4810
|
-
|
|
4899
|
+
logger10.error({ error }, "[Document Processor] \u274C Error searching knowledge");
|
|
4811
4900
|
sendError(res, 500, "SEARCH_ERROR", "Failed to search knowledge", error.message);
|
|
4812
4901
|
}
|
|
4813
4902
|
}
|
|
@@ -4824,7 +4913,7 @@ async function getGraphNodesHandler(req, res, runtime) {
|
|
|
4824
4913
|
const page = Number.isNaN(parsedPage) || parsedPage < 1 ? 1 : parsedPage;
|
|
4825
4914
|
const limit = Number.isNaN(parsedLimit) || parsedLimit < 1 ? 20 : Math.min(parsedLimit, 50);
|
|
4826
4915
|
const offset = (page - 1) * limit;
|
|
4827
|
-
|
|
4916
|
+
logger10.debug(
|
|
4828
4917
|
`[Graph API] \u{1F4CA} Fetching graph nodes: page=${page}, limit=${limit}, type=${type || "all"}, agent=${agentId}`
|
|
4829
4918
|
);
|
|
4830
4919
|
const totalDocuments = await service.countMemories({
|
|
@@ -4845,7 +4934,7 @@ async function getGraphNodesHandler(req, res, runtime) {
|
|
|
4845
4934
|
const links = [];
|
|
4846
4935
|
paginatedDocuments.forEach((doc) => {
|
|
4847
4936
|
if (!doc.id) {
|
|
4848
|
-
|
|
4937
|
+
logger10.warn(`[Graph API] \u26A0\uFE0F Skipping document without ID`);
|
|
4849
4938
|
return;
|
|
4850
4939
|
}
|
|
4851
4940
|
nodes.push({ id: doc.id, type: "document" });
|
|
@@ -4857,9 +4946,9 @@ async function getGraphNodesHandler(req, res, runtime) {
|
|
|
4857
4946
|
count: 5e4
|
|
4858
4947
|
// Reduced from 100000 - still high enough for large documents
|
|
4859
4948
|
});
|
|
4860
|
-
|
|
4949
|
+
logger10.debug(`[Graph API] \u{1F4CA} Total fragments found: ${allFragments.length}`);
|
|
4861
4950
|
if (allFragments.length > 0) {
|
|
4862
|
-
|
|
4951
|
+
logger10.debug(
|
|
4863
4952
|
`[Graph API] \u{1F4CA} Sample fragment metadata: ${JSON.stringify(
|
|
4864
4953
|
allFragments.slice(0, 3).map((f) => ({
|
|
4865
4954
|
id: f.id,
|
|
@@ -4875,17 +4964,17 @@ async function getGraphNodesHandler(req, res, runtime) {
|
|
|
4875
4964
|
const docFragments = allFragments.filter((fragment) => {
|
|
4876
4965
|
const metadata = fragment.metadata;
|
|
4877
4966
|
const typeString = typeof metadata?.type === "string" ? metadata.type : null;
|
|
4878
|
-
const isFragment = typeString && typeString.toLowerCase() === "fragment" || metadata?.type ===
|
|
4967
|
+
const isFragment = typeString && typeString.toLowerCase() === "fragment" || metadata?.type === MemoryType5.FRAGMENT || // If no type but has documentId, assume it's a fragment
|
|
4879
4968
|
!metadata?.type && metadata?.documentId;
|
|
4880
4969
|
return metadata?.documentId === doc.id && isFragment;
|
|
4881
4970
|
});
|
|
4882
4971
|
if (docFragments.length > 0) {
|
|
4883
|
-
|
|
4972
|
+
logger10.debug(`[Graph API] \u{1F4CA} Document ${doc.id} has ${docFragments.length} fragments`);
|
|
4884
4973
|
}
|
|
4885
4974
|
docFragments.forEach((frag) => {
|
|
4886
4975
|
const docId = doc.id;
|
|
4887
4976
|
if (!frag.id || !docId) {
|
|
4888
|
-
|
|
4977
|
+
logger10.warn(
|
|
4889
4978
|
`[Graph API] \u26A0\uFE0F Skipping fragment without ID for document ${docId || "unknown"}`
|
|
4890
4979
|
);
|
|
4891
4980
|
return;
|
|
@@ -4894,7 +4983,7 @@ async function getGraphNodesHandler(req, res, runtime) {
|
|
|
4894
4983
|
links.push({ source: docId, target: frag.id });
|
|
4895
4984
|
});
|
|
4896
4985
|
});
|
|
4897
|
-
|
|
4986
|
+
logger10.info(
|
|
4898
4987
|
`[Graph API] \u{1F4CA} Final graph: ${nodes.length} nodes (${paginatedDocuments.length} documents), ${links.length} links`
|
|
4899
4988
|
);
|
|
4900
4989
|
}
|
|
@@ -4909,7 +4998,7 @@ async function getGraphNodesHandler(req, res, runtime) {
|
|
|
4909
4998
|
}
|
|
4910
4999
|
});
|
|
4911
5000
|
} catch (error) {
|
|
4912
|
-
|
|
5001
|
+
logger10.error("[Graph API] \u274C Error fetching graph nodes:", error);
|
|
4913
5002
|
sendError(res, 500, "GRAPH_ERROR", "Failed to fetch graph nodes", error.message);
|
|
4914
5003
|
}
|
|
4915
5004
|
}
|
|
@@ -4924,24 +5013,24 @@ async function getGraphNodeDetailsHandler(req, res, runtime) {
|
|
|
4924
5013
|
return sendError(res, 400, "INVALID_ID", "Invalid node ID format");
|
|
4925
5014
|
}
|
|
4926
5015
|
try {
|
|
4927
|
-
|
|
5016
|
+
logger10.info(`[Graph API] \u{1F4CA} Fetching node details for: ${nodeId}, agent: ${agentId}`);
|
|
4928
5017
|
const allDocuments = await service.getMemories({
|
|
4929
5018
|
tableName: "documents",
|
|
4930
5019
|
count: 1e4
|
|
4931
5020
|
});
|
|
4932
|
-
|
|
5021
|
+
logger10.debug(`[Graph API] \u{1F4CA} Total documents in DB: ${allDocuments.length}`);
|
|
4933
5022
|
let document = allDocuments.find((doc) => doc.id === nodeId && doc.roomId === agentId);
|
|
4934
5023
|
if (!document) {
|
|
4935
|
-
|
|
5024
|
+
logger10.debug(`[Graph API] \u{1F4CA} Document not found with roomId filter, trying without filter`);
|
|
4936
5025
|
document = allDocuments.find((doc) => doc.id === nodeId);
|
|
4937
5026
|
if (document) {
|
|
4938
|
-
|
|
5027
|
+
logger10.warn(
|
|
4939
5028
|
`[Graph API] \u26A0\uFE0F Document ${nodeId} found but has different roomId: ${document.roomId} vs ${agentId}`
|
|
4940
5029
|
);
|
|
4941
5030
|
}
|
|
4942
5031
|
}
|
|
4943
5032
|
if (document) {
|
|
4944
|
-
|
|
5033
|
+
logger10.info(`[Graph API] \u2705 Found document: ${nodeId}`);
|
|
4945
5034
|
sendSuccess(res, {
|
|
4946
5035
|
id: document.id,
|
|
4947
5036
|
type: "document",
|
|
@@ -4955,25 +5044,25 @@ async function getGraphNodeDetailsHandler(req, res, runtime) {
|
|
|
4955
5044
|
});
|
|
4956
5045
|
return;
|
|
4957
5046
|
}
|
|
4958
|
-
|
|
5047
|
+
logger10.debug(`[Graph API] \u{1F4CA} Document not found, searching in fragments`);
|
|
4959
5048
|
const allFragments = await service.getMemories({
|
|
4960
5049
|
tableName: "knowledge",
|
|
4961
5050
|
count: 5e4
|
|
4962
5051
|
// Reduced from 100000 - still high enough for large documents
|
|
4963
5052
|
});
|
|
4964
|
-
|
|
5053
|
+
logger10.debug(`[Graph API] \u{1F4CA} Total fragments in DB: ${allFragments.length}`);
|
|
4965
5054
|
let fragment = allFragments.find((frag) => frag.id === nodeId && frag.roomId === agentId);
|
|
4966
5055
|
if (!fragment) {
|
|
4967
|
-
|
|
5056
|
+
logger10.debug(`[Graph API] \u{1F4CA} Fragment not found with roomId filter, trying without filter`);
|
|
4968
5057
|
fragment = allFragments.find((frag) => frag.id === nodeId);
|
|
4969
5058
|
if (fragment) {
|
|
4970
|
-
|
|
5059
|
+
logger10.warn(
|
|
4971
5060
|
`[Graph API] \u26A0\uFE0F Fragment ${nodeId} found but has different roomId: ${fragment.roomId} vs ${agentId}`
|
|
4972
5061
|
);
|
|
4973
5062
|
}
|
|
4974
5063
|
}
|
|
4975
5064
|
if (fragment) {
|
|
4976
|
-
|
|
5065
|
+
logger10.info(`[Graph API] \u2705 Found fragment: ${nodeId}`);
|
|
4977
5066
|
sendSuccess(res, {
|
|
4978
5067
|
id: fragment.id,
|
|
4979
5068
|
type: "fragment",
|
|
@@ -4987,10 +5076,10 @@ async function getGraphNodeDetailsHandler(req, res, runtime) {
|
|
|
4987
5076
|
});
|
|
4988
5077
|
return;
|
|
4989
5078
|
}
|
|
4990
|
-
|
|
5079
|
+
logger10.error(`[Graph API] \u274C Node ${nodeId} not found in documents or fragments`);
|
|
4991
5080
|
sendError(res, 404, "NOT_FOUND", `Node with ID ${nodeId} not found`);
|
|
4992
5081
|
} catch (error) {
|
|
4993
|
-
|
|
5082
|
+
logger10.error(`[Graph API] \u274C Error fetching node details for ${nodeId}:`, error);
|
|
4994
5083
|
sendError(res, 500, "GRAPH_ERROR", "Failed to fetch node details", error.message);
|
|
4995
5084
|
}
|
|
4996
5085
|
}
|
|
@@ -5005,7 +5094,7 @@ async function expandDocumentGraphHandler(req, res, runtime) {
|
|
|
5005
5094
|
return sendError(res, 400, "INVALID_ID", "Invalid document ID format");
|
|
5006
5095
|
}
|
|
5007
5096
|
try {
|
|
5008
|
-
|
|
5097
|
+
logger10.debug(`[Graph API] \u{1F4CA} Expanding document: ${documentId}, agent: ${agentId}`);
|
|
5009
5098
|
const allFragments = await service.getMemories({
|
|
5010
5099
|
tableName: "knowledge",
|
|
5011
5100
|
roomId: agentId,
|
|
@@ -5013,33 +5102,33 @@ async function expandDocumentGraphHandler(req, res, runtime) {
|
|
|
5013
5102
|
count: 5e4
|
|
5014
5103
|
// Reduced from 100000 - still high enough for large documents
|
|
5015
5104
|
});
|
|
5016
|
-
|
|
5105
|
+
logger10.debug(`[Graph API] \u{1F4CA} Total fragments in knowledge table: ${allFragments.length}`);
|
|
5017
5106
|
if (allFragments.length > 0 && process.env.NODE_ENV !== "production") {
|
|
5018
|
-
|
|
5107
|
+
logger10.debug(
|
|
5019
5108
|
`[Graph API] \u{1F4CA} Sample fragment metadata: ${JSON.stringify(allFragments[0].metadata)}`
|
|
5020
5109
|
);
|
|
5021
5110
|
const uniqueTypes = new Set(allFragments.map((f) => f.metadata?.type));
|
|
5022
|
-
|
|
5111
|
+
logger10.debug(
|
|
5023
5112
|
`[Graph API] \u{1F4CA} Unique metadata types found in knowledge table: ${JSON.stringify(Array.from(uniqueTypes))}`
|
|
5024
5113
|
);
|
|
5025
5114
|
const relevantFragments = allFragments.filter((fragment) => {
|
|
5026
5115
|
const metadata = fragment.metadata;
|
|
5027
5116
|
const hasDocumentId = metadata?.documentId === documentId;
|
|
5028
5117
|
if (hasDocumentId) {
|
|
5029
|
-
|
|
5118
|
+
logger10.debug(
|
|
5030
5119
|
`[Graph API] \u{1F4CA} Fragment ${fragment.id} metadata: ${JSON.stringify(metadata)}`
|
|
5031
5120
|
);
|
|
5032
5121
|
}
|
|
5033
5122
|
return hasDocumentId;
|
|
5034
5123
|
});
|
|
5035
|
-
|
|
5124
|
+
logger10.debug(
|
|
5036
5125
|
`[Graph API] \u{1F4CA} Fragments with matching documentId: ${relevantFragments.length}`
|
|
5037
5126
|
);
|
|
5038
5127
|
}
|
|
5039
5128
|
const documentFragments = allFragments.filter((fragment) => {
|
|
5040
5129
|
const metadata = fragment.metadata;
|
|
5041
5130
|
const typeString = typeof metadata?.type === "string" ? metadata.type : null;
|
|
5042
|
-
const isFragment = typeString && typeString.toLowerCase() === "fragment" || metadata?.type ===
|
|
5131
|
+
const isFragment = typeString && typeString.toLowerCase() === "fragment" || metadata?.type === MemoryType5.FRAGMENT || // If no type but has documentId, assume it's a fragment
|
|
5043
5132
|
!metadata?.type && metadata?.documentId;
|
|
5044
5133
|
return metadata?.documentId === documentId && isFragment;
|
|
5045
5134
|
});
|
|
@@ -5051,7 +5140,7 @@ async function expandDocumentGraphHandler(req, res, runtime) {
|
|
|
5051
5140
|
source: documentId,
|
|
5052
5141
|
target: frag.id
|
|
5053
5142
|
}));
|
|
5054
|
-
|
|
5143
|
+
logger10.info(`[Graph API] \u{1F4CA} Found ${nodes.length} fragments for document ${documentId}`);
|
|
5055
5144
|
sendSuccess(res, {
|
|
5056
5145
|
documentId,
|
|
5057
5146
|
nodes,
|
|
@@ -5059,7 +5148,7 @@ async function expandDocumentGraphHandler(req, res, runtime) {
|
|
|
5059
5148
|
fragmentCount: nodes.length
|
|
5060
5149
|
});
|
|
5061
5150
|
} catch (error) {
|
|
5062
|
-
|
|
5151
|
+
logger10.error(`[Graph API] \u274C Error expanding document ${documentId}:`, error);
|
|
5063
5152
|
sendError(res, 500, "GRAPH_ERROR", "Failed to expand document", error.message);
|
|
5064
5153
|
}
|
|
5065
5154
|
}
|
|
@@ -5071,7 +5160,7 @@ async function uploadKnowledgeWithMulter(req, res, runtime) {
|
|
|
5071
5160
|
);
|
|
5072
5161
|
uploadArray(req, res, (err) => {
|
|
5073
5162
|
if (err) {
|
|
5074
|
-
|
|
5163
|
+
logger10.error({ error: err }, "[Document Processor] \u274C File upload error");
|
|
5075
5164
|
return sendError(res, 400, "UPLOAD_ERROR", err.message);
|
|
5076
5165
|
}
|
|
5077
5166
|
uploadKnowledgeHandler(req, res, runtime);
|
|
@@ -5145,13 +5234,13 @@ function createKnowledgePlugin(config = {}) {
|
|
|
5145
5234
|
name: "knowledge",
|
|
5146
5235
|
description: "Plugin for Retrieval Augmented Generation, including knowledge management and embedding.",
|
|
5147
5236
|
services: [KnowledgeService],
|
|
5148
|
-
providers: [knowledgeProvider]
|
|
5237
|
+
providers: [knowledgeProvider, documentsProvider]
|
|
5149
5238
|
};
|
|
5150
5239
|
if (enableUI || enableRoutes) {
|
|
5151
5240
|
plugin.routes = knowledgeRoutes;
|
|
5152
|
-
|
|
5241
|
+
logger11.debug("[Knowledge Plugin] Routes enabled");
|
|
5153
5242
|
} else {
|
|
5154
|
-
|
|
5243
|
+
logger11.info("[Knowledge Plugin] Running in headless mode (no routes or UI)");
|
|
5155
5244
|
}
|
|
5156
5245
|
if (enableActions) {
|
|
5157
5246
|
plugin.actions = knowledgeActions;
|
|
@@ -5186,6 +5275,7 @@ export {
|
|
|
5186
5275
|
ModelConfigSchema,
|
|
5187
5276
|
createKnowledgePlugin,
|
|
5188
5277
|
index_default as default,
|
|
5278
|
+
documentsProvider,
|
|
5189
5279
|
knowledgePlugin,
|
|
5190
5280
|
knowledgePluginCore,
|
|
5191
5281
|
knowledgePluginHeadless,
|