Files
reverse-engineering-anything/src/cli/omittableDefaults.ts
T
morlutoandCursor Agent 5c2917266d fix(inputs): validate command admission and preserve valid MCP requests (#9901)
* fix(cli): validate named inputs before target admission

* fix(mcp): preserve valid inputs when advertised schema references widen

* test(inputs): reach session behavior with admitted inputs

One-shot admission now rejects incomplete requests before a session exists. Lifecycle tests supply the required fields, and unknown arguments are rejected before provider issues are retained.

* fix(cli): preserve Electron fuse path spelling

Anchor relative fuse paths without stripping dot segments, and let an empty path reach the operation so it still reports invalid_request.

* fix(cli): reject outline-depth unless detail is summary

The advertised schema already required detail summary whenever outline-depth
was present. The parser still applied the full default and accepted that
combination, so its output failed the same schema. Parsing now rejects it
before the command runs.

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
2026-11-11 00:43:30 -05:00

56 lines
1.9 KiB
TypeScript

import { z } from "incur";
import type { CliInstance } from "./types.js";
import { visitRegisteredCommands } from "./visitRegisteredCommands.js";
type CommandInputs = Partial<Record<(typeof INPUT_GROUPS)[number], unknown>>;
const INPUT_GROUPS = ["args", "env", "options"] as const;
/**
* Advertise parser-filled defaults as omittable CLI inputs.
*
* Incur derives `--schema`, the `--llms` manifests, and help synopses from
* Zod's output view, where a defaulted field always has a value and is
* therefore listed as required. Callers may omit such a field, so each one is
* wrapped as optional while its default, constraints, metadata, and parsed
* value stay unchanged.
*/
export const presentOmittableDefaults = (cli: CliInstance): void => {
visitRegisteredCommands(cli, (command) => presentInputs(command));
};
const presentInputs = (command: CommandInputs): void => {
for (const group of INPUT_GROUPS) {
const schema = command[group];
if (schema instanceof z.ZodObject)
command[group] = withOmittableDefaults(schema);
}
};
const withOmittableDefaults = (schema: z.ZodObject): z.ZodObject => {
const omittable = Object.entries(schema.shape).filter(([, field]) =>
fillsOmission(field),
);
if (omittable.length === 0) return schema;
const metadata = schema.meta();
const result = schema.safeExtend(
Object.fromEntries(
omittable.map(([key, field]) => [key, optionalWithMetadata(field)]),
),
);
return metadata === undefined ? result : result.meta(metadata);
};
/** Let the object parser decide omission; Incur advertises required outputs. */
const fillsOmission = (field: z.ZodType): boolean =>
field._zod.optout === undefined &&
z.object({ value: field }).safeParse({}).success;
const optionalWithMetadata = (field: z.ZodType): z.ZodType => {
const metadata = field.meta();
return metadata === undefined
? field.optional()
: field.optional().meta(metadata);
};