1
+ import { Provider , IAgentRuntime , Memory , State , elizaLogger } from "@ai16z/eliza" ;
2
+ import { GitBookResponse , GitBookClientConfig } from '../types' ;
3
+
4
+ function cleanText ( text : string ) : string {
5
+ const cleaned = text
6
+ . replace ( / < @ ! ? \d + > / g, '' ) // Discord mentions
7
+ . replace ( / < # \d + > / g, '' ) // Discord channels
8
+ . replace ( / < @ & \d + > / g, '' ) // Discord roles
9
+ . replace ( / (?: ^ | \s ) @ [ \w _ ] + / g, '' ) // Platform mentions
10
+ . trim ( ) ;
11
+
12
+ return cleaned ;
13
+ }
14
+
15
+ async function validateQuery ( runtime : IAgentRuntime , text : string ) : Promise < boolean > {
16
+ // Default general queries - everything else comes from config
17
+ let keywords = {
18
+ generalQueries : [
19
+ 'how' , 'what' , 'where' , 'explain' , 'show' , 'tell' ,
20
+ 'can' , 'does' , 'is' , 'are' , 'will' , 'why' ,
21
+ 'benefits' , 'features' , 'cost' , 'price' ,
22
+ 'use' , 'using' , 'work' , 'access' , 'get'
23
+ ]
24
+ } ;
25
+
26
+ try {
27
+ const gitbookConfig = runtime . character . clientConfig ?. gitbook as GitBookClientConfig ;
28
+
29
+ // Get project terms and document triggers from config
30
+ const projectTerms = gitbookConfig ?. keywords ?. projectTerms || [ ] ;
31
+ const documentTriggers = gitbookConfig ?. documentTriggers || [ ] ;
32
+
33
+ // Merge any additional general queries from config
34
+ if ( gitbookConfig ?. keywords ?. generalQueries ) {
35
+ keywords . generalQueries = [
36
+ ...keywords . generalQueries ,
37
+ ...gitbookConfig . keywords . generalQueries
38
+ ] ;
39
+ }
40
+
41
+ const containsAnyWord = ( text : string , words : string [ ] = [ ] ) => {
42
+ return words . length === 0 || words . some ( word => {
43
+ if ( word . includes ( ' ' ) ) {
44
+ return text . includes ( word . toLowerCase ( ) ) ;
45
+ }
46
+ const regex = new RegExp ( `\\b${ word } \\b` , 'i' ) ;
47
+ return regex . test ( text ) ;
48
+ } ) ;
49
+ } ;
50
+
51
+ const hasProjectTerm = containsAnyWord ( text , projectTerms ) ;
52
+ const hasDocTrigger = containsAnyWord ( text , documentTriggers ) ;
53
+ const hasGeneralQuery = containsAnyWord ( text , keywords . generalQueries ) ;
54
+
55
+ const isValid = hasProjectTerm || hasDocTrigger || hasGeneralQuery ;
56
+
57
+ elizaLogger . info ( `✅ Is GitBook Validation Result: ${ isValid } ` )
58
+ return isValid ;
59
+
60
+ } catch ( error ) {
61
+ elizaLogger . warn ( `❌ Error in GitBook validation:\n${ error } ` )
62
+ return false ;
63
+ }
64
+ }
65
+
66
+ export const gitbookProvider : Provider = {
67
+ get : async ( runtime : IAgentRuntime , message : Memory , _state ?: State ) : Promise < string > => {
68
+ try {
69
+ const spaceId = runtime . getSetting ( "GITBOOK_SPACE_ID" ) ;
70
+ if ( ! spaceId ) {
71
+ elizaLogger . error ( '⚠️ GitBook Space ID not configured' )
72
+ return "" ;
73
+ }
74
+
75
+ const text = message . content . text . toLowerCase ( ) . trim ( ) ;
76
+ const isValidQuery = await validateQuery ( runtime , text ) ;
77
+
78
+ if ( ! isValidQuery ) {
79
+ elizaLogger . info ( '⚠️ GitBook Query validation failed' )
80
+ return "" ;
81
+ }
82
+
83
+ const cleanedQuery = cleanText ( message . content . text ) ;
84
+
85
+ const response = await fetch (
86
+ `https://api.gitbook.com/v1/spaces/${ spaceId } /search/ask` ,
87
+ {
88
+ method : "POST" ,
89
+ headers : {
90
+ "Content-Type" : "application/json"
91
+ } ,
92
+ body : JSON . stringify ( {
93
+ query : cleanedQuery ,
94
+ variables : { }
95
+ } )
96
+ }
97
+ ) ;
98
+
99
+ if ( ! response . ok ) {
100
+ console . error ( '❌ GitBook API error:' , response . status ) ;
101
+ return "" ;
102
+ }
103
+
104
+ const result : GitBookResponse = await response . json ( ) ;
105
+
106
+ return result . answer ?. text || "" ;
107
+ } catch ( error ) {
108
+ console . error ( "❌ Error in GitBook provider:" , error ) ;
109
+ return "" ;
110
+ }
111
+ }
112
+ } ;
0 commit comments