@changfenhuang/dsh-genui 0.9.6 → 0.9.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -22,8 +22,11 @@ import type { ContentBlock } from '@deepseek-ai/dsh-llm'
22
22
  import type { JsonValue } from '@deepseek-ai/dsh-session'
23
23
  import type { GenericCallView, GenericResultView, JsonSchemaNode, ToolDefinition } from '@deepseek-ai/dsh-tools'
24
24
  import type { GenuiSpec } from '../client/spec.ts'
25
- import { GENUI_LIMITS, countDeclaredGenuiNodes, countGenuiNodes, repairGenuiSpec } from '../client/guard.ts'
25
+ import {
26
+ GENUI_LIMITS, countDeclaredGenuiNodes, countGenuiNodes, repairGenuiSpec,
27
+ } from '../client/guard.ts'
26
28
  import { completeFenceJson } from '../shared/fence-repair.ts'
29
+ import { validateRenderableChartSemantics } from './chart-contract.ts'
27
30
 
28
31
  /**
29
32
  * Arguments schema: an open `spec` slot. The schema must NOT reject anything
@@ -172,7 +175,12 @@ export function createRenderUiTool(): ToolDefinition {
172
175
  },
173
176
  },
174
177
  async execute(args: unknown): Promise<JsonValue> {
175
- const spec = repairGenuiSpec(specOf(args))
178
+ const input = specOf(args)
179
+ const chartErrors = validateRenderableChartSemantics(input)
180
+ if (chartErrors.length > 0) {
181
+ throw new Error('render_ui spec invalid: ' + chartErrors.join('; '))
182
+ }
183
+ const spec = repairGenuiSpec(input)
176
184
  if (spec === null) {
177
185
  return 'render_ui:spec 无效 —— 根对象需要 "items" 数组(组件树白名单见系统提示词),请修正后重试。'
178
186
  }
@@ -277,6 +285,12 @@ function bracketDiagnostic(raw: string): string {
277
285
  const COMMON_CAUSES =
278
286
  '常见原因:① 收尾括号错位/缺失({ 与 }、[ 与 ] 数量不相等)② 字符串值内用了半角引号 "(中文引语请用 “” 或 「」)③ 尾随逗号 ④ 字符串未闭合'
279
287
 
288
+ /** Return the model-facing chart field failure for one parsed fence body. */
289
+ function chartValidationFailure(value: unknown): string | undefined {
290
+ const errors = validateRenderableChartSemantics(value)
291
+ return errors.length === 0 ? undefined : `❌ chart 字段验证失败:\n- ${errors.join('\n- ')}`
292
+ }
293
+
280
294
  /** Build the validate_dsh_ui tool definition (registered alongside render_ui). */
281
295
  export function createValidateDshUiTool(): ToolDefinition {
282
296
  return {
@@ -304,11 +318,18 @@ export function createValidateDshUiTool(): ToolDefinition {
304
318
  // FIXED JSON instead of asking it to re-author the fix — re-writing
305
319
  // the whole fence by hand is where the next typo comes from.
306
320
  const repaired = completeFenceJson(raw)
307
- if (repaired !== null && repairGenuiSpec(JSON.parse(repaired.text) as unknown) !== null) {
308
- return `❌ dsh-ui 围栏 JSON 解析失败:${detail}。\n${bracketDiagnostic(raw)} 已自动修复 ${repaired.repairs} 处,下面是修复后的 JSON,直接作为围栏正文发出即可(无需再验证):\n\`\`\`\n${repaired.text}\n\`\`\``
321
+ if (repaired !== null) {
322
+ const repairedValue = JSON.parse(repaired.text) as unknown
323
+ const chartFailure = chartValidationFailure(repairedValue)
324
+ if (chartFailure !== undefined) return chartFailure
325
+ if (repairGenuiSpec(repairedValue) !== null) {
326
+ return `❌ dsh-ui 围栏 JSON 解析失败:${detail}。\n${bracketDiagnostic(raw)} 已自动修复 ${repaired.repairs} 处,下面是修复后的 JSON,直接作为围栏正文发出即可(无需再验证):\n\`\`\`\n${repaired.text}\n\`\`\``
327
+ }
309
328
  }
310
329
  return `❌ dsh-ui 围栏 JSON 解析失败:${detail}。\n${bracketDiagnostic(raw)} 自动修复未能恢复(结构损坏),请按错误信息修正后重新调用本工具验证,通过后再发出围栏。\n${COMMON_CAUSES}`
311
330
  }
331
+ const chartFailure = chartValidationFailure(parsed)
332
+ if (chartFailure !== undefined) return chartFailure
312
333
  const spec = repairGenuiSpec(parsed)
313
334
  if (spec === null) {
314
335
  return '❌ 不是合法 GenUI spec:根对象需要 "items" 数组,且每个节点 type 必须在白名单内(见系统提示词)。请修正后重新验证。'