From c1a63cb37d67f1d8a58b89330688cb6d8b8318ef Mon Sep 17 00:00:00 2001 From: cliffhall Date: Mon, 20 Apr 2026 19:57:58 -0400 Subject: [PATCH] Phase 2: Refactor Sampling/Elicitation cluster to MCP SDK types Replace ad hoc local types with SDK schema types across the Sampling and Elicitation group components. - SamplingRequestPanel: accept `request: CreateMessageRequestParams` + `draftResult: CreateMessageResult` instead of 16 flat props; derive messages, model preferences, and parameters from the request object; drop `tools`/`toolChoice` (not in MCP 2025-11-25 CreateMessageRequest) - InlineSamplingRequest: accept `request: CreateMessageRequestParams`; derive messagePreview and modelHints from the request - ElicitationFormPanel: accept `request: ElicitRequest['params']` + `serverName`; pass requestedSchema directly to SchemaForm - ElicitationUrlPanel: rename `elicitationId` to `requestId` - InlineElicitationRequest: accept `request: ElicitRequest['params']`; discriminate form vs URL mode on request shape instead of `mode` prop - PendingClientRequests: unchanged (children-based wrapper) - Delete local `SamplingTool` type - Update all stories with real SDK type fixtures Co-Authored-By: Claude Opus 4.6 (1M context) --- .../ElicitationFormPanel.stories.tsx | 84 ++++----- .../ElicitationFormPanel.tsx | 26 ++- .../ElicitationUrlPanel.stories.tsx | 2 +- .../ElicitationUrlPanel.tsx | 10 +- .../InlineElicitationRequest.stories.tsx | 38 ++-- .../InlineElicitationRequest.tsx | 41 +++-- .../InlineSamplingRequest.stories.tsx | 27 ++- .../InlineSamplingRequest.tsx | 29 +++- .../PendingClientRequests.stories.tsx | 79 ++++++--- .../SamplingRequestPanel.stories.tsx | 164 +++++++----------- .../SamplingRequestPanel.tsx | 131 ++++++-------- 11 files changed, 329 insertions(+), 302 deletions(-) diff --git a/clients/web/src/components/groups/ElicitationFormPanel/ElicitationFormPanel.stories.tsx b/clients/web/src/components/groups/ElicitationFormPanel/ElicitationFormPanel.stories.tsx index bcddc0cc..aaecba8f 100644 --- a/clients/web/src/components/groups/ElicitationFormPanel/ElicitationFormPanel.stories.tsx +++ b/clients/web/src/components/groups/ElicitationFormPanel/ElicitationFormPanel.stories.tsx @@ -1,4 +1,5 @@ import type { Meta, StoryObj } from "@storybook/react-vite"; +import type { ElicitRequest } from "@modelcontextprotocol/sdk/types.js"; import { fn } from "storybook/test"; import { ElicitationFormPanel } from "./ElicitationFormPanel"; @@ -10,7 +11,6 @@ const meta: Meta = { onSubmit: fn(), onCancel: fn(), serverName: "postgres-server", - message: "Please provide database connection details.", values: {}, }, }; @@ -18,49 +18,55 @@ const meta: Meta = { export default meta; type Story = StoryObj; -export const SimpleForm: Story = { - args: { - schema: { - type: "object", - properties: { - host: { type: "string", title: "Host" }, - port: { type: "integer", title: "Port" }, - database: { type: "string", title: "Database" }, - }, - required: ["host", "port"], +const dbRequest = { + message: "Please provide database connection details.", + requestedSchema: { + type: "object" as const, + properties: { + host: { type: "string" as const, title: "Host" }, + port: { type: "string" as const, title: "Port" }, + database: { type: "string" as const, title: "Database" }, }, }, +} satisfies ElicitRequest["params"]; + +const sslRequest = { + message: "Please select your SSL mode preference.", + requestedSchema: { + type: "object" as const, + properties: { + sslMode: { + type: "string" as const, + title: "SSL Mode", + enum: ["disable", "require", "verify-full"], + }, + }, + }, +} satisfies ElicitRequest["params"]; + +const deployRequest = { + message: "Please confirm the deployment.", + requestedSchema: { + type: "object" as const, + properties: { + environment: { + type: "string" as const, + title: "Environment", + enum: ["staging", "production"], + }, + confirm: { type: "boolean" as const, title: "Confirm deployment" }, + }, + }, +} satisfies ElicitRequest["params"]; + +export const SimpleForm: Story = { + args: { request: dbRequest }, }; export const WithEnums: Story = { - args: { - schema: { - type: "object", - properties: { - sslMode: { - type: "string", - title: "SSL Mode", - oneOf: [ - { const: "disable", title: "Disable" }, - { const: "require", title: "Require" }, - { const: "verify-full", title: "Verify Full" }, - ], - }, - }, - }, - }, + args: { request: sslRequest }, }; -export const AllRequired: Story = { - args: { - schema: { - type: "object", - properties: { - host: { type: "string", title: "Host" }, - port: { type: "integer", title: "Port" }, - database: { type: "string", title: "Database" }, - }, - required: ["host", "port", "database"], - }, - }, +export const BooleanField: Story = { + args: { request: deployRequest }, }; diff --git a/clients/web/src/components/groups/ElicitationFormPanel/ElicitationFormPanel.tsx b/clients/web/src/components/groups/ElicitationFormPanel/ElicitationFormPanel.tsx index 6507ec5f..7cad356f 100644 --- a/clients/web/src/components/groups/ElicitationFormPanel/ElicitationFormPanel.tsx +++ b/clients/web/src/components/groups/ElicitationFormPanel/ElicitationFormPanel.tsx @@ -1,12 +1,12 @@ import { Alert, Button, Divider, Group, Stack, Text } from "@mantine/core"; -import type { JsonSchema } from "../SchemaForm/SchemaForm"; +import type { ElicitRequest } from "@modelcontextprotocol/sdk/types.js"; import { SchemaForm } from "../SchemaForm/SchemaForm"; +import type { JsonSchema } from "../SchemaForm/SchemaForm"; export interface ElicitationFormPanelProps { - message: string; - schema: JsonSchema; - values: Record; + request: ElicitRequest["params"]; serverName: string; + values: Record; onChange: (values: Record) => void; onSubmit: () => void; onCancel: () => void; @@ -26,19 +26,27 @@ function formatWarning(serverName: string): string { } export function ElicitationFormPanel({ - message, - schema, - values, + request, serverName, + values, onChange, onSubmit, onCancel, }: ElicitationFormPanelProps) { + const schema = + "requestedSchema" in request ? request.requestedSchema : undefined; + return ( - {formatQuoted(message)} + {formatQuoted(request.message)} - + {schema && ( + + )} {formatWarning(serverName)} diff --git a/clients/web/src/components/groups/ElicitationUrlPanel/ElicitationUrlPanel.stories.tsx b/clients/web/src/components/groups/ElicitationUrlPanel/ElicitationUrlPanel.stories.tsx index 06b15b39..d70bc3b0 100644 --- a/clients/web/src/components/groups/ElicitationUrlPanel/ElicitationUrlPanel.stories.tsx +++ b/clients/web/src/components/groups/ElicitationUrlPanel/ElicitationUrlPanel.stories.tsx @@ -10,7 +10,7 @@ const meta: Meta = { onOpenInBrowser: fn(), onCancel: fn(), message: "Please authenticate with the external service.", - elicitationId: "elicit-abc-123", + requestId: "elicit-abc-123", }, }; diff --git a/clients/web/src/components/groups/ElicitationUrlPanel/ElicitationUrlPanel.tsx b/clients/web/src/components/groups/ElicitationUrlPanel/ElicitationUrlPanel.tsx index fa6c552d..d58a0d3f 100644 --- a/clients/web/src/components/groups/ElicitationUrlPanel/ElicitationUrlPanel.tsx +++ b/clients/web/src/components/groups/ElicitationUrlPanel/ElicitationUrlPanel.tsx @@ -12,7 +12,7 @@ import { export interface ElicitationUrlPanelProps { message: string; url: string; - elicitationId: string; + requestId: string; isWaiting: boolean; onCopyUrl: () => void; onOpenInBrowser: () => void; @@ -39,14 +39,14 @@ const MetaText = Text.withProps({ c: "dimmed", }); -function formatElicitationId(id: string): string { - return `Elicitation ID: ${id}`; +function formatRequestId(id: string): string { + return `Request ID: ${id}`; } export function ElicitationUrlPanel({ message, url, - elicitationId, + requestId, isWaiting, onCopyUrl, onOpenInBrowser, @@ -73,7 +73,7 @@ export function ElicitationUrlPanel({ Waiting for completion... )} - {formatElicitationId(elicitationId)} + {formatRequestId(requestId)} This will open an external URL. Verify the domain before proceeding. diff --git a/clients/web/src/components/groups/InlineElicitationRequest/InlineElicitationRequest.stories.tsx b/clients/web/src/components/groups/InlineElicitationRequest/InlineElicitationRequest.stories.tsx index a637420b..36f59d0f 100644 --- a/clients/web/src/components/groups/InlineElicitationRequest/InlineElicitationRequest.stories.tsx +++ b/clients/web/src/components/groups/InlineElicitationRequest/InlineElicitationRequest.stories.tsx @@ -1,12 +1,31 @@ import type { Meta, StoryObj } from "@storybook/react-vite"; +import type { ElicitRequest } from "@modelcontextprotocol/sdk/types.js"; import { fn } from "storybook/test"; import { InlineElicitationRequest } from "./InlineElicitationRequest"; +const formRequest = { + message: "Please provide your database connection details.", + requestedSchema: { + type: "object" as const, + properties: { + host: { type: "string" as const, title: "Host" }, + port: { type: "string" as const, title: "Port" }, + database: { type: "string" as const, title: "Database" }, + }, + }, +} satisfies ElicitRequest["params"]; + +const urlRequest: ElicitRequest["params"] = { + mode: "url", + message: "Please authenticate via the external URL.", + url: "https://example.com/auth/callback?session=abc123", + elicitationId: "elicit-abc-123", +}; + const meta: Meta = { title: "Groups/InlineElicitationRequest", component: InlineElicitationRequest, args: { - message: "Please provide your database connection details.", queuePosition: "1 of 1", onChange: fn(), onSubmit: fn(), @@ -19,32 +38,21 @@ type Story = StoryObj; export const FormMode: Story = { args: { - mode: "form", - schema: { - type: "object", - properties: { - host: { type: "string", title: "Host" }, - port: { type: "integer", title: "Port" }, - database: { type: "string", title: "Database" }, - }, - required: ["host", "port"], - }, + request: formRequest, values: {}, }, }; export const UrlMode: Story = { args: { - mode: "url", - url: "https://example.com/auth/callback?session=abc123", + request: urlRequest, isWaiting: false, }, }; export const UrlWaiting: Story = { args: { - mode: "url", - url: "https://example.com/auth/callback?session=abc123", + request: urlRequest, isWaiting: true, }, }; diff --git a/clients/web/src/components/groups/InlineElicitationRequest/InlineElicitationRequest.tsx b/clients/web/src/components/groups/InlineElicitationRequest/InlineElicitationRequest.tsx index 916ba139..e4efd69d 100644 --- a/clients/web/src/components/groups/InlineElicitationRequest/InlineElicitationRequest.tsx +++ b/clients/web/src/components/groups/InlineElicitationRequest/InlineElicitationRequest.tsx @@ -8,16 +8,14 @@ import { Stack, Text, } from "@mantine/core"; -import type { JsonSchema } from "../SchemaForm/SchemaForm"; +import type { ElicitRequest } from "@modelcontextprotocol/sdk/types.js"; import { SchemaForm } from "../SchemaForm/SchemaForm"; +import type { JsonSchema } from "../SchemaForm/SchemaForm"; export interface InlineElicitationRequestProps { - mode: "form" | "url"; - message: string; + request: ElicitRequest["params"]; queuePosition: string; - schema?: JsonSchema; values?: Record; - url?: string; isWaiting?: boolean; onChange: (values: Record) => void; onSubmit: () => void; @@ -49,45 +47,52 @@ const CompactButton = Button.withProps({ variant: "light", }); -function getBadgeLabel(mode: "form" | "url"): string { - return mode === "form" +function isFormMode( + request: ElicitRequest["params"], +): request is ElicitRequest["params"] & { + requestedSchema: Record; +} { + return "requestedSchema" in request; +} + +function getBadgeLabel(request: ElicitRequest["params"]): string { + return isFormMode(request) ? "elicitation/create (form)" : "elicitation/create (url)"; } export function InlineElicitationRequest({ - mode, - message, + request, queuePosition, - schema, values, - url, isWaiting, onChange, onSubmit, onCancel, }: InlineElicitationRequestProps) { + const formMode = isFormMode(request); + return ( - {getBadgeLabel(mode)} + {getBadgeLabel(request)} {queuePosition} - {message} + {request.message} - {mode === "form" && schema && ( + {formMode && ( )} - {mode === "url" && url && ( + {!formMode && "url" in request && ( <> - {url} + {(request as { url: string }).url} {isWaiting && ( @@ -99,7 +104,7 @@ export function InlineElicitationRequest({ Cancel - {mode === "form" && ( + {formMode && ( diff --git a/clients/web/src/components/groups/InlineSamplingRequest/InlineSamplingRequest.stories.tsx b/clients/web/src/components/groups/InlineSamplingRequest/InlineSamplingRequest.stories.tsx index 8c5e3bf7..a245cf5d 100644 --- a/clients/web/src/components/groups/InlineSamplingRequest/InlineSamplingRequest.stories.tsx +++ b/clients/web/src/components/groups/InlineSamplingRequest/InlineSamplingRequest.stories.tsx @@ -1,14 +1,27 @@ import type { Meta, StoryObj } from "@storybook/react-vite"; +import type { CreateMessageRequestParams } from "@modelcontextprotocol/sdk/types.js"; import { fn } from "storybook/test"; import { InlineSamplingRequest } from "./InlineSamplingRequest"; +const defaultRequest: CreateMessageRequestParams = { + messages: [ + { + role: "user", + content: { + type: "text", + text: "Please analyze the following code and suggest improvements for performance and readability.", + }, + }, + ], + maxTokens: 1024, +}; + const meta: Meta = { title: "Groups/InlineSamplingRequest", component: InlineSamplingRequest, args: { + request: defaultRequest, queuePosition: "1 of 1", - messagePreview: - "Please analyze the following code and suggest improvements for performance and readability.", responseText: "", onAutoRespond: fn(), onEditAndSend: fn(), @@ -24,7 +37,15 @@ export const Default: Story = {}; export const WithModelHints: Story = { args: { - modelHints: ["claude-3-opus", "claude-3-sonnet"], + request: { + ...defaultRequest, + modelPreferences: { + hints: [ + { name: "claude-opus-4-20250514" }, + { name: "claude-sonnet-4-20250514" }, + ], + }, + }, }, }; diff --git a/clients/web/src/components/groups/InlineSamplingRequest/InlineSamplingRequest.tsx b/clients/web/src/components/groups/InlineSamplingRequest/InlineSamplingRequest.tsx index 182e08e9..afa7582a 100644 --- a/clients/web/src/components/groups/InlineSamplingRequest/InlineSamplingRequest.tsx +++ b/clients/web/src/components/groups/InlineSamplingRequest/InlineSamplingRequest.tsx @@ -7,11 +7,11 @@ import { Text, Textarea, } from "@mantine/core"; +import type { CreateMessageRequestParams } from "@modelcontextprotocol/sdk/types.js"; export interface InlineSamplingRequestProps { + request: CreateMessageRequestParams; queuePosition: string; - modelHints?: string[]; - messagePreview: string; responseText: string; onAutoRespond: () => void; onEditAndSend: () => void; @@ -56,20 +56,41 @@ const RejectButton = Button.withProps({ color: "red", }); +function extractPreview(request: CreateMessageRequestParams): string { + const lastMessage = request.messages[request.messages.length - 1]; + if (!lastMessage) return ""; + const content = lastMessage.content; + if (Array.isArray(content)) { + const textBlock = content.find((b) => b.type === "text"); + return textBlock && "text" in textBlock ? textBlock.text : ""; + } + return content.type === "text" ? content.text : `[${content.type}]`; +} + +function extractModelHints( + request: CreateMessageRequestParams, +): string[] | undefined { + const hints = request.modelPreferences?.hints; + if (!hints || hints.length === 0) return undefined; + return hints.map((h) => h.name).filter(Boolean) as string[]; +} + function formatModelHints(hints: string[]): string { return `Model hints: ${hints.join(", ")}`; } export function InlineSamplingRequest({ + request, queuePosition, - modelHints, - messagePreview, responseText, onAutoRespond, onEditAndSend, onReject, onViewDetails, }: InlineSamplingRequestProps) { + const modelHints = extractModelHints(request); + const messagePreview = extractPreview(request); + return ( diff --git a/clients/web/src/components/groups/PendingClientRequests/PendingClientRequests.stories.tsx b/clients/web/src/components/groups/PendingClientRequests/PendingClientRequests.stories.tsx index 8cdcf0cd..6441e71b 100644 --- a/clients/web/src/components/groups/PendingClientRequests/PendingClientRequests.stories.tsx +++ b/clients/web/src/components/groups/PendingClientRequests/PendingClientRequests.stories.tsx @@ -1,4 +1,5 @@ import type { Meta, StoryObj } from "@storybook/react-vite"; +import type { ElicitRequest } from "@modelcontextprotocol/sdk/types.js"; import { fn } from "storybook/test"; import { PendingClientRequests } from "./PendingClientRequests"; import { InlineSamplingRequest } from "../InlineSamplingRequest/InlineSamplingRequest"; @@ -12,13 +13,50 @@ const meta: Meta = { export default meta; type Story = StoryObj; +const elicitFormRequest = { + message: "Please provide your database connection details.", + requestedSchema: { + type: "object" as const, + properties: { + host: { type: "string" as const, title: "Host" }, + port: { type: "string" as const, title: "Port" }, + }, + }, +} satisfies ElicitRequest["params"]; + +const elicitDeployRequest = { + message: "Please confirm the deployment target.", + requestedSchema: { + type: "object" as const, + properties: { + environment: { + type: "string" as const, + title: "Environment", + enum: ["staging", "production"], + }, + confirm: { type: "boolean" as const, title: "Confirm deployment" }, + }, + }, +} satisfies ElicitRequest["params"]; + export const SingleSampling: Story = { args: { count: 1, children: ( = { title: "Groups/SamplingRequestPanel", component: SamplingRequestPanel, args: { - responseText: "", - modelUsed: "claude-3-sonnet", - stopReason: "end_turn", - onResponseChange: fn(), - onModelChange: fn(), - onStopReasonChange: fn(), + draftResult: defaultDraftResult, + onResultChange: fn(), onAutoRespond: fn(), onSend: fn(), onReject: fn(), @@ -21,115 +27,69 @@ const meta: Meta = { export default meta; type Story = StoryObj; -export const SimpleRequest: Story = { - args: { - messages: [ - { - role: "user", - content: { - type: "text", - text: "What is the capital of France?", - }, - }, - ], - }, +const simpleRequest: CreateMessageRequestParams = { + messages: [ + { + role: "user", + content: { type: "text", text: "What is the capital of France?" }, + }, + ], + maxTokens: 1024, }; -export const WithModelHints: Story = { - args: { - messages: [ - { - role: "user", - content: { type: "text", text: "Summarize this document for me." }, - }, - ], - modelHints: ["claude-3-sonnet", "gpt-4"], - }, -}; - -export const WithPriorities: Story = { - args: { - messages: [ - { - role: "user", - content: { type: "text", text: "Translate this text to Spanish." }, - }, - ], - modelHints: ["claude-3-sonnet"], +const withPreferencesRequest: CreateMessageRequestParams = { + messages: [ + { + role: "user", + content: { type: "text", text: "Summarize this document for me." }, + }, + ], + maxTokens: 2048, + modelPreferences: { + hints: [{ name: "claude-sonnet-4-20250514" }, { name: "gpt-4" }], costPriority: 0.3, speedPriority: 0.5, intelligencePriority: 0.9, }, }; -export const WithAllParams: Story = { - args: { - messages: [ - { - role: "user", - content: { type: "text", text: "Write a haiku about programming." }, - }, - { - role: "assistant", - content: { type: "text", text: "Here is a haiku:" }, - }, - ], - maxTokens: 1024, - stopSequences: ["\n\n", "END"], - temperature: 0.7, - includeContext: "thisServer", - }, +const fullRequest: CreateMessageRequestParams = { + messages: [ + { + role: "user", + content: { type: "text", text: "Write a haiku about programming." }, + }, + { + role: "assistant", + content: { type: "text", text: "Here is a haiku:" }, + }, + ], + maxTokens: 1024, + stopSequences: ["\n\n", "END"], + temperature: 0.7, + includeContext: "thisServer", }; -export const WithTools: Story = { - args: { - messages: [ - { - role: "user", - content: { - type: "text", - text: "Look up the weather in San Francisco.", - }, - }, - ], - tools: [ - { - name: "get_weather", - description: "Get the current weather for a given location.", - inputSchema: { - type: "object", - properties: { - location: { type: "string", description: "City name" }, - }, - required: ["location"], - }, - }, - { - name: "search_web", - description: "Search the web for information.", - inputSchema: { - type: "object", - properties: { - query: { type: "string", description: "Search query" }, - }, - required: ["query"], - }, - }, - ], - toolChoice: "auto", - }, +export const SimpleRequest: Story = { + args: { request: simpleRequest }, +}; + +export const WithModelHints: Story = { + args: { request: withPreferencesRequest }, +}; + +export const WithAllParams: Story = { + args: { request: fullRequest }, }; export const PrefilledResponse: Story = { args: { - messages: [ - { - role: "user", - content: { type: "text", text: "What is 2 + 2?" }, - }, - ], - responseText: "The answer is 4.", - modelUsed: "claude-3-haiku", - stopReason: "end_turn", + request: simpleRequest, + draftResult: { + role: "assistant", + content: { type: "text", text: "The capital of France is Paris." }, + model: "claude-haiku-4-5-20251001", + stopReason: "endTurn", + }, }, }; diff --git a/clients/web/src/components/groups/SamplingRequestPanel/SamplingRequestPanel.tsx b/clients/web/src/components/groups/SamplingRequestPanel/SamplingRequestPanel.tsx index 2b31db56..b39f1a4e 100644 --- a/clients/web/src/components/groups/SamplingRequestPanel/SamplingRequestPanel.tsx +++ b/clients/web/src/components/groups/SamplingRequestPanel/SamplingRequestPanel.tsx @@ -11,33 +11,16 @@ import { Textarea, Title, } from "@mantine/core"; -import type { SamplingMessage } from "@modelcontextprotocol/sdk/types.js"; +import type { + CreateMessageRequestParams, + CreateMessageResult, +} from "@modelcontextprotocol/sdk/types.js"; import { MessageBubble } from "../../elements/MessageBubble/MessageBubble"; -export interface SamplingTool { - name: string; - description?: string; - inputSchema: Record; -} - export interface SamplingRequestPanelProps { - messages: SamplingMessage[]; - modelHints?: string[]; - costPriority?: number; - speedPriority?: number; - intelligencePriority?: number; - maxTokens?: number; - stopSequences?: string[]; - temperature?: number; - includeContext?: string; - tools?: SamplingTool[]; - toolChoice?: string; - responseText: string; - modelUsed: string; - stopReason: string; - onResponseChange: (text: string) => void; - onModelChange: (model: string) => void; - onStopReasonChange: (reason: string) => void; + request: CreateMessageRequestParams; + draftResult: CreateMessageResult; + onResultChange: (result: CreateMessageResult) => void; onAutoRespond: () => void; onSend: () => void; onReject: () => void; @@ -67,43 +50,30 @@ const PreferencesContainer = Paper.withProps({ withBorder: true, }); -const ToolCard = Paper.withProps({ - p: "xs", - withBorder: true, -}); - -const ToolName = Text.withProps({ - size: "sm", - fw: 600, -}); - const RejectButton = Button.withProps({ variant: "light", color: "red", }); export function SamplingRequestPanel({ - messages, - modelHints, - costPriority, - speedPriority, - intelligencePriority, - maxTokens, - stopSequences, - temperature, - includeContext, - tools, - toolChoice, - responseText, - modelUsed, - stopReason, - onResponseChange, - onModelChange, - onStopReasonChange, + request, + draftResult, + onResultChange, onAutoRespond, onSend, onReject, }: SamplingRequestPanelProps) { + const { + messages, + modelPreferences, + maxTokens, + stopSequences, + temperature, + includeContext, + } = request; + + const hints = modelPreferences?.hints?.map((h) => h.name) ?? []; + return ( The server is requesting an LLM completion. @@ -113,29 +83,30 @@ export function SamplingRequestPanel({ ))} - {modelHints && modelHints.length > 0 && ( + {hints.length > 0 && ( Model Preferences: Hints: - {modelHints.map((hint) => ( + {hints.map((hint) => ( {hint} ))} - {costPriority !== undefined && ( + {modelPreferences?.costPriority !== undefined && ( - Cost Priority: {formatPriority(costPriority)} + Cost Priority: {formatPriority(modelPreferences.costPriority)} )} - {speedPriority !== undefined && ( + {modelPreferences?.speedPriority !== undefined && ( - Speed Priority: {formatPriority(speedPriority)} + Speed Priority: {formatPriority(modelPreferences.speedPriority)} )} - {intelligencePriority !== undefined && ( + {modelPreferences?.intelligencePriority !== undefined && ( - Intelligence Priority: {formatPriority(intelligencePriority)} + Intelligence Priority:{" "} + {formatPriority(modelPreferences.intelligencePriority)} )} @@ -161,40 +132,40 @@ export function SamplingRequestPanel({ )} - {tools && tools.length > 0 && ( - <> - Available Tools: - {tools.map((tool) => ( - - {tool.name} - {tool.description && {tool.description}} - - ))} - - )} - - {toolChoice && Tool Choice: {toolChoice}} - Response: