fix: emit #/$defs/ refs in set_tasks schema
TypeBox Type.Cyclic generates bare local refs ("AddTask") which strict
moonshot-flavored JSON Schema gateways (Console Go upstream) reject with
HTTP 400. Rewrite all local $ref values to the #/$defs/ form after
building the schema, and add a regression test asserting the ref format.
Bump version to 0.2.2.
This commit is contained in:
+36
-11
@@ -15,6 +15,29 @@ const TaskStatusSchema = StringEnum(["pending", "in-progress", "blocked", "done"
|
||||
const SetTaskModeSchema = StringEnum(["append", "replace"] as const);
|
||||
const RemovalReasonSchema = StringEnum(["mistaken", "duplicate", "canceled"] as const);
|
||||
|
||||
/**
|
||||
* TypeBox's Type.Cyclic emits bare local refs ("AddTask") instead of URI
|
||||
* references ("#/$defs/AddTask"). Strict JSON Schema gateways (e.g. the
|
||||
* moonshot-flavored validator behind Console Go) reject those with a 400.
|
||||
* Rewrite every local $ref in place to the #/$defs/ form.
|
||||
*/
|
||||
function normalizeLocalRefs<T>(schema: T): T {
|
||||
if (Array.isArray(schema)) {
|
||||
for (const item of schema) normalizeLocalRefs(item);
|
||||
return schema;
|
||||
}
|
||||
if (schema && typeof schema === "object") {
|
||||
for (const [key, value] of Object.entries(schema)) {
|
||||
if (key === "$ref" && typeof value === "string" && !value.startsWith("#") && !value.includes("://")) {
|
||||
(schema as Record<string, unknown>)[key] = `#/$defs/${value}`;
|
||||
} else {
|
||||
normalizeLocalRefs(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return schema;
|
||||
}
|
||||
|
||||
const AddTaskSchema = Type.Cyclic(
|
||||
{
|
||||
AddTask: Type.Object(
|
||||
@@ -38,17 +61,19 @@ const AddTaskSchema = Type.Cyclic(
|
||||
"AddTask",
|
||||
);
|
||||
|
||||
export const SetTaskParams = Type.Object(
|
||||
{
|
||||
mode: SetTaskModeSchema,
|
||||
tasks: Type.Array(AddTaskSchema, {
|
||||
description: "Tasks to append or install. May be empty only in replace mode.",
|
||||
}),
|
||||
force: Type.Optional(
|
||||
Type.Boolean({ description: "Use only when the user explicitly abandons unfinished tasks." }),
|
||||
),
|
||||
},
|
||||
{ additionalProperties: false },
|
||||
export const SetTaskParams = normalizeLocalRefs(
|
||||
Type.Object(
|
||||
{
|
||||
mode: SetTaskModeSchema,
|
||||
tasks: Type.Array(AddTaskSchema, {
|
||||
description: "Tasks to append or install. May be empty only in replace mode.",
|
||||
}),
|
||||
force: Type.Optional(
|
||||
Type.Boolean({ description: "Use only when the user explicitly abandons unfinished tasks." }),
|
||||
),
|
||||
},
|
||||
{ additionalProperties: false },
|
||||
),
|
||||
);
|
||||
|
||||
const TaskPatchSchema = Type.Object(
|
||||
|
||||
Reference in New Issue
Block a user