Files
reverse-engineering-anything/src/domain/inputIssueProjection.ts
T
morluto b8a9da0c0f refactor(mcp): make analysis states unrepresentable (#468)
* refactor(config): parse capability settings into exact states

* refactor(runtime): encode replay and process outcomes exactly

* refactor: make analysis states unrepresentable

* refactor(mcp): register canonical schemas with SDK

* fix: preserve capability and catalog invariants

* fix(build): remove stale compiled modules

* fix(replay): update real verifier policy dependency

* fix(package): verify the complete MCP catalog

* fix(test): supply complete replay reload policy

* refactor(contracts): centralize output schema lookup

* refactor(mcp): delegate protocol boundaries to SDK

* fix(browser): approve real source capture

* fix(mcp): preserve catalog guidance
2026-08-10 02:28:11 +08:00

95 lines
2.7 KiB
TypeScript

import type { z } from "zod";
import type { AnalysisInputIssue } from "./errors.js";
/** Project Zod failures to secret-safe caller correction metadata. */
export const projectInputIssues = (
issues: readonly z.core.$ZodIssue[],
input: unknown,
): readonly AnalysisInputIssue[] =>
issues.flatMap((issue) => projectIssue(issue, input));
const projectIssue = (
issue: z.core.$ZodIssue,
input: unknown,
): readonly AnalysisInputIssue[] => {
const path = issue.path.flatMap((part) =>
typeof part === "string" || typeof part === "number" ? [part] : [],
);
if (issue.code === "invalid_union")
return issue.errors.flatMap((branch) =>
branch.flatMap((branchIssue) => projectIssue(branchIssue, input)),
);
if (issue.code === "unrecognized_keys")
return issue.keys.map((key) => ({
path: [...path, key],
reason: "unknown_argument" as const,
}));
if (issue.code === "invalid_type")
return [
{
path,
reason:
valueAtPath(input, path) === undefined
? "missing_argument"
: "invalid_type",
expected: safeExpected(issue.expected),
},
];
if (issue.code === "too_small")
return [boundedIssue(path, "minimum", numericBound(issue.minimum))];
if (issue.code === "too_big")
return [boundedIssue(path, "maximum", numericBound(issue.maximum))];
if (issue.code === "invalid_format")
return [{ path, reason: "invalid_format", expected: issue.format }];
if (issue.code === "invalid_value")
return [
{
path,
reason: "invalid_value",
expected: issue.values.filter(isSafeExpected),
},
];
return [
{
path,
reason: "invalid_value",
...(issue.message.length > 0 ? { message: issue.message } : {}),
},
];
};
const valueAtPath = (
input: unknown,
path: readonly (string | number)[],
): unknown => {
let current = input;
for (const part of path) {
if (typeof current !== "object" || current === null) return undefined;
const next: unknown = Reflect.get(current, part);
current = next;
}
return current;
};
const numericBound = (value: number | bigint): number | undefined =>
typeof value === "number" && Number.isFinite(value) ? value : undefined;
const isSafeExpected = (
value: unknown,
): value is string | number | boolean | null =>
value === null || ["string", "number", "boolean"].includes(typeof value);
const safeExpected = (value: unknown) =>
isSafeExpected(value) ? value : "schema-defined value";
const boundedIssue = (
path: readonly (string | number)[],
key: "minimum" | "maximum",
value: number | undefined,
): AnalysisInputIssue => ({
path,
reason: "out_of_range",
...(value === undefined ? {} : { [key]: value }),
});