agent build
This commit is contained in:
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/krow/krow-backend/go-api/internal/authctx"
|
||||
@@ -888,3 +889,146 @@ pages:
|
||||
t.Errorf("custom skill output mismatch: %+v", resCustom)
|
||||
}
|
||||
}
|
||||
|
||||
/* ── Pinned versions ────────────────────────────────────────────────────── */
|
||||
|
||||
// TestAPinnedRunUsesTheAgentAsItWas.
|
||||
//
|
||||
// §3: "Running conversations pin the version they started with."
|
||||
//
|
||||
// The reason this matters is not tidiness. A person approves a write while
|
||||
// looking at version 1; somebody publishes version 2 with different
|
||||
// instructions and a different tool list; the approval is then carried out. If
|
||||
// the run silently moved to version 2, the thing performed would not be the
|
||||
// thing that was shown — which is the failure the whole confirmation mechanism
|
||||
// exists to prevent, arriving through the registry instead of through the gate.
|
||||
func TestAPinnedRunUsesTheAgentAsItWas(t *testing.T) {
|
||||
f := newFixture(t)
|
||||
ctx := context.Background()
|
||||
|
||||
v1 := `---
|
||||
id: pinned-agent
|
||||
name: Pinned Agent
|
||||
status: published
|
||||
version: 1
|
||||
pages:
|
||||
- activity
|
||||
tools:
|
||||
- activity_breakdown
|
||||
---
|
||||
|
||||
## Instructions
|
||||
Version one instructions.
|
||||
`
|
||||
v2 := `---
|
||||
id: pinned-agent
|
||||
name: Pinned Agent
|
||||
status: published
|
||||
version: 2
|
||||
pages:
|
||||
- activity
|
||||
tools:
|
||||
- activity_breakdown
|
||||
- activity_signals
|
||||
---
|
||||
|
||||
## Instructions
|
||||
Version two instructions.
|
||||
`
|
||||
|
||||
if _, err := f.h.Pool.Exec(ctx, `
|
||||
INSERT INTO agent_definitions (definition_id, org_id, visibility, created_by,
|
||||
markdown, status, version, name, description, pages)
|
||||
VALUES ('pinned-agent', $1::uuid, 'organization', $2::uuid, $3::text,
|
||||
'published', 2, 'Pinned Agent', '', ARRAY['activity'])`,
|
||||
f.org1, f.userA.UserID, v2); err != nil {
|
||||
t.Fatalf("seed current definition: %v", err)
|
||||
}
|
||||
|
||||
versions := repo.NewVersionsRepo(f.h.Pool)
|
||||
for _, s := range []repo.SnapshotInput{
|
||||
{Kind: repo.KindAgent, DefinitionID: "pinned-agent", Version: 1, Markdown: v1, Name: "Pinned Agent"},
|
||||
{Kind: repo.KindAgent, DefinitionID: "pinned-agent", Version: 2, Markdown: v2, Name: "Pinned Agent"},
|
||||
} {
|
||||
if err := versions.Snapshot(ctx, f.userA, s); err != nil {
|
||||
t.Fatalf("snapshot v%d: %v", s.Version, err)
|
||||
}
|
||||
}
|
||||
|
||||
// Unpinned: the current definition, which is version 2.
|
||||
current, fellBack, err := f.loader.LoadAgentVersion(ctx, f.userA, "pinned-agent", 0)
|
||||
if err != nil {
|
||||
t.Fatalf("load current: %v", err)
|
||||
}
|
||||
if fellBack {
|
||||
t.Error("an unpinned load reported a fallback")
|
||||
}
|
||||
if current.Version != 2 || !strings.Contains(current.Instructions, "Version two") {
|
||||
t.Errorf("current is v%d: %q", current.Version, current.Instructions)
|
||||
}
|
||||
if len(current.Tools) != 2 {
|
||||
t.Errorf("v2 should carry 2 tools, got %v", current.Tools)
|
||||
}
|
||||
|
||||
// Pinned to 1: the agent as it was, INCLUDING its narrower tool list. That
|
||||
// last part is the one that would let an approved write reach a tool the
|
||||
// approver's version never offered.
|
||||
pinned, fellBack, err := f.loader.LoadAgentVersion(ctx, f.userA, "pinned-agent", 1)
|
||||
if err != nil {
|
||||
t.Fatalf("load v1: %v", err)
|
||||
}
|
||||
if fellBack {
|
||||
t.Error("a version that exists reported a fallback")
|
||||
}
|
||||
if pinned.Version != 1 {
|
||||
t.Errorf("pinned version = %d, want 1", pinned.Version)
|
||||
}
|
||||
if !strings.Contains(pinned.Instructions, "Version one") {
|
||||
t.Errorf("pinned instructions are v2's: %q", pinned.Instructions)
|
||||
}
|
||||
if len(pinned.Tools) != 1 || pinned.Tools[0] != "activity_breakdown" {
|
||||
t.Errorf("pinned tools are %v; v1 offered only activity_breakdown", pinned.Tools)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAVersionWithNoSnapshotFallsBackAndSaysSo(t *testing.T) {
|
||||
// Every definition published before versions were recorded has no snapshot.
|
||||
// Refusing those would break every conversation that predates the feature,
|
||||
// to enforce a rule they could not have followed. The run continues on the
|
||||
// current definition and the fallback is REPORTED, because a silent
|
||||
// substitution is the thing worth preventing.
|
||||
f := newFixture(t)
|
||||
ctx := context.Background()
|
||||
|
||||
md := `---
|
||||
id: unversioned-agent
|
||||
name: Unversioned
|
||||
status: published
|
||||
version: 1
|
||||
pages:
|
||||
- activity
|
||||
---
|
||||
|
||||
## Instructions
|
||||
Only ever existed as one thing.
|
||||
`
|
||||
if _, err := f.h.Pool.Exec(ctx, `
|
||||
INSERT INTO agent_definitions (definition_id, org_id, visibility, created_by,
|
||||
markdown, status, version, name, description, pages)
|
||||
VALUES ('unversioned-agent', $1::uuid, 'organization', $2::uuid, $3::text,
|
||||
'published', 1, 'Unversioned', '', ARRAY['activity'])`,
|
||||
f.org1, f.userA.UserID, md); err != nil {
|
||||
t.Fatalf("seed: %v", err)
|
||||
}
|
||||
|
||||
agent, fellBack, err := f.loader.LoadAgentVersion(ctx, f.userA, "unversioned-agent", 7)
|
||||
if err != nil {
|
||||
t.Fatalf("a missing snapshot failed the load: %v", err)
|
||||
}
|
||||
if !fellBack {
|
||||
t.Error("a version with no snapshot did not report a fallback")
|
||||
}
|
||||
if agent == nil || agent.Version != 1 {
|
||||
t.Errorf("the fallback did not return the current definition: %+v", agent)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user