inspector/clients/web/src/components/screens/screenUiState.ts
cliffhall 219298b24d feat(web): add Console (stderr) tab; show it on stdio connect failure (#1621)
A failed stdio launch had no useful diagnostic surface: the message log
(History) is cleared on the error transition and there are no HTTP
requests (Network), so the auto-opened monitoring column was empty. The
process's stderr — which explains the failure (e.g. "No module named
mcp_server_time") — was captured in StderrLogState but never displayed.

- New ConsoleScreen renders the captured stderr stream (search / sort /
  clear / export; embeddable in the monitoring column), wired through App
  via the existing useStderrLog hook + StderrLogState.
- Console is a pinnable monitor tab like Logs/History/Network, gated to
  stdio servers (HTTP has no child process). It lives in the header menu
  when the column isn't pinned, and moves into the column when it is.
- The failure column now picks its tabs by which diagnostic actually
  captured content (stderr → Console, fetch requests → Network), not by
  the active server's transport: a connect failure fires the client
  `disconnect` event, which clears `activeServer`, so transport can't be
  read back there. The memo re-runs as stderr/fetch entries stream in, so
  the diagnostic tab appears as soon as the failing process prints.

Verified live against a failing `python -m mcp_server_time` stdio server:
the column auto-opens to Console showing the real ModuleNotFoundError.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BrihGWcrM9JGRyu41nzZYw
2026-07-09 14:06:13 -04:00

81 lines
2.6 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 { HistoryUiState } from "./HistoryScreen/HistoryScreen";
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 = {
selectedToolName: 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_HISTORY_UI: HistoryUiState = {
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 },
History: { empty: EMPTY_HISTORY_UI },
Network: { empty: EMPTY_NETWORK_UI },
} as const;