1
1
import type { Agent , Character , Content , IAgentRuntime , Memory , UUID } from '@elizaos/core' ;
2
2
import {
3
3
ChannelType ,
4
- EventType ,
5
4
ModelType ,
6
5
composePrompt ,
7
6
composePromptFromState ,
8
7
createUniqueUuid ,
9
8
logger ,
10
9
messageHandlerTemplate ,
11
10
validateUuid ,
11
+ MemoryType ,
12
12
} from '@elizaos/core' ;
13
13
import express from 'express' ;
14
14
import fs from 'node:fs' ;
@@ -21,13 +21,17 @@ import { upload } from '../loader';
21
21
* @interface CustomRequest
22
22
* @extends express.Request
23
23
* @property {Express.Multer.File } [file] - Optional property representing a file uploaded with the request
24
+ * @property {Express.Multer.File[] } [files] - Optional property representing multiple files uploaded with the request
24
25
* @property {Object } params - Object representing parameters included in the request
25
26
* @property {string } params.agentId - The unique identifier for the agent associated with the request
27
+ * @property {string } [params.knowledgeId] - Optional knowledge ID parameter
26
28
*/
27
29
interface CustomRequest extends express . Request {
28
30
file ?: Express . Multer . File ;
31
+ files ?: Express . Multer . File [ ] ;
29
32
params : {
30
33
agentId : string ;
34
+ knowledgeId ?: string ;
31
35
} ;
32
36
}
33
37
@@ -1403,9 +1407,12 @@ export function agentRouter(
1403
1407
return ;
1404
1408
}
1405
1409
1410
+ // Get tableName from query params, default to "messages"
1411
+ const tableName = ( req . query . tableName as string ) || 'messages' ;
1412
+
1406
1413
const memories = await runtime . getMemories ( {
1407
1414
agentId,
1408
- tableName : 'messages' ,
1415
+ tableName,
1409
1416
} ) ;
1410
1417
1411
1418
const cleanMemories = memories . map ( ( memory ) => {
@@ -1611,5 +1618,148 @@ export function agentRouter(
1611
1618
}
1612
1619
} ) ;
1613
1620
1621
+ // Knowledge management routes
1622
+ router . post ( '/:agentId/memories/upload-knowledge' , upload . array ( 'files' ) , async ( req , res ) => {
1623
+ const agentId = validateUuid ( req . params . agentId ) ;
1624
+
1625
+ if ( ! agentId ) {
1626
+ res . status ( 400 ) . json ( {
1627
+ success : false ,
1628
+ error : {
1629
+ code : 'INVALID_ID' ,
1630
+ message : 'Invalid agent ID format' ,
1631
+ } ,
1632
+ } ) ;
1633
+ return ;
1634
+ }
1635
+
1636
+ const runtime = agents . get ( agentId ) ;
1637
+
1638
+ if ( ! runtime ) {
1639
+ res . status ( 404 ) . json ( {
1640
+ success : false ,
1641
+ error : {
1642
+ code : 'NOT_FOUND' ,
1643
+ message : 'Agent not found' ,
1644
+ } ,
1645
+ } ) ;
1646
+ return ;
1647
+ }
1648
+
1649
+ const files = req . files as Express . Multer . File [ ] ;
1650
+
1651
+ if ( ! files || files . length === 0 ) {
1652
+ res . status ( 400 ) . json ( {
1653
+ success : false ,
1654
+ error : {
1655
+ code : 'NO_FILES' ,
1656
+ message : 'No files uploaded' ,
1657
+ } ,
1658
+ } ) ;
1659
+ return ;
1660
+ }
1661
+
1662
+ try {
1663
+ const results = [ ] ;
1664
+
1665
+ for ( const file of files ) {
1666
+ try {
1667
+ // Read file content
1668
+ const content = fs . readFileSync ( file . path , 'utf8' ) ;
1669
+
1670
+ // Format the content with Path: prefix like in the devRel/index.ts example
1671
+ const relativePath = file . originalname ;
1672
+ const formattedContent = `Path: ${ relativePath } \n\n${ content } ` ;
1673
+
1674
+ // Create knowledge item with proper metadata
1675
+ const knowledgeId = createUniqueUuid ( runtime , `knowledge-${ Date . now ( ) } ` ) ;
1676
+ const fileExt = file . originalname . split ( '.' ) . pop ( ) ?. toLowerCase ( ) || '' ;
1677
+ const filename = file . originalname ;
1678
+ const title = filename . replace ( `.${ fileExt } ` , '' ) ;
1679
+
1680
+ const knowledgeItem = {
1681
+ id : knowledgeId ,
1682
+ content : {
1683
+ text : formattedContent ,
1684
+ } ,
1685
+ metadata : {
1686
+ type : MemoryType . DOCUMENT ,
1687
+ timestamp : Date . now ( ) ,
1688
+ filename : filename ,
1689
+ fileExt : fileExt ,
1690
+ title : title ,
1691
+ path : relativePath ,
1692
+ fileType : file . mimetype ,
1693
+ fileSize : file . size ,
1694
+ source : 'upload' ,
1695
+ } ,
1696
+ } ;
1697
+
1698
+ // Add knowledge to agent
1699
+ await runtime . addKnowledge ( knowledgeItem , {
1700
+ targetTokens : 3000 ,
1701
+ overlap : 200 ,
1702
+ modelContextSize : 4096 ,
1703
+ } ) ;
1704
+
1705
+ // Clean up temp file immediately after successful processing
1706
+ if ( file . path && fs . existsSync ( file . path ) ) {
1707
+ fs . unlinkSync ( file . path ) ;
1708
+ }
1709
+
1710
+ results . push ( {
1711
+ id : knowledgeId ,
1712
+ filename : relativePath ,
1713
+ type : file . mimetype ,
1714
+ size : file . size ,
1715
+ uploadedAt : Date . now ( ) ,
1716
+ preview :
1717
+ formattedContent . length > 0
1718
+ ? `${ formattedContent . substring ( 0 , 150 ) } ${ formattedContent . length > 150 ? '...' : '' } `
1719
+ : 'No preview available' ,
1720
+ } ) ;
1721
+ } catch ( fileError ) {
1722
+ logger . error ( `[KNOWLEDGE POST] Error processing file ${ file . originalname } : ${ fileError } ` ) ;
1723
+ // Clean up this file if it exists
1724
+ if ( file . path && fs . existsSync ( file . path ) ) {
1725
+ fs . unlinkSync ( file . path ) ;
1726
+ }
1727
+ // Continue with other files even if one fails
1728
+ }
1729
+ }
1730
+
1731
+ res . json ( {
1732
+ success : true ,
1733
+ data : results ,
1734
+ } ) ;
1735
+ } catch ( error ) {
1736
+ logger . error ( `[KNOWLEDGE POST] Error uploading knowledge: ${ error } ` ) ;
1737
+
1738
+ // Clean up any remaining files
1739
+ if ( files ) {
1740
+ for ( const file of files ) {
1741
+ if ( file . path && fs . existsSync ( file . path ) ) {
1742
+ try {
1743
+ fs . unlinkSync ( file . path ) ;
1744
+ } catch ( cleanupError ) {
1745
+ logger . error (
1746
+ `[KNOWLEDGE POST] Error cleaning up file ${ file . originalname } : ${ cleanupError } `
1747
+ ) ;
1748
+ }
1749
+ }
1750
+ }
1751
+ }
1752
+
1753
+ res . status ( 500 ) . json ( {
1754
+ success : false ,
1755
+ error : {
1756
+ code : 500 ,
1757
+ message : 'Failed to upload knowledge' ,
1758
+ details : error . message ,
1759
+ } ,
1760
+ } ) ;
1761
+ }
1762
+ } ) ;
1763
+
1614
1764
return router ;
1615
1765
}
0 commit comments