From 15d97c620a0e2d83d3138c5135198397605a8012 Mon Sep 17 00:00:00 2001 From: 0xbbjoker <0xbbjoker@proton.me> Date: Thu, 30 Oct 2025 12:38:41 +0100 Subject: [PATCH] feat: Add static provider for listing available documents --- package.json | 2 +- src/documents-provider.ts | 121 ++++++++++++++++++++++++++++++++++++++ src/index.ts | 4 +- 3 files changed, 125 insertions(+), 2 deletions(-) create mode 100644 src/documents-provider.ts diff --git a/package.json b/package.json index 5798819..d9ca2ae 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@elizaos/plugin-knowledge", "description": "Plugin for Knowledge", - "version": "1.5.12", + "version": "1.5.13", "type": "module", "main": "dist/index.js", "module": "dist/index.js", diff --git a/src/documents-provider.ts b/src/documents-provider.ts new file mode 100644 index 0000000..182da72 --- /dev/null +++ b/src/documents-provider.ts @@ -0,0 +1,121 @@ +import type { IAgentRuntime, Memory, Provider } from '@elizaos/core'; +import { addHeader, logger, MemoryType } from '@elizaos/core'; +import { KnowledgeService } from './service.ts'; + +/** + * Represents a static provider that lists available documents in the knowledge base. + * This provider helps the agent understand which documents are available for retrieval. + * @type {Provider} + * @property {string} name - The name of the documents provider. + * @property {string} description - The description of the documents provider. + * @property {boolean} dynamic - Indicates if the provider is static (false). + * @property {Function} get - Asynchronously retrieves the list of available documents. + * @param {IAgentRuntime} runtime - The agent runtime object. + * @returns {Object} An object containing the available documents list. + */ +export const documentsProvider: Provider = { + name: 'AVAILABLE_DOCUMENTS', + description: + 'List of documents available in the knowledge base. Shows which documents the agent can reference and retrieve information from.', + dynamic: false, // Static provider - doesn't change based on the message + get: async (runtime: IAgentRuntime) => { + try { + const knowledgeService = runtime.getService('knowledge') as KnowledgeService; + + if (!knowledgeService) { + logger.warn('Knowledge service not available for documents provider'); + return { + data: { documents: [] }, + values: { documents: '' }, + text: '', + }; + } + + // Retrieve all documents for the agent + const allMemories = await knowledgeService.getMemories({ + tableName: 'documents', + roomId: runtime.agentId, + count: 100, // Limit to 100 documents to avoid context overflow + }); + + // Filter to only documents (not fragments) + const documents = allMemories.filter( + (memory) => memory.metadata?.type === MemoryType.DOCUMENT + ); + + if (!documents || documents.length === 0) { + return { + data: { documents: [] }, + values: { documents: '' }, + text: '', + }; + } + + // Format documents concisely + const documentsList = documents + .map((doc, index) => { + const metadata = doc.metadata as any; + const filename = metadata?.filename || metadata?.title || `Document ${index + 1}`; + const fileType = metadata?.fileExt || metadata?.fileType || 'unknown'; + const source = metadata?.source || 'upload'; + const fileSize = metadata?.fileSize; + + // Build description from metadata + const parts = [filename]; + + // Add file type info + if (fileType && fileType !== 'unknown') { + parts.push(fileType); + } + + // Add file size if available + if (fileSize) { + const sizeKB = Math.round(fileSize / 1024); + if (sizeKB > 1024) { + parts.push(`${Math.round(sizeKB / 1024)}MB`); + } else { + parts.push(`${sizeKB}KB`); + } + } + + // Add source if meaningful + if (source && source !== 'upload') { + parts.push(`from ${source}`); + } + + // Format: "filename (type, size, source)" + return parts.join(' - '); + }) + .join('\n'); + + const documentsText = addHeader( + '# Available Documents', + `${documents.length} document(s) in knowledge base:\n${documentsList}` + ); + + return { + data: { + documents: documents.map((doc) => ({ + id: doc.id, + filename: (doc.metadata as any)?.filename || (doc.metadata as any)?.title, + fileType: (doc.metadata as any)?.fileType || (doc.metadata as any)?.fileExt, + source: (doc.metadata as any)?.source, + })), + count: documents.length, + }, + values: { + documentsCount: documents.length, + documents: documentsList, + }, + text: documentsText, + }; + } catch (error: any) { + logger.error('Error in documents provider:', error.message); + return { + data: { documents: [], error: error.message }, + values: { documents: '' }, + text: '', + }; + } + }, +}; diff --git a/src/index.ts b/src/index.ts index 9686a57..4984f08 100644 --- a/src/index.ts +++ b/src/index.ts @@ -7,6 +7,7 @@ import type { Plugin, IAgentRuntime } from '@elizaos/core'; import { logger } from '@elizaos/core'; import { KnowledgeService } from './service'; import { knowledgeProvider } from './provider'; +import { documentsProvider } from './documents-provider'; import knowledgeTestSuite from './tests'; import { knowledgeActions } from './actions'; import { knowledgeRoutes } from './routes'; @@ -73,7 +74,7 @@ export function createKnowledgePlugin(config: KnowledgePluginConfig = {}): Plugi description: 'Plugin for Retrieval Augmented Generation, including knowledge management and embedding.', services: [KnowledgeService], - providers: [knowledgeProvider], + providers: [knowledgeProvider, documentsProvider], }; // Add routes only if UI or routes are enabled @@ -145,3 +146,4 @@ export * from './types'; */ export { KnowledgeService } from './service'; export { knowledgeProvider } from './provider'; +export { documentsProvider } from './documents-provider';