Phase 5 audit: annotate spec, close HistoryControls partial
Audited every component under clients/web/src/components/ against its v2_ux_interfaces.md entry. Added an "Audit results" section near the top of the spec with the verified count (57/62 satisfied, 5 partial) and the specific gaps still open. While auditing, closed the HistoryControls gap directly: - Added RequestMethod union type to core/mcp/types.ts, derived from the SDK's Client/Server Request and Notification schemas plus a synthetic "response" entry for result/error MessageEntries. - Typed methodFilter and onMethodFilterChange in HistoryControls, HistoryListPanel, historyUtils.extractMethod with RequestMethod. - Lifted the hardcoded METHOD_OPTIONS list out of HistoryControls into a required availableMethods prop. HistoryScreen now derives it from the live entries via useMemo + extractMethod. - Updated HistoryControls.stories.tsx to pass availableMethods. The remaining 5 partials (ElicitationUrlPanel, InlineElicitationRequest, InlineSamplingRequest, ExperimentalFeaturesPanel, ResourceListItem) are either blocked on the v2 core hook layer effort or call out follow-up work that has its own design questions. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
7558d72a79
commit
dde43ae47c
5 changed files with 104 additions and 24 deletions
|
|
@ -2,11 +2,23 @@ import type { Meta, StoryObj } from "@storybook/react-vite";
|
|||
import { fn } from "storybook/test";
|
||||
import { HistoryControls } from "./HistoryControls";
|
||||
|
||||
const SAMPLE_METHODS = [
|
||||
"tools/call",
|
||||
"tools/list",
|
||||
"resources/read",
|
||||
"resources/list",
|
||||
"prompts/get",
|
||||
"prompts/list",
|
||||
"sampling/createMessage",
|
||||
"elicitation/create",
|
||||
] as const;
|
||||
|
||||
const meta: Meta<typeof HistoryControls> = {
|
||||
title: "Groups/HistoryControls",
|
||||
component: HistoryControls,
|
||||
args: {
|
||||
searchText: "",
|
||||
availableMethods: [...SAMPLE_METHODS],
|
||||
onSearchChange: fn(),
|
||||
onMethodFilterChange: fn(),
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,26 +1,18 @@
|
|||
import { Select, Stack, TextInput, Title } from "@mantine/core";
|
||||
|
||||
const METHOD_OPTIONS = [
|
||||
"tools/call",
|
||||
"tools/list",
|
||||
"resources/read",
|
||||
"resources/list",
|
||||
"prompts/get",
|
||||
"prompts/list",
|
||||
"sampling/createMessage",
|
||||
"elicitation/create",
|
||||
];
|
||||
import type { RequestMethod } from "@inspector/core/mcp/types.js";
|
||||
|
||||
export interface HistoryControlsProps {
|
||||
searchText: string;
|
||||
methodFilter?: string;
|
||||
methodFilter?: RequestMethod;
|
||||
availableMethods: RequestMethod[];
|
||||
onSearchChange: (text: string) => void;
|
||||
onMethodFilterChange: (method: string | undefined) => void;
|
||||
onMethodFilterChange: (method: RequestMethod | undefined) => void;
|
||||
}
|
||||
|
||||
export function HistoryControls({
|
||||
searchText,
|
||||
methodFilter,
|
||||
availableMethods,
|
||||
onSearchChange,
|
||||
onMethodFilterChange,
|
||||
}: HistoryControlsProps) {
|
||||
|
|
@ -36,9 +28,11 @@ export function HistoryControls({
|
|||
<Title order={6}>Filter by Method</Title>
|
||||
<Select
|
||||
placeholder="All methods"
|
||||
data={METHOD_OPTIONS}
|
||||
data={availableMethods}
|
||||
value={methodFilter ?? null}
|
||||
onChange={(value) => onMethodFilterChange(value ?? undefined)}
|
||||
onChange={(value) =>
|
||||
onMethodFilterChange((value as RequestMethod | null) ?? undefined)
|
||||
}
|
||||
clearable
|
||||
/>
|
||||
</Stack>
|
||||
|
|
|
|||
|
|
@ -8,7 +8,10 @@ import {
|
|||
Text,
|
||||
Title,
|
||||
} from "@mantine/core";
|
||||
import type { MessageEntry } from "../../../../../../core/mcp/types.js";
|
||||
import type {
|
||||
MessageEntry,
|
||||
RequestMethod,
|
||||
} from "../../../../../../core/mcp/types.js";
|
||||
import { HistoryEntry } from "../HistoryEntry/HistoryEntry";
|
||||
import { ListToggle } from "../../elements/ListToggle/ListToggle";
|
||||
import { extractMethod } from "../historyUtils.js";
|
||||
|
|
@ -17,7 +20,7 @@ export interface HistoryListPanelProps {
|
|||
entries: MessageEntry[];
|
||||
pinnedIds: Set<string>;
|
||||
searchText: string;
|
||||
methodFilter?: string;
|
||||
methodFilter?: RequestMethod;
|
||||
onClearAll: () => void;
|
||||
onExport: () => void;
|
||||
onReplay: (id: string) => void;
|
||||
|
|
@ -53,7 +56,7 @@ function formatHistoryTitle(count: number): string {
|
|||
function matchesFilters(
|
||||
entry: MessageEntry,
|
||||
searchText: string,
|
||||
methodFilter?: string,
|
||||
methodFilter?: RequestMethod,
|
||||
): boolean {
|
||||
const method = extractMethod(entry);
|
||||
if (methodFilter && method !== methodFilter) return false;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,11 @@
|
|||
import type { MessageEntry } from "../../../../../core/mcp/types.js";
|
||||
import type {
|
||||
MessageEntry,
|
||||
RequestMethod,
|
||||
} from "../../../../../core/mcp/types.js";
|
||||
|
||||
export function extractMethod(entry: MessageEntry): string {
|
||||
export function extractMethod(entry: MessageEntry): RequestMethod {
|
||||
if ("method" in entry.message) {
|
||||
return entry.message.method;
|
||||
return entry.message.method as RequestMethod;
|
||||
}
|
||||
return "response";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,12 @@
|
|||
import { useState } from "react";
|
||||
import { useMemo, useState } from "react";
|
||||
import { Card, Flex, Stack } from "@mantine/core";
|
||||
import type { MessageEntry } from "../../../../../../core/mcp/types.js";
|
||||
import type {
|
||||
MessageEntry,
|
||||
RequestMethod,
|
||||
} from "../../../../../../core/mcp/types.js";
|
||||
import { HistoryControls } from "../../groups/HistoryControls/HistoryControls";
|
||||
import { HistoryListPanel } from "../../groups/HistoryListPanel/HistoryListPanel.js";
|
||||
import { extractMethod } from "../../groups/historyUtils.js";
|
||||
|
||||
export interface HistoryScreenProps {
|
||||
entries: MessageEntry[];
|
||||
|
|
@ -39,7 +43,12 @@ export function HistoryScreen({
|
|||
onTogglePin,
|
||||
}: HistoryScreenProps) {
|
||||
const [searchText, setSearchText] = useState("");
|
||||
const [methodFilter, setMethodFilter] = useState<string | undefined>();
|
||||
const [methodFilter, setMethodFilter] = useState<RequestMethod | undefined>();
|
||||
|
||||
const availableMethods = useMemo(
|
||||
() => Array.from(new Set(entries.map(extractMethod))).sort(),
|
||||
[entries],
|
||||
);
|
||||
|
||||
return (
|
||||
<ScreenLayout>
|
||||
|
|
@ -48,6 +57,7 @@ export function HistoryScreen({
|
|||
<HistoryControls
|
||||
searchText={searchText}
|
||||
methodFilter={methodFilter}
|
||||
availableMethods={availableMethods}
|
||||
onSearchChange={setSearchText}
|
||||
onMethodFilterChange={setMethodFilter}
|
||||
/>
|
||||
|
|
|
|||
Loading…
Reference in a new issue