agnets done

This commit is contained in:
2026-08-28 11:13:20 +05:30
parent eaf08e061d
commit 814073e97b
3 changed files with 65 additions and 4 deletions

View File

@@ -5212,6 +5212,53 @@ record('...and leaves the date-anchored shift records to the Go seeder',
!('ShiftRecord' in JSON.parse(builtFixture).entities) && seedModule.seedData.ShiftRecord.length > 0,
`${seedModule.seedData.ShiftRecord.length} shift records held in seed.js only`);
/* ── The registry does not report a shipped agent as an override of itself ── */
/**
* Authored agents now come from `/api/v1/agent-definitions`, and that registry
* holds both kinds: the shipped set, published from the same files this build
* ships, and anything a person authored. Passing the first kind through as an
* authored source made every shipped agent report that it "replaces the
* built-in agent of the same id" — nine warnings on the one screen that exists
* to say what is wrong, about a deployment that was working correctly.
*
* The rows below are the shape the live registry actually returns.
*/
const storeModule = await server.ssrLoadModule('/src/lib/agents/agentStore.js');
const agentsModule = await server.ssrLoadModule('/src/lib/agents/registry.js');
const shippedIds = new Set(agentsModule.AGENTS.map((a) => a.id));
const registryRows = [
...agentsModule.AGENTS.map((a) => ({
definition_id: a.id, visibility: 'organization', markdown: a.markdown,
})),
{
definition_id: 'authored-example', visibility: 'personal',
markdown: '---\nid: authored-example\nname: Authored Example\nstatus: published\n'
+ 'version: 1\npages:\n - control-center\n---\n\n# Authored Example\n',
},
];
const built = agentsModule.readAgentRegistry(
storeModule.sourcesFrom(registryRows, shippedIds), { customSkills: [] });
const falseShadows = built.diagnostics.filter((d) => d.kind === 'shadowed');
record('a shipped agent published to the registry is not reported as overriding itself',
falseShadows.length === 0,
falseShadows.map((d) => d.agentId).join(', ') || 'no false overrides');
record('...and an authored agent still appears beside the shipped ones',
built.agents.some((a) => a.id === 'authored-example')
&& built.agents.length === agentsModule.AGENTS.length + 1,
`${built.agents.length} agents from ${registryRows.length} rows`);
/* A genuine personal override of a shipped id is still reported — the
diagnostic is useful, it was only being raised for the wrong rows. */
const overridden = agentsModule.readAgentRegistry(
storeModule.sourcesFrom([{
definition_id: agentsModule.AGENTS[0].id, visibility: 'personal',
markdown: agentsModule.AGENTS[0].markdown,
}], shippedIds), { customSkills: [] });
record('a personal override of a shipped agent is still reported as one',
overridden.diagnostics.some((d) => d.kind === 'shadowed'),
overridden.diagnostics.map((d) => d.kind).join(', ') || 'none');
/* The seed must exercise every status, or none of the above can catch anything. */
const seededStatuses = new Set(seedModule.seedData.JobApplication.map((a) => a.status));
const neverSeeded = records.APPLICATION_STATUSES.filter((st) => !seededStatuses.has(st));

View File

@@ -39,9 +39,20 @@ export function useAgentDefinitions() {
* `{ path, raw }` is the shape `readAgentRegistry` already takes, so the reader
* did not have to learn where definitions come from — only the store changed.
*/
export function sourcesFrom(rows) {
export function sourcesFrom(rows, shippedIds = new Set()) {
return (rows || [])
.filter((r) => r && typeof r.markdown === 'string' && r.markdown.trim())
/* An organization row whose id is a shipped agent IS that shipped agent:
`importagents` publishes the same files this build ships, so the registry
and the bundle hold one definition between them, not two.
Passing it through as an authored source made every shipped agent report
that it "replaces the built-in agent of the same id" — nine warnings, on
the one screen that exists to say what is wrong, describing a deployment
that was working correctly. A personal row is a genuine override and is
still reported as one; an organization row with an id nothing ships is a
shared agent somebody authored, and belongs in the list. */
.filter((r) => !(r.visibility === 'organization' && shippedIds.has(r.definition_id)))
.map((r) => ({ path: `authored/${r.definition_id || r.id}.md`, raw: r.markdown }));
}
@@ -110,8 +121,8 @@ export function useRowFor(rows) {
}
/** Memoised sources, so the registry is not rebuilt on every render. */
export function useAuthoredSources(rows) {
return useMemo(() => sourcesFrom(rows), [rows]);
export function useAuthoredSources(rows, shippedIds) {
return useMemo(() => sourcesFrom(rows, shippedIds), [rows, shippedIds]);
}
/**

View File

@@ -39,7 +39,10 @@ export function useAgents() {
const deleteDefinition = useDeleteAgentDefinition();
const rows = useMemo(() => definitions.data || [], [definitions.data]);
const stored = useAuthoredSources(rows);
/* The ids this build ships. An organization row carrying one of them is that
same definition as published by importagents, not an override of it. */
const shippedIds = useMemo(() => new Set(AGENTS.map((a) => a.id)), []);
const stored = useAuthoredSources(rows, shippedIds);
const customSkills = useMemo(() => preferences.customSkills || [], [preferences.customSkills]);
/* Anything an author wrote before the store moved. Without this it would stop