import * as React from 'react'; import { AlertCircle, BookOpen, CheckCircle2, Cpu, Layers, Play, Search, Sparkles, Wrench, } from 'lucide-react'; import { Badge, Input, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@/components/ds'; import { allSkills, matchSkill, pageKeyForContext, skillsForContext } from '@/lib/skills/registry'; import { PLACEMENT_ROUTES } from '@/components/ai-assistant/placement'; import { ASSISTANT_CONTEXTS } from '@/components/ai-assistant/contexts'; import { agentCovers, agentScopedDisabled, classifyQuestion } from '@/lib/agents/runtime'; import { toolsForContext } from '@/lib/skills/tools'; import { retrieveKnowledge } from '@/lib/agents/knowledge'; import { cn } from '@/lib/utils'; /** * What this agent would do, on a page, before it is published. * * Runs the live runtime classifier, skill matcher, tool resolver, and * knowledge retriever to display comprehensive diagnostics. */ const CONTEXT_OPTIONS = Object.entries(PLACEMENT_ROUTES).map(([route, contextId]) => ({ contextId, route, label: ASSISTANT_CONTEXTS[contextId]?.page || contextId, })); const CLASSIFICATION_COPY = { structured: 'Reads workforce records through an attached skill.', knowledge: 'Answers directly from reference knowledge.', combined: 'Requires both structured records and knowledge retrieval.', }; /** @param {any} props */ export function AgentTestPanel({ fields, dirty, customSkills = [], onRunLive }) { const [contextId, setContextId] = React.useState( () => CONTEXT_OPTIONS.find((o) => fields.pages.includes(pageKeyForContext(o.contextId)))?.contextId || CONTEXT_OPTIONS[0].contextId ); const [question, setQuestion] = React.useState('What needs my attention?'); /* The draft as the runtime sees it */ const draftAgent = React.useMemo(() => ({ id: fields.id || 'draft', name: fields.name || 'This agent', pages: fields.pages, skills: fields.skills, subagents: fields.subagents, knowledge: fields.knowledge, starters: fields.starters, reasoning: fields.reasoning, webSearch: fields.webSearch, status: 'published', }), [fields]); const registry = React.useMemo(() => allSkills(customSkills), [customSkills]); const result = React.useMemo(() => { const covers = agentCovers(draftAgent, contextId); const disabled = agentScopedDisabled(draftAgent, registry, []); const pageOnly = skillsForContext(contextId, [], customSkills); const scoped = covers ? skillsForContext(contextId, disabled, customSkills) : []; const matched = covers ? matchSkill(question, contextId, disabled, customSkills) : null; return { covers, disabled, pageOnly, scoped, matched, tools: covers ? toolsForContext(contextId, disabled, customSkills) : [], knowledge: retrieveKnowledge({ agent: draftAgent, contextId, question }), classification: classifyQuestion({ question }), }; }, [draftAgent, contextId, question, registry, customSkills]); const activePageLabel = ASSISTANT_CONTEXTS[contextId]?.page || 'Current Page'; return (
Evaluate real-time intent routing and skill activation without publishing changes.
{result.covers ? result.scoped.length ? `${result.scoped.length} of ${result.pageOnly.length} operational skills are active and ready on this surface.` : `This page provides ${result.pageOnly.length} skills. With none attached, this agent will answer using the page's standard reader.` : `This agent has not been assigned to ${activePageLabel}. When asked on this page, it will politely decline or defer to the workspace reader.`}
{CLASSIFICATION_COPY[result.classification] || CLASSIFICATION_COPY.structured}
{result.matched ? ({result.matched.description}