agent build

This commit is contained in:
2026-08-28 12:21:44 +05:30
parent b6f8655909
commit f7df96c973
138 changed files with 24164 additions and 207 deletions

View File

@@ -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
}