@elizaos/plugin-knowledge 1.5.12 → 1.5.14
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 +210 -128
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
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 {
|
|
@@ -20,16 +20,16 @@ import {
|
|
|
20
20
|
splitChunks
|
|
21
21
|
} from "@elizaos/core";
|
|
22
22
|
|
|
23
|
-
// node_modules/uuid/dist/
|
|
23
|
+
// node_modules/uuid/dist-node/regex.js
|
|
24
24
|
var regex_default = /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/i;
|
|
25
25
|
|
|
26
|
-
// node_modules/uuid/dist/
|
|
26
|
+
// node_modules/uuid/dist-node/validate.js
|
|
27
27
|
function validate(uuid) {
|
|
28
28
|
return typeof uuid === "string" && regex_default.test(uuid);
|
|
29
29
|
}
|
|
30
30
|
var validate_default = validate;
|
|
31
31
|
|
|
32
|
-
// node_modules/uuid/dist/
|
|
32
|
+
// node_modules/uuid/dist-node/parse.js
|
|
33
33
|
function parse(uuid) {
|
|
34
34
|
if (!validate_default(uuid)) {
|
|
35
35
|
throw TypeError("Invalid UUID");
|
|
@@ -39,7 +39,7 @@ function parse(uuid) {
|
|
|
39
39
|
}
|
|
40
40
|
var parse_default = parse;
|
|
41
41
|
|
|
42
|
-
// node_modules/uuid/dist/
|
|
42
|
+
// node_modules/uuid/dist-node/stringify.js
|
|
43
43
|
var byteToHex = [];
|
|
44
44
|
for (let i = 0; i < 256; ++i) {
|
|
45
45
|
byteToHex.push((i + 256).toString(16).slice(1));
|
|
@@ -48,7 +48,7 @@ function unsafeStringify(arr, offset = 0) {
|
|
|
48
48
|
return (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase();
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
// node_modules/uuid/dist/
|
|
51
|
+
// node_modules/uuid/dist-node/rng.js
|
|
52
52
|
import { randomFillSync } from "crypto";
|
|
53
53
|
var rnds8Pool = new Uint8Array(256);
|
|
54
54
|
var poolPtr = rnds8Pool.length;
|
|
@@ -60,7 +60,7 @@ function rng() {
|
|
|
60
60
|
return rnds8Pool.slice(poolPtr, poolPtr += 16);
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
// node_modules/uuid/dist/
|
|
63
|
+
// node_modules/uuid/dist-node/v35.js
|
|
64
64
|
function stringToBytes(str) {
|
|
65
65
|
str = unescape(encodeURIComponent(str));
|
|
66
66
|
const bytes = new Uint8Array(str.length);
|
|
@@ -96,15 +96,12 @@ function v35(version, hash, value, namespace, buf, offset) {
|
|
|
96
96
|
return unsafeStringify(bytes);
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
-
// node_modules/uuid/dist/
|
|
99
|
+
// node_modules/uuid/dist-node/native.js
|
|
100
100
|
import { randomUUID } from "crypto";
|
|
101
101
|
var native_default = { randomUUID };
|
|
102
102
|
|
|
103
|
-
// node_modules/uuid/dist/
|
|
104
|
-
function
|
|
105
|
-
if (native_default.randomUUID && !buf && !options) {
|
|
106
|
-
return native_default.randomUUID();
|
|
107
|
-
}
|
|
103
|
+
// node_modules/uuid/dist-node/v4.js
|
|
104
|
+
function _v4(options, buf, offset) {
|
|
108
105
|
options = options || {};
|
|
109
106
|
const rnds = options.random ?? options.rng?.() ?? rng();
|
|
110
107
|
if (rnds.length < 16) {
|
|
@@ -124,9 +121,15 @@ function v4(options, buf, offset) {
|
|
|
124
121
|
}
|
|
125
122
|
return unsafeStringify(rnds);
|
|
126
123
|
}
|
|
124
|
+
function v4(options, buf, offset) {
|
|
125
|
+
if (native_default.randomUUID && !buf && !options) {
|
|
126
|
+
return native_default.randomUUID();
|
|
127
|
+
}
|
|
128
|
+
return _v4(options, buf, offset);
|
|
129
|
+
}
|
|
127
130
|
var v4_default = v4;
|
|
128
131
|
|
|
129
|
-
// node_modules/uuid/dist/
|
|
132
|
+
// node_modules/uuid/dist-node/sha1.js
|
|
130
133
|
import { createHash } from "crypto";
|
|
131
134
|
function sha1(bytes) {
|
|
132
135
|
if (Array.isArray(bytes)) {
|
|
@@ -138,7 +141,7 @@ function sha1(bytes) {
|
|
|
138
141
|
}
|
|
139
142
|
var sha1_default = sha1;
|
|
140
143
|
|
|
141
|
-
// node_modules/uuid/dist/
|
|
144
|
+
// node_modules/uuid/dist-node/v5.js
|
|
142
145
|
function v5(value, namespace, buf, offset) {
|
|
143
146
|
return v35(80, sha1_default, value, namespace, buf, offset);
|
|
144
147
|
}
|
|
@@ -1083,7 +1086,7 @@ function logCacheMetrics(result) {
|
|
|
1083
1086
|
import { Buffer as Buffer2 } from "buffer";
|
|
1084
1087
|
import * as mammoth from "mammoth";
|
|
1085
1088
|
import { logger as logger3 } from "@elizaos/core";
|
|
1086
|
-
import {
|
|
1089
|
+
import { extractText } from "unpdf";
|
|
1087
1090
|
import { createHash as createHash2 } from "crypto";
|
|
1088
1091
|
var PLAIN_TEXT_CONTENT_TYPES = [
|
|
1089
1092
|
"application/typescript",
|
|
@@ -1162,32 +1165,24 @@ This document was indexed for search but cannot be displayed directly in the bro
|
|
|
1162
1165
|
}
|
|
1163
1166
|
async function convertPdfToTextFromBuffer(pdfBuffer, filename) {
|
|
1164
1167
|
const docName = filename || "unnamed-document";
|
|
1165
|
-
logger3.debug(`[PdfService] Starting conversion for ${docName}`);
|
|
1168
|
+
logger3.debug(`[PdfService] Starting conversion for ${docName} using unpdf`);
|
|
1166
1169
|
try {
|
|
1167
|
-
const uint8Array = new Uint8Array(
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
const
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
const yPos = Math.round(item.transform[5]);
|
|
1178
|
-
if (!lineMap.has(yPos)) {
|
|
1179
|
-
lineMap.set(yPos, []);
|
|
1180
|
-
}
|
|
1181
|
-
lineMap.get(yPos).push(item);
|
|
1182
|
-
});
|
|
1183
|
-
const sortedLines = Array.from(lineMap.entries()).sort((a, b) => b[0] - a[0]).map(
|
|
1184
|
-
([_, items]) => items.sort((a, b) => a.transform[4] - b.transform[4]).map((item) => item.str).join(" ")
|
|
1185
|
-
);
|
|
1186
|
-
textPages.push(sortedLines.join("\n"));
|
|
1170
|
+
const uint8Array = new Uint8Array(
|
|
1171
|
+
pdfBuffer.buffer.slice(pdfBuffer.byteOffset, pdfBuffer.byteOffset + pdfBuffer.byteLength)
|
|
1172
|
+
);
|
|
1173
|
+
const result = await extractText(uint8Array, {
|
|
1174
|
+
mergePages: true
|
|
1175
|
+
// Merge all pages into a single string
|
|
1176
|
+
});
|
|
1177
|
+
if (!result.text || result.text.trim().length === 0) {
|
|
1178
|
+
logger3.warn(`[PdfService] No text extracted from ${docName}`);
|
|
1179
|
+
return "";
|
|
1187
1180
|
}
|
|
1188
|
-
const
|
|
1189
|
-
logger3.debug(
|
|
1190
|
-
|
|
1181
|
+
const cleanedText = result.text.split("\n").map((line) => line.trim()).filter((line) => line.length > 0).join("\n").replace(/\n{3,}/g, "\n\n");
|
|
1182
|
+
logger3.debug(
|
|
1183
|
+
`[PdfService] Conversion complete for ${docName}, ${result.totalPages} pages, length: ${cleanedText.length}`
|
|
1184
|
+
);
|
|
1185
|
+
return cleanedText;
|
|
1191
1186
|
} catch (error) {
|
|
1192
1187
|
logger3.error(`[PdfService] Error converting PDF ${docName}:`, error.message);
|
|
1193
1188
|
throw new Error(`Failed to convert PDF to text: ${error.message}`);
|
|
@@ -1336,9 +1331,6 @@ function isBinaryContentType(contentType, filename) {
|
|
|
1336
1331
|
];
|
|
1337
1332
|
return binaryExtensions.includes(fileExt);
|
|
1338
1333
|
}
|
|
1339
|
-
function isTextItem(item) {
|
|
1340
|
-
return "str" in item;
|
|
1341
|
-
}
|
|
1342
1334
|
function normalizeS3Url(url) {
|
|
1343
1335
|
try {
|
|
1344
1336
|
const urlObj = new URL(url);
|
|
@@ -3033,8 +3025,97 @@ var knowledgeProvider = {
|
|
|
3033
3025
|
}
|
|
3034
3026
|
};
|
|
3035
3027
|
|
|
3028
|
+
// src/documents-provider.ts
|
|
3029
|
+
import { addHeader as addHeader2, logger as logger8, MemoryType as MemoryType3 } from "@elizaos/core";
|
|
3030
|
+
var documentsProvider = {
|
|
3031
|
+
name: "AVAILABLE_DOCUMENTS",
|
|
3032
|
+
description: "List of documents available in the knowledge base. Shows which documents the agent can reference and retrieve information from.",
|
|
3033
|
+
dynamic: false,
|
|
3034
|
+
// Static provider - doesn't change based on the message
|
|
3035
|
+
get: async (runtime) => {
|
|
3036
|
+
try {
|
|
3037
|
+
const knowledgeService = runtime.getService("knowledge");
|
|
3038
|
+
if (!knowledgeService) {
|
|
3039
|
+
logger8.warn("Knowledge service not available for documents provider");
|
|
3040
|
+
return {
|
|
3041
|
+
data: { documents: [] },
|
|
3042
|
+
values: { documents: "" },
|
|
3043
|
+
text: ""
|
|
3044
|
+
};
|
|
3045
|
+
}
|
|
3046
|
+
const allMemories = await knowledgeService.getMemories({
|
|
3047
|
+
tableName: "documents",
|
|
3048
|
+
roomId: runtime.agentId,
|
|
3049
|
+
count: 100
|
|
3050
|
+
// Limit to 100 documents to avoid context overflow
|
|
3051
|
+
});
|
|
3052
|
+
const documents = allMemories.filter(
|
|
3053
|
+
(memory) => memory.metadata?.type === MemoryType3.DOCUMENT
|
|
3054
|
+
);
|
|
3055
|
+
if (!documents || documents.length === 0) {
|
|
3056
|
+
return {
|
|
3057
|
+
data: { documents: [] },
|
|
3058
|
+
values: { documents: "" },
|
|
3059
|
+
text: ""
|
|
3060
|
+
};
|
|
3061
|
+
}
|
|
3062
|
+
const documentsList = documents.map((doc, index) => {
|
|
3063
|
+
const metadata = doc.metadata;
|
|
3064
|
+
const filename = metadata?.filename || metadata?.title || `Document ${index + 1}`;
|
|
3065
|
+
const fileType = metadata?.fileExt || metadata?.fileType || "unknown";
|
|
3066
|
+
const source = metadata?.source || "upload";
|
|
3067
|
+
const fileSize = metadata?.fileSize;
|
|
3068
|
+
const parts = [filename];
|
|
3069
|
+
if (fileType && fileType !== "unknown") {
|
|
3070
|
+
parts.push(fileType);
|
|
3071
|
+
}
|
|
3072
|
+
if (fileSize) {
|
|
3073
|
+
const sizeKB = Math.round(fileSize / 1024);
|
|
3074
|
+
if (sizeKB > 1024) {
|
|
3075
|
+
parts.push(`${Math.round(sizeKB / 1024)}MB`);
|
|
3076
|
+
} else {
|
|
3077
|
+
parts.push(`${sizeKB}KB`);
|
|
3078
|
+
}
|
|
3079
|
+
}
|
|
3080
|
+
if (source && source !== "upload") {
|
|
3081
|
+
parts.push(`from ${source}`);
|
|
3082
|
+
}
|
|
3083
|
+
return parts.join(" - ");
|
|
3084
|
+
}).join("\n");
|
|
3085
|
+
const documentsText = addHeader2(
|
|
3086
|
+
"# Available Documents",
|
|
3087
|
+
`${documents.length} document(s) in knowledge base:
|
|
3088
|
+
${documentsList}`
|
|
3089
|
+
);
|
|
3090
|
+
return {
|
|
3091
|
+
data: {
|
|
3092
|
+
documents: documents.map((doc) => ({
|
|
3093
|
+
id: doc.id,
|
|
3094
|
+
filename: doc.metadata?.filename || doc.metadata?.title,
|
|
3095
|
+
fileType: doc.metadata?.fileType || doc.metadata?.fileExt,
|
|
3096
|
+
source: doc.metadata?.source
|
|
3097
|
+
})),
|
|
3098
|
+
count: documents.length
|
|
3099
|
+
},
|
|
3100
|
+
values: {
|
|
3101
|
+
documentsCount: documents.length,
|
|
3102
|
+
documents: documentsList
|
|
3103
|
+
},
|
|
3104
|
+
text: documentsText
|
|
3105
|
+
};
|
|
3106
|
+
} catch (error) {
|
|
3107
|
+
logger8.error("Error in documents provider:", error.message);
|
|
3108
|
+
return {
|
|
3109
|
+
data: { documents: [], error: error.message },
|
|
3110
|
+
values: { documents: "" },
|
|
3111
|
+
text: ""
|
|
3112
|
+
};
|
|
3113
|
+
}
|
|
3114
|
+
}
|
|
3115
|
+
};
|
|
3116
|
+
|
|
3036
3117
|
// src/tests.ts
|
|
3037
|
-
import { MemoryType as
|
|
3118
|
+
import { MemoryType as MemoryType4, ModelType as ModelType3 } from "@elizaos/core";
|
|
3038
3119
|
import { Buffer as Buffer3 } from "buffer";
|
|
3039
3120
|
import * as fs2 from "fs";
|
|
3040
3121
|
import * as path2 from "path";
|
|
@@ -3159,9 +3240,9 @@ function createMockRuntime(overrides) {
|
|
|
3159
3240
|
const results = Array.from(memories.values()).filter((m) => {
|
|
3160
3241
|
if (params.roomId && m.roomId !== params.roomId) return false;
|
|
3161
3242
|
if (params.entityId && m.entityId !== params.entityId) return false;
|
|
3162
|
-
if (params.tableName === "knowledge" && m.metadata?.type !==
|
|
3243
|
+
if (params.tableName === "knowledge" && m.metadata?.type !== MemoryType4.FRAGMENT)
|
|
3163
3244
|
return false;
|
|
3164
|
-
if (params.tableName === "documents" && m.metadata?.type !==
|
|
3245
|
+
if (params.tableName === "documents" && m.metadata?.type !== MemoryType4.DOCUMENT)
|
|
3165
3246
|
return false;
|
|
3166
3247
|
return true;
|
|
3167
3248
|
});
|
|
@@ -3175,7 +3256,7 @@ function createMockRuntime(overrides) {
|
|
|
3175
3256
|
},
|
|
3176
3257
|
async searchMemories(params) {
|
|
3177
3258
|
const fragments = Array.from(memories.values()).filter(
|
|
3178
|
-
(m) => m.metadata?.type ===
|
|
3259
|
+
(m) => m.metadata?.type === MemoryType4.FRAGMENT
|
|
3179
3260
|
);
|
|
3180
3261
|
return fragments.map((f) => ({
|
|
3181
3262
|
...f,
|
|
@@ -3547,7 +3628,7 @@ var KnowledgeTestSuite = class {
|
|
|
3547
3628
|
if (!memory.id) {
|
|
3548
3629
|
throw new Error("Document memory should have an ID");
|
|
3549
3630
|
}
|
|
3550
|
-
if (memory.metadata?.type !==
|
|
3631
|
+
if (memory.metadata?.type !== MemoryType4.DOCUMENT) {
|
|
3551
3632
|
throw new Error("Document memory should have DOCUMENT type");
|
|
3552
3633
|
}
|
|
3553
3634
|
if (memory.content.text !== params.text) {
|
|
@@ -3920,7 +4001,7 @@ var KnowledgeTestSuite = class {
|
|
|
3920
4001
|
var tests_default = new KnowledgeTestSuite();
|
|
3921
4002
|
|
|
3922
4003
|
// src/actions.ts
|
|
3923
|
-
import { logger as
|
|
4004
|
+
import { logger as logger9, stringToUuid } from "@elizaos/core";
|
|
3924
4005
|
import * as fs3 from "fs";
|
|
3925
4006
|
import * as path3 from "path";
|
|
3926
4007
|
var processKnowledgeAction = {
|
|
@@ -3978,7 +4059,7 @@ var processKnowledgeAction = {
|
|
|
3978
4059
|
const hasPath = pathPattern.test(text);
|
|
3979
4060
|
const service = runtime.getService(KnowledgeService.serviceType);
|
|
3980
4061
|
if (!service) {
|
|
3981
|
-
|
|
4062
|
+
logger9.warn("Knowledge service not available for PROCESS_KNOWLEDGE action");
|
|
3982
4063
|
return false;
|
|
3983
4064
|
}
|
|
3984
4065
|
return hasKeyword || hasPath;
|
|
@@ -4056,7 +4137,7 @@ var processKnowledgeAction = {
|
|
|
4056
4137
|
await callback(response);
|
|
4057
4138
|
}
|
|
4058
4139
|
} catch (error) {
|
|
4059
|
-
|
|
4140
|
+
logger9.error({ error }, "Error in PROCESS_KNOWLEDGE action");
|
|
4060
4141
|
const errorResponse = {
|
|
4061
4142
|
text: `I encountered an error while processing the knowledge: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
4062
4143
|
};
|
|
@@ -4147,7 +4228,7 @@ ${formattedResults}`
|
|
|
4147
4228
|
await callback(response);
|
|
4148
4229
|
}
|
|
4149
4230
|
} catch (error) {
|
|
4150
|
-
|
|
4231
|
+
logger9.error({ error }, "Error in SEARCH_KNOWLEDGE action");
|
|
4151
4232
|
const errorResponse = {
|
|
4152
4233
|
text: `I encountered an error while searching the knowledge base: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
4153
4234
|
};
|
|
@@ -4160,7 +4241,7 @@ ${formattedResults}`
|
|
|
4160
4241
|
var knowledgeActions = [processKnowledgeAction, searchKnowledgeAction];
|
|
4161
4242
|
|
|
4162
4243
|
// src/routes.ts
|
|
4163
|
-
import { MemoryType as
|
|
4244
|
+
import { MemoryType as MemoryType5, createUniqueUuid as createUniqueUuid2, logger as logger10, ModelType as ModelType4 } from "@elizaos/core";
|
|
4164
4245
|
import fs4 from "fs";
|
|
4165
4246
|
import path4 from "path";
|
|
4166
4247
|
import multer from "multer";
|
|
@@ -4211,7 +4292,7 @@ var cleanupFile = (filePath) => {
|
|
|
4211
4292
|
try {
|
|
4212
4293
|
fs4.unlinkSync(filePath);
|
|
4213
4294
|
} catch (error) {
|
|
4214
|
-
|
|
4295
|
+
logger10.error({ error }, `Error cleaning up file ${filePath}`);
|
|
4215
4296
|
}
|
|
4216
4297
|
}
|
|
4217
4298
|
};
|
|
@@ -4238,15 +4319,15 @@ async function uploadKnowledgeHandler(req, res, runtime) {
|
|
|
4238
4319
|
}
|
|
4239
4320
|
const invalidFiles = files.filter((file) => {
|
|
4240
4321
|
if (file.size === 0) {
|
|
4241
|
-
|
|
4322
|
+
logger10.warn(`File ${file.originalname} is empty`);
|
|
4242
4323
|
return true;
|
|
4243
4324
|
}
|
|
4244
4325
|
if (!file.originalname || file.originalname.trim() === "") {
|
|
4245
|
-
|
|
4326
|
+
logger10.warn(`File has no name`);
|
|
4246
4327
|
return true;
|
|
4247
4328
|
}
|
|
4248
4329
|
if (!file.path) {
|
|
4249
|
-
|
|
4330
|
+
logger10.warn(`File ${file.originalname} has no path`);
|
|
4250
4331
|
return true;
|
|
4251
4332
|
}
|
|
4252
4333
|
return false;
|
|
@@ -4263,7 +4344,7 @@ async function uploadKnowledgeHandler(req, res, runtime) {
|
|
|
4263
4344
|
}
|
|
4264
4345
|
const agentId = req.body.agentId || req.query.agentId;
|
|
4265
4346
|
if (!agentId) {
|
|
4266
|
-
|
|
4347
|
+
logger10.error("[Document Processor] \u274C No agent ID provided in upload request");
|
|
4267
4348
|
return sendError(
|
|
4268
4349
|
res,
|
|
4269
4350
|
400,
|
|
@@ -4272,11 +4353,11 @@ async function uploadKnowledgeHandler(req, res, runtime) {
|
|
|
4272
4353
|
);
|
|
4273
4354
|
}
|
|
4274
4355
|
const worldId = req.body.worldId || agentId;
|
|
4275
|
-
|
|
4356
|
+
logger10.info(`[Document Processor] \u{1F4E4} Processing file upload for agent: ${agentId}`);
|
|
4276
4357
|
const processingPromises = files.map(async (file, index) => {
|
|
4277
4358
|
const originalFilename = file.originalname;
|
|
4278
4359
|
const filePath = file.path;
|
|
4279
|
-
|
|
4360
|
+
logger10.debug(
|
|
4280
4361
|
`[Document Processor] \u{1F4C4} Processing file: ${originalFilename} (agent: ${agentId})`
|
|
4281
4362
|
);
|
|
4282
4363
|
try {
|
|
@@ -4311,7 +4392,7 @@ async function uploadKnowledgeHandler(req, res, runtime) {
|
|
|
4311
4392
|
status: "success"
|
|
4312
4393
|
};
|
|
4313
4394
|
} catch (fileError) {
|
|
4314
|
-
|
|
4395
|
+
logger10.error(
|
|
4315
4396
|
`[Document Processor] \u274C Error processing file ${file.originalname}:`,
|
|
4316
4397
|
fileError
|
|
4317
4398
|
);
|
|
@@ -4334,7 +4415,7 @@ async function uploadKnowledgeHandler(req, res, runtime) {
|
|
|
4334
4415
|
}
|
|
4335
4416
|
const agentId = req.body.agentId || req.query.agentId;
|
|
4336
4417
|
if (!agentId) {
|
|
4337
|
-
|
|
4418
|
+
logger10.error("[Document Processor] \u274C No agent ID provided in URL request");
|
|
4338
4419
|
return sendError(
|
|
4339
4420
|
res,
|
|
4340
4421
|
400,
|
|
@@ -4342,7 +4423,7 @@ async function uploadKnowledgeHandler(req, res, runtime) {
|
|
|
4342
4423
|
"Agent ID is required for uploading knowledge from URLs"
|
|
4343
4424
|
);
|
|
4344
4425
|
}
|
|
4345
|
-
|
|
4426
|
+
logger10.info(`[Document Processor] \u{1F4E4} Processing URL upload for agent: ${agentId}`);
|
|
4346
4427
|
const processingPromises = fileUrls.map(async (fileUrl) => {
|
|
4347
4428
|
try {
|
|
4348
4429
|
const normalizedUrl = normalizeS3Url(fileUrl);
|
|
@@ -4350,7 +4431,7 @@ async function uploadKnowledgeHandler(req, res, runtime) {
|
|
|
4350
4431
|
const pathSegments = urlObject.pathname.split("/");
|
|
4351
4432
|
const encodedFilename = pathSegments[pathSegments.length - 1] || "document.pdf";
|
|
4352
4433
|
const originalFilename = decodeURIComponent(encodedFilename);
|
|
4353
|
-
|
|
4434
|
+
logger10.debug(`[Document Processor] \u{1F310} Fetching content from URL: ${fileUrl}`);
|
|
4354
4435
|
const { content, contentType: fetchedContentType } = await fetchUrlContent(fileUrl);
|
|
4355
4436
|
let contentType = fetchedContentType;
|
|
4356
4437
|
if (contentType === "application/octet-stream") {
|
|
@@ -4390,7 +4471,7 @@ async function uploadKnowledgeHandler(req, res, runtime) {
|
|
|
4390
4471
|
url: normalizedUrl
|
|
4391
4472
|
}
|
|
4392
4473
|
};
|
|
4393
|
-
|
|
4474
|
+
logger10.debug(
|
|
4394
4475
|
`[Document Processor] \u{1F4C4} Processing knowledge from URL: ${originalFilename} (type: ${contentType})`
|
|
4395
4476
|
);
|
|
4396
4477
|
const result = await service.addKnowledge(addKnowledgeOpts);
|
|
@@ -4405,7 +4486,7 @@ async function uploadKnowledgeHandler(req, res, runtime) {
|
|
|
4405
4486
|
status: "success"
|
|
4406
4487
|
};
|
|
4407
4488
|
} catch (urlError) {
|
|
4408
|
-
|
|
4489
|
+
logger10.error(`[Document Processor] \u274C Error processing URL ${fileUrl}:`, urlError);
|
|
4409
4490
|
return {
|
|
4410
4491
|
fileUrl,
|
|
4411
4492
|
status: "error_processing",
|
|
@@ -4417,7 +4498,7 @@ async function uploadKnowledgeHandler(req, res, runtime) {
|
|
|
4417
4498
|
sendSuccess(res, results);
|
|
4418
4499
|
}
|
|
4419
4500
|
} catch (error) {
|
|
4420
|
-
|
|
4501
|
+
logger10.error({ error }, "[Document Processor] \u274C Error processing knowledge");
|
|
4421
4502
|
if (hasUploadedFiles) {
|
|
4422
4503
|
cleanupFiles(req.files);
|
|
4423
4504
|
}
|
|
@@ -4456,7 +4537,7 @@ async function getKnowledgeDocumentsHandler(req, res, runtime) {
|
|
|
4456
4537
|
// Or if the URL is stored in the metadata (check if it exists)
|
|
4457
4538
|
memory.metadata && "url" in memory.metadata && typeof memory.metadata.url === "string" && normalizedRequestUrls.includes(normalizeS3Url(memory.metadata.url))
|
|
4458
4539
|
);
|
|
4459
|
-
|
|
4540
|
+
logger10.debug(
|
|
4460
4541
|
`[Document Processor] \u{1F50D} Filtered documents by URLs: ${fileUrls.length} URLs, found ${filteredMemories.length} matching documents`
|
|
4461
4542
|
);
|
|
4462
4543
|
}
|
|
@@ -4471,12 +4552,12 @@ async function getKnowledgeDocumentsHandler(req, res, runtime) {
|
|
|
4471
4552
|
totalRequested: fileUrls ? fileUrls.length : 0
|
|
4472
4553
|
});
|
|
4473
4554
|
} catch (error) {
|
|
4474
|
-
|
|
4555
|
+
logger10.error({ error }, "[Document Processor] \u274C Error retrieving documents");
|
|
4475
4556
|
sendError(res, 500, "RETRIEVAL_ERROR", "Failed to retrieve documents", error.message);
|
|
4476
4557
|
}
|
|
4477
4558
|
}
|
|
4478
4559
|
async function deleteKnowledgeDocumentHandler(req, res, runtime) {
|
|
4479
|
-
|
|
4560
|
+
logger10.debug(`[Document Processor] \u{1F5D1}\uFE0F DELETE request for document: ${req.params.knowledgeId}`);
|
|
4480
4561
|
const service = runtime.getService(KnowledgeService.serviceType);
|
|
4481
4562
|
if (!service) {
|
|
4482
4563
|
return sendError(
|
|
@@ -4488,22 +4569,22 @@ async function deleteKnowledgeDocumentHandler(req, res, runtime) {
|
|
|
4488
4569
|
}
|
|
4489
4570
|
const knowledgeId = req.params.knowledgeId;
|
|
4490
4571
|
if (!knowledgeId || knowledgeId.length < 36) {
|
|
4491
|
-
|
|
4572
|
+
logger10.error(`[Document Processor] \u274C Invalid knowledge ID format: ${knowledgeId}`);
|
|
4492
4573
|
return sendError(res, 400, "INVALID_ID", "Invalid Knowledge ID format");
|
|
4493
4574
|
}
|
|
4494
4575
|
try {
|
|
4495
4576
|
const typedKnowledgeId = knowledgeId;
|
|
4496
|
-
|
|
4577
|
+
logger10.debug(`[Document Processor] \u{1F5D1}\uFE0F Deleting document: ${typedKnowledgeId}`);
|
|
4497
4578
|
await service.deleteMemory(typedKnowledgeId);
|
|
4498
|
-
|
|
4579
|
+
logger10.info(`[Document Processor] \u2705 Successfully deleted document: ${typedKnowledgeId}`);
|
|
4499
4580
|
sendSuccess(res, null, 204);
|
|
4500
4581
|
} catch (error) {
|
|
4501
|
-
|
|
4582
|
+
logger10.error({ error }, `[Document Processor] \u274C Error deleting document ${knowledgeId}`);
|
|
4502
4583
|
sendError(res, 500, "DELETE_ERROR", "Failed to delete document", error.message);
|
|
4503
4584
|
}
|
|
4504
4585
|
}
|
|
4505
4586
|
async function getKnowledgeByIdHandler(req, res, runtime) {
|
|
4506
|
-
|
|
4587
|
+
logger10.debug(`[Document Processor] \u{1F50D} GET request for document: ${req.params.knowledgeId}`);
|
|
4507
4588
|
const service = runtime.getService(KnowledgeService.serviceType);
|
|
4508
4589
|
if (!service) {
|
|
4509
4590
|
return sendError(
|
|
@@ -4515,11 +4596,11 @@ async function getKnowledgeByIdHandler(req, res, runtime) {
|
|
|
4515
4596
|
}
|
|
4516
4597
|
const knowledgeId = req.params.knowledgeId;
|
|
4517
4598
|
if (!knowledgeId || knowledgeId.length < 36) {
|
|
4518
|
-
|
|
4599
|
+
logger10.error(`[Document Processor] \u274C Invalid knowledge ID format: ${knowledgeId}`);
|
|
4519
4600
|
return sendError(res, 400, "INVALID_ID", "Invalid Knowledge ID format");
|
|
4520
4601
|
}
|
|
4521
4602
|
try {
|
|
4522
|
-
|
|
4603
|
+
logger10.debug(`[Document Processor] \u{1F50D} Retrieving document: ${knowledgeId}`);
|
|
4523
4604
|
const agentId = req.query.agentId;
|
|
4524
4605
|
const memories = await service.getMemories({
|
|
4525
4606
|
tableName: "documents",
|
|
@@ -4536,20 +4617,20 @@ async function getKnowledgeByIdHandler(req, res, runtime) {
|
|
|
4536
4617
|
};
|
|
4537
4618
|
sendSuccess(res, { document: cleanDocument });
|
|
4538
4619
|
} catch (error) {
|
|
4539
|
-
|
|
4620
|
+
logger10.error({ error }, `[Document Processor] \u274C Error retrieving document ${knowledgeId}`);
|
|
4540
4621
|
sendError(res, 500, "RETRIEVAL_ERROR", "Failed to retrieve document", error.message);
|
|
4541
4622
|
}
|
|
4542
4623
|
}
|
|
4543
4624
|
async function knowledgePanelHandler(req, res, runtime) {
|
|
4544
4625
|
const agentId = runtime.agentId;
|
|
4545
|
-
|
|
4626
|
+
logger10.debug(`[Document Processor] \u{1F310} Serving knowledge panel for agent ${agentId}`);
|
|
4546
4627
|
const requestPath = req.originalUrl || req.url || req.path;
|
|
4547
4628
|
const pluginBasePath = requestPath.replace(/\/display.*$/, "");
|
|
4548
|
-
|
|
4629
|
+
logger10.debug(`[Document Processor] \u{1F310} Plugin base path: ${pluginBasePath}`);
|
|
4549
4630
|
try {
|
|
4550
4631
|
const currentDir = path4.dirname(new URL(import.meta.url).pathname);
|
|
4551
4632
|
const frontendPath = path4.join(currentDir, "../dist/index.html");
|
|
4552
|
-
|
|
4633
|
+
logger10.debug(`[Document Processor] \u{1F310} Looking for frontend at: ${frontendPath}`);
|
|
4553
4634
|
if (fs4.existsSync(frontendPath)) {
|
|
4554
4635
|
const html = await fs4.promises.readFile(frontendPath, "utf8");
|
|
4555
4636
|
let injectedHtml = html.replace(
|
|
@@ -4585,10 +4666,10 @@ async function knowledgePanelHandler(req, res, runtime) {
|
|
|
4585
4666
|
}
|
|
4586
4667
|
}
|
|
4587
4668
|
} catch (manifestError) {
|
|
4588
|
-
|
|
4669
|
+
logger10.error({ error: manifestError }, "[Document Processor] \u274C Error reading manifest");
|
|
4589
4670
|
}
|
|
4590
4671
|
}
|
|
4591
|
-
|
|
4672
|
+
logger10.debug(`[Document Processor] \u{1F310} Using fallback with CSS: ${cssFile}, JS: ${jsFile}`);
|
|
4592
4673
|
const html = `
|
|
4593
4674
|
<!DOCTYPE html>
|
|
4594
4675
|
<html lang="en">
|
|
@@ -4622,14 +4703,14 @@ async function knowledgePanelHandler(req, res, runtime) {
|
|
|
4622
4703
|
res.end(html);
|
|
4623
4704
|
}
|
|
4624
4705
|
} catch (error) {
|
|
4625
|
-
|
|
4706
|
+
logger10.error({ error }, "[Document Processor] \u274C Error serving frontend");
|
|
4626
4707
|
sendError(res, 500, "FRONTEND_ERROR", "Failed to load knowledge panel", error.message);
|
|
4627
4708
|
}
|
|
4628
4709
|
}
|
|
4629
4710
|
async function frontendAssetHandler(req, res, runtime) {
|
|
4630
4711
|
try {
|
|
4631
4712
|
const fullPath = req.originalUrl || req.url || req.path;
|
|
4632
|
-
|
|
4713
|
+
logger10.debug(`[Document Processor] \u{1F310} Asset request: ${fullPath}`);
|
|
4633
4714
|
const currentDir = path4.dirname(new URL(import.meta.url).pathname);
|
|
4634
4715
|
const assetsMarker = "/assets/";
|
|
4635
4716
|
const assetsStartIndex = fullPath.lastIndexOf(assetsMarker);
|
|
@@ -4650,7 +4731,7 @@ async function frontendAssetHandler(req, res, runtime) {
|
|
|
4650
4731
|
);
|
|
4651
4732
|
}
|
|
4652
4733
|
const assetPath = path4.join(currentDir, "../dist/assets", assetName);
|
|
4653
|
-
|
|
4734
|
+
logger10.debug(`[Document Processor] \u{1F310} Serving asset: ${assetPath}`);
|
|
4654
4735
|
if (fs4.existsSync(assetPath)) {
|
|
4655
4736
|
const fileStream = fs4.createReadStream(assetPath);
|
|
4656
4737
|
let contentType = "application/octet-stream";
|
|
@@ -4665,7 +4746,7 @@ async function frontendAssetHandler(req, res, runtime) {
|
|
|
4665
4746
|
sendError(res, 404, "NOT_FOUND", `Asset not found: ${req.url}`);
|
|
4666
4747
|
}
|
|
4667
4748
|
} catch (error) {
|
|
4668
|
-
|
|
4749
|
+
logger10.error({ error }, `[Document Processor] \u274C Error serving asset ${req.url}`);
|
|
4669
4750
|
sendError(res, 500, "ASSET_ERROR", `Failed to load asset ${req.url}`, error.message);
|
|
4670
4751
|
}
|
|
4671
4752
|
}
|
|
@@ -4726,7 +4807,7 @@ async function getKnowledgeChunksHandler(req, res, runtime) {
|
|
|
4726
4807
|
}
|
|
4727
4808
|
});
|
|
4728
4809
|
} catch (error) {
|
|
4729
|
-
|
|
4810
|
+
logger10.error({ error }, "[Document Processor] \u274C Error retrieving chunks");
|
|
4730
4811
|
sendError(res, 500, "RETRIEVAL_ERROR", "Failed to retrieve knowledge chunks", error.message);
|
|
4731
4812
|
}
|
|
4732
4813
|
}
|
|
@@ -4748,14 +4829,14 @@ async function searchKnowledgeHandler(req, res, runtime) {
|
|
|
4748
4829
|
return sendError(res, 400, "INVALID_QUERY", "Search query cannot be empty");
|
|
4749
4830
|
}
|
|
4750
4831
|
if (req.query.threshold && (parsedThreshold < 0 || parsedThreshold > 1)) {
|
|
4751
|
-
|
|
4832
|
+
logger10.debug(
|
|
4752
4833
|
`[Document Processor] \u{1F50D} Threshold value ${parsedThreshold} was clamped to ${matchThreshold}`
|
|
4753
4834
|
);
|
|
4754
4835
|
}
|
|
4755
4836
|
if (req.query.limit && (parsedLimit < 1 || parsedLimit > 100)) {
|
|
4756
|
-
|
|
4837
|
+
logger10.debug(`[Document Processor] \u{1F50D} Limit value ${parsedLimit} was clamped to ${limit}`);
|
|
4757
4838
|
}
|
|
4758
|
-
|
|
4839
|
+
logger10.debug(
|
|
4759
4840
|
`[Document Processor] \u{1F50D} Searching: "${searchText}" (threshold: ${matchThreshold}, limit: ${limit})`
|
|
4760
4841
|
);
|
|
4761
4842
|
const embedding = await runtime.useModel(ModelType4.TEXT_EMBEDDING, {
|
|
@@ -4782,7 +4863,7 @@ async function searchKnowledgeHandler(req, res, runtime) {
|
|
|
4782
4863
|
documentFilename = document.metadata.filename || documentFilename;
|
|
4783
4864
|
}
|
|
4784
4865
|
} catch (e) {
|
|
4785
|
-
|
|
4866
|
+
logger10.debug(`Could not fetch document ${documentId} for fragment`);
|
|
4786
4867
|
}
|
|
4787
4868
|
}
|
|
4788
4869
|
return {
|
|
@@ -4797,7 +4878,7 @@ async function searchKnowledgeHandler(req, res, runtime) {
|
|
|
4797
4878
|
};
|
|
4798
4879
|
})
|
|
4799
4880
|
);
|
|
4800
|
-
|
|
4881
|
+
logger10.info(
|
|
4801
4882
|
`[Document Processor] \u{1F50D} Found ${enhancedResults.length} results for: "${searchText}"`
|
|
4802
4883
|
);
|
|
4803
4884
|
sendSuccess(res, {
|
|
@@ -4807,7 +4888,7 @@ async function searchKnowledgeHandler(req, res, runtime) {
|
|
|
4807
4888
|
count: enhancedResults.length
|
|
4808
4889
|
});
|
|
4809
4890
|
} catch (error) {
|
|
4810
|
-
|
|
4891
|
+
logger10.error({ error }, "[Document Processor] \u274C Error searching knowledge");
|
|
4811
4892
|
sendError(res, 500, "SEARCH_ERROR", "Failed to search knowledge", error.message);
|
|
4812
4893
|
}
|
|
4813
4894
|
}
|
|
@@ -4824,7 +4905,7 @@ async function getGraphNodesHandler(req, res, runtime) {
|
|
|
4824
4905
|
const page = Number.isNaN(parsedPage) || parsedPage < 1 ? 1 : parsedPage;
|
|
4825
4906
|
const limit = Number.isNaN(parsedLimit) || parsedLimit < 1 ? 20 : Math.min(parsedLimit, 50);
|
|
4826
4907
|
const offset = (page - 1) * limit;
|
|
4827
|
-
|
|
4908
|
+
logger10.debug(
|
|
4828
4909
|
`[Graph API] \u{1F4CA} Fetching graph nodes: page=${page}, limit=${limit}, type=${type || "all"}, agent=${agentId}`
|
|
4829
4910
|
);
|
|
4830
4911
|
const totalDocuments = await service.countMemories({
|
|
@@ -4845,7 +4926,7 @@ async function getGraphNodesHandler(req, res, runtime) {
|
|
|
4845
4926
|
const links = [];
|
|
4846
4927
|
paginatedDocuments.forEach((doc) => {
|
|
4847
4928
|
if (!doc.id) {
|
|
4848
|
-
|
|
4929
|
+
logger10.warn(`[Graph API] \u26A0\uFE0F Skipping document without ID`);
|
|
4849
4930
|
return;
|
|
4850
4931
|
}
|
|
4851
4932
|
nodes.push({ id: doc.id, type: "document" });
|
|
@@ -4857,9 +4938,9 @@ async function getGraphNodesHandler(req, res, runtime) {
|
|
|
4857
4938
|
count: 5e4
|
|
4858
4939
|
// Reduced from 100000 - still high enough for large documents
|
|
4859
4940
|
});
|
|
4860
|
-
|
|
4941
|
+
logger10.debug(`[Graph API] \u{1F4CA} Total fragments found: ${allFragments.length}`);
|
|
4861
4942
|
if (allFragments.length > 0) {
|
|
4862
|
-
|
|
4943
|
+
logger10.debug(
|
|
4863
4944
|
`[Graph API] \u{1F4CA} Sample fragment metadata: ${JSON.stringify(
|
|
4864
4945
|
allFragments.slice(0, 3).map((f) => ({
|
|
4865
4946
|
id: f.id,
|
|
@@ -4875,17 +4956,17 @@ async function getGraphNodesHandler(req, res, runtime) {
|
|
|
4875
4956
|
const docFragments = allFragments.filter((fragment) => {
|
|
4876
4957
|
const metadata = fragment.metadata;
|
|
4877
4958
|
const typeString = typeof metadata?.type === "string" ? metadata.type : null;
|
|
4878
|
-
const isFragment = typeString && typeString.toLowerCase() === "fragment" || metadata?.type ===
|
|
4959
|
+
const isFragment = typeString && typeString.toLowerCase() === "fragment" || metadata?.type === MemoryType5.FRAGMENT || // If no type but has documentId, assume it's a fragment
|
|
4879
4960
|
!metadata?.type && metadata?.documentId;
|
|
4880
4961
|
return metadata?.documentId === doc.id && isFragment;
|
|
4881
4962
|
});
|
|
4882
4963
|
if (docFragments.length > 0) {
|
|
4883
|
-
|
|
4964
|
+
logger10.debug(`[Graph API] \u{1F4CA} Document ${doc.id} has ${docFragments.length} fragments`);
|
|
4884
4965
|
}
|
|
4885
4966
|
docFragments.forEach((frag) => {
|
|
4886
4967
|
const docId = doc.id;
|
|
4887
4968
|
if (!frag.id || !docId) {
|
|
4888
|
-
|
|
4969
|
+
logger10.warn(
|
|
4889
4970
|
`[Graph API] \u26A0\uFE0F Skipping fragment without ID for document ${docId || "unknown"}`
|
|
4890
4971
|
);
|
|
4891
4972
|
return;
|
|
@@ -4894,7 +4975,7 @@ async function getGraphNodesHandler(req, res, runtime) {
|
|
|
4894
4975
|
links.push({ source: docId, target: frag.id });
|
|
4895
4976
|
});
|
|
4896
4977
|
});
|
|
4897
|
-
|
|
4978
|
+
logger10.info(
|
|
4898
4979
|
`[Graph API] \u{1F4CA} Final graph: ${nodes.length} nodes (${paginatedDocuments.length} documents), ${links.length} links`
|
|
4899
4980
|
);
|
|
4900
4981
|
}
|
|
@@ -4909,7 +4990,7 @@ async function getGraphNodesHandler(req, res, runtime) {
|
|
|
4909
4990
|
}
|
|
4910
4991
|
});
|
|
4911
4992
|
} catch (error) {
|
|
4912
|
-
|
|
4993
|
+
logger10.error("[Graph API] \u274C Error fetching graph nodes:", error);
|
|
4913
4994
|
sendError(res, 500, "GRAPH_ERROR", "Failed to fetch graph nodes", error.message);
|
|
4914
4995
|
}
|
|
4915
4996
|
}
|
|
@@ -4924,24 +5005,24 @@ async function getGraphNodeDetailsHandler(req, res, runtime) {
|
|
|
4924
5005
|
return sendError(res, 400, "INVALID_ID", "Invalid node ID format");
|
|
4925
5006
|
}
|
|
4926
5007
|
try {
|
|
4927
|
-
|
|
5008
|
+
logger10.info(`[Graph API] \u{1F4CA} Fetching node details for: ${nodeId}, agent: ${agentId}`);
|
|
4928
5009
|
const allDocuments = await service.getMemories({
|
|
4929
5010
|
tableName: "documents",
|
|
4930
5011
|
count: 1e4
|
|
4931
5012
|
});
|
|
4932
|
-
|
|
5013
|
+
logger10.debug(`[Graph API] \u{1F4CA} Total documents in DB: ${allDocuments.length}`);
|
|
4933
5014
|
let document = allDocuments.find((doc) => doc.id === nodeId && doc.roomId === agentId);
|
|
4934
5015
|
if (!document) {
|
|
4935
|
-
|
|
5016
|
+
logger10.debug(`[Graph API] \u{1F4CA} Document not found with roomId filter, trying without filter`);
|
|
4936
5017
|
document = allDocuments.find((doc) => doc.id === nodeId);
|
|
4937
5018
|
if (document) {
|
|
4938
|
-
|
|
5019
|
+
logger10.warn(
|
|
4939
5020
|
`[Graph API] \u26A0\uFE0F Document ${nodeId} found but has different roomId: ${document.roomId} vs ${agentId}`
|
|
4940
5021
|
);
|
|
4941
5022
|
}
|
|
4942
5023
|
}
|
|
4943
5024
|
if (document) {
|
|
4944
|
-
|
|
5025
|
+
logger10.info(`[Graph API] \u2705 Found document: ${nodeId}`);
|
|
4945
5026
|
sendSuccess(res, {
|
|
4946
5027
|
id: document.id,
|
|
4947
5028
|
type: "document",
|
|
@@ -4955,25 +5036,25 @@ async function getGraphNodeDetailsHandler(req, res, runtime) {
|
|
|
4955
5036
|
});
|
|
4956
5037
|
return;
|
|
4957
5038
|
}
|
|
4958
|
-
|
|
5039
|
+
logger10.debug(`[Graph API] \u{1F4CA} Document not found, searching in fragments`);
|
|
4959
5040
|
const allFragments = await service.getMemories({
|
|
4960
5041
|
tableName: "knowledge",
|
|
4961
5042
|
count: 5e4
|
|
4962
5043
|
// Reduced from 100000 - still high enough for large documents
|
|
4963
5044
|
});
|
|
4964
|
-
|
|
5045
|
+
logger10.debug(`[Graph API] \u{1F4CA} Total fragments in DB: ${allFragments.length}`);
|
|
4965
5046
|
let fragment = allFragments.find((frag) => frag.id === nodeId && frag.roomId === agentId);
|
|
4966
5047
|
if (!fragment) {
|
|
4967
|
-
|
|
5048
|
+
logger10.debug(`[Graph API] \u{1F4CA} Fragment not found with roomId filter, trying without filter`);
|
|
4968
5049
|
fragment = allFragments.find((frag) => frag.id === nodeId);
|
|
4969
5050
|
if (fragment) {
|
|
4970
|
-
|
|
5051
|
+
logger10.warn(
|
|
4971
5052
|
`[Graph API] \u26A0\uFE0F Fragment ${nodeId} found but has different roomId: ${fragment.roomId} vs ${agentId}`
|
|
4972
5053
|
);
|
|
4973
5054
|
}
|
|
4974
5055
|
}
|
|
4975
5056
|
if (fragment) {
|
|
4976
|
-
|
|
5057
|
+
logger10.info(`[Graph API] \u2705 Found fragment: ${nodeId}`);
|
|
4977
5058
|
sendSuccess(res, {
|
|
4978
5059
|
id: fragment.id,
|
|
4979
5060
|
type: "fragment",
|
|
@@ -4987,10 +5068,10 @@ async function getGraphNodeDetailsHandler(req, res, runtime) {
|
|
|
4987
5068
|
});
|
|
4988
5069
|
return;
|
|
4989
5070
|
}
|
|
4990
|
-
|
|
5071
|
+
logger10.error(`[Graph API] \u274C Node ${nodeId} not found in documents or fragments`);
|
|
4991
5072
|
sendError(res, 404, "NOT_FOUND", `Node with ID ${nodeId} not found`);
|
|
4992
5073
|
} catch (error) {
|
|
4993
|
-
|
|
5074
|
+
logger10.error(`[Graph API] \u274C Error fetching node details for ${nodeId}:`, error);
|
|
4994
5075
|
sendError(res, 500, "GRAPH_ERROR", "Failed to fetch node details", error.message);
|
|
4995
5076
|
}
|
|
4996
5077
|
}
|
|
@@ -5005,7 +5086,7 @@ async function expandDocumentGraphHandler(req, res, runtime) {
|
|
|
5005
5086
|
return sendError(res, 400, "INVALID_ID", "Invalid document ID format");
|
|
5006
5087
|
}
|
|
5007
5088
|
try {
|
|
5008
|
-
|
|
5089
|
+
logger10.debug(`[Graph API] \u{1F4CA} Expanding document: ${documentId}, agent: ${agentId}`);
|
|
5009
5090
|
const allFragments = await service.getMemories({
|
|
5010
5091
|
tableName: "knowledge",
|
|
5011
5092
|
roomId: agentId,
|
|
@@ -5013,33 +5094,33 @@ async function expandDocumentGraphHandler(req, res, runtime) {
|
|
|
5013
5094
|
count: 5e4
|
|
5014
5095
|
// Reduced from 100000 - still high enough for large documents
|
|
5015
5096
|
});
|
|
5016
|
-
|
|
5097
|
+
logger10.debug(`[Graph API] \u{1F4CA} Total fragments in knowledge table: ${allFragments.length}`);
|
|
5017
5098
|
if (allFragments.length > 0 && process.env.NODE_ENV !== "production") {
|
|
5018
|
-
|
|
5099
|
+
logger10.debug(
|
|
5019
5100
|
`[Graph API] \u{1F4CA} Sample fragment metadata: ${JSON.stringify(allFragments[0].metadata)}`
|
|
5020
5101
|
);
|
|
5021
5102
|
const uniqueTypes = new Set(allFragments.map((f) => f.metadata?.type));
|
|
5022
|
-
|
|
5103
|
+
logger10.debug(
|
|
5023
5104
|
`[Graph API] \u{1F4CA} Unique metadata types found in knowledge table: ${JSON.stringify(Array.from(uniqueTypes))}`
|
|
5024
5105
|
);
|
|
5025
5106
|
const relevantFragments = allFragments.filter((fragment) => {
|
|
5026
5107
|
const metadata = fragment.metadata;
|
|
5027
5108
|
const hasDocumentId = metadata?.documentId === documentId;
|
|
5028
5109
|
if (hasDocumentId) {
|
|
5029
|
-
|
|
5110
|
+
logger10.debug(
|
|
5030
5111
|
`[Graph API] \u{1F4CA} Fragment ${fragment.id} metadata: ${JSON.stringify(metadata)}`
|
|
5031
5112
|
);
|
|
5032
5113
|
}
|
|
5033
5114
|
return hasDocumentId;
|
|
5034
5115
|
});
|
|
5035
|
-
|
|
5116
|
+
logger10.debug(
|
|
5036
5117
|
`[Graph API] \u{1F4CA} Fragments with matching documentId: ${relevantFragments.length}`
|
|
5037
5118
|
);
|
|
5038
5119
|
}
|
|
5039
5120
|
const documentFragments = allFragments.filter((fragment) => {
|
|
5040
5121
|
const metadata = fragment.metadata;
|
|
5041
5122
|
const typeString = typeof metadata?.type === "string" ? metadata.type : null;
|
|
5042
|
-
const isFragment = typeString && typeString.toLowerCase() === "fragment" || metadata?.type ===
|
|
5123
|
+
const isFragment = typeString && typeString.toLowerCase() === "fragment" || metadata?.type === MemoryType5.FRAGMENT || // If no type but has documentId, assume it's a fragment
|
|
5043
5124
|
!metadata?.type && metadata?.documentId;
|
|
5044
5125
|
return metadata?.documentId === documentId && isFragment;
|
|
5045
5126
|
});
|
|
@@ -5051,7 +5132,7 @@ async function expandDocumentGraphHandler(req, res, runtime) {
|
|
|
5051
5132
|
source: documentId,
|
|
5052
5133
|
target: frag.id
|
|
5053
5134
|
}));
|
|
5054
|
-
|
|
5135
|
+
logger10.info(`[Graph API] \u{1F4CA} Found ${nodes.length} fragments for document ${documentId}`);
|
|
5055
5136
|
sendSuccess(res, {
|
|
5056
5137
|
documentId,
|
|
5057
5138
|
nodes,
|
|
@@ -5059,7 +5140,7 @@ async function expandDocumentGraphHandler(req, res, runtime) {
|
|
|
5059
5140
|
fragmentCount: nodes.length
|
|
5060
5141
|
});
|
|
5061
5142
|
} catch (error) {
|
|
5062
|
-
|
|
5143
|
+
logger10.error(`[Graph API] \u274C Error expanding document ${documentId}:`, error);
|
|
5063
5144
|
sendError(res, 500, "GRAPH_ERROR", "Failed to expand document", error.message);
|
|
5064
5145
|
}
|
|
5065
5146
|
}
|
|
@@ -5071,7 +5152,7 @@ async function uploadKnowledgeWithMulter(req, res, runtime) {
|
|
|
5071
5152
|
);
|
|
5072
5153
|
uploadArray(req, res, (err) => {
|
|
5073
5154
|
if (err) {
|
|
5074
|
-
|
|
5155
|
+
logger10.error({ error: err }, "[Document Processor] \u274C File upload error");
|
|
5075
5156
|
return sendError(res, 400, "UPLOAD_ERROR", err.message);
|
|
5076
5157
|
}
|
|
5077
5158
|
uploadKnowledgeHandler(req, res, runtime);
|
|
@@ -5145,13 +5226,13 @@ function createKnowledgePlugin(config = {}) {
|
|
|
5145
5226
|
name: "knowledge",
|
|
5146
5227
|
description: "Plugin for Retrieval Augmented Generation, including knowledge management and embedding.",
|
|
5147
5228
|
services: [KnowledgeService],
|
|
5148
|
-
providers: [knowledgeProvider]
|
|
5229
|
+
providers: [knowledgeProvider, documentsProvider]
|
|
5149
5230
|
};
|
|
5150
5231
|
if (enableUI || enableRoutes) {
|
|
5151
5232
|
plugin.routes = knowledgeRoutes;
|
|
5152
|
-
|
|
5233
|
+
logger11.debug("[Knowledge Plugin] Routes enabled");
|
|
5153
5234
|
} else {
|
|
5154
|
-
|
|
5235
|
+
logger11.info("[Knowledge Plugin] Running in headless mode (no routes or UI)");
|
|
5155
5236
|
}
|
|
5156
5237
|
if (enableActions) {
|
|
5157
5238
|
plugin.actions = knowledgeActions;
|
|
@@ -5186,6 +5267,7 @@ export {
|
|
|
5186
5267
|
ModelConfigSchema,
|
|
5187
5268
|
createKnowledgePlugin,
|
|
5188
5269
|
index_default as default,
|
|
5270
|
+
documentsProvider,
|
|
5189
5271
|
knowledgePlugin,
|
|
5190
5272
|
knowledgePluginCore,
|
|
5191
5273
|
knowledgePluginHeadless,
|