agent build
This commit is contained in:
@@ -21,11 +21,18 @@ func isUUID(s string) bool {
|
||||
// Loader loads and validates authored definitions into runtime representations with tenant isolation.
|
||||
type Loader struct {
|
||||
repo *repo.DefinitionsRepo
|
||||
|
||||
// versions resolves a pinned version back to the definition that answered.
|
||||
// See LoadAgentVersion.
|
||||
versions *repo.VersionsRepo
|
||||
}
|
||||
|
||||
// NewLoader builds a runtime definition loader over a storage repository.
|
||||
func NewLoader(db repo.Querier) *Loader {
|
||||
return &Loader{repo: repo.NewDefinitionsRepo(db)}
|
||||
return &Loader{
|
||||
repo: repo.NewDefinitionsRepo(db),
|
||||
versions: repo.NewVersionsRepo(db),
|
||||
}
|
||||
}
|
||||
|
||||
// LoadAgent loads an agent definition by id or definition_id, parsing it into a runtime representation.
|
||||
@@ -77,8 +84,13 @@ func (l *Loader) LoadAgent(ctx context.Context, ident authctx.Identity, idOrDefI
|
||||
WebSearch: parsed.WebSearch,
|
||||
Instructions: parsed.Instructions,
|
||||
Skills: parsed.Skills,
|
||||
Subagents: parsed.Subagents,
|
||||
RawMarkdown: rawMD,
|
||||
Tools: parsed.Tools,
|
||||
// The spec's corpora, and the ONLY place they come from. A model that
|
||||
// asked to search a source its agent was not granted is asking for a
|
||||
// list it has no way to set — see tools.Context.KnowledgeSources.
|
||||
KnowledgeSources: parsed.Sources,
|
||||
Subagents: parsed.Subagents,
|
||||
RawMarkdown: rawMD,
|
||||
}
|
||||
|
||||
if rec["owner_user_id"] != nil {
|
||||
@@ -235,3 +247,59 @@ func (l *Loader) LoadExecutableSkill(ctx context.Context, ident authctx.Identity
|
||||
|
||||
return skill, nil
|
||||
}
|
||||
|
||||
/* ── Pinned versions ────────────────────────────────────────────────────── */
|
||||
|
||||
// LoadAgentVersion loads an agent AS IT WAS at a published version.
|
||||
//
|
||||
// The current definition is not consulted at all — that is the point. An agent
|
||||
// edited since a conversation began is a different agent, and a run that quietly
|
||||
// switched to it would answer a question the reader never asked with tools they
|
||||
// were never offered.
|
||||
//
|
||||
// Falls back to the current definition when the version is not in the history,
|
||||
// and does so deliberately rather than failing. Every definition published
|
||||
// before migration 000010 has no snapshot; refusing those would break every
|
||||
// existing conversation to enforce a rule that could not have been followed
|
||||
// when they started. The fallback is recorded by the caller, so a run that
|
||||
// could not pin is visible rather than silent.
|
||||
func (l *Loader) LoadAgentVersion(ctx context.Context, ident authctx.Identity,
|
||||
idOrDefID string, version int) (*Agent, bool, error) {
|
||||
|
||||
current, err := l.LoadExecutableAgent(ctx, ident, idOrDefID)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
if version <= 0 || version == current.Version {
|
||||
return current, false, nil
|
||||
}
|
||||
|
||||
snapshot, err := l.versions.Load(ctx, ident, repo.KindAgent, current.ID, version)
|
||||
if err != nil || snapshot == nil {
|
||||
// No snapshot for that number. The run continues on the current
|
||||
// definition — see the note above — and the caller records that it
|
||||
// could not pin.
|
||||
return current, true, nil
|
||||
}
|
||||
|
||||
parsed, err := definition.ParseAgent(snapshot.Markdown, definition.Options{})
|
||||
if err != nil {
|
||||
return current, true, nil
|
||||
}
|
||||
|
||||
// Rebuilt from the snapshot, keeping the identity fields that belong to the
|
||||
// row rather than to the definition text.
|
||||
pinned := *current
|
||||
pinned.Name = parsed.Name
|
||||
pinned.Description = parsed.Description
|
||||
pinned.Version = snapshot.Version
|
||||
pinned.Pages = parsed.Pages
|
||||
pinned.Reasoning = parsed.Reasoning
|
||||
pinned.Instructions = parsed.Instructions
|
||||
pinned.Skills = parsed.Skills
|
||||
pinned.Tools = parsed.Tools
|
||||
pinned.KnowledgeSources = parsed.Sources
|
||||
pinned.Subagents = parsed.Subagents
|
||||
pinned.RawMarkdown = snapshot.Markdown
|
||||
return &pinned, false, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user