Files
executus/tools/file_storage.go
T
steve 89f3334512 P3: meta + primitive tool group (think/now/cite + classify/extract/summarize)
Grow executus/tools into a real generic tool library:

- Register(reg): the always-available, zero-config tools — think, now (UTC
  unless a CurrentTimeProvider is wired), cite (inert unless a CitationStorage
  is wired). All nil-safe; a light host calls Register and is useful.
- RegisterMeta(reg, MetaDeps): the LLM-backed meta tools — classify,
  extract_entities, summarize — over the llmmeta helper. Budget defaults to the
  shipped in-memory per-run cap; Files optional; caps default.
- Seams moved (interface/type-only, no host coupling): research_providers.go
  (CurrentTimeProvider/CitationStorage/SearchBudget/PageExtractor/PDFFetcher/…)
  and file_storage.go (FileStorage + FileDomainMeta). Plus the in-memory budget
  default (research_defaults.go) and scope_validate.go.

calculate deferred (drags github.com/Krognol/go-wolfram + a module-path replace
— not worth it in the lean core for one tool). Core go.sum still free of
gorm/redis/discordgo/sqlite/wolfram.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-26 22:02:54 -04:00

50 lines
1.8 KiB
Go

// file_storage.go declares the narrow FileStorage interface that the
// four v4 file tools (file_save, file_get, file_list, file_delete)
// need at execute time.
//
// Why a narrow interface (vs importing pkg/logic/skills directly): same
// cycle constraint as kv_storage.go — pkg/logic/skills imports
// pkg/skilltools, so we mirror the FileMeta shape here and let
// pkg/logic/mort.go adapt at wiring time.
//
// FileDomainMeta is field-for-field with skills.FileMeta; the production
// adapter is a struct copy.
package tools
import (
"context"
"errors"
"time"
)
// FileStorage is the narrow surface file tools need from the skills
// package. Production wiring (mort.go) bridges *skills.System.Storage().
// nil-safe: tools constructed against a nil FileStorage surface "not
// configured" at the first call.
type FileStorage interface {
FileSave(ctx context.Context, meta FileDomainMeta, content []byte) (string, error)
FileGet(ctx context.Context, fileID string) (*FileDomainMeta, []byte, error)
FileList(ctx context.Context, skillID, scope string) ([]FileDomainMeta, error)
FileDelete(ctx context.Context, fileID string) error
FileUsageBytes(ctx context.Context, skillID string) (int64, error)
}
// FileDomainMeta mirrors skills.FileMeta. Field-for-field; the
// production adapter is a struct copy.
type FileDomainMeta struct {
ID string // UUID, the public file_id
SkillID string
Scope string
Name string
ContentHash string // SHA256 hex
MimeType string
SizeBytes int64
CreatedAt time.Time
}
// ErrFileNotFound mirrors skills.ErrFileNotFound. The production
// adapter returns this sentinel when wrapping a skills.ErrFileNotFound;
// tools detect it with errors.Is to surface a "not_found" string to the
// LLM rather than a generic error.
var ErrFileNotFound = errors.New("file: not found")