Phase 2: Refactor Prompts cluster to MCP SDK types
Replace ad hoc local types with MCP SDK schema types across the Prompts group components and PromptsScreen, per the v2 UX interfaces plan. - PromptListItem: accept `prompt: Prompt` instead of flat `name`/`description`; render `title ?? name` as primary label - PromptControls: accept `Prompt[]` + `selectedName` instead of `PromptItem[]`; no-op on clicking already-selected prompt; search includes title field - PromptArgumentsForm: accept `prompt: Prompt` instead of flat props; read `prompt.arguments` directly; display `title ?? name` as heading - PromptMessagesDisplay: narrow type from `(PromptMessage | SamplingMessage)[]` to `PromptMessage[]` per spec - PromptsScreen: accept `Prompt[]` + `selectedPromptName` + `GetPromptState`; derive selected prompt via `prompts.find()`; own `argumentValues` state locally; reset arguments on tool switch - Delete local `PromptItem`, `SelectedPrompt`, `PromptArgument` types - Update all stories with real SDK `Prompt` fixtures - Update ConnectedView PromptsActive story Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
12c41cbed7
commit
de40b3720e
2 changed files with 230 additions and 226 deletions
|
|
@ -1,4 +1,5 @@
|
|||
import type { Meta, StoryObj } from "@storybook/react-vite";
|
||||
import type { Prompt } from "@modelcontextprotocol/sdk/types.js";
|
||||
import { fn } from "storybook/test";
|
||||
import { PromptArgumentsForm } from "./PromptArgumentsForm";
|
||||
|
||||
|
|
@ -14,64 +15,73 @@ const meta: Meta<typeof PromptArgumentsForm> = {
|
|||
export default meta;
|
||||
type Story = StoryObj<typeof PromptArgumentsForm>;
|
||||
|
||||
const summarizePrompt: Prompt = {
|
||||
name: "summarize",
|
||||
description: "Summarize the given text into key points",
|
||||
};
|
||||
|
||||
const translatePrompt: Prompt = {
|
||||
name: "translate",
|
||||
description: "Translate text from one language to another",
|
||||
arguments: [
|
||||
{ name: "text", required: true, description: "The text to translate" },
|
||||
{
|
||||
name: "targetLanguage",
|
||||
required: true,
|
||||
description: "The language to translate into",
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const summarizeWithArgsPrompt: Prompt = {
|
||||
name: "summarize",
|
||||
description: "Summarize the given text into key points",
|
||||
arguments: [
|
||||
{ name: "text", required: true, description: "The text to summarize" },
|
||||
{
|
||||
name: "maxLength",
|
||||
required: true,
|
||||
description: "Maximum length of summary in words",
|
||||
},
|
||||
{
|
||||
name: "format",
|
||||
required: false,
|
||||
description: "Output format (bullets or paragraph)",
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const codeReviewPrompt: Prompt = {
|
||||
name: "code-review",
|
||||
arguments: [
|
||||
{ name: "code", required: true, description: "The code to review" },
|
||||
],
|
||||
};
|
||||
|
||||
export const NoArguments: Story = {
|
||||
args: {
|
||||
name: "summarize",
|
||||
description: "Summarize the given text into key points",
|
||||
arguments: [],
|
||||
prompt: summarizePrompt,
|
||||
argumentValues: {},
|
||||
},
|
||||
};
|
||||
|
||||
export const WithArguments: Story = {
|
||||
args: {
|
||||
name: "translate",
|
||||
description: "Translate text from one language to another",
|
||||
arguments: [
|
||||
{ name: "text", required: true, description: "The text to translate" },
|
||||
{
|
||||
name: "targetLanguage",
|
||||
required: true,
|
||||
description: "The language to translate into",
|
||||
},
|
||||
],
|
||||
prompt: translatePrompt,
|
||||
argumentValues: {},
|
||||
},
|
||||
};
|
||||
|
||||
export const WithRequiredAndOptional: Story = {
|
||||
args: {
|
||||
name: "summarize",
|
||||
description: "Summarize the given text into key points",
|
||||
arguments: [
|
||||
{ name: "text", required: true, description: "The text to summarize" },
|
||||
{
|
||||
name: "maxLength",
|
||||
required: true,
|
||||
description: "Maximum length of summary in words",
|
||||
},
|
||||
{
|
||||
name: "format",
|
||||
required: false,
|
||||
description: "Output format (bullets or paragraph)",
|
||||
},
|
||||
],
|
||||
prompt: summarizeWithArgsPrompt,
|
||||
argumentValues: {},
|
||||
},
|
||||
};
|
||||
|
||||
export const AllFilled: Story = {
|
||||
args: {
|
||||
name: "translate",
|
||||
description: "Translate text from one language to another",
|
||||
arguments: [
|
||||
{ name: "text", required: true, description: "The text to translate" },
|
||||
{
|
||||
name: "targetLanguage",
|
||||
required: true,
|
||||
description: "The language to translate into",
|
||||
},
|
||||
],
|
||||
prompt: translatePrompt,
|
||||
argumentValues: {
|
||||
text: "Hello, how are you?",
|
||||
targetLanguage: "Spanish",
|
||||
|
|
@ -81,10 +91,7 @@ export const AllFilled: Story = {
|
|||
|
||||
export const NoDescription: Story = {
|
||||
args: {
|
||||
name: "code-review",
|
||||
arguments: [
|
||||
{ name: "code", required: true, description: "The code to review" },
|
||||
],
|
||||
prompt: codeReviewPrompt,
|
||||
argumentValues: {},
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,20 +1,19 @@
|
|||
import { Button, Group, Stack, Text, TextInput, Title } from "@mantine/core";
|
||||
|
||||
export interface PromptArgument {
|
||||
name: string;
|
||||
required: boolean;
|
||||
description?: string;
|
||||
}
|
||||
import type { Prompt } from "@modelcontextprotocol/sdk/types.js";
|
||||
|
||||
export interface PromptArgumentsFormProps {
|
||||
name: string;
|
||||
description?: string;
|
||||
arguments: PromptArgument[];
|
||||
prompt: Prompt;
|
||||
argumentValues: Record<string, string>;
|
||||
onArgumentChange: (name: string, value: string) => void;
|
||||
onGetPrompt: () => void;
|
||||
}
|
||||
|
||||
const PromptTitle = Text.withProps({
|
||||
fw: 700,
|
||||
size: "lg",
|
||||
truncate: "end",
|
||||
});
|
||||
|
||||
const DescriptionText = Text.withProps({
|
||||
size: "sm",
|
||||
c: "dimmed",
|
||||
|
|
@ -25,23 +24,25 @@ function formatPlaceholder(name: string): string {
|
|||
}
|
||||
|
||||
export function PromptArgumentsForm({
|
||||
description,
|
||||
arguments: promptArguments,
|
||||
prompt,
|
||||
argumentValues,
|
||||
onArgumentChange,
|
||||
onGetPrompt,
|
||||
}: PromptArgumentsFormProps) {
|
||||
const { name, title, description, arguments: promptArguments } = prompt;
|
||||
|
||||
return (
|
||||
<Stack gap="md">
|
||||
<Title order={4}>Prompt Arguments</Title>
|
||||
<PromptTitle>{title ?? name}</PromptTitle>
|
||||
{description && <DescriptionText>{description}</DescriptionText>}
|
||||
{promptArguments.length > 0 && (
|
||||
<Title order={4}>Arguments</Title>
|
||||
{promptArguments && promptArguments.length > 0 && (
|
||||
<Stack gap="sm">
|
||||
{promptArguments.map((arg) => (
|
||||
<TextInput
|
||||
key={arg.name}
|
||||
label={arg.name}
|
||||
withAsterisk={arg.required}
|
||||
withAsterisk={arg.required === true}
|
||||
description={arg.description}
|
||||
placeholder={formatPlaceholder(arg.name)}
|
||||
value={argumentValues[arg.name] || ""}
|
||||
|
|
|
|||
Loading…
Reference in a new issue