From 80ddf7c8a700e458e4b2bd03af4bc6399a051846 Mon Sep 17 00:00:00 2001 From: "mars.yu" Date: Wed, 26 Aug 2026 18:04:02 +0800 Subject: [PATCH] Agent test UI: pick tools and agents rather than type them A tool name and an agent name are both things an author has in front of them and cannot spell from memory, and both fail silently when mistyped: a toolCalled on a function that does not exist can never pass, and a routedToAgent on a misspelt agent fails every run while reading like a real regression. The datalist on the tool fields only suggested -- it never stopped a typo. - toolCalled / toolNotCalled target, and a mock's function name, are now searchable pickers over the tool catalogue. - routedToAgent expected is an agent picker. It stores the name, not the id: both are accepted (AgentChainHop.Matches), and the name is what the run report prints in the expected and actual columns. - agentChain expected is an ordered chip list -- add from a picker, remove, move. Ordered rather than a multi-select because in `ordered` and `exact` mode the sequence IS the assertion, and a multi-select hands its options back in list order rather than click order. The move controls appear only under those two modes. Two things the pickers needed to be usable at all: The tool list is no longer just the suite agent's. A case can enter on a different agent, and the negative form of a routing assertion names the signature tool of the agent the conversation must stay away from -- by definition someone else's. Tools are now cached per agent id and unioned across the suite agent, the entry agent and the involved agents, kept current by one effect rather than a call at each of the five places those fields can change. Every picker keeps a manual escape hatch, and a stored value the picker cannot offer switches its own row to the text box instead of being quietly dropped on the next save. Neither catalogue is the whole truth: MCP tools are discovered at run time, and a stored case can name a function its agent has since lost. The manual-entry flags are editor-only -- buildPayload lists the fields the backend has, so they never reach the API. Co-Authored-By: Claude Opus 5 --- src/lib/langs/en.json | 13 +- src/lib/langs/zh.json | 13 +- src/lib/styles/pages/_agent-test.scss | 48 ++ .../[suiteId]/case/[caseId]/+page.svelte | 413 ++++++++++++++++-- 4 files changed, 447 insertions(+), 40 deletions(-) diff --git a/src/lib/langs/en.json b/src/lib/langs/en.json index 084812fa..75430d0d 100644 --- a/src/lib/langs/en.json +++ b/src/lib/langs/en.json @@ -665,5 +665,16 @@ "Worth checking:": "Worth checking:", "changed by chat": "changed by chat", "New Case by Chat": "New Case by Chat", - "This suite has no judge model configured, so chat authoring has no default to fall back on -- pick one above.": "This suite has no judge model configured, so chat authoring has no default to fall back on -- pick one above." + "This suite has no judge model configured, so chat authoring has no default to fall back on -- pick one above.": "This suite has no judge model configured, so chat authoring has no default to fall back on -- pick one above.", + "Search tools": "Search tools", + "Pick a tool": "Pick a tool", + "Pick an agent": "Pick an agent", + "Type a name instead": "Type a name instead", + "Pick from the list": "Pick from the list", + "agent name or id": "agent name or id", + "Add an agent to the chain": "Add an agent to the chain", + "Move earlier": "Move earlier", + "Move later": "Move later", + "Remove agent from the chain": "Remove agent from the chain", + "No tools found for the agents on this case. Add the agent under Involved agents, or type the name.": "No tools found for the agents on this case. Add the agent under Involved agents, or type the name." } diff --git a/src/lib/langs/zh.json b/src/lib/langs/zh.json index ab7f6f34..574713a3 100644 --- a/src/lib/langs/zh.json +++ b/src/lib/langs/zh.json @@ -859,5 +859,16 @@ "Worth checking:": "建议确认一下:", "changed by chat": "对话改动过", "New Case by Chat": "用对话新建", - "This suite has no judge model configured, so chat authoring has no default to fall back on -- pick one above.": "这个套件没有配置判官模型,对话出题也就没有默认可用的模型——请在上面选一个。" + "This suite has no judge model configured, so chat authoring has no default to fall back on -- pick one above.": "这个套件没有配置判官模型,对话出题也就没有默认可用的模型——请在上面选一个。", + "Search tools": "搜索工具", + "Pick a tool": "选择工具", + "Pick an agent": "选择 Agent", + "Type a name instead": "改为手动输入", + "Pick from the list": "改为从列表选择", + "agent name or id": "Agent 名称或 id", + "Add an agent to the chain": "往调用链里加一个 Agent", + "Move earlier": "前移", + "Move later": "后移", + "Remove agent from the chain": "从调用链里移除", + "No tools found for the agents on this case. Add the agent under Involved agents, or type the name.": "这条用例涉及的 Agent 没有查到可用工具。可以在\"涉及的 Agent\"里补上对应 Agent,或者手动输入工具名。" } diff --git a/src/lib/styles/pages/_agent-test.scss b/src/lib/styles/pages/_agent-test.scss index 1f098c9d..0ecfc726 100644 --- a/src/lib/styles/pages/_agent-test.scss +++ b/src/lib/styles/pages/_agent-test.scss @@ -474,6 +474,54 @@ color: var(--ats-tone); } +/* ======================================================================== + * Agent chain editor + * + * The expected list of an agentChain assertion. Chips rather than a text field + * because the order is the assertion in `ordered`/`exact` mode, and a chip can + * carry its own move and remove controls. + * ======================================================================== */ + +.ats-chain { + display: flex; + flex-wrap: wrap; + gap: 0.375rem; + margin-bottom: 0.375rem; +} + +/* Inline control inside a chip: sized down to the chip's own line-height so a + chip with three of them stays the height of a plain badge. */ +.ats-chip-btn { + display: inline-flex; + align-items: center; + justify-content: center; + width: 1rem; + height: 1rem; + padding: 0; + border: 0; + border-radius: 0.1875rem; + background: transparent; + color: inherit; + line-height: 1; + + & i { + font-size: 0.875rem; + } + + &:hover:not(:disabled) { + background-color: color-mix(in srgb, var(--ats-tone) 25%, transparent); + } + + &:disabled { + opacity: 0.35; + } +} + +.ats-chip-index { + opacity: 0.7; + font-variant-numeric: tabular-nums; +} + /* ======================================================================== * Alerts (replaces .alert.alert-danger / -warning / -info) * ======================================================================== */ diff --git a/src/routes/page/agent-test/[suiteId]/case/[caseId]/+page.svelte b/src/routes/page/agent-test/[suiteId]/case/[caseId]/+page.svelte index 806c0eaa..c67e4205 100644 --- a/src/routes/page/agent-test/[suiteId]/case/[caseId]/+page.svelte +++ b/src/routes/page/agent-test/[suiteId]/case/[caseId]/+page.svelte @@ -1,5 +1,5 @@