cordis_define tool: plugin object parameter always fails oneOf validation (matched 0)
#1122
ProblemWhen calling Reproduction
Expected BehaviorThe Environment
|
Replies: 6 comments 2 replies
|
I think this is probably not a oneOf semantics problem itself, but an object-validation / Web realm boundary issue in 0.1.0-rc.6. There are two clues: your plugin value matches the first branch correctly: That makes the common denominator the nested object value, rather than the union itself. The current validator has explicit support for plain JSON values across JavaScript realms, and oneOf validation counts how many branches successfully validate: exactly 1 branch -> valid If the Web UI object is rejected before its properties are evaluated as a plain JSON record, both object branches fail and oneOf naturally reports: must match exactly one oneOf branch (matched 0) So the matched 0 message is likely the downstream symptom, not the root cause. There is also a useful confirmation in current master: the Web E2E Cordis test explicitly asks the model to call cordis_define with: plugin kind "new", idPrefix "snap" and asserts that cordis_inspect_self → cordis_define → cordis_run → cordis_stop all complete successfully in the real Web composition. In other words, this exact shape is expected to work in current source. I would test: npx @deepseek-ai/dsh@latest web or, from current source: git clone https://github.com/deepseek-ai/deepseek-harness.git Then retry the same call unchanged: { If it works on current master but still fails on 0.1.0-rc.6, that would strongly indicate this is an rc.6 Web/object-boundary regression. I would not remove the oneOf or change the plugin payload as a workaround, because the current cordis_define schema still intentionally uses the same discriminated oneOf: kind: "new" + idPrefix So your original payload shape looks correct. |
|
That payload looks valid against the current
I'd try the identical request against current main/latest first. If it still reproduces, logging the raw value immediately before schema validation should show whether its shape/prototype is being changed somewhere between the Web UI and the validator. |
|
I ran into the same thing on two machines (an Ubuntu server and my Windows laptop), and since the First, the tool declares its input as "input": { "description": "Optional query input; ..." }No Second, faced with an untyped field, the API layer emits the nested object as a JSON string. I confirmed this by replicating the validator locally: Third, nothing downstream compensates. One thing though — I don't think the Scope seems contained, at least: I scanned the shipped Something that works as a local stopgap — a defensive re-parse in async execute(args, exec) {
- const data = await ctx.cordisInspect.query(args.platform, args.provider, args.method, args.input, requireAgent(exec), exec.signal);
+ let input = args.input;
+ if (typeof input === "string") {
+ try { input = JSON.parse(input); } catch { /* fall through */ }
+ }
+ const data = await ctx.cordisInspect.query(args.platform, args.provider, args.method, input, requireAgent(exec), exec.signal);
return {Parse failures fall through to the normal validator error, so malformed strings still get reported properly. Longer term, giving Caveat: both my machines route through the DeepSeek endpoint, so no idea whether other routes behave differently. |
|
Thanks, that distinction is convincing. :) The defensive parse is a useful stopgap for |
|
Update: working fix at In both async execute(args, exec) {
function _coerceArgs(val) {
if (typeof val === "string") {
if (val.charCodeAt(0) === 123 || val.charCodeAt(0) === 91) {
try { return JSON.parse(val); } catch { return val; }
}
return val;
}
if (Array.isArray(val)) return val.map(_coerceArgs);
if (val !== null && typeof val === "object") {
const out = {};
for (const k of Object.keys(val)) out[k] = _coerceArgs(val[k]);
return out;
}
return val;
}
const coerced = _coerceArgs(args);
const violations = validate(coerced);
if (violations.length > 0) throw new ToolArgsError(violations);
return userExecute(coerced, exec);
}The original Tested on |
|
That confirms the failure boundary. The I would avoid recursively The safer fix is either to preserve nested JSON values in the Web/tool-call transport, or make any compatibility coercion schema-guided so it only applies where the declared schema expects an object, array, JSON value, or matching I would also add a Web-path regression covering both |
Update: working fix at
defineToollevel indsh-toolsIn both
dsh-tools/lib/index.jsanddsh-tools/lib/types/schema.js, replace theexecutewrapper insidedefineToolwith: