mirror of
https://github.com/morluto/rea.git
synced 2026-11-15 19:23:24 +00:00
* 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>
56 lines
1.9 KiB
TypeScript
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);
|
|
};
|