#1961 keyed the sidebar's React children by source position, but everything downstream still identified a tool by `tool.name`. With a `tools/list` that repeats a name, both copies highlighted at once, the click guard made the other copy a no-op, and `tools.find((t) => t.name === …)` always resolved to the first — so a later copy rendered but could never be opened. Thread the row key through selection instead: - `utils/toolUtils.ts` now owns `toolRowKey` (moved out of ToolControls) and adds `findToolByRowKey`, which compares computed keys rather than parsing one so the two can't drift. - `ToolControls`: `selectedName` → `selectedKey`; the highlight and the click guard compare keys, and `onSelectTool` emits the row key. - `ToolsScreen`: `ToolsUiState.selectedToolName` → `selectedToolKey`, with both lookups going through `findToolByRowKey`. Renamed through `screenUiState.ts` and `App.tsx`'s `onToolsUiChange`. `onCallTool` still sends `selectedTool.name` — the duplicated name is the genuine wire identity; only the UI identity needed to be unique. Also prefixes the excluded (SEP-2243) rows' keys: they render into the same `Stack` as the list rows but index within their own list, so an excluded tool sharing a name and index with a listed one collided in the key space. Closes #2001 Signed-off-by: cliffhall <cliff@futurescale.com>
81 lines
2.7 KiB
TypeScript
81 lines
2.7 KiB
TypeScript
// Empty-state defaults for each screen's lifted `ui` object — the value App
|
|
// seeds its per-screen UI state with and resets to on disconnect (#1417). The
|
|
// `*UiState` interfaces live alongside their screens; the defaults are gathered
|
|
// here (a non-component module) so the screen files can keep a single component
|
|
// export under the react-refresh rule, mirroring logLevels.ts / fetchCategories.ts.
|
|
import type { ToolsUiState } from "./ToolsScreen/ToolsScreen";
|
|
import type { PromptsUiState } from "./PromptsScreen/PromptsScreen";
|
|
import type { ResourcesUiState } from "./ResourcesScreen/ResourcesScreen";
|
|
import type { AppsUiState } from "./AppsScreen/AppsScreen";
|
|
import type { TasksUiState } from "./TasksScreen/TasksScreen";
|
|
import type { LogsUiState } from "./LoggingScreen/LoggingScreen";
|
|
import type { ProtocolUiState } from "./ProtocolScreen/ProtocolScreen";
|
|
import type { NetworkUiState } from "./NetworkScreen/NetworkScreen";
|
|
import type { ConsoleUiState } from "./ConsoleScreen/ConsoleScreen";
|
|
import { ALL_LEVELS_VISIBLE } from "./LoggingScreen/logLevels";
|
|
import { ALL_CATEGORIES_VISIBLE } from "./NetworkScreen/fetchCategories";
|
|
|
|
export const EMPTY_TOOLS_UI: ToolsUiState = {
|
|
selectedToolKey: undefined,
|
|
formValues: {},
|
|
search: "",
|
|
runAsTask: false,
|
|
};
|
|
|
|
export const EMPTY_PROMPTS_UI: PromptsUiState = {
|
|
selectedPromptName: undefined,
|
|
argumentValues: {},
|
|
submittedFor: undefined,
|
|
search: "",
|
|
};
|
|
|
|
export const EMPTY_RESOURCES_UI: ResourcesUiState = {
|
|
selectedResourceUri: undefined,
|
|
selectedTemplateUri: undefined,
|
|
originatingTemplateUri: undefined,
|
|
search: "",
|
|
openSections: undefined,
|
|
};
|
|
|
|
export const EMPTY_APPS_UI: AppsUiState = {
|
|
selectedAppName: undefined,
|
|
formValues: {},
|
|
search: "",
|
|
};
|
|
|
|
export const EMPTY_TASKS_UI: TasksUiState = {
|
|
search: "",
|
|
statusFilter: undefined,
|
|
};
|
|
|
|
export const EMPTY_LOGS_UI: LogsUiState = {
|
|
filterText: "",
|
|
visibleLevels: ALL_LEVELS_VISIBLE,
|
|
};
|
|
|
|
export const EMPTY_PROTOCOL_UI: ProtocolUiState = {
|
|
search: "",
|
|
methodFilter: undefined,
|
|
visibleDirections: { client: true, server: true },
|
|
};
|
|
|
|
export const EMPTY_NETWORK_UI: NetworkUiState = {
|
|
filterText: "",
|
|
visibleCategories: ALL_CATEGORIES_VISIBLE,
|
|
};
|
|
|
|
export const EMPTY_CONSOLE_UI: ConsoleUiState = {
|
|
filterText: "",
|
|
};
|
|
|
|
/** Registry for OAuth resume snapshot restore (data-only; setters live in App). */
|
|
export const TAB_UI_REGISTRY = {
|
|
Apps: { empty: EMPTY_APPS_UI },
|
|
Tools: { empty: EMPTY_TOOLS_UI },
|
|
Prompts: { empty: EMPTY_PROMPTS_UI },
|
|
Resources: { empty: EMPTY_RESOURCES_UI },
|
|
Tasks: { empty: EMPTY_TASKS_UI },
|
|
Logs: { empty: EMPTY_LOGS_UI },
|
|
Protocol: { empty: EMPTY_PROTOCOL_UI },
|
|
Network: { empty: EMPTY_NETWORK_UI },
|
|
} as const;
|