chore: close quality-gate coverage gaps (#1689) (#1766)
Some checks failed
Run install, format, lint, build, and test on every push / build (push) Has been cancelled
Run install, format, lint, build, and test on every push / publish (push) Has been cancelled
Run install, format, lint, build, and test on every push / publish-github-container-registry (push) Has been cancelled
Some checks failed
Run install, format, lint, build, and test on every push / build (push) Has been cancelled
Run install, format, lint, build, and test on every push / publish (push) Has been cancelled
Run install, format, lint, build, and test on every push / publish-github-container-registry (push) Has been cancelled
Closes #1689. Typecheck cli/tui src, add a core/ format+lint gate, and gate core/json + core/client coverage. See PR #1766 for the full review history.
This commit is contained in:
parent
d76c4d5379
commit
373f346e5f
3 changed files with 2210 additions and 467 deletions
|
|
@ -1660,6 +1660,7 @@ function App({
|
|||
<InfoTab
|
||||
serverName={selectedServer}
|
||||
serverConfig={selectedServerConfig}
|
||||
serverSettings={selectedServerEntry?.settings ?? null}
|
||||
serverState={currentServerState}
|
||||
width={contentWidth}
|
||||
height={contentHeight}
|
||||
|
|
|
|||
|
|
@ -5,10 +5,16 @@ import type {
|
|||
MCPServerConfig,
|
||||
ServerState,
|
||||
} from "@inspector/core/mcp/index.js";
|
||||
import type { InspectorServerSettings } from "@inspector/core/mcp/types.js";
|
||||
|
||||
interface InfoTabProps {
|
||||
serverName: string | null;
|
||||
serverConfig: MCPServerConfig | null;
|
||||
// HTTP headers live on the per-server settings (pair-array form), not on the
|
||||
// transport `serverConfig` — `mcpConfigToServerEntries` lifts the on-disk
|
||||
// `headers` map into `InspectorServerSettings.headers`. Read them here so the
|
||||
// SSE / streamable-http header display reflects the real source.
|
||||
serverSettings?: InspectorServerSettings | null;
|
||||
serverState: ServerState | null;
|
||||
width: number;
|
||||
height: number;
|
||||
|
|
@ -18,11 +24,24 @@ interface InfoTabProps {
|
|||
export function InfoTab({
|
||||
serverName,
|
||||
serverConfig,
|
||||
serverSettings = null,
|
||||
serverState,
|
||||
width,
|
||||
height,
|
||||
focused = false,
|
||||
}: InfoTabProps) {
|
||||
const headerPairs = serverSettings?.headers ?? [];
|
||||
// Shared header display for the sse / streamable-http branches (identical for
|
||||
// both transports — the header source is `serverSettings`, not the transport).
|
||||
const headersBlock =
|
||||
headerPairs.length > 0 ? (
|
||||
<Box marginTop={1}>
|
||||
<Text dimColor>
|
||||
Headers:{" "}
|
||||
{headerPairs.map(({ key, value }) => `${key}=${value}`).join(", ")}
|
||||
</Text>
|
||||
</Box>
|
||||
) : null;
|
||||
const scrollViewRef = useRef<ScrollViewRef>(null);
|
||||
|
||||
// Handle keyboard input for scrolling
|
||||
|
|
@ -111,33 +130,13 @@ export function InfoTab({
|
|||
<>
|
||||
<Text dimColor>Type: sse</Text>
|
||||
<Text dimColor>URL: {serverConfig.url}</Text>
|
||||
{serverConfig.headers &&
|
||||
Object.keys(serverConfig.headers).length > 0 && (
|
||||
<Box marginTop={1}>
|
||||
<Text dimColor>
|
||||
Headers:{" "}
|
||||
{Object.entries(serverConfig.headers)
|
||||
.map(([k, v]) => `${k}=${v}`)
|
||||
.join(", ")}
|
||||
</Text>
|
||||
</Box>
|
||||
)}
|
||||
{headersBlock}
|
||||
</>
|
||||
) : serverConfig.type === "streamable-http" ? (
|
||||
<>
|
||||
<Text dimColor>Type: streamable-http</Text>
|
||||
<Text dimColor>URL: {serverConfig.url}</Text>
|
||||
{serverConfig.headers &&
|
||||
Object.keys(serverConfig.headers).length > 0 && (
|
||||
<Box marginTop={1}>
|
||||
<Text dimColor>
|
||||
Headers:{" "}
|
||||
{Object.entries(serverConfig.headers)
|
||||
.map(([k, v]) => `${k}=${v}`)
|
||||
.join(", ")}
|
||||
</Text>
|
||||
</Box>
|
||||
)}
|
||||
{headersBlock}
|
||||
</>
|
||||
) : null}
|
||||
</Box>
|
||||
|
|
|
|||
|
|
@ -34,9 +34,14 @@ function toSelectOptions(
|
|||
}));
|
||||
}
|
||||
|
||||
/** Minimal JSON Schema object shape (properties + required) */
|
||||
/**
|
||||
* Minimal JSON Schema object shape (properties + required). Property values are
|
||||
* `unknown` so the SDK's broadly-typed `Tool["inputSchema"]` (whose `properties`
|
||||
* values are the recursive JSON type) is assignable here; each value is narrowed
|
||||
* to {@link JsonSchemaProperty} at the point of use below.
|
||||
*/
|
||||
interface JsonSchemaObject {
|
||||
properties?: Record<string, JsonSchemaProperty>;
|
||||
properties?: Record<string, unknown>;
|
||||
required?: string[];
|
||||
}
|
||||
|
||||
|
|
@ -60,7 +65,12 @@ export function schemaToForm(
|
|||
const required = schema.required || [];
|
||||
|
||||
for (const [key, prop] of Object.entries(properties)) {
|
||||
const property = prop as JsonSchemaProperty;
|
||||
// `properties` values are `unknown` (the SDK schema admits anything), so
|
||||
// guard before treating a value as a schema object — a malformed server
|
||||
// schema with e.g. `properties: { foo: null }` must not throw on `.title`.
|
||||
const property = (
|
||||
typeof prop === "object" && prop !== null ? prop : {}
|
||||
) as JsonSchemaProperty;
|
||||
const baseField = {
|
||||
name: key,
|
||||
label: property.title || key,
|
||||
|
|
|
|||
Loading…
Reference in a new issue