Ctrl K
ComunidadGuías…

internal/memory/record_index.go

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
package memory

import (
	"context"
	"errors"
	"fmt"
	"os"
	"path/filepath"
	"strings"
	"sync"

	"github.com/yeomyeonggeori/bluememo"
)

const (
	recordIndexFileMode  = 0o600
	recordIndexScanLimit = 5000
	recordFrameSuffix    = "#frame"
)

type RecordIndex struct {
	stores  *Stores
	mutex   sync.Mutex
	opened  *bluememo.Store
	indexed map[string]string
}

type RecordEntry struct {
	ID        string
	Content   string
	ChangedAt string
}

type RecordRise struct {
	ID   string
	Rise float64
}

func (stores *Stores) RecordIndex() *RecordIndex {
	stores.mutex.Lock()
	defer stores.mutex.Unlock()
	if stores.recordIndex == nil {
		stores.recordIndex = &RecordIndex{stores: stores, indexed: map[string]string{}}
	}
	return stores.recordIndex
}

func (index *RecordIndex) Hold(ctx context.Context, source string, entry RecordEntry) error {
	fileID := recordFileID(source, entry.ID)
	if index.isHeld(fileID, entry.ChangedAt) {
		return nil
	}
	if errorValue := index.storeFile(ctx, fileID, entry.ID, entry.Content); errorValue != nil {
		return errorValue
	}
	index.markHeld(fileID, entry.ChangedAt)
	return nil
}

func (index *RecordIndex) HoldFrame(ctx context.Context, source string, frame string) error {
	fileID := source + recordFrameSuffix
	if index.isHeld(fileID, frame) {
		return nil
	}
	if errorValue := index.storeFile(ctx, fileID, fileID, frame); errorValue != nil {
		return errorValue
	}
	index.markHeld(fileID, frame)
	return nil
}

func (index *RecordIndex) Nearest(ctx context.Context, source string, query string, minimumRise float64, limit int) ([]RecordRise, error) {
	store, errorValue := index.store(ctx)
	if errorValue != nil {
		return nil, errorValue
	}
	ranked, errorValue := store.RecallFiles(ctx, bluememo.FileRequest{Text: query, Limit: recordIndexScanLimit})
	if errorValue != nil {
		return nil, errorValue
	}
	frame, hasFrame := frameRelevance(ranked, source)
	if !hasFrame {
		return nil, nil
	}
	rises := []RecordRise{}
	prefix := source + "/"
	for _, recalled := range ranked {
		rise := recalled.Relevance - frame
		if !strings.HasPrefix(recalled.File.FileID, prefix) || rise < minimumRise {
			continue
		}
		rises = append(rises, RecordRise{ID: strings.TrimPrefix(recalled.File.FileID, prefix), Rise: rise})
		if len(rises) == limit {
			break
		}
	}
	return rises, nil
}

func frameRelevance(ranked []bluememo.RecalledFile, source string) (float64, bool) {
	for _, recalled := range ranked {
		if recalled.File.FileID == source+recordFrameSuffix {
			return recalled.Relevance, true
		}
	}
	return 0, false
}

func recordFileID(source string, id string) string {
	return source + "/" + id
}

func (index *RecordIndex) isHeld(fileID string, version string) bool {
	index.mutex.Lock()
	defer index.mutex.Unlock()
	held, isHeld := index.indexed[fileID]
	return isHeld && held == version
}

func (index *RecordIndex) markHeld(fileID string, version string) {
	index.mutex.Lock()
	defer index.mutex.Unlock()
	index.indexed[fileID] = version
}

func (index *RecordIndex) storeFile(ctx context.Context, fileID string, name string, content string) error {
	store, errorValue := index.store(ctx)
	if errorValue != nil {
		return errorValue
	}
	return store.StoreFile(ctx, bluememo.File{FileID: fileID, Name: name, Medium: bluememo.MediumDocument, Summary: content})
}

func (index *RecordIndex) store(ctx context.Context) (*bluememo.Store, error) {
	index.mutex.Lock()
	defer index.mutex.Unlock()
	if index.opened != nil {
		return index.opened, nil
	}
	if strings.TrimSpace(index.stores.workspaceRootPath) == "" {
		return nil, errors.New("the record index has no workspace root to sit under")
	}
	path := filepath.Join(index.stores.workspaceRootPath, ".blueclaw", "state", "record-index.db")
	if errorValue := makeHoldingDirectory(path); errorValue != nil {
		return nil, errorValue
	}
	opened, errorValue := bluememo.Open(ctx, path, index.stores.configuration)
	if errorValue != nil {
		return nil, errorValue
	}
	if errorValue := os.Chmod(path, recordIndexFileMode); errorValue != nil {
		_ = opened.Close()
		return nil, fmt.Errorf("keep the record index to the service at %s: %w", path, errorValue)
	}
	index.opened = opened
	return opened, nil
}

func (index *RecordIndex) Close() error {
	index.mutex.Lock()
	defer index.mutex.Unlock()
	if index.opened == nil {
		return nil
	}
	errorValue := index.opened.Close()
	index.opened = nil
	return errorValue
}