mirror of
https://github.com/mudler/LocalAI.git
synced 2026-11-06 04:23:15 -05:00
A source declares a scope (user, agent or channel), a home-relative index path and a byte cap. The loader reads the indexes that apply to a chat and returns one bounded block under a fixed header, plus a key that changes with it. Details of a topic are read next to the index; the path is built from the registry and the chat, so the model can only name a topic. The package only reads. A Writer interface lets a later change plug in the save path, and CheckIndex and CheckProfile return the current entries when a write would pass a cap, so the model merges them. Assisted-by: Claude Code:claude-sonnet-5-5 Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
54 lines
1.7 KiB
Go
54 lines
1.7 KiB
Go
package contextfiles
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
// OverCapError means a write would make a file larger than its cap. Current
|
|
// holds what the file has now, so the writer can show it to the model, which
|
|
// must merge the entries instead of adding to them.
|
|
type OverCapError struct {
|
|
What string // "index" or "profile"
|
|
Lines, Len int // size of the refused text
|
|
MaxLines int // 0: no line limit
|
|
MaxBytes int
|
|
Current string
|
|
}
|
|
|
|
func (e *OverCapError) Error() string {
|
|
limit := fmt.Sprintf("%d bytes", e.MaxBytes)
|
|
if e.MaxLines > 0 {
|
|
limit = fmt.Sprintf("%d lines and %s", e.MaxLines, limit)
|
|
}
|
|
return fmt.Sprintf("the %s would be too long (%d lines, %d bytes; the limit is %s): merge or drop entries, then save the whole %s again. Current entries:\n%s",
|
|
e.What, e.Lines, e.Len, limit, e.What, e.Current)
|
|
}
|
|
|
|
func countLines(b []byte) int {
|
|
n := 0
|
|
for line := range strings.SplitSeq(string(b), "\n") {
|
|
if strings.TrimSpace(line) != "" {
|
|
n++
|
|
}
|
|
}
|
|
return n
|
|
}
|
|
|
|
// CheckIndex checks a new index of the source against its caps. Over a cap it
|
|
// returns an *OverCapError that carries the current index.
|
|
func CheckIndex(src Source, current, next []byte) error {
|
|
if lines := countLines(next); lines > MaxIndexLines || len(next) > src.limit() {
|
|
return &OverCapError{What: "index", Lines: lines, Len: len(next), MaxLines: MaxIndexLines, MaxBytes: src.limit(), Current: string(current)}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// CheckProfile checks a new agent profile against MaxProfileBytes.
|
|
func CheckProfile(current, next []byte) error {
|
|
if len(next) > MaxProfileBytes {
|
|
return &OverCapError{What: "profile", Lines: countLines(next), Len: len(next), MaxBytes: MaxProfileBytes, Current: string(current)}
|
|
}
|
|
return nil
|
|
}
|