137 lines
3.8 KiB
Go
137 lines
3.8 KiB
Go
|
|
package rest
|
||
|
|
|
||
|
|
import (
|
||
|
|
"bufio"
|
||
|
|
"os"
|
||
|
|
"path/filepath"
|
||
|
|
"strings"
|
||
|
|
)
|
||
|
|
|
||
|
|
func loadAIDocSnippets(query string) ([]AIDocSnippet, string, string) {
|
||
|
|
root := findAIWorkspaceRoot()
|
||
|
|
if root == "" {
|
||
|
|
return nil, "", "workspace docs root unavailable for ai doc retrieval"
|
||
|
|
}
|
||
|
|
|
||
|
|
relativePaths := []string{
|
||
|
|
"docs/11-references/ADDRESS_MATRIX_AND_STATUS.md",
|
||
|
|
"docs/11-references/LIQUIDITY_POOLS_MASTER_MAP.md",
|
||
|
|
"docs/11-references/DEPLOYED_TOKENS_BRIDGES_LPS_AND_ROUTING_STATUS.md",
|
||
|
|
"docs/11-references/EXPLORER_TOKEN_LIST_CROSSCHECK.md",
|
||
|
|
"explorer-monorepo/docs/EXPLORER_API_ACCESS.md",
|
||
|
|
}
|
||
|
|
|
||
|
|
terms := buildDocSearchTerms(query)
|
||
|
|
if len(terms) == 0 {
|
||
|
|
terms = []string{"chain 138", "bridge", "liquidity"}
|
||
|
|
}
|
||
|
|
|
||
|
|
snippets := []AIDocSnippet{}
|
||
|
|
for _, rel := range relativePaths {
|
||
|
|
fullPath := filepath.Join(root, rel)
|
||
|
|
fileSnippets := scanDocForTerms(fullPath, rel, terms)
|
||
|
|
snippets = append(snippets, fileSnippets...)
|
||
|
|
if len(snippets) >= maxExplorerAIDocSnippets {
|
||
|
|
break
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if len(snippets) == 0 {
|
||
|
|
return nil, root, "no matching workspace docs found for ai context"
|
||
|
|
}
|
||
|
|
if len(snippets) > maxExplorerAIDocSnippets {
|
||
|
|
snippets = snippets[:maxExplorerAIDocSnippets]
|
||
|
|
}
|
||
|
|
return snippets, root, ""
|
||
|
|
}
|
||
|
|
|
||
|
|
func findAIWorkspaceRoot() string {
|
||
|
|
candidates := []string{}
|
||
|
|
if envRoot := strings.TrimSpace(os.Getenv("EXPLORER_AI_WORKSPACE_ROOT")); envRoot != "" {
|
||
|
|
candidates = append(candidates, envRoot)
|
||
|
|
}
|
||
|
|
if cwd, err := os.Getwd(); err == nil {
|
||
|
|
candidates = append(candidates, cwd)
|
||
|
|
dir := cwd
|
||
|
|
for i := 0; i < 4; i++ {
|
||
|
|
dir = filepath.Dir(dir)
|
||
|
|
candidates = append(candidates, dir)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
candidates = append(candidates, "/opt/explorer-monorepo", "/home/intlc/projects/proxmox")
|
||
|
|
|
||
|
|
for _, candidate := range candidates {
|
||
|
|
if candidate == "" {
|
||
|
|
continue
|
||
|
|
}
|
||
|
|
if fileExists(filepath.Join(candidate, "docs")) && (fileExists(filepath.Join(candidate, "explorer-monorepo")) || fileExists(filepath.Join(candidate, "smom-dbis-138")) || fileExists(filepath.Join(candidate, "config"))) {
|
||
|
|
return candidate
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return ""
|
||
|
|
}
|
||
|
|
|
||
|
|
func scanDocForTerms(fullPath, relativePath string, terms []string) []AIDocSnippet {
|
||
|
|
file, err := os.Open(fullPath)
|
||
|
|
if err != nil {
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
defer file.Close()
|
||
|
|
|
||
|
|
normalizedTerms := make([]string, 0, len(terms))
|
||
|
|
for _, term := range terms {
|
||
|
|
term = strings.ToLower(strings.TrimSpace(term))
|
||
|
|
if len(term) >= 3 {
|
||
|
|
normalizedTerms = append(normalizedTerms, term)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
scanner := bufio.NewScanner(file)
|
||
|
|
lineNumber := 0
|
||
|
|
snippets := []AIDocSnippet{}
|
||
|
|
for scanner.Scan() {
|
||
|
|
lineNumber++
|
||
|
|
line := scanner.Text()
|
||
|
|
lower := strings.ToLower(line)
|
||
|
|
for _, term := range normalizedTerms {
|
||
|
|
if strings.Contains(lower, term) {
|
||
|
|
snippets = append(snippets, AIDocSnippet{
|
||
|
|
Path: relativePath,
|
||
|
|
Line: lineNumber,
|
||
|
|
Snippet: clipString(strings.TrimSpace(line), 280),
|
||
|
|
})
|
||
|
|
break
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if len(snippets) >= 2 {
|
||
|
|
break
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return snippets
|
||
|
|
}
|
||
|
|
|
||
|
|
func buildDocSearchTerms(query string) []string {
|
||
|
|
words := strings.Fields(strings.ToLower(query))
|
||
|
|
stopWords := map[string]bool{
|
||
|
|
"what": true, "when": true, "where": true, "which": true, "with": true, "from": true,
|
||
|
|
"that": true, "this": true, "have": true, "about": true, "into": true, "show": true,
|
||
|
|
"live": true, "help": true, "explain": true, "tell": true,
|
||
|
|
}
|
||
|
|
terms := []string{}
|
||
|
|
for _, word := range words {
|
||
|
|
word = strings.Trim(word, ".,:;!?()[]{}\"'")
|
||
|
|
if len(word) < 4 || stopWords[word] {
|
||
|
|
continue
|
||
|
|
}
|
||
|
|
terms = append(terms, word)
|
||
|
|
}
|
||
|
|
for _, match := range addressPattern.FindAllString(query, -1) {
|
||
|
|
terms = append(terms, strings.ToLower(match))
|
||
|
|
}
|
||
|
|
for _, symbol := range []string{"cUSDT", "cUSDC", "cXAUC", "cEURT", "USDT", "USDC", "WETH", "WETH10", "Mainnet", "bridge", "liquidity", "pool"} {
|
||
|
|
if strings.Contains(strings.ToLower(query), strings.ToLower(symbol)) {
|
||
|
|
terms = append(terms, strings.ToLower(symbol))
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return uniqueStrings(terms)
|
||
|
|
}
|