fix(subagent): declare the dsh-scope dependency; make the re-assert REPLACE conflicting entries

ds-review-bot round-2 findings: (1) dsh-subagent's runtime import of
@deepseek-ai/dsh-scope was undeclared in its manifest and tsconfig
references (the root paths map masked it; the emitted package would import
an undeclared dependency) — wired as peer+dev with the project reference,
module graph regenerated. (2) The structured re-assert only ensured
PRESENCE, so a downstream listener injecting a same-named entry with the
wrong schema kept it model-visible while validateStructuredValue enforced
the real one; it now REPLACES any same-named tool/section with the run's
own. Pinned by a wrong-schema-injection test asserting exactly one entry
carrying the run's schema.
This commit is contained in:
Tianyi Cui
2026-07-09 05:21:06 +08:00
parent db6aed0459
commit e5093244fb
6 changed files with 48 additions and 7 deletions

View File

@@ -135,12 +135,18 @@ export function attachStructuredRuntime(childCtx: Context, schema: StructuredOut
this: unknown, _assembly: PromptAssembly, _context: AssembleContext, next: () => Promise<PromptAssembly>,
): Promise<PromptAssembly> {
const final = await next()
if (!final.tools.some(tool => tool.name === STRUCTURED_OUTPUT_TOOL)) {
final.tools = [...final.tools, { ...schemaEntry, parameters: structuredClone(schemaEntry.parameters) }]
}
if (!final.sections.some(section => section.name === `tool:${STRUCTURED_OUTPUT_TOOL}`)) {
final.sections = [...final.sections, { name: `tool:${STRUCTURED_OUTPUT_TOOL}`, order: 190, text: STRUCTURED_OUTPUT_INSTRUCTION }]
}
// REPLACE, not merely ensure-present: a downstream listener may have
// mutated or injected a same-named entry with the WRONG schema/text, and
// the model-visible demand must be exactly this run's own — the same
// schema validateStructuredValue enforces.
final.tools = [
...final.tools.filter(tool => tool.name !== STRUCTURED_OUTPUT_TOOL),
{ ...schemaEntry, parameters: structuredClone(schemaEntry.parameters) },
]
final.sections = [
...final.sections.filter(section => section.name !== `tool:${STRUCTURED_OUTPUT_TOOL}`),
{ name: `tool:${STRUCTURED_OUTPUT_TOOL}`, order: 190, text: STRUCTURED_OUTPUT_INSTRUCTION },
]
return final
}, { prepend: true })