mirror of
https://github.com/hansjone/netxops.git
synced 2026-10-20 07:40:46 +08:00
Netx tools: convert MCP inputSchema to the DSH value schema DSL
defineTool rejected netx tools whose parameters carry standard JSON
Schema constraints ("parameters.page.minimum is not supported by the
value schema DSL"), and the old pass-through dropped the top-level
required list.
- mcp-schema.ts: fold minimum/maxItems/pattern/... into the description,
mark required per property, map anyOf/oneOf/type arrays (minus null)
to oneOf, default additionalProperties to true.
- Test compiles all 39 real /mcp tool schemas through defineTool.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
2ef3a43c63
commit
277a61894d
12 changed files with 2852 additions and 117 deletions
|
|
@ -2,7 +2,7 @@
|
||||||
"format": 1,
|
"format": 1,
|
||||||
"builds": {
|
"builds": {
|
||||||
"lib/agent-tools-biz-monitor.js": {
|
"lib/agent-tools-biz-monitor.js": {
|
||||||
"output": "2b382bb050cd2bdbba42c018359fcd81fd56f7caa77ab5fcea7dded47841eeb5",
|
"output": "35b27ce03d1f8fe8b8bf919d1649d0506fd957dbcb1d7856c3991a2781559f11",
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"package.json": "1bb1fb8d615f49c69665a3a89b5912fa414a3b93aa3c541ce909ff57f97e100d",
|
"package.json": "1bb1fb8d615f49c69665a3a89b5912fa414a3b93aa3c541ce909ff57f97e100d",
|
||||||
"pnpm-lock.yaml": "f1209ac70e9c2294e0f300c0aad88b64aeecd6aa19dfc929c5766c7d033615a3",
|
"pnpm-lock.yaml": "f1209ac70e9c2294e0f300c0aad88b64aeecd6aa19dfc929c5766c7d033615a3",
|
||||||
|
|
@ -25,15 +25,16 @@
|
||||||
"src/netx/kb-runtime.ts": "ebf2fd36c407439f1a59344af18d9fe7275825925adbe08719595d06161d6d5b",
|
"src/netx/kb-runtime.ts": "ebf2fd36c407439f1a59344af18d9fe7275825925adbe08719595d06161d6d5b",
|
||||||
"src/netx/mcp-catalog.ts": "b79962da8f74f04595ed89b166b851d83cac41e8338b80b7629da2021a2c281d",
|
"src/netx/mcp-catalog.ts": "b79962da8f74f04595ed89b166b851d83cac41e8338b80b7629da2021a2c281d",
|
||||||
"src/netx/mcp-remote.ts": "d79925538e6adaccd8dbf8c65a90027d98464d37a57dce00b3e3155c08b02843",
|
"src/netx/mcp-remote.ts": "d79925538e6adaccd8dbf8c65a90027d98464d37a57dce00b3e3155c08b02843",
|
||||||
|
"src/netx/mcp-schema.ts": "2bb2eccd001101bd97389578c627931e89fbab4e057dab500e8b7b8bd655366f",
|
||||||
"src/netx/mcp-store.ts": "eb93e466e16c3bca81bff01407689025711be52d55e79acbdfa4bec64bd0a6f3",
|
"src/netx/mcp-store.ts": "eb93e466e16c3bca81bff01407689025711be52d55e79acbdfa4bec64bd0a6f3",
|
||||||
"src/netx/mcp-types.ts": "4b30d6e8fba328b0e116c43a1a90d2b686ef4b9fc648b521063876426e9c2833",
|
"src/netx/mcp-types.ts": "4b30d6e8fba328b0e116c43a1a90d2b686ef4b9fc648b521063876426e9c2833",
|
||||||
"src/netx/runtime.ts": "238555c92c3972ee9de8ec062b14d6a86961ec4c64609565ba1164b1a460d386",
|
"src/netx/runtime.ts": "238555c92c3972ee9de8ec062b14d6a86961ec4c64609565ba1164b1a460d386",
|
||||||
"src/netx/tool-mount-status.ts": "783981774d717ca5e7bf7c0ec7273b40787ef12a6b40749c74543b30fa390faf",
|
"src/netx/tool-mount-status.ts": "783981774d717ca5e7bf7c0ec7273b40787ef12a6b40749c74543b30fa390faf",
|
||||||
"src/netx/tools.ts": "0dfc3fdada56ab04ce40fecbe6f229aabae4ff6132d60809a8fb8daade948641"
|
"src/netx/tools.ts": "88c925aba50a7d6b3fc800986789955fd77c7aca8387c399b1ef58edbf7b9139"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"lib/agent-tools-common.js": {
|
"lib/agent-tools-common.js": {
|
||||||
"output": "3e51e500080dfad4c0a2ea6060afb1b7fe4e6a349d13030aed7ad37db49eedfa",
|
"output": "529aa5d79d0c40030920a8b8053797f43812bf6d8fa4cb6df7ea7e62a46e4777",
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"package.json": "1bb1fb8d615f49c69665a3a89b5912fa414a3b93aa3c541ce909ff57f97e100d",
|
"package.json": "1bb1fb8d615f49c69665a3a89b5912fa414a3b93aa3c541ce909ff57f97e100d",
|
||||||
"pnpm-lock.yaml": "f1209ac70e9c2294e0f300c0aad88b64aeecd6aa19dfc929c5766c7d033615a3",
|
"pnpm-lock.yaml": "f1209ac70e9c2294e0f300c0aad88b64aeecd6aa19dfc929c5766c7d033615a3",
|
||||||
|
|
@ -56,15 +57,16 @@
|
||||||
"src/netx/kb-runtime.ts": "ebf2fd36c407439f1a59344af18d9fe7275825925adbe08719595d06161d6d5b",
|
"src/netx/kb-runtime.ts": "ebf2fd36c407439f1a59344af18d9fe7275825925adbe08719595d06161d6d5b",
|
||||||
"src/netx/mcp-catalog.ts": "b79962da8f74f04595ed89b166b851d83cac41e8338b80b7629da2021a2c281d",
|
"src/netx/mcp-catalog.ts": "b79962da8f74f04595ed89b166b851d83cac41e8338b80b7629da2021a2c281d",
|
||||||
"src/netx/mcp-remote.ts": "d79925538e6adaccd8dbf8c65a90027d98464d37a57dce00b3e3155c08b02843",
|
"src/netx/mcp-remote.ts": "d79925538e6adaccd8dbf8c65a90027d98464d37a57dce00b3e3155c08b02843",
|
||||||
|
"src/netx/mcp-schema.ts": "2bb2eccd001101bd97389578c627931e89fbab4e057dab500e8b7b8bd655366f",
|
||||||
"src/netx/mcp-store.ts": "eb93e466e16c3bca81bff01407689025711be52d55e79acbdfa4bec64bd0a6f3",
|
"src/netx/mcp-store.ts": "eb93e466e16c3bca81bff01407689025711be52d55e79acbdfa4bec64bd0a6f3",
|
||||||
"src/netx/mcp-types.ts": "4b30d6e8fba328b0e116c43a1a90d2b686ef4b9fc648b521063876426e9c2833",
|
"src/netx/mcp-types.ts": "4b30d6e8fba328b0e116c43a1a90d2b686ef4b9fc648b521063876426e9c2833",
|
||||||
"src/netx/runtime.ts": "238555c92c3972ee9de8ec062b14d6a86961ec4c64609565ba1164b1a460d386",
|
"src/netx/runtime.ts": "238555c92c3972ee9de8ec062b14d6a86961ec4c64609565ba1164b1a460d386",
|
||||||
"src/netx/tool-mount-status.ts": "783981774d717ca5e7bf7c0ec7273b40787ef12a6b40749c74543b30fa390faf",
|
"src/netx/tool-mount-status.ts": "783981774d717ca5e7bf7c0ec7273b40787ef12a6b40749c74543b30fa390faf",
|
||||||
"src/netx/tools.ts": "0dfc3fdada56ab04ce40fecbe6f229aabae4ff6132d60809a8fb8daade948641"
|
"src/netx/tools.ts": "88c925aba50a7d6b3fc800986789955fd77c7aca8387c399b1ef58edbf7b9139"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"lib/agent-tools-nms.js": {
|
"lib/agent-tools-nms.js": {
|
||||||
"output": "895e3fdf1ab1a9fc9a0fd0d79f2d51b22f164a1a6ea1e0897f975b4b3103d647",
|
"output": "75b7a381afdae9932b5d2ec9d4ca6fc63aa0e6da1c6ff1466c57759e6a932528",
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"package.json": "1bb1fb8d615f49c69665a3a89b5912fa414a3b93aa3c541ce909ff57f97e100d",
|
"package.json": "1bb1fb8d615f49c69665a3a89b5912fa414a3b93aa3c541ce909ff57f97e100d",
|
||||||
"pnpm-lock.yaml": "f1209ac70e9c2294e0f300c0aad88b64aeecd6aa19dfc929c5766c7d033615a3",
|
"pnpm-lock.yaml": "f1209ac70e9c2294e0f300c0aad88b64aeecd6aa19dfc929c5766c7d033615a3",
|
||||||
|
|
@ -87,15 +89,16 @@
|
||||||
"src/netx/kb-runtime.ts": "ebf2fd36c407439f1a59344af18d9fe7275825925adbe08719595d06161d6d5b",
|
"src/netx/kb-runtime.ts": "ebf2fd36c407439f1a59344af18d9fe7275825925adbe08719595d06161d6d5b",
|
||||||
"src/netx/mcp-catalog.ts": "b79962da8f74f04595ed89b166b851d83cac41e8338b80b7629da2021a2c281d",
|
"src/netx/mcp-catalog.ts": "b79962da8f74f04595ed89b166b851d83cac41e8338b80b7629da2021a2c281d",
|
||||||
"src/netx/mcp-remote.ts": "d79925538e6adaccd8dbf8c65a90027d98464d37a57dce00b3e3155c08b02843",
|
"src/netx/mcp-remote.ts": "d79925538e6adaccd8dbf8c65a90027d98464d37a57dce00b3e3155c08b02843",
|
||||||
|
"src/netx/mcp-schema.ts": "2bb2eccd001101bd97389578c627931e89fbab4e057dab500e8b7b8bd655366f",
|
||||||
"src/netx/mcp-store.ts": "eb93e466e16c3bca81bff01407689025711be52d55e79acbdfa4bec64bd0a6f3",
|
"src/netx/mcp-store.ts": "eb93e466e16c3bca81bff01407689025711be52d55e79acbdfa4bec64bd0a6f3",
|
||||||
"src/netx/mcp-types.ts": "4b30d6e8fba328b0e116c43a1a90d2b686ef4b9fc648b521063876426e9c2833",
|
"src/netx/mcp-types.ts": "4b30d6e8fba328b0e116c43a1a90d2b686ef4b9fc648b521063876426e9c2833",
|
||||||
"src/netx/runtime.ts": "238555c92c3972ee9de8ec062b14d6a86961ec4c64609565ba1164b1a460d386",
|
"src/netx/runtime.ts": "238555c92c3972ee9de8ec062b14d6a86961ec4c64609565ba1164b1a460d386",
|
||||||
"src/netx/tool-mount-status.ts": "783981774d717ca5e7bf7c0ec7273b40787ef12a6b40749c74543b30fa390faf",
|
"src/netx/tool-mount-status.ts": "783981774d717ca5e7bf7c0ec7273b40787ef12a6b40749c74543b30fa390faf",
|
||||||
"src/netx/tools.ts": "0dfc3fdada56ab04ce40fecbe6f229aabae4ff6132d60809a8fb8daade948641"
|
"src/netx/tools.ts": "88c925aba50a7d6b3fc800986789955fd77c7aca8387c399b1ef58edbf7b9139"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"lib/agent-tools-ops.js": {
|
"lib/agent-tools-ops.js": {
|
||||||
"output": "4ece4e983ee4c50a0591a9e601a6cded04f55ebe1c849b4b2eb9d458854e0a18",
|
"output": "16151108566b1f3313bfaace216ebb84656704c236b90cb468ba7f559dcd5e96",
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"package.json": "1bb1fb8d615f49c69665a3a89b5912fa414a3b93aa3c541ce909ff57f97e100d",
|
"package.json": "1bb1fb8d615f49c69665a3a89b5912fa414a3b93aa3c541ce909ff57f97e100d",
|
||||||
"pnpm-lock.yaml": "f1209ac70e9c2294e0f300c0aad88b64aeecd6aa19dfc929c5766c7d033615a3",
|
"pnpm-lock.yaml": "f1209ac70e9c2294e0f300c0aad88b64aeecd6aa19dfc929c5766c7d033615a3",
|
||||||
|
|
@ -118,15 +121,16 @@
|
||||||
"src/netx/kb-runtime.ts": "ebf2fd36c407439f1a59344af18d9fe7275825925adbe08719595d06161d6d5b",
|
"src/netx/kb-runtime.ts": "ebf2fd36c407439f1a59344af18d9fe7275825925adbe08719595d06161d6d5b",
|
||||||
"src/netx/mcp-catalog.ts": "b79962da8f74f04595ed89b166b851d83cac41e8338b80b7629da2021a2c281d",
|
"src/netx/mcp-catalog.ts": "b79962da8f74f04595ed89b166b851d83cac41e8338b80b7629da2021a2c281d",
|
||||||
"src/netx/mcp-remote.ts": "d79925538e6adaccd8dbf8c65a90027d98464d37a57dce00b3e3155c08b02843",
|
"src/netx/mcp-remote.ts": "d79925538e6adaccd8dbf8c65a90027d98464d37a57dce00b3e3155c08b02843",
|
||||||
|
"src/netx/mcp-schema.ts": "2bb2eccd001101bd97389578c627931e89fbab4e057dab500e8b7b8bd655366f",
|
||||||
"src/netx/mcp-store.ts": "eb93e466e16c3bca81bff01407689025711be52d55e79acbdfa4bec64bd0a6f3",
|
"src/netx/mcp-store.ts": "eb93e466e16c3bca81bff01407689025711be52d55e79acbdfa4bec64bd0a6f3",
|
||||||
"src/netx/mcp-types.ts": "4b30d6e8fba328b0e116c43a1a90d2b686ef4b9fc648b521063876426e9c2833",
|
"src/netx/mcp-types.ts": "4b30d6e8fba328b0e116c43a1a90d2b686ef4b9fc648b521063876426e9c2833",
|
||||||
"src/netx/runtime.ts": "238555c92c3972ee9de8ec062b14d6a86961ec4c64609565ba1164b1a460d386",
|
"src/netx/runtime.ts": "238555c92c3972ee9de8ec062b14d6a86961ec4c64609565ba1164b1a460d386",
|
||||||
"src/netx/tool-mount-status.ts": "783981774d717ca5e7bf7c0ec7273b40787ef12a6b40749c74543b30fa390faf",
|
"src/netx/tool-mount-status.ts": "783981774d717ca5e7bf7c0ec7273b40787ef12a6b40749c74543b30fa390faf",
|
||||||
"src/netx/tools.ts": "0dfc3fdada56ab04ce40fecbe6f229aabae4ff6132d60809a8fb8daade948641"
|
"src/netx/tools.ts": "88c925aba50a7d6b3fc800986789955fd77c7aca8387c399b1ef58edbf7b9139"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"lib/agent-tools-topology.js": {
|
"lib/agent-tools-topology.js": {
|
||||||
"output": "cec2f877d8fe03b5e537c35ec39a0d66c5885910385f690a8a3bcb96e8ad3954",
|
"output": "2e3b6268a7e11cab0717faaf4d13bc3ee5a195f1aea94960118211f6773dac28",
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"package.json": "1bb1fb8d615f49c69665a3a89b5912fa414a3b93aa3c541ce909ff57f97e100d",
|
"package.json": "1bb1fb8d615f49c69665a3a89b5912fa414a3b93aa3c541ce909ff57f97e100d",
|
||||||
"pnpm-lock.yaml": "f1209ac70e9c2294e0f300c0aad88b64aeecd6aa19dfc929c5766c7d033615a3",
|
"pnpm-lock.yaml": "f1209ac70e9c2294e0f300c0aad88b64aeecd6aa19dfc929c5766c7d033615a3",
|
||||||
|
|
@ -149,15 +153,16 @@
|
||||||
"src/netx/kb-runtime.ts": "ebf2fd36c407439f1a59344af18d9fe7275825925adbe08719595d06161d6d5b",
|
"src/netx/kb-runtime.ts": "ebf2fd36c407439f1a59344af18d9fe7275825925adbe08719595d06161d6d5b",
|
||||||
"src/netx/mcp-catalog.ts": "b79962da8f74f04595ed89b166b851d83cac41e8338b80b7629da2021a2c281d",
|
"src/netx/mcp-catalog.ts": "b79962da8f74f04595ed89b166b851d83cac41e8338b80b7629da2021a2c281d",
|
||||||
"src/netx/mcp-remote.ts": "d79925538e6adaccd8dbf8c65a90027d98464d37a57dce00b3e3155c08b02843",
|
"src/netx/mcp-remote.ts": "d79925538e6adaccd8dbf8c65a90027d98464d37a57dce00b3e3155c08b02843",
|
||||||
|
"src/netx/mcp-schema.ts": "2bb2eccd001101bd97389578c627931e89fbab4e057dab500e8b7b8bd655366f",
|
||||||
"src/netx/mcp-store.ts": "eb93e466e16c3bca81bff01407689025711be52d55e79acbdfa4bec64bd0a6f3",
|
"src/netx/mcp-store.ts": "eb93e466e16c3bca81bff01407689025711be52d55e79acbdfa4bec64bd0a6f3",
|
||||||
"src/netx/mcp-types.ts": "4b30d6e8fba328b0e116c43a1a90d2b686ef4b9fc648b521063876426e9c2833",
|
"src/netx/mcp-types.ts": "4b30d6e8fba328b0e116c43a1a90d2b686ef4b9fc648b521063876426e9c2833",
|
||||||
"src/netx/runtime.ts": "238555c92c3972ee9de8ec062b14d6a86961ec4c64609565ba1164b1a460d386",
|
"src/netx/runtime.ts": "238555c92c3972ee9de8ec062b14d6a86961ec4c64609565ba1164b1a460d386",
|
||||||
"src/netx/tool-mount-status.ts": "783981774d717ca5e7bf7c0ec7273b40787ef12a6b40749c74543b30fa390faf",
|
"src/netx/tool-mount-status.ts": "783981774d717ca5e7bf7c0ec7273b40787ef12a6b40749c74543b30fa390faf",
|
||||||
"src/netx/tools.ts": "0dfc3fdada56ab04ce40fecbe6f229aabae4ff6132d60809a8fb8daade948641"
|
"src/netx/tools.ts": "88c925aba50a7d6b3fc800986789955fd77c7aca8387c399b1ef58edbf7b9139"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"lib/agent-tools.js": {
|
"lib/agent-tools.js": {
|
||||||
"output": "9c51c136d5b5be9de1479abcae7bd4a69a20fe4e1f92562ca6e13e59663669cc",
|
"output": "d14c5187ce4ea92c7a9e2a54949c6381c8ad9aede9a78264eeaca82d6618de6a",
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"package.json": "1bb1fb8d615f49c69665a3a89b5912fa414a3b93aa3c541ce909ff57f97e100d",
|
"package.json": "1bb1fb8d615f49c69665a3a89b5912fa414a3b93aa3c541ce909ff57f97e100d",
|
||||||
"pnpm-lock.yaml": "f1209ac70e9c2294e0f300c0aad88b64aeecd6aa19dfc929c5766c7d033615a3",
|
"pnpm-lock.yaml": "f1209ac70e9c2294e0f300c0aad88b64aeecd6aa19dfc929c5766c7d033615a3",
|
||||||
|
|
@ -180,11 +185,12 @@
|
||||||
"src/netx/kb-runtime.ts": "ebf2fd36c407439f1a59344af18d9fe7275825925adbe08719595d06161d6d5b",
|
"src/netx/kb-runtime.ts": "ebf2fd36c407439f1a59344af18d9fe7275825925adbe08719595d06161d6d5b",
|
||||||
"src/netx/mcp-catalog.ts": "b79962da8f74f04595ed89b166b851d83cac41e8338b80b7629da2021a2c281d",
|
"src/netx/mcp-catalog.ts": "b79962da8f74f04595ed89b166b851d83cac41e8338b80b7629da2021a2c281d",
|
||||||
"src/netx/mcp-remote.ts": "d79925538e6adaccd8dbf8c65a90027d98464d37a57dce00b3e3155c08b02843",
|
"src/netx/mcp-remote.ts": "d79925538e6adaccd8dbf8c65a90027d98464d37a57dce00b3e3155c08b02843",
|
||||||
|
"src/netx/mcp-schema.ts": "2bb2eccd001101bd97389578c627931e89fbab4e057dab500e8b7b8bd655366f",
|
||||||
"src/netx/mcp-store.ts": "eb93e466e16c3bca81bff01407689025711be52d55e79acbdfa4bec64bd0a6f3",
|
"src/netx/mcp-store.ts": "eb93e466e16c3bca81bff01407689025711be52d55e79acbdfa4bec64bd0a6f3",
|
||||||
"src/netx/mcp-types.ts": "4b30d6e8fba328b0e116c43a1a90d2b686ef4b9fc648b521063876426e9c2833",
|
"src/netx/mcp-types.ts": "4b30d6e8fba328b0e116c43a1a90d2b686ef4b9fc648b521063876426e9c2833",
|
||||||
"src/netx/runtime.ts": "238555c92c3972ee9de8ec062b14d6a86961ec4c64609565ba1164b1a460d386",
|
"src/netx/runtime.ts": "238555c92c3972ee9de8ec062b14d6a86961ec4c64609565ba1164b1a460d386",
|
||||||
"src/netx/tool-mount-status.ts": "783981774d717ca5e7bf7c0ec7273b40787ef12a6b40749c74543b30fa390faf",
|
"src/netx/tool-mount-status.ts": "783981774d717ca5e7bf7c0ec7273b40787ef12a6b40749c74543b30fa390faf",
|
||||||
"src/netx/tools.ts": "0dfc3fdada56ab04ce40fecbe6f229aabae4ff6132d60809a8fb8daade948641"
|
"src/netx/tools.ts": "88c925aba50a7d6b3fc800986789955fd77c7aca8387c399b1ef58edbf7b9139"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"lib/client.js": {
|
"lib/client.js": {
|
||||||
|
|
@ -219,7 +225,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"lib/index.js": {
|
"lib/index.js": {
|
||||||
"output": "778c85d88498127abf5bb490b251b8b6f94b3ec38a8d7ad5c46c13854cc65d1f",
|
"output": "ceb3cb1b0e366d086fdca112904a73d8dbb0c9926064bbe13e8602e86267307d",
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"package.json": "1bb1fb8d615f49c69665a3a89b5912fa414a3b93aa3c541ce909ff57f97e100d",
|
"package.json": "1bb1fb8d615f49c69665a3a89b5912fa414a3b93aa3c541ce909ff57f97e100d",
|
||||||
"pnpm-lock.yaml": "f1209ac70e9c2294e0f300c0aad88b64aeecd6aa19dfc929c5766c7d033615a3",
|
"pnpm-lock.yaml": "f1209ac70e9c2294e0f300c0aad88b64aeecd6aa19dfc929c5766c7d033615a3",
|
||||||
|
|
@ -251,6 +257,7 @@
|
||||||
"src/netx/kb-runtime.ts": "ebf2fd36c407439f1a59344af18d9fe7275825925adbe08719595d06161d6d5b",
|
"src/netx/kb-runtime.ts": "ebf2fd36c407439f1a59344af18d9fe7275825925adbe08719595d06161d6d5b",
|
||||||
"src/netx/mcp-catalog.ts": "b79962da8f74f04595ed89b166b851d83cac41e8338b80b7629da2021a2c281d",
|
"src/netx/mcp-catalog.ts": "b79962da8f74f04595ed89b166b851d83cac41e8338b80b7629da2021a2c281d",
|
||||||
"src/netx/mcp-remote.ts": "d79925538e6adaccd8dbf8c65a90027d98464d37a57dce00b3e3155c08b02843",
|
"src/netx/mcp-remote.ts": "d79925538e6adaccd8dbf8c65a90027d98464d37a57dce00b3e3155c08b02843",
|
||||||
|
"src/netx/mcp-schema.ts": "2bb2eccd001101bd97389578c627931e89fbab4e057dab500e8b7b8bd655366f",
|
||||||
"src/netx/mcp-store.ts": "eb93e466e16c3bca81bff01407689025711be52d55e79acbdfa4bec64bd0a6f3",
|
"src/netx/mcp-store.ts": "eb93e466e16c3bca81bff01407689025711be52d55e79acbdfa4bec64bd0a6f3",
|
||||||
"src/netx/mcp-types.ts": "4b30d6e8fba328b0e116c43a1a90d2b686ef4b9fc648b521063876426e9c2833",
|
"src/netx/mcp-types.ts": "4b30d6e8fba328b0e116c43a1a90d2b686ef4b9fc648b521063876426e9c2833",
|
||||||
"src/netx/model-language.ts": "07df448b407086237c184a71bfc78e7cb27e50d7f8c499995d8b368b14780c9e",
|
"src/netx/model-language.ts": "07df448b407086237c184a71bfc78e7cb27e50d7f8c499995d8b368b14780c9e",
|
||||||
|
|
@ -259,7 +266,7 @@
|
||||||
"src/netx/runtime.ts": "238555c92c3972ee9de8ec062b14d6a86961ec4c64609565ba1164b1a460d386",
|
"src/netx/runtime.ts": "238555c92c3972ee9de8ec062b14d6a86961ec4c64609565ba1164b1a460d386",
|
||||||
"src/netx/session-export.ts": "8e6e9a3094045901563366fac3d6dc74d9bfd78bbff853358d6500955d3dcff6",
|
"src/netx/session-export.ts": "8e6e9a3094045901563366fac3d6dc74d9bfd78bbff853358d6500955d3dcff6",
|
||||||
"src/netx/tool-mount-status.ts": "783981774d717ca5e7bf7c0ec7273b40787ef12a6b40749c74543b30fa390faf",
|
"src/netx/tool-mount-status.ts": "783981774d717ca5e7bf7c0ec7273b40787ef12a6b40749c74543b30fa390faf",
|
||||||
"src/netx/tools.ts": "0dfc3fdada56ab04ce40fecbe6f229aabae4ff6132d60809a8fb8daade948641",
|
"src/netx/tools.ts": "88c925aba50a7d6b3fc800986789955fd77c7aca8387c399b1ef58edbf7b9139",
|
||||||
"src/session-export-shared.ts": "e30d884ec22a0ea2e016c1479f62a8bc8d7ddcce5369a36647d411d07a8620d5"
|
"src/session-export-shared.ts": "e30d884ec22a0ea2e016c1479f62a8bc8d7ddcce5369a36647d411d07a8620d5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1803,6 +1803,104 @@ import { readFileSync as readFileSync5 } from "node:fs";
|
||||||
import { dirname as dirname5, join as join9 } from "node:path";
|
import { dirname as dirname5, join as join9 } from "node:path";
|
||||||
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
||||||
import { defineTool as defineTool2 } from "@deepseek-ai/dsh-tools";
|
import { defineTool as defineTool2 } from "@deepseek-ai/dsh-tools";
|
||||||
|
|
||||||
|
// src/netx/mcp-schema.ts
|
||||||
|
var ANNOTATIONS = ["description", "title", "default", "examples"];
|
||||||
|
var SCALAR_TYPES = new Set(["string", "number", "integer", "boolean", "null"]);
|
||||||
|
var CONSTRAINTS = [
|
||||||
|
"minimum",
|
||||||
|
"maximum",
|
||||||
|
"exclusiveMinimum",
|
||||||
|
"exclusiveMaximum",
|
||||||
|
"multipleOf",
|
||||||
|
"minLength",
|
||||||
|
"maxLength",
|
||||||
|
"pattern",
|
||||||
|
"format",
|
||||||
|
"minItems",
|
||||||
|
"maxItems",
|
||||||
|
"uniqueItems"
|
||||||
|
];
|
||||||
|
function isRecord(value) {
|
||||||
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
||||||
|
}
|
||||||
|
function withAnnotations(source, target) {
|
||||||
|
for (const key of ANNOTATIONS) {
|
||||||
|
if (Object.hasOwn(source, key))
|
||||||
|
target[key] = source[key];
|
||||||
|
}
|
||||||
|
const notes = CONSTRAINTS.filter((key) => Object.hasOwn(source, key)).map((key) => `${key}=${JSON.stringify(source[key])}`);
|
||||||
|
if (notes.length > 0) {
|
||||||
|
const base = typeof target.description === "string" ? target.description : "";
|
||||||
|
target.description = `${base}${base ? " " : ""}(${notes.join(", ")})`;
|
||||||
|
}
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
function variants(node) {
|
||||||
|
const list = Array.isArray(node.oneOf) ? node.oneOf : Array.isArray(node.anyOf) ? node.anyOf : undefined;
|
||||||
|
if (list)
|
||||||
|
return list.filter(isRecord).filter((branch) => branch.type !== "null");
|
||||||
|
if (Array.isArray(node.type)) {
|
||||||
|
const { type: _types, ...rest } = node;
|
||||||
|
return node.type.filter((t) => t !== "null").map((t) => ({ ...rest, type: t }));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
function toValue(node) {
|
||||||
|
if (!isRecord(node))
|
||||||
|
return { type: "json" };
|
||||||
|
const branches = variants(node);
|
||||||
|
if (branches) {
|
||||||
|
if (branches.length === 0)
|
||||||
|
return withAnnotations(node, { type: "json" });
|
||||||
|
if (branches.length === 1)
|
||||||
|
return withAnnotations(node, toValue({ ...branches[0] }));
|
||||||
|
return withAnnotations(node, { oneOf: branches.map(toValue) });
|
||||||
|
}
|
||||||
|
const type = node.type;
|
||||||
|
if (type === "object" || type === undefined && isRecord(node.properties)) {
|
||||||
|
const out = {
|
||||||
|
type: "object",
|
||||||
|
additionalProperties: typeof node.additionalProperties === "boolean" ? node.additionalProperties : true
|
||||||
|
};
|
||||||
|
if (isRecord(node.properties))
|
||||||
|
out.properties = toProperties(node.properties, node.required);
|
||||||
|
return withAnnotations(node, out);
|
||||||
|
}
|
||||||
|
if (type === "array") {
|
||||||
|
const out = { type: "array" };
|
||||||
|
if (Object.hasOwn(node, "items"))
|
||||||
|
out.items = toValue(node.items);
|
||||||
|
return withAnnotations(node, out);
|
||||||
|
}
|
||||||
|
if (typeof type === "string" && SCALAR_TYPES.has(type)) {
|
||||||
|
const out = { type };
|
||||||
|
if (Array.isArray(node.enum) && node.enum.length > 0)
|
||||||
|
out.enum = node.enum;
|
||||||
|
if (Object.hasOwn(node, "const"))
|
||||||
|
out.const = node.const;
|
||||||
|
return withAnnotations(node, out);
|
||||||
|
}
|
||||||
|
return withAnnotations(node, { type: "json" });
|
||||||
|
}
|
||||||
|
function toProperties(properties, required) {
|
||||||
|
const requiredSet = new Set(Array.isArray(required) ? required.filter((k) => typeof k === "string") : []);
|
||||||
|
const out = {};
|
||||||
|
for (const [key, value] of Object.entries(properties)) {
|
||||||
|
const converted = toValue(value);
|
||||||
|
if (requiredSet.has(key))
|
||||||
|
converted.required = true;
|
||||||
|
out[key] = converted;
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
function parametersFromInputSchema(schema) {
|
||||||
|
if (!isRecord(schema) || !isRecord(schema.properties))
|
||||||
|
return {};
|
||||||
|
return toProperties(schema.properties, schema.required);
|
||||||
|
}
|
||||||
|
|
||||||
|
// src/netx/tools.ts
|
||||||
function packageVersion() {
|
function packageVersion() {
|
||||||
try {
|
try {
|
||||||
const here = dirname5(fileURLToPath2(import.meta.url));
|
const here = dirname5(fileURLToPath2(import.meta.url));
|
||||||
|
|
@ -1828,18 +1926,6 @@ var mcpOut = {
|
||||||
schema: { type: "object", additionalProperties: true },
|
schema: { type: "object", additionalProperties: true },
|
||||||
render: renderMcpResult
|
render: renderMcpResult
|
||||||
};
|
};
|
||||||
function parametersFromInputSchema(schema) {
|
|
||||||
if (schema && typeof schema === "object" && !Array.isArray(schema)) {
|
|
||||||
const props = schema.properties;
|
|
||||||
if (props && typeof props === "object" && !Array.isArray(props)) {
|
|
||||||
return props;
|
|
||||||
}
|
|
||||||
if (schema.type === undefined && schema.properties === undefined) {
|
|
||||||
return schema;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
function defineRemoteTool(tool2, timeoutMs) {
|
function defineRemoteTool(tool2, timeoutMs) {
|
||||||
const name = publicToolName(tool2.name);
|
const name = publicToolName(tool2.name);
|
||||||
return defineTool2({
|
return defineTool2({
|
||||||
|
|
|
||||||
|
|
@ -1803,6 +1803,104 @@ import { readFileSync as readFileSync5 } from "node:fs";
|
||||||
import { dirname as dirname5, join as join9 } from "node:path";
|
import { dirname as dirname5, join as join9 } from "node:path";
|
||||||
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
||||||
import { defineTool as defineTool2 } from "@deepseek-ai/dsh-tools";
|
import { defineTool as defineTool2 } from "@deepseek-ai/dsh-tools";
|
||||||
|
|
||||||
|
// src/netx/mcp-schema.ts
|
||||||
|
var ANNOTATIONS = ["description", "title", "default", "examples"];
|
||||||
|
var SCALAR_TYPES = new Set(["string", "number", "integer", "boolean", "null"]);
|
||||||
|
var CONSTRAINTS = [
|
||||||
|
"minimum",
|
||||||
|
"maximum",
|
||||||
|
"exclusiveMinimum",
|
||||||
|
"exclusiveMaximum",
|
||||||
|
"multipleOf",
|
||||||
|
"minLength",
|
||||||
|
"maxLength",
|
||||||
|
"pattern",
|
||||||
|
"format",
|
||||||
|
"minItems",
|
||||||
|
"maxItems",
|
||||||
|
"uniqueItems"
|
||||||
|
];
|
||||||
|
function isRecord(value) {
|
||||||
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
||||||
|
}
|
||||||
|
function withAnnotations(source, target) {
|
||||||
|
for (const key of ANNOTATIONS) {
|
||||||
|
if (Object.hasOwn(source, key))
|
||||||
|
target[key] = source[key];
|
||||||
|
}
|
||||||
|
const notes = CONSTRAINTS.filter((key) => Object.hasOwn(source, key)).map((key) => `${key}=${JSON.stringify(source[key])}`);
|
||||||
|
if (notes.length > 0) {
|
||||||
|
const base = typeof target.description === "string" ? target.description : "";
|
||||||
|
target.description = `${base}${base ? " " : ""}(${notes.join(", ")})`;
|
||||||
|
}
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
function variants(node) {
|
||||||
|
const list = Array.isArray(node.oneOf) ? node.oneOf : Array.isArray(node.anyOf) ? node.anyOf : undefined;
|
||||||
|
if (list)
|
||||||
|
return list.filter(isRecord).filter((branch) => branch.type !== "null");
|
||||||
|
if (Array.isArray(node.type)) {
|
||||||
|
const { type: _types, ...rest } = node;
|
||||||
|
return node.type.filter((t) => t !== "null").map((t) => ({ ...rest, type: t }));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
function toValue(node) {
|
||||||
|
if (!isRecord(node))
|
||||||
|
return { type: "json" };
|
||||||
|
const branches = variants(node);
|
||||||
|
if (branches) {
|
||||||
|
if (branches.length === 0)
|
||||||
|
return withAnnotations(node, { type: "json" });
|
||||||
|
if (branches.length === 1)
|
||||||
|
return withAnnotations(node, toValue({ ...branches[0] }));
|
||||||
|
return withAnnotations(node, { oneOf: branches.map(toValue) });
|
||||||
|
}
|
||||||
|
const type = node.type;
|
||||||
|
if (type === "object" || type === undefined && isRecord(node.properties)) {
|
||||||
|
const out = {
|
||||||
|
type: "object",
|
||||||
|
additionalProperties: typeof node.additionalProperties === "boolean" ? node.additionalProperties : true
|
||||||
|
};
|
||||||
|
if (isRecord(node.properties))
|
||||||
|
out.properties = toProperties(node.properties, node.required);
|
||||||
|
return withAnnotations(node, out);
|
||||||
|
}
|
||||||
|
if (type === "array") {
|
||||||
|
const out = { type: "array" };
|
||||||
|
if (Object.hasOwn(node, "items"))
|
||||||
|
out.items = toValue(node.items);
|
||||||
|
return withAnnotations(node, out);
|
||||||
|
}
|
||||||
|
if (typeof type === "string" && SCALAR_TYPES.has(type)) {
|
||||||
|
const out = { type };
|
||||||
|
if (Array.isArray(node.enum) && node.enum.length > 0)
|
||||||
|
out.enum = node.enum;
|
||||||
|
if (Object.hasOwn(node, "const"))
|
||||||
|
out.const = node.const;
|
||||||
|
return withAnnotations(node, out);
|
||||||
|
}
|
||||||
|
return withAnnotations(node, { type: "json" });
|
||||||
|
}
|
||||||
|
function toProperties(properties, required) {
|
||||||
|
const requiredSet = new Set(Array.isArray(required) ? required.filter((k) => typeof k === "string") : []);
|
||||||
|
const out = {};
|
||||||
|
for (const [key, value] of Object.entries(properties)) {
|
||||||
|
const converted = toValue(value);
|
||||||
|
if (requiredSet.has(key))
|
||||||
|
converted.required = true;
|
||||||
|
out[key] = converted;
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
function parametersFromInputSchema(schema) {
|
||||||
|
if (!isRecord(schema) || !isRecord(schema.properties))
|
||||||
|
return {};
|
||||||
|
return toProperties(schema.properties, schema.required);
|
||||||
|
}
|
||||||
|
|
||||||
|
// src/netx/tools.ts
|
||||||
function packageVersion() {
|
function packageVersion() {
|
||||||
try {
|
try {
|
||||||
const here = dirname5(fileURLToPath2(import.meta.url));
|
const here = dirname5(fileURLToPath2(import.meta.url));
|
||||||
|
|
@ -1828,18 +1926,6 @@ var mcpOut = {
|
||||||
schema: { type: "object", additionalProperties: true },
|
schema: { type: "object", additionalProperties: true },
|
||||||
render: renderMcpResult
|
render: renderMcpResult
|
||||||
};
|
};
|
||||||
function parametersFromInputSchema(schema) {
|
|
||||||
if (schema && typeof schema === "object" && !Array.isArray(schema)) {
|
|
||||||
const props = schema.properties;
|
|
||||||
if (props && typeof props === "object" && !Array.isArray(props)) {
|
|
||||||
return props;
|
|
||||||
}
|
|
||||||
if (schema.type === undefined && schema.properties === undefined) {
|
|
||||||
return schema;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
function defineRemoteTool(tool2, timeoutMs) {
|
function defineRemoteTool(tool2, timeoutMs) {
|
||||||
const name = publicToolName(tool2.name);
|
const name = publicToolName(tool2.name);
|
||||||
return defineTool2({
|
return defineTool2({
|
||||||
|
|
|
||||||
|
|
@ -1803,6 +1803,104 @@ import { readFileSync as readFileSync5 } from "node:fs";
|
||||||
import { dirname as dirname5, join as join9 } from "node:path";
|
import { dirname as dirname5, join as join9 } from "node:path";
|
||||||
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
||||||
import { defineTool as defineTool2 } from "@deepseek-ai/dsh-tools";
|
import { defineTool as defineTool2 } from "@deepseek-ai/dsh-tools";
|
||||||
|
|
||||||
|
// src/netx/mcp-schema.ts
|
||||||
|
var ANNOTATIONS = ["description", "title", "default", "examples"];
|
||||||
|
var SCALAR_TYPES = new Set(["string", "number", "integer", "boolean", "null"]);
|
||||||
|
var CONSTRAINTS = [
|
||||||
|
"minimum",
|
||||||
|
"maximum",
|
||||||
|
"exclusiveMinimum",
|
||||||
|
"exclusiveMaximum",
|
||||||
|
"multipleOf",
|
||||||
|
"minLength",
|
||||||
|
"maxLength",
|
||||||
|
"pattern",
|
||||||
|
"format",
|
||||||
|
"minItems",
|
||||||
|
"maxItems",
|
||||||
|
"uniqueItems"
|
||||||
|
];
|
||||||
|
function isRecord(value) {
|
||||||
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
||||||
|
}
|
||||||
|
function withAnnotations(source, target) {
|
||||||
|
for (const key of ANNOTATIONS) {
|
||||||
|
if (Object.hasOwn(source, key))
|
||||||
|
target[key] = source[key];
|
||||||
|
}
|
||||||
|
const notes = CONSTRAINTS.filter((key) => Object.hasOwn(source, key)).map((key) => `${key}=${JSON.stringify(source[key])}`);
|
||||||
|
if (notes.length > 0) {
|
||||||
|
const base = typeof target.description === "string" ? target.description : "";
|
||||||
|
target.description = `${base}${base ? " " : ""}(${notes.join(", ")})`;
|
||||||
|
}
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
function variants(node) {
|
||||||
|
const list = Array.isArray(node.oneOf) ? node.oneOf : Array.isArray(node.anyOf) ? node.anyOf : undefined;
|
||||||
|
if (list)
|
||||||
|
return list.filter(isRecord).filter((branch) => branch.type !== "null");
|
||||||
|
if (Array.isArray(node.type)) {
|
||||||
|
const { type: _types, ...rest } = node;
|
||||||
|
return node.type.filter((t) => t !== "null").map((t) => ({ ...rest, type: t }));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
function toValue(node) {
|
||||||
|
if (!isRecord(node))
|
||||||
|
return { type: "json" };
|
||||||
|
const branches = variants(node);
|
||||||
|
if (branches) {
|
||||||
|
if (branches.length === 0)
|
||||||
|
return withAnnotations(node, { type: "json" });
|
||||||
|
if (branches.length === 1)
|
||||||
|
return withAnnotations(node, toValue({ ...branches[0] }));
|
||||||
|
return withAnnotations(node, { oneOf: branches.map(toValue) });
|
||||||
|
}
|
||||||
|
const type = node.type;
|
||||||
|
if (type === "object" || type === undefined && isRecord(node.properties)) {
|
||||||
|
const out = {
|
||||||
|
type: "object",
|
||||||
|
additionalProperties: typeof node.additionalProperties === "boolean" ? node.additionalProperties : true
|
||||||
|
};
|
||||||
|
if (isRecord(node.properties))
|
||||||
|
out.properties = toProperties(node.properties, node.required);
|
||||||
|
return withAnnotations(node, out);
|
||||||
|
}
|
||||||
|
if (type === "array") {
|
||||||
|
const out = { type: "array" };
|
||||||
|
if (Object.hasOwn(node, "items"))
|
||||||
|
out.items = toValue(node.items);
|
||||||
|
return withAnnotations(node, out);
|
||||||
|
}
|
||||||
|
if (typeof type === "string" && SCALAR_TYPES.has(type)) {
|
||||||
|
const out = { type };
|
||||||
|
if (Array.isArray(node.enum) && node.enum.length > 0)
|
||||||
|
out.enum = node.enum;
|
||||||
|
if (Object.hasOwn(node, "const"))
|
||||||
|
out.const = node.const;
|
||||||
|
return withAnnotations(node, out);
|
||||||
|
}
|
||||||
|
return withAnnotations(node, { type: "json" });
|
||||||
|
}
|
||||||
|
function toProperties(properties, required) {
|
||||||
|
const requiredSet = new Set(Array.isArray(required) ? required.filter((k) => typeof k === "string") : []);
|
||||||
|
const out = {};
|
||||||
|
for (const [key, value] of Object.entries(properties)) {
|
||||||
|
const converted = toValue(value);
|
||||||
|
if (requiredSet.has(key))
|
||||||
|
converted.required = true;
|
||||||
|
out[key] = converted;
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
function parametersFromInputSchema(schema) {
|
||||||
|
if (!isRecord(schema) || !isRecord(schema.properties))
|
||||||
|
return {};
|
||||||
|
return toProperties(schema.properties, schema.required);
|
||||||
|
}
|
||||||
|
|
||||||
|
// src/netx/tools.ts
|
||||||
function packageVersion() {
|
function packageVersion() {
|
||||||
try {
|
try {
|
||||||
const here = dirname5(fileURLToPath2(import.meta.url));
|
const here = dirname5(fileURLToPath2(import.meta.url));
|
||||||
|
|
@ -1828,18 +1926,6 @@ var mcpOut = {
|
||||||
schema: { type: "object", additionalProperties: true },
|
schema: { type: "object", additionalProperties: true },
|
||||||
render: renderMcpResult
|
render: renderMcpResult
|
||||||
};
|
};
|
||||||
function parametersFromInputSchema(schema) {
|
|
||||||
if (schema && typeof schema === "object" && !Array.isArray(schema)) {
|
|
||||||
const props = schema.properties;
|
|
||||||
if (props && typeof props === "object" && !Array.isArray(props)) {
|
|
||||||
return props;
|
|
||||||
}
|
|
||||||
if (schema.type === undefined && schema.properties === undefined) {
|
|
||||||
return schema;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
function defineRemoteTool(tool2, timeoutMs) {
|
function defineRemoteTool(tool2, timeoutMs) {
|
||||||
const name = publicToolName(tool2.name);
|
const name = publicToolName(tool2.name);
|
||||||
return defineTool2({
|
return defineTool2({
|
||||||
|
|
|
||||||
|
|
@ -1803,6 +1803,104 @@ import { readFileSync as readFileSync5 } from "node:fs";
|
||||||
import { dirname as dirname5, join as join9 } from "node:path";
|
import { dirname as dirname5, join as join9 } from "node:path";
|
||||||
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
||||||
import { defineTool as defineTool2 } from "@deepseek-ai/dsh-tools";
|
import { defineTool as defineTool2 } from "@deepseek-ai/dsh-tools";
|
||||||
|
|
||||||
|
// src/netx/mcp-schema.ts
|
||||||
|
var ANNOTATIONS = ["description", "title", "default", "examples"];
|
||||||
|
var SCALAR_TYPES = new Set(["string", "number", "integer", "boolean", "null"]);
|
||||||
|
var CONSTRAINTS = [
|
||||||
|
"minimum",
|
||||||
|
"maximum",
|
||||||
|
"exclusiveMinimum",
|
||||||
|
"exclusiveMaximum",
|
||||||
|
"multipleOf",
|
||||||
|
"minLength",
|
||||||
|
"maxLength",
|
||||||
|
"pattern",
|
||||||
|
"format",
|
||||||
|
"minItems",
|
||||||
|
"maxItems",
|
||||||
|
"uniqueItems"
|
||||||
|
];
|
||||||
|
function isRecord(value) {
|
||||||
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
||||||
|
}
|
||||||
|
function withAnnotations(source, target) {
|
||||||
|
for (const key of ANNOTATIONS) {
|
||||||
|
if (Object.hasOwn(source, key))
|
||||||
|
target[key] = source[key];
|
||||||
|
}
|
||||||
|
const notes = CONSTRAINTS.filter((key) => Object.hasOwn(source, key)).map((key) => `${key}=${JSON.stringify(source[key])}`);
|
||||||
|
if (notes.length > 0) {
|
||||||
|
const base = typeof target.description === "string" ? target.description : "";
|
||||||
|
target.description = `${base}${base ? " " : ""}(${notes.join(", ")})`;
|
||||||
|
}
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
function variants(node) {
|
||||||
|
const list = Array.isArray(node.oneOf) ? node.oneOf : Array.isArray(node.anyOf) ? node.anyOf : undefined;
|
||||||
|
if (list)
|
||||||
|
return list.filter(isRecord).filter((branch) => branch.type !== "null");
|
||||||
|
if (Array.isArray(node.type)) {
|
||||||
|
const { type: _types, ...rest } = node;
|
||||||
|
return node.type.filter((t) => t !== "null").map((t) => ({ ...rest, type: t }));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
function toValue(node) {
|
||||||
|
if (!isRecord(node))
|
||||||
|
return { type: "json" };
|
||||||
|
const branches = variants(node);
|
||||||
|
if (branches) {
|
||||||
|
if (branches.length === 0)
|
||||||
|
return withAnnotations(node, { type: "json" });
|
||||||
|
if (branches.length === 1)
|
||||||
|
return withAnnotations(node, toValue({ ...branches[0] }));
|
||||||
|
return withAnnotations(node, { oneOf: branches.map(toValue) });
|
||||||
|
}
|
||||||
|
const type = node.type;
|
||||||
|
if (type === "object" || type === undefined && isRecord(node.properties)) {
|
||||||
|
const out = {
|
||||||
|
type: "object",
|
||||||
|
additionalProperties: typeof node.additionalProperties === "boolean" ? node.additionalProperties : true
|
||||||
|
};
|
||||||
|
if (isRecord(node.properties))
|
||||||
|
out.properties = toProperties(node.properties, node.required);
|
||||||
|
return withAnnotations(node, out);
|
||||||
|
}
|
||||||
|
if (type === "array") {
|
||||||
|
const out = { type: "array" };
|
||||||
|
if (Object.hasOwn(node, "items"))
|
||||||
|
out.items = toValue(node.items);
|
||||||
|
return withAnnotations(node, out);
|
||||||
|
}
|
||||||
|
if (typeof type === "string" && SCALAR_TYPES.has(type)) {
|
||||||
|
const out = { type };
|
||||||
|
if (Array.isArray(node.enum) && node.enum.length > 0)
|
||||||
|
out.enum = node.enum;
|
||||||
|
if (Object.hasOwn(node, "const"))
|
||||||
|
out.const = node.const;
|
||||||
|
return withAnnotations(node, out);
|
||||||
|
}
|
||||||
|
return withAnnotations(node, { type: "json" });
|
||||||
|
}
|
||||||
|
function toProperties(properties, required) {
|
||||||
|
const requiredSet = new Set(Array.isArray(required) ? required.filter((k) => typeof k === "string") : []);
|
||||||
|
const out = {};
|
||||||
|
for (const [key, value] of Object.entries(properties)) {
|
||||||
|
const converted = toValue(value);
|
||||||
|
if (requiredSet.has(key))
|
||||||
|
converted.required = true;
|
||||||
|
out[key] = converted;
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
function parametersFromInputSchema(schema) {
|
||||||
|
if (!isRecord(schema) || !isRecord(schema.properties))
|
||||||
|
return {};
|
||||||
|
return toProperties(schema.properties, schema.required);
|
||||||
|
}
|
||||||
|
|
||||||
|
// src/netx/tools.ts
|
||||||
function packageVersion() {
|
function packageVersion() {
|
||||||
try {
|
try {
|
||||||
const here = dirname5(fileURLToPath2(import.meta.url));
|
const here = dirname5(fileURLToPath2(import.meta.url));
|
||||||
|
|
@ -1828,18 +1926,6 @@ var mcpOut = {
|
||||||
schema: { type: "object", additionalProperties: true },
|
schema: { type: "object", additionalProperties: true },
|
||||||
render: renderMcpResult
|
render: renderMcpResult
|
||||||
};
|
};
|
||||||
function parametersFromInputSchema(schema) {
|
|
||||||
if (schema && typeof schema === "object" && !Array.isArray(schema)) {
|
|
||||||
const props = schema.properties;
|
|
||||||
if (props && typeof props === "object" && !Array.isArray(props)) {
|
|
||||||
return props;
|
|
||||||
}
|
|
||||||
if (schema.type === undefined && schema.properties === undefined) {
|
|
||||||
return schema;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
function defineRemoteTool(tool2, timeoutMs) {
|
function defineRemoteTool(tool2, timeoutMs) {
|
||||||
const name = publicToolName(tool2.name);
|
const name = publicToolName(tool2.name);
|
||||||
return defineTool2({
|
return defineTool2({
|
||||||
|
|
|
||||||
|
|
@ -1803,6 +1803,104 @@ import { readFileSync as readFileSync5 } from "node:fs";
|
||||||
import { dirname as dirname5, join as join9 } from "node:path";
|
import { dirname as dirname5, join as join9 } from "node:path";
|
||||||
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
||||||
import { defineTool as defineTool2 } from "@deepseek-ai/dsh-tools";
|
import { defineTool as defineTool2 } from "@deepseek-ai/dsh-tools";
|
||||||
|
|
||||||
|
// src/netx/mcp-schema.ts
|
||||||
|
var ANNOTATIONS = ["description", "title", "default", "examples"];
|
||||||
|
var SCALAR_TYPES = new Set(["string", "number", "integer", "boolean", "null"]);
|
||||||
|
var CONSTRAINTS = [
|
||||||
|
"minimum",
|
||||||
|
"maximum",
|
||||||
|
"exclusiveMinimum",
|
||||||
|
"exclusiveMaximum",
|
||||||
|
"multipleOf",
|
||||||
|
"minLength",
|
||||||
|
"maxLength",
|
||||||
|
"pattern",
|
||||||
|
"format",
|
||||||
|
"minItems",
|
||||||
|
"maxItems",
|
||||||
|
"uniqueItems"
|
||||||
|
];
|
||||||
|
function isRecord(value) {
|
||||||
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
||||||
|
}
|
||||||
|
function withAnnotations(source, target) {
|
||||||
|
for (const key of ANNOTATIONS) {
|
||||||
|
if (Object.hasOwn(source, key))
|
||||||
|
target[key] = source[key];
|
||||||
|
}
|
||||||
|
const notes = CONSTRAINTS.filter((key) => Object.hasOwn(source, key)).map((key) => `${key}=${JSON.stringify(source[key])}`);
|
||||||
|
if (notes.length > 0) {
|
||||||
|
const base = typeof target.description === "string" ? target.description : "";
|
||||||
|
target.description = `${base}${base ? " " : ""}(${notes.join(", ")})`;
|
||||||
|
}
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
function variants(node) {
|
||||||
|
const list = Array.isArray(node.oneOf) ? node.oneOf : Array.isArray(node.anyOf) ? node.anyOf : undefined;
|
||||||
|
if (list)
|
||||||
|
return list.filter(isRecord).filter((branch) => branch.type !== "null");
|
||||||
|
if (Array.isArray(node.type)) {
|
||||||
|
const { type: _types, ...rest } = node;
|
||||||
|
return node.type.filter((t) => t !== "null").map((t) => ({ ...rest, type: t }));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
function toValue(node) {
|
||||||
|
if (!isRecord(node))
|
||||||
|
return { type: "json" };
|
||||||
|
const branches = variants(node);
|
||||||
|
if (branches) {
|
||||||
|
if (branches.length === 0)
|
||||||
|
return withAnnotations(node, { type: "json" });
|
||||||
|
if (branches.length === 1)
|
||||||
|
return withAnnotations(node, toValue({ ...branches[0] }));
|
||||||
|
return withAnnotations(node, { oneOf: branches.map(toValue) });
|
||||||
|
}
|
||||||
|
const type = node.type;
|
||||||
|
if (type === "object" || type === undefined && isRecord(node.properties)) {
|
||||||
|
const out = {
|
||||||
|
type: "object",
|
||||||
|
additionalProperties: typeof node.additionalProperties === "boolean" ? node.additionalProperties : true
|
||||||
|
};
|
||||||
|
if (isRecord(node.properties))
|
||||||
|
out.properties = toProperties(node.properties, node.required);
|
||||||
|
return withAnnotations(node, out);
|
||||||
|
}
|
||||||
|
if (type === "array") {
|
||||||
|
const out = { type: "array" };
|
||||||
|
if (Object.hasOwn(node, "items"))
|
||||||
|
out.items = toValue(node.items);
|
||||||
|
return withAnnotations(node, out);
|
||||||
|
}
|
||||||
|
if (typeof type === "string" && SCALAR_TYPES.has(type)) {
|
||||||
|
const out = { type };
|
||||||
|
if (Array.isArray(node.enum) && node.enum.length > 0)
|
||||||
|
out.enum = node.enum;
|
||||||
|
if (Object.hasOwn(node, "const"))
|
||||||
|
out.const = node.const;
|
||||||
|
return withAnnotations(node, out);
|
||||||
|
}
|
||||||
|
return withAnnotations(node, { type: "json" });
|
||||||
|
}
|
||||||
|
function toProperties(properties, required) {
|
||||||
|
const requiredSet = new Set(Array.isArray(required) ? required.filter((k) => typeof k === "string") : []);
|
||||||
|
const out = {};
|
||||||
|
for (const [key, value] of Object.entries(properties)) {
|
||||||
|
const converted = toValue(value);
|
||||||
|
if (requiredSet.has(key))
|
||||||
|
converted.required = true;
|
||||||
|
out[key] = converted;
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
function parametersFromInputSchema(schema) {
|
||||||
|
if (!isRecord(schema) || !isRecord(schema.properties))
|
||||||
|
return {};
|
||||||
|
return toProperties(schema.properties, schema.required);
|
||||||
|
}
|
||||||
|
|
||||||
|
// src/netx/tools.ts
|
||||||
function packageVersion() {
|
function packageVersion() {
|
||||||
try {
|
try {
|
||||||
const here = dirname5(fileURLToPath2(import.meta.url));
|
const here = dirname5(fileURLToPath2(import.meta.url));
|
||||||
|
|
@ -1828,18 +1926,6 @@ var mcpOut = {
|
||||||
schema: { type: "object", additionalProperties: true },
|
schema: { type: "object", additionalProperties: true },
|
||||||
render: renderMcpResult
|
render: renderMcpResult
|
||||||
};
|
};
|
||||||
function parametersFromInputSchema(schema) {
|
|
||||||
if (schema && typeof schema === "object" && !Array.isArray(schema)) {
|
|
||||||
const props = schema.properties;
|
|
||||||
if (props && typeof props === "object" && !Array.isArray(props)) {
|
|
||||||
return props;
|
|
||||||
}
|
|
||||||
if (schema.type === undefined && schema.properties === undefined) {
|
|
||||||
return schema;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
function defineRemoteTool(tool2, timeoutMs) {
|
function defineRemoteTool(tool2, timeoutMs) {
|
||||||
const name = publicToolName(tool2.name);
|
const name = publicToolName(tool2.name);
|
||||||
return defineTool2({
|
return defineTool2({
|
||||||
|
|
|
||||||
|
|
@ -1803,6 +1803,104 @@ import { readFileSync as readFileSync5 } from "node:fs";
|
||||||
import { dirname as dirname5, join as join9 } from "node:path";
|
import { dirname as dirname5, join as join9 } from "node:path";
|
||||||
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
||||||
import { defineTool as defineTool2 } from "@deepseek-ai/dsh-tools";
|
import { defineTool as defineTool2 } from "@deepseek-ai/dsh-tools";
|
||||||
|
|
||||||
|
// src/netx/mcp-schema.ts
|
||||||
|
var ANNOTATIONS = ["description", "title", "default", "examples"];
|
||||||
|
var SCALAR_TYPES = new Set(["string", "number", "integer", "boolean", "null"]);
|
||||||
|
var CONSTRAINTS = [
|
||||||
|
"minimum",
|
||||||
|
"maximum",
|
||||||
|
"exclusiveMinimum",
|
||||||
|
"exclusiveMaximum",
|
||||||
|
"multipleOf",
|
||||||
|
"minLength",
|
||||||
|
"maxLength",
|
||||||
|
"pattern",
|
||||||
|
"format",
|
||||||
|
"minItems",
|
||||||
|
"maxItems",
|
||||||
|
"uniqueItems"
|
||||||
|
];
|
||||||
|
function isRecord(value) {
|
||||||
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
||||||
|
}
|
||||||
|
function withAnnotations(source, target) {
|
||||||
|
for (const key of ANNOTATIONS) {
|
||||||
|
if (Object.hasOwn(source, key))
|
||||||
|
target[key] = source[key];
|
||||||
|
}
|
||||||
|
const notes = CONSTRAINTS.filter((key) => Object.hasOwn(source, key)).map((key) => `${key}=${JSON.stringify(source[key])}`);
|
||||||
|
if (notes.length > 0) {
|
||||||
|
const base = typeof target.description === "string" ? target.description : "";
|
||||||
|
target.description = `${base}${base ? " " : ""}(${notes.join(", ")})`;
|
||||||
|
}
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
function variants(node) {
|
||||||
|
const list = Array.isArray(node.oneOf) ? node.oneOf : Array.isArray(node.anyOf) ? node.anyOf : undefined;
|
||||||
|
if (list)
|
||||||
|
return list.filter(isRecord).filter((branch) => branch.type !== "null");
|
||||||
|
if (Array.isArray(node.type)) {
|
||||||
|
const { type: _types, ...rest } = node;
|
||||||
|
return node.type.filter((t) => t !== "null").map((t) => ({ ...rest, type: t }));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
function toValue(node) {
|
||||||
|
if (!isRecord(node))
|
||||||
|
return { type: "json" };
|
||||||
|
const branches = variants(node);
|
||||||
|
if (branches) {
|
||||||
|
if (branches.length === 0)
|
||||||
|
return withAnnotations(node, { type: "json" });
|
||||||
|
if (branches.length === 1)
|
||||||
|
return withAnnotations(node, toValue({ ...branches[0] }));
|
||||||
|
return withAnnotations(node, { oneOf: branches.map(toValue) });
|
||||||
|
}
|
||||||
|
const type = node.type;
|
||||||
|
if (type === "object" || type === undefined && isRecord(node.properties)) {
|
||||||
|
const out = {
|
||||||
|
type: "object",
|
||||||
|
additionalProperties: typeof node.additionalProperties === "boolean" ? node.additionalProperties : true
|
||||||
|
};
|
||||||
|
if (isRecord(node.properties))
|
||||||
|
out.properties = toProperties(node.properties, node.required);
|
||||||
|
return withAnnotations(node, out);
|
||||||
|
}
|
||||||
|
if (type === "array") {
|
||||||
|
const out = { type: "array" };
|
||||||
|
if (Object.hasOwn(node, "items"))
|
||||||
|
out.items = toValue(node.items);
|
||||||
|
return withAnnotations(node, out);
|
||||||
|
}
|
||||||
|
if (typeof type === "string" && SCALAR_TYPES.has(type)) {
|
||||||
|
const out = { type };
|
||||||
|
if (Array.isArray(node.enum) && node.enum.length > 0)
|
||||||
|
out.enum = node.enum;
|
||||||
|
if (Object.hasOwn(node, "const"))
|
||||||
|
out.const = node.const;
|
||||||
|
return withAnnotations(node, out);
|
||||||
|
}
|
||||||
|
return withAnnotations(node, { type: "json" });
|
||||||
|
}
|
||||||
|
function toProperties(properties, required) {
|
||||||
|
const requiredSet = new Set(Array.isArray(required) ? required.filter((k) => typeof k === "string") : []);
|
||||||
|
const out = {};
|
||||||
|
for (const [key, value] of Object.entries(properties)) {
|
||||||
|
const converted = toValue(value);
|
||||||
|
if (requiredSet.has(key))
|
||||||
|
converted.required = true;
|
||||||
|
out[key] = converted;
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
function parametersFromInputSchema(schema) {
|
||||||
|
if (!isRecord(schema) || !isRecord(schema.properties))
|
||||||
|
return {};
|
||||||
|
return toProperties(schema.properties, schema.required);
|
||||||
|
}
|
||||||
|
|
||||||
|
// src/netx/tools.ts
|
||||||
function packageVersion() {
|
function packageVersion() {
|
||||||
try {
|
try {
|
||||||
const here = dirname5(fileURLToPath2(import.meta.url));
|
const here = dirname5(fileURLToPath2(import.meta.url));
|
||||||
|
|
@ -1828,18 +1926,6 @@ var mcpOut = {
|
||||||
schema: { type: "object", additionalProperties: true },
|
schema: { type: "object", additionalProperties: true },
|
||||||
render: renderMcpResult
|
render: renderMcpResult
|
||||||
};
|
};
|
||||||
function parametersFromInputSchema(schema) {
|
|
||||||
if (schema && typeof schema === "object" && !Array.isArray(schema)) {
|
|
||||||
const props = schema.properties;
|
|
||||||
if (props && typeof props === "object" && !Array.isArray(props)) {
|
|
||||||
return props;
|
|
||||||
}
|
|
||||||
if (schema.type === undefined && schema.properties === undefined) {
|
|
||||||
return schema;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
function defineRemoteTool(tool2, timeoutMs) {
|
function defineRemoteTool(tool2, timeoutMs) {
|
||||||
const name = publicToolName(tool2.name);
|
const name = publicToolName(tool2.name);
|
||||||
return defineTool2({
|
return defineTool2({
|
||||||
|
|
|
||||||
110
lib/index.js
110
lib/index.js
|
|
@ -3217,7 +3217,7 @@ function watchNetxConnection(listener) {
|
||||||
// src/netx/session-export.ts
|
// src/netx/session-export.ts
|
||||||
import { homedir as homedir4, hostname as osHostname } from "node:os";
|
import { homedir as homedir4, hostname as osHostname } from "node:os";
|
||||||
|
|
||||||
// ../../netxops/node_modules/.pnpm/fflate@0.8.3/node_modules/fflate/esm/index.mjs
|
// node_modules/.pnpm/fflate@0.8.3/node_modules/fflate/esm/index.mjs
|
||||||
import { createRequire as createRequire3 } from "module";
|
import { createRequire as createRequire3 } from "module";
|
||||||
var require2 = createRequire3("/");
|
var require2 = createRequire3("/");
|
||||||
var _a;
|
var _a;
|
||||||
|
|
@ -4744,6 +4744,102 @@ function mcpContentText(content, fallback = "") {
|
||||||
`) || fallback;
|
`) || fallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// src/netx/mcp-schema.ts
|
||||||
|
var ANNOTATIONS = ["description", "title", "default", "examples"];
|
||||||
|
var SCALAR_TYPES = new Set(["string", "number", "integer", "boolean", "null"]);
|
||||||
|
var CONSTRAINTS = [
|
||||||
|
"minimum",
|
||||||
|
"maximum",
|
||||||
|
"exclusiveMinimum",
|
||||||
|
"exclusiveMaximum",
|
||||||
|
"multipleOf",
|
||||||
|
"minLength",
|
||||||
|
"maxLength",
|
||||||
|
"pattern",
|
||||||
|
"format",
|
||||||
|
"minItems",
|
||||||
|
"maxItems",
|
||||||
|
"uniqueItems"
|
||||||
|
];
|
||||||
|
function isRecord(value) {
|
||||||
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
||||||
|
}
|
||||||
|
function withAnnotations(source, target) {
|
||||||
|
for (const key of ANNOTATIONS) {
|
||||||
|
if (Object.hasOwn(source, key))
|
||||||
|
target[key] = source[key];
|
||||||
|
}
|
||||||
|
const notes = CONSTRAINTS.filter((key) => Object.hasOwn(source, key)).map((key) => `${key}=${JSON.stringify(source[key])}`);
|
||||||
|
if (notes.length > 0) {
|
||||||
|
const base = typeof target.description === "string" ? target.description : "";
|
||||||
|
target.description = `${base}${base ? " " : ""}(${notes.join(", ")})`;
|
||||||
|
}
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
function variants(node) {
|
||||||
|
const list = Array.isArray(node.oneOf) ? node.oneOf : Array.isArray(node.anyOf) ? node.anyOf : undefined;
|
||||||
|
if (list)
|
||||||
|
return list.filter(isRecord).filter((branch) => branch.type !== "null");
|
||||||
|
if (Array.isArray(node.type)) {
|
||||||
|
const { type: _types, ...rest } = node;
|
||||||
|
return node.type.filter((t) => t !== "null").map((t) => ({ ...rest, type: t }));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
function toValue(node) {
|
||||||
|
if (!isRecord(node))
|
||||||
|
return { type: "json" };
|
||||||
|
const branches = variants(node);
|
||||||
|
if (branches) {
|
||||||
|
if (branches.length === 0)
|
||||||
|
return withAnnotations(node, { type: "json" });
|
||||||
|
if (branches.length === 1)
|
||||||
|
return withAnnotations(node, toValue({ ...branches[0] }));
|
||||||
|
return withAnnotations(node, { oneOf: branches.map(toValue) });
|
||||||
|
}
|
||||||
|
const type = node.type;
|
||||||
|
if (type === "object" || type === undefined && isRecord(node.properties)) {
|
||||||
|
const out = {
|
||||||
|
type: "object",
|
||||||
|
additionalProperties: typeof node.additionalProperties === "boolean" ? node.additionalProperties : true
|
||||||
|
};
|
||||||
|
if (isRecord(node.properties))
|
||||||
|
out.properties = toProperties(node.properties, node.required);
|
||||||
|
return withAnnotations(node, out);
|
||||||
|
}
|
||||||
|
if (type === "array") {
|
||||||
|
const out = { type: "array" };
|
||||||
|
if (Object.hasOwn(node, "items"))
|
||||||
|
out.items = toValue(node.items);
|
||||||
|
return withAnnotations(node, out);
|
||||||
|
}
|
||||||
|
if (typeof type === "string" && SCALAR_TYPES.has(type)) {
|
||||||
|
const out = { type };
|
||||||
|
if (Array.isArray(node.enum) && node.enum.length > 0)
|
||||||
|
out.enum = node.enum;
|
||||||
|
if (Object.hasOwn(node, "const"))
|
||||||
|
out.const = node.const;
|
||||||
|
return withAnnotations(node, out);
|
||||||
|
}
|
||||||
|
return withAnnotations(node, { type: "json" });
|
||||||
|
}
|
||||||
|
function toProperties(properties, required) {
|
||||||
|
const requiredSet = new Set(Array.isArray(required) ? required.filter((k) => typeof k === "string") : []);
|
||||||
|
const out = {};
|
||||||
|
for (const [key, value] of Object.entries(properties)) {
|
||||||
|
const converted = toValue(value);
|
||||||
|
if (requiredSet.has(key))
|
||||||
|
converted.required = true;
|
||||||
|
out[key] = converted;
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
function parametersFromInputSchema(schema) {
|
||||||
|
if (!isRecord(schema) || !isRecord(schema.properties))
|
||||||
|
return {};
|
||||||
|
return toProperties(schema.properties, schema.required);
|
||||||
|
}
|
||||||
|
|
||||||
// src/netx/mcp-store.ts
|
// src/netx/mcp-store.ts
|
||||||
var STORE_KEY4 = Symbol.for("dsh-netxops.mcp-catalog-store");
|
var STORE_KEY4 = Symbol.for("dsh-netxops.mcp-catalog-store");
|
||||||
var EMPTY = Object.freeze({
|
var EMPTY = Object.freeze({
|
||||||
|
|
@ -4879,18 +4975,6 @@ var mcpOut = {
|
||||||
schema: { type: "object", additionalProperties: true },
|
schema: { type: "object", additionalProperties: true },
|
||||||
render: renderMcpResult
|
render: renderMcpResult
|
||||||
};
|
};
|
||||||
function parametersFromInputSchema(schema) {
|
|
||||||
if (schema && typeof schema === "object" && !Array.isArray(schema)) {
|
|
||||||
const props = schema.properties;
|
|
||||||
if (props && typeof props === "object" && !Array.isArray(props)) {
|
|
||||||
return props;
|
|
||||||
}
|
|
||||||
if (schema.type === undefined && schema.properties === undefined) {
|
|
||||||
return schema;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
function defineRemoteTool(tool2, timeoutMs) {
|
function defineRemoteTool(tool2, timeoutMs) {
|
||||||
const name = publicToolName(tool2.name);
|
const name = publicToolName(tool2.name);
|
||||||
return defineTool2({
|
return defineTool2({
|
||||||
|
|
|
||||||
104
src/netx/mcp-schema.ts
Normal file
104
src/netx/mcp-schema.ts
Normal file
|
|
@ -0,0 +1,104 @@
|
||||||
|
/**
|
||||||
|
* Convert netx MCP `inputSchema` (standard JSON Schema) into the DSH value
|
||||||
|
* schema DSL accepted by `defineTool({ parameters })`.
|
||||||
|
*
|
||||||
|
* The DSL is a strict subset: nodes allow only type / enum / const /
|
||||||
|
* properties / additionalProperties / items / oneOf plus annotations, and
|
||||||
|
* `required` is a per-property `true`. Range and size constraints
|
||||||
|
* (`minimum`, `maxItems`, ...) are folded into the description so the model
|
||||||
|
* still sees them; netx validates arguments server-side anyway.
|
||||||
|
*/
|
||||||
|
|
||||||
|
type Json = Record<string, unknown>
|
||||||
|
|
||||||
|
const ANNOTATIONS = ['description', 'title', 'default', 'examples'] as const
|
||||||
|
const SCALAR_TYPES = new Set(['string', 'number', 'integer', 'boolean', 'null'])
|
||||||
|
const CONSTRAINTS = [
|
||||||
|
'minimum',
|
||||||
|
'maximum',
|
||||||
|
'exclusiveMinimum',
|
||||||
|
'exclusiveMaximum',
|
||||||
|
'multipleOf',
|
||||||
|
'minLength',
|
||||||
|
'maxLength',
|
||||||
|
'pattern',
|
||||||
|
'format',
|
||||||
|
'minItems',
|
||||||
|
'maxItems',
|
||||||
|
'uniqueItems',
|
||||||
|
] as const
|
||||||
|
|
||||||
|
function isRecord(value: unknown): value is Json {
|
||||||
|
return typeof value === 'object' && value !== null && !Array.isArray(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
function withAnnotations(source: Json, target: Json): Json {
|
||||||
|
for (const key of ANNOTATIONS) {
|
||||||
|
if (Object.hasOwn(source, key)) target[key] = source[key]
|
||||||
|
}
|
||||||
|
const notes = CONSTRAINTS.filter(key => Object.hasOwn(source, key)).map(key => `${key}=${JSON.stringify(source[key])}`)
|
||||||
|
if (notes.length > 0) {
|
||||||
|
const base = typeof target.description === 'string' ? target.description : ''
|
||||||
|
target.description = `${base}${base ? ' ' : ''}(${notes.join(', ')})`
|
||||||
|
}
|
||||||
|
return target
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Branches of anyOf / oneOf / a type array, minus `null` (nullable = optional here). */
|
||||||
|
function variants(node: Json): Json[] | undefined {
|
||||||
|
const list = Array.isArray(node.oneOf) ? node.oneOf : Array.isArray(node.anyOf) ? node.anyOf : undefined
|
||||||
|
if (list) return list.filter(isRecord).filter(branch => branch.type !== 'null')
|
||||||
|
if (Array.isArray(node.type)) {
|
||||||
|
const { type: _types, ...rest } = node
|
||||||
|
return node.type.filter(t => t !== 'null').map(t => ({ ...rest, type: t }))
|
||||||
|
}
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
function toValue(node: unknown): Json {
|
||||||
|
if (!isRecord(node)) return { type: 'json' }
|
||||||
|
const branches = variants(node)
|
||||||
|
if (branches) {
|
||||||
|
if (branches.length === 0) return withAnnotations(node, { type: 'json' })
|
||||||
|
if (branches.length === 1) return withAnnotations(node, toValue({ ...branches[0] }))
|
||||||
|
return withAnnotations(node, { oneOf: branches.map(toValue) })
|
||||||
|
}
|
||||||
|
const type = node.type
|
||||||
|
if (type === 'object' || (type === undefined && isRecord(node.properties))) {
|
||||||
|
const out: Json = {
|
||||||
|
type: 'object',
|
||||||
|
additionalProperties: typeof node.additionalProperties === 'boolean' ? node.additionalProperties : true,
|
||||||
|
}
|
||||||
|
if (isRecord(node.properties)) out.properties = toProperties(node.properties, node.required)
|
||||||
|
return withAnnotations(node, out)
|
||||||
|
}
|
||||||
|
if (type === 'array') {
|
||||||
|
const out: Json = { type: 'array' }
|
||||||
|
if (Object.hasOwn(node, 'items')) out.items = toValue(node.items)
|
||||||
|
return withAnnotations(node, out)
|
||||||
|
}
|
||||||
|
if (typeof type === 'string' && SCALAR_TYPES.has(type)) {
|
||||||
|
const out: Json = { type }
|
||||||
|
if (Array.isArray(node.enum) && node.enum.length > 0) out.enum = node.enum
|
||||||
|
if (Object.hasOwn(node, 'const')) out.const = node.const
|
||||||
|
return withAnnotations(node, out)
|
||||||
|
}
|
||||||
|
return withAnnotations(node, { type: 'json' })
|
||||||
|
}
|
||||||
|
|
||||||
|
function toProperties(properties: Json, required: unknown): Json {
|
||||||
|
const requiredSet = new Set(Array.isArray(required) ? required.filter(k => typeof k === 'string') : [])
|
||||||
|
const out: Json = {}
|
||||||
|
for (const [key, value] of Object.entries(properties)) {
|
||||||
|
const converted = toValue(value)
|
||||||
|
if (requiredSet.has(key)) converted.required = true
|
||||||
|
out[key] = converted
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
/** `defineTool` parameters (a property map) from an MCP tool `inputSchema`. */
|
||||||
|
export function parametersFromInputSchema(schema: unknown): Json {
|
||||||
|
if (!isRecord(schema) || !isRecord(schema.properties)) return {}
|
||||||
|
return toProperties(schema.properties, schema.required)
|
||||||
|
}
|
||||||
|
|
@ -14,6 +14,7 @@ import { defineTool } from '@deepseek-ai/dsh-tools'
|
||||||
import type { NetxCapabilityGroupId, NetxCapabilityGroups } from './capability-groups.ts'
|
import type { NetxCapabilityGroupId, NetxCapabilityGroups } from './capability-groups.ts'
|
||||||
import { resolveEnabledTools } from './mcp-catalog.ts'
|
import { resolveEnabledTools } from './mcp-catalog.ts'
|
||||||
import { callMcpTool, mcpContentText, mcpEndpointUrl } from './mcp-remote.ts'
|
import { callMcpTool, mcpContentText, mcpEndpointUrl } from './mcp-remote.ts'
|
||||||
|
import { parametersFromInputSchema } from './mcp-schema.ts'
|
||||||
import { getMcpCatalogTools } from './mcp-store.ts'
|
import { getMcpCatalogTools } from './mcp-store.ts'
|
||||||
import { publicToolName, type NetxMcpToolDescriptor } from './mcp-types.ts'
|
import { publicToolName, type NetxMcpToolDescriptor } from './mcp-types.ts'
|
||||||
import { getNetxConnection } from './runtime.ts'
|
import { getNetxConnection } from './runtime.ts'
|
||||||
|
|
@ -73,24 +74,6 @@ const mcpOut = {
|
||||||
render: renderMcpResult,
|
render: renderMcpResult,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* `defineTool` expects a property map (DSH ParameterSchemaSpec), not a full
|
|
||||||
* JSON Schema document. MCP `inputSchema` is usually `{ type:'object', properties }`.
|
|
||||||
*/
|
|
||||||
function parametersFromInputSchema(schema: Record<string, unknown>): Record<string, unknown> {
|
|
||||||
if (schema && typeof schema === 'object' && !Array.isArray(schema)) {
|
|
||||||
const props = schema.properties
|
|
||||||
if (props && typeof props === 'object' && !Array.isArray(props)) {
|
|
||||||
return props as Record<string, unknown>
|
|
||||||
}
|
|
||||||
// Already a property map (legacy / odd servers).
|
|
||||||
if (schema.type === undefined && schema.properties === undefined) {
|
|
||||||
return schema
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {}
|
|
||||||
}
|
|
||||||
|
|
||||||
function defineRemoteTool(
|
function defineRemoteTool(
|
||||||
tool: NetxMcpToolDescriptor,
|
tool: NetxMcpToolDescriptor,
|
||||||
timeoutMs: number,
|
timeoutMs: number,
|
||||||
|
|
|
||||||
1990
test/fixtures-netx-mcp-tools.json
Normal file
1990
test/fixtures-netx-mcp-tools.json
Normal file
File diff suppressed because it is too large
Load diff
51
test/mcp-schema.test.mjs
Normal file
51
test/mcp-schema.test.mjs
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
import assert from 'node:assert/strict'
|
||||||
|
import { readFileSync } from 'node:fs'
|
||||||
|
import test from 'node:test'
|
||||||
|
import { defineTool } from '@deepseek-ai/dsh-tools'
|
||||||
|
import { parametersFromInputSchema } from '../src/netx/mcp-schema.ts'
|
||||||
|
|
||||||
|
const tools = JSON.parse(readFileSync(new URL('./fixtures-netx-mcp-tools.json', import.meta.url), 'utf8'))
|
||||||
|
|
||||||
|
function define(name, inputSchema) {
|
||||||
|
return defineTool({
|
||||||
|
name: `netx__${name}`,
|
||||||
|
description: name,
|
||||||
|
parameters: parametersFromInputSchema(inputSchema),
|
||||||
|
output: { schema: { type: 'object', additionalProperties: true }, render: () => [] },
|
||||||
|
async execute() {
|
||||||
|
return {}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
test('every real netx /mcp tool schema compiles in the DSH value schema DSL', () => {
|
||||||
|
assert.ok(tools.length >= 39)
|
||||||
|
for (const tool of tools) {
|
||||||
|
assert.doesNotThrow(() => define(tool.name, tool.inputSchema), tool.name)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
test('required, constraints and nullable unions survive conversion', () => {
|
||||||
|
const params = parametersFromInputSchema({
|
||||||
|
type: 'object',
|
||||||
|
required: ['ne_id'],
|
||||||
|
properties: {
|
||||||
|
ne_id: { type: 'string', description: 'NE id' },
|
||||||
|
page: { type: 'integer', minimum: 1, maximum: 50, default: 1 },
|
||||||
|
ids: { type: 'array', items: { type: 'string' }, maxItems: 20 },
|
||||||
|
filter: { type: 'object', required: ['k'], properties: { k: { type: 'string' } } },
|
||||||
|
maybe: { anyOf: [{ type: 'string' }, { type: 'null' }] },
|
||||||
|
either: { type: ['string', 'integer'] },
|
||||||
|
},
|
||||||
|
})
|
||||||
|
assert.equal(params.ne_id.required, true)
|
||||||
|
assert.equal(params.page.required, undefined)
|
||||||
|
assert.equal(params.page.minimum, undefined)
|
||||||
|
assert.match(params.page.description, /minimum=1, maximum=50/)
|
||||||
|
assert.match(params.ids.description, /maxItems=20/)
|
||||||
|
assert.equal(params.filter.additionalProperties, true)
|
||||||
|
assert.equal(params.filter.properties.k.required, true)
|
||||||
|
assert.equal(params.maybe.type, 'string')
|
||||||
|
assert.equal(params.either.oneOf.length, 2)
|
||||||
|
assert.doesNotThrow(() => define('sample', { type: 'object', properties: params }))
|
||||||
|
})
|
||||||
Loading…
Add table
Add a link
Reference in a new issue