78e6858751
RegisterStore(reg, StoreDeps) registers the persistent-memory tools over the host's KV and/or File backends: - kv_get/set/list/delete (KVStorage seam) - file_save/get/get_text/get_metadata/list/delete (FileStorage seam), plus file_search (FileSearcher) and create_file_url (FileTokenMinter) when wired. Near-zero-config: Quota defaults to a generous static cap (staticQuota), the per-value/per-file caps default, and the kv vs file groups register independently (a host can take just one). Seams moved clean (interface-only): kv_storage.go, quota_provider.go, file_descendant_grant.go. The default in-memory KV/File backends come with contrib/store at P4. Core go.sum still free of gorm/redis/discordgo/sqlite. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
78 lines
2.4 KiB
Go
78 lines
2.4 KiB
Go
package tools
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
|
|
"gitea.stevedudenhoeffer.com/steve/executus/tool"
|
|
)
|
|
|
|
// StoreDeps wires the persistent-memory tools (kv_* and file_*). A host
|
|
// supplies its KV and/or File backends; the kv group registers only when KV is
|
|
// set and the file group only when Files is set, so a host can take just one.
|
|
// Everything else has a sensible default:
|
|
//
|
|
// - Quota defaults to a generous static cap (a host that meters per-skill
|
|
// storage supplies its own QuotaProvider).
|
|
// - FileSearch / Minter+BaseURL are optional — file_search and
|
|
// create_file_url register only when wired.
|
|
// - MaxValueBytes / MaxFileBytes default when non-positive.
|
|
type StoreDeps struct {
|
|
KV KVStorage
|
|
Files FileStorage
|
|
Quota QuotaProvider
|
|
FileSearch FileSearcher
|
|
Minter FileTokenMinter
|
|
BaseURL string
|
|
|
|
MaxValueBytes int // kv_set per-value cap; default 256 KiB
|
|
MaxFileBytes int // file_save per-file cap; default 16 MiB
|
|
}
|
|
|
|
// RegisterStore registers the kv_* tools (when KV is set) and the file_* tools
|
|
// (when Files is set). At least one of KV/Files is required.
|
|
func RegisterStore(reg tool.Registry, d StoreDeps) error {
|
|
if d.KV == nil && d.Files == nil {
|
|
return errors.New("tools: RegisterStore needs at least KV or Files")
|
|
}
|
|
if d.Quota == nil {
|
|
d.Quota = staticQuota{kvMax: 64 << 20, filesMax: 1 << 30}
|
|
}
|
|
if d.MaxValueBytes <= 0 {
|
|
d.MaxValueBytes = 256 << 10
|
|
}
|
|
if d.MaxFileBytes <= 0 {
|
|
d.MaxFileBytes = 16 << 20
|
|
}
|
|
|
|
var ts []tool.Tool
|
|
if d.KV != nil {
|
|
ts = append(ts,
|
|
NewKVGet(d.KV), NewKVSet(d.KV, d.Quota, d.MaxValueBytes),
|
|
NewKVList(d.KV), NewKVDelete(d.KV),
|
|
)
|
|
}
|
|
if d.Files != nil {
|
|
ts = append(ts,
|
|
NewFileSave(d.Files, d.Quota, d.MaxFileBytes),
|
|
NewFileGet(d.Files), NewFileGetText(d.Files), NewFileGetMetadata(d.Files),
|
|
NewFileList(d.Files), NewFileDelete(d.Files),
|
|
)
|
|
if d.FileSearch != nil {
|
|
ts = append(ts, NewFileSearch(d.FileSearch))
|
|
}
|
|
if d.Minter != nil && d.BaseURL != "" {
|
|
ts = append(ts, NewCreateFileURL(d.Minter, d.Files, d.BaseURL))
|
|
}
|
|
}
|
|
return registerAll(reg, ts...)
|
|
}
|
|
|
|
// staticQuota is the default QuotaProvider: a fixed KV/file byte cap for every
|
|
// skill. A host that needs per-skill metering supplies its own.
|
|
type staticQuota struct{ kvMax, filesMax int64 }
|
|
|
|
func (q staticQuota) EffectiveQuota(context.Context, string) (kvMax, filesMax int64, err error) {
|
|
return q.kvMax, q.filesMax, nil
|
|
}
|