Fix Netx Ops tool schemas for DSH additionalProperties requirement.

positions[] items and layout params objects now declare additionalProperties explicitly.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
oliver 2026-09-06 01:52:51 +08:00
parent 3c9a383071
commit 6e591be2b5
6 changed files with 121 additions and 12 deletions

View file

@ -1374,6 +1374,11 @@ var strArr = (description) => ({
items: { type: "string" }, items: { type: "string" },
...description ? { description } : {} ...description ? { description } : {}
}); });
var anyObj = (description) => ({
type: "object",
additionalProperties: true,
...description ? { description } : {}
});
function renderJson(_args, value) { function renderJson(_args, value) {
return [{ type: "text", text: JSON.stringify(value, null, 0) }]; return [{ type: "text", text: JSON.stringify(value, null, 0) }];
} }
@ -1507,6 +1512,7 @@ function registerNetxTools(ctx, connection, options) {
additionalProperties: false, additionalProperties: false,
properties: { properties: {
ne_id: str3(), ne_id: str3(),
nms_ne_id: str3(),
ume_ne_id: str3(), ume_ne_id: str3(),
commands: strArr() commands: strArr()
} }
@ -1579,7 +1585,19 @@ function registerNetxTools(ctx, connection, options) {
}, copyTopologyViewNodes, getClient, t), }, copyTopologyViewNodes, getClient, t),
tool("netx__updateTopologyViewPositions", "Move nodes on a view via positions[] or layout=grid|offset|stack + filters.", { tool("netx__updateTopologyViewPositions", "Move nodes on a view via positions[] or layout=grid|offset|stack + filters.", {
view_id: { type: "string", required: true }, view_id: { type: "string", required: true },
positions: { type: "array", items: { type: "object" } }, positions: {
type: "array",
description: "Manual placements: [{ fabric_node_id, x, y }, …]",
items: {
type: "object",
additionalProperties: false,
properties: {
fabric_node_id: str3(),
x: num3(),
y: num3()
}
}
},
layout: str3("grid | offset | stack"), layout: str3("grid | offset | stack"),
keyword: str3(), keyword: str3(),
role: str3(), role: str3(),
@ -1684,7 +1702,7 @@ function registerNetxTools(ctx, connection, options) {
preset: str3(), preset: str3(),
mode: str3("preview | apply"), mode: str3("preview | apply"),
tune: bool3(), tune: bool3(),
params: { type: "object" }, params: anyObj("Action-specific options (move_nodes / recipes / polish)."),
catalog: bool3(), catalog: bool3(),
fabric_node_ids: strArr(), fabric_node_ids: strArr(),
park: bool3(), park: bool3(),

View file

@ -1374,6 +1374,11 @@ var strArr = (description) => ({
items: { type: "string" }, items: { type: "string" },
...description ? { description } : {} ...description ? { description } : {}
}); });
var anyObj = (description) => ({
type: "object",
additionalProperties: true,
...description ? { description } : {}
});
function renderJson(_args, value) { function renderJson(_args, value) {
return [{ type: "text", text: JSON.stringify(value, null, 0) }]; return [{ type: "text", text: JSON.stringify(value, null, 0) }];
} }
@ -1507,6 +1512,7 @@ function registerNetxTools(ctx, connection, options) {
additionalProperties: false, additionalProperties: false,
properties: { properties: {
ne_id: str3(), ne_id: str3(),
nms_ne_id: str3(),
ume_ne_id: str3(), ume_ne_id: str3(),
commands: strArr() commands: strArr()
} }
@ -1579,7 +1585,19 @@ function registerNetxTools(ctx, connection, options) {
}, copyTopologyViewNodes, getClient, t), }, copyTopologyViewNodes, getClient, t),
tool("netx__updateTopologyViewPositions", "Move nodes on a view via positions[] or layout=grid|offset|stack + filters.", { tool("netx__updateTopologyViewPositions", "Move nodes on a view via positions[] or layout=grid|offset|stack + filters.", {
view_id: { type: "string", required: true }, view_id: { type: "string", required: true },
positions: { type: "array", items: { type: "object" } }, positions: {
type: "array",
description: "Manual placements: [{ fabric_node_id, x, y }, …]",
items: {
type: "object",
additionalProperties: false,
properties: {
fabric_node_id: str3(),
x: num3(),
y: num3()
}
}
},
layout: str3("grid | offset | stack"), layout: str3("grid | offset | stack"),
keyword: str3(), keyword: str3(),
role: str3(), role: str3(),
@ -1684,7 +1702,7 @@ function registerNetxTools(ctx, connection, options) {
preset: str3(), preset: str3(),
mode: str3("preview | apply"), mode: str3("preview | apply"),
tune: bool3(), tune: bool3(),
params: { type: "object" }, params: anyObj("Action-specific options (move_nodes / recipes / polish)."),
catalog: bool3(), catalog: bool3(),
fabric_node_ids: strArr(), fabric_node_ids: strArr(),
park: bool3(), park: bool3(),

View file

@ -1374,6 +1374,11 @@ var strArr = (description) => ({
items: { type: "string" }, items: { type: "string" },
...description ? { description } : {} ...description ? { description } : {}
}); });
var anyObj = (description) => ({
type: "object",
additionalProperties: true,
...description ? { description } : {}
});
function renderJson(_args, value) { function renderJson(_args, value) {
return [{ type: "text", text: JSON.stringify(value, null, 0) }]; return [{ type: "text", text: JSON.stringify(value, null, 0) }];
} }
@ -1507,6 +1512,7 @@ function registerNetxTools(ctx, connection, options) {
additionalProperties: false, additionalProperties: false,
properties: { properties: {
ne_id: str3(), ne_id: str3(),
nms_ne_id: str3(),
ume_ne_id: str3(), ume_ne_id: str3(),
commands: strArr() commands: strArr()
} }
@ -1579,7 +1585,19 @@ function registerNetxTools(ctx, connection, options) {
}, copyTopologyViewNodes, getClient, t), }, copyTopologyViewNodes, getClient, t),
tool("netx__updateTopologyViewPositions", "Move nodes on a view via positions[] or layout=grid|offset|stack + filters.", { tool("netx__updateTopologyViewPositions", "Move nodes on a view via positions[] or layout=grid|offset|stack + filters.", {
view_id: { type: "string", required: true }, view_id: { type: "string", required: true },
positions: { type: "array", items: { type: "object" } }, positions: {
type: "array",
description: "Manual placements: [{ fabric_node_id, x, y }, …]",
items: {
type: "object",
additionalProperties: false,
properties: {
fabric_node_id: str3(),
x: num3(),
y: num3()
}
}
},
layout: str3("grid | offset | stack"), layout: str3("grid | offset | stack"),
keyword: str3(), keyword: str3(),
role: str3(), role: str3(),
@ -1684,7 +1702,7 @@ function registerNetxTools(ctx, connection, options) {
preset: str3(), preset: str3(),
mode: str3("preview | apply"), mode: str3("preview | apply"),
tune: bool3(), tune: bool3(),
params: { type: "object" }, params: anyObj("Action-specific options (move_nodes / recipes / polish)."),
catalog: bool3(), catalog: bool3(),
fabric_node_ids: strArr(), fabric_node_ids: strArr(),
park: bool3(), park: bool3(),

View file

@ -1374,6 +1374,11 @@ var strArr = (description) => ({
items: { type: "string" }, items: { type: "string" },
...description ? { description } : {} ...description ? { description } : {}
}); });
var anyObj = (description) => ({
type: "object",
additionalProperties: true,
...description ? { description } : {}
});
function renderJson(_args, value) { function renderJson(_args, value) {
return [{ type: "text", text: JSON.stringify(value, null, 0) }]; return [{ type: "text", text: JSON.stringify(value, null, 0) }];
} }
@ -1507,6 +1512,7 @@ function registerNetxTools(ctx, connection, options) {
additionalProperties: false, additionalProperties: false,
properties: { properties: {
ne_id: str3(), ne_id: str3(),
nms_ne_id: str3(),
ume_ne_id: str3(), ume_ne_id: str3(),
commands: strArr() commands: strArr()
} }
@ -1579,7 +1585,19 @@ function registerNetxTools(ctx, connection, options) {
}, copyTopologyViewNodes, getClient, t), }, copyTopologyViewNodes, getClient, t),
tool("netx__updateTopologyViewPositions", "Move nodes on a view via positions[] or layout=grid|offset|stack + filters.", { tool("netx__updateTopologyViewPositions", "Move nodes on a view via positions[] or layout=grid|offset|stack + filters.", {
view_id: { type: "string", required: true }, view_id: { type: "string", required: true },
positions: { type: "array", items: { type: "object" } }, positions: {
type: "array",
description: "Manual placements: [{ fabric_node_id, x, y }, …]",
items: {
type: "object",
additionalProperties: false,
properties: {
fabric_node_id: str3(),
x: num3(),
y: num3()
}
}
},
layout: str3("grid | offset | stack"), layout: str3("grid | offset | stack"),
keyword: str3(), keyword: str3(),
role: str3(), role: str3(),
@ -1684,7 +1702,7 @@ function registerNetxTools(ctx, connection, options) {
preset: str3(), preset: str3(),
mode: str3("preview | apply"), mode: str3("preview | apply"),
tune: bool3(), tune: bool3(),
params: { type: "object" }, params: anyObj("Action-specific options (move_nodes / recipes / polish)."),
catalog: bool3(), catalog: bool3(),
fabric_node_ids: strArr(), fabric_node_ids: strArr(),
park: bool3(), park: bool3(),

View file

@ -1791,6 +1791,11 @@ var strArr = (description) => ({
items: { type: "string" }, items: { type: "string" },
...description ? { description } : {} ...description ? { description } : {}
}); });
var anyObj = (description) => ({
type: "object",
additionalProperties: true,
...description ? { description } : {}
});
function renderJson(_args, value) { function renderJson(_args, value) {
return [{ type: "text", text: JSON.stringify(value, null, 0) }]; return [{ type: "text", text: JSON.stringify(value, null, 0) }];
} }
@ -1924,6 +1929,7 @@ function registerNetxTools(ctx, connection, options) {
additionalProperties: false, additionalProperties: false,
properties: { properties: {
ne_id: str3(), ne_id: str3(),
nms_ne_id: str3(),
ume_ne_id: str3(), ume_ne_id: str3(),
commands: strArr() commands: strArr()
} }
@ -1996,7 +2002,19 @@ function registerNetxTools(ctx, connection, options) {
}, copyTopologyViewNodes, getClient, t), }, copyTopologyViewNodes, getClient, t),
tool("netx__updateTopologyViewPositions", "Move nodes on a view via positions[] or layout=grid|offset|stack + filters.", { tool("netx__updateTopologyViewPositions", "Move nodes on a view via positions[] or layout=grid|offset|stack + filters.", {
view_id: { type: "string", required: true }, view_id: { type: "string", required: true },
positions: { type: "array", items: { type: "object" } }, positions: {
type: "array",
description: "Manual placements: [{ fabric_node_id, x, y }, …]",
items: {
type: "object",
additionalProperties: false,
properties: {
fabric_node_id: str3(),
x: num3(),
y: num3()
}
}
},
layout: str3("grid | offset | stack"), layout: str3("grid | offset | stack"),
keyword: str3(), keyword: str3(),
role: str3(), role: str3(),
@ -2101,7 +2119,7 @@ function registerNetxTools(ctx, connection, options) {
preset: str3(), preset: str3(),
mode: str3("preview | apply"), mode: str3("preview | apply"),
tune: bool3(), tune: bool3(),
params: { type: "object" }, params: anyObj("Action-specific options (move_nodes / recipes / polish)."),
catalog: bool3(), catalog: bool3(),
fabric_node_ids: strArr(), fabric_node_ids: strArr(),
park: bool3(), park: bool3(),

View file

@ -34,6 +34,12 @@ const strArr = (description?: string) => ({
items: { type: 'string' as const }, items: { type: 'string' as const },
...(description ? { description } : {}), ...(description ? { description } : {}),
}) })
/** Free-form JSON object — DSH requires an explicit additionalProperties boolean. */
const anyObj = (description?: string) => ({
type: 'object' as const,
additionalProperties: true as const,
...(description ? { description } : {}),
})
function renderJson(_args: unknown, value: unknown) { function renderJson(_args: unknown, value: unknown) {
return [{ type: 'text' as const, text: JSON.stringify(value, null, 0) }] return [{ type: 'text' as const, text: JSON.stringify(value, null, 0) }]
@ -262,6 +268,7 @@ export function registerNetxTools(
additionalProperties: false, additionalProperties: false,
properties: { properties: {
ne_id: str(), ne_id: str(),
nms_ne_id: str(),
ume_ne_id: str(), ume_ne_id: str(),
commands: strArr(), commands: strArr(),
}, },
@ -380,7 +387,19 @@ export function registerNetxTools(
'Move nodes on a view via positions[] or layout=grid|offset|stack + filters.', 'Move nodes on a view via positions[] or layout=grid|offset|stack + filters.',
{ {
view_id: { type: 'string' as const, required: true as const }, view_id: { type: 'string' as const, required: true as const },
positions: { type: 'array' as const, items: { type: 'object' as const } }, positions: {
type: 'array' as const,
description: 'Manual placements: [{ fabric_node_id, x, y }, …]',
items: {
type: 'object' as const,
additionalProperties: false,
properties: {
fabric_node_id: str(),
x: num(),
y: num(),
},
},
},
layout: str('grid | offset | stack'), layout: str('grid | offset | stack'),
keyword: str(), keyword: str(),
role: str(), role: str(),
@ -530,7 +549,7 @@ export function registerNetxTools(
preset: str(), preset: str(),
mode: str('preview | apply'), mode: str('preview | apply'),
tune: bool(), tune: bool(),
params: { type: 'object' as const }, params: anyObj('Action-specific options (move_nodes / recipes / polish).'),
catalog: bool(), catalog: bool(),
fabric_node_ids: strArr(), fabric_node_ids: strArr(),
park: bool(), park: bool(),