mirror of
https://github.com/coder/coder.git
synced 2026-10-16 14:48:56 +08:00
fix(site/src/pages/AgentsPage): lead find_tools header with the match count (#29178)
This commit is contained in:
+1
-1
@@ -602,7 +602,7 @@ export const FindToolsSearchResult: Story = {
|
||||
play: async ({ canvasElement }) => {
|
||||
const canvas = within(canvasElement);
|
||||
const summary = canvas.getByRole("button", {
|
||||
name: "Searched tools: github issues, pull requests, name:github__list_issues -> 2 matched",
|
||||
name: "Matched 2 tools: github__list_issues, github__list_pull_requests",
|
||||
});
|
||||
await userEvent.click(summary);
|
||||
},
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
import type { Meta, StoryObj } from "@storybook/react-vite";
|
||||
import { FindToolsTool } from "./FindToolsTool";
|
||||
|
||||
const githubMatches = [
|
||||
{
|
||||
name: "github__list_issues",
|
||||
description: "List issues in a GitHub repository.",
|
||||
},
|
||||
{
|
||||
name: "github__list_pull_requests",
|
||||
description: "List pull requests in a GitHub repository.",
|
||||
},
|
||||
];
|
||||
|
||||
const meta: Meta<typeof FindToolsTool> = {
|
||||
title: "pages/AgentsPage/ChatElements/tools/FindToolsTool",
|
||||
component: FindToolsTool,
|
||||
args: {
|
||||
queries: ["github issues", "pull requests"],
|
||||
names: ["github__list_issues"],
|
||||
matches: githubMatches,
|
||||
status: "completed",
|
||||
isError: false,
|
||||
},
|
||||
decorators: [
|
||||
(Story) => (
|
||||
<div className="mx-auto w-full max-w-3xl py-6 font-sans text-xs">
|
||||
<Story />
|
||||
</div>
|
||||
),
|
||||
],
|
||||
};
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof FindToolsTool>;
|
||||
|
||||
export const Running: Story = {
|
||||
args: { status: "running", matches: [] },
|
||||
};
|
||||
|
||||
export const ManyMatches: Story = {};
|
||||
|
||||
export const SingleMatch: Story = {
|
||||
args: {
|
||||
queries: ["github issues"],
|
||||
names: [],
|
||||
matches: githubMatches.slice(0, 1),
|
||||
},
|
||||
};
|
||||
|
||||
export const NoMatches: Story = {
|
||||
args: {
|
||||
queries: ["nonexistent capability"],
|
||||
names: [],
|
||||
matches: [],
|
||||
},
|
||||
};
|
||||
|
||||
// A long match list overflows the header, so the match count leads the
|
||||
// label and only the tool names are truncated.
|
||||
export const LongMatchListTruncates: Story = {
|
||||
decorators: [
|
||||
(Story) => (
|
||||
<div className="w-80">
|
||||
<Story />
|
||||
</div>
|
||||
),
|
||||
],
|
||||
args: {
|
||||
queries: ["microsoft documentation", "code samples"],
|
||||
names: [],
|
||||
matches: [
|
||||
"mslearn__microsoft_docs_search",
|
||||
"mslearn__microsoft_docs_fetch",
|
||||
"mslearn__microsoft_code_sample_search",
|
||||
"mslearn__microsoft_learn_catalog",
|
||||
].map((name) => ({ name, description: `${name} description` })),
|
||||
},
|
||||
};
|
||||
|
||||
// A long search with no results falls back to showing the search terms.
|
||||
export const LongSearchNoMatchesTruncates: Story = {
|
||||
decorators: [
|
||||
(Story) => (
|
||||
<div className="w-80">
|
||||
<Story />
|
||||
</div>
|
||||
),
|
||||
],
|
||||
args: {
|
||||
queries: [
|
||||
"list github issues for a repository",
|
||||
"open pull requests assigned to me",
|
||||
"comment on a pull request review thread",
|
||||
],
|
||||
names: ["github__list_issues"],
|
||||
matches: [],
|
||||
},
|
||||
};
|
||||
|
||||
export const Failed: Story = {
|
||||
args: {
|
||||
queries: ["github issues"],
|
||||
names: [],
|
||||
matches: [],
|
||||
status: "error",
|
||||
isError: true,
|
||||
errorMessage:
|
||||
"The schema budget for this step is exhausted; call the tools already activated or retry next step.",
|
||||
},
|
||||
};
|
||||
@@ -24,12 +24,23 @@ export const FindToolsTool: FC<FindToolsToolProps> = ({
|
||||
isError,
|
||||
errorMessage,
|
||||
}) => {
|
||||
const queryLabel =
|
||||
[...queries, ...names.map((name) => `name:${name}`)].join(", ") || "tools";
|
||||
const label =
|
||||
status === "running"
|
||||
? `Searching tools: ${queryLabel}`
|
||||
: `Searched tools: ${queryLabel} -> ${matches.length} matched`;
|
||||
// The header label truncates from the end, so the outcome leads and
|
||||
// the list absorbs any overflow. Search terms only appear when there
|
||||
// are no matched tool names to show instead.
|
||||
const searchTerms = [...queries, ...names].join(", ");
|
||||
const searchSuffix = searchTerms ? `: ${searchTerms}` : "";
|
||||
let label: string;
|
||||
if (status === "running") {
|
||||
label = `Searching tools${searchSuffix}`;
|
||||
} else if (isError) {
|
||||
label = `Failed to search tools${searchSuffix}`;
|
||||
} else if (matches.length === 0) {
|
||||
label = `No tools matched${searchSuffix}`;
|
||||
} else {
|
||||
const noun = matches.length === 1 ? "tool" : "tools";
|
||||
const matchedNames = matches.map((match) => match.name).join(", ");
|
||||
label = `Matched ${matches.length} ${noun}: ${matchedNames}`;
|
||||
}
|
||||
|
||||
return (
|
||||
<ToolCall.Root
|
||||
|
||||
Reference in New Issue
Block a user