dsh-motion-ui 0.5.6 → 0.6.0
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.
- package/CHANGELOG.md +55 -0
- package/README.md +76 -4
- package/VERIFICATION.md +109 -0
- package/client.js +3764 -22300
- package/index.js +107 -81
- package/lib/assets/echarts-core.js +47 -0
- package/lib/assets/echarts-full.js +78 -0
- package/lib/assets/katex-fonts/KaTeX_AMS-Regular.woff2 +0 -0
- package/lib/assets/katex-fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
- package/lib/assets/katex-fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
- package/lib/assets/katex-fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
- package/lib/assets/katex-fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
- package/lib/assets/katex-fonts/KaTeX_Main-Bold.woff2 +0 -0
- package/lib/assets/katex-fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
- package/lib/assets/katex-fonts/KaTeX_Main-Italic.woff2 +0 -0
- package/lib/assets/katex-fonts/KaTeX_Main-Regular.woff2 +0 -0
- package/lib/assets/katex-fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
- package/lib/assets/katex-fonts/KaTeX_Math-Italic.woff2 +0 -0
- package/lib/assets/katex-fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
- package/lib/assets/katex-fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
- package/lib/assets/katex-fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
- package/lib/assets/katex-fonts/KaTeX_Script-Regular.woff2 +0 -0
- package/lib/assets/katex-fonts/KaTeX_Size1-Regular.woff2 +0 -0
- package/lib/assets/katex-fonts/KaTeX_Size2-Regular.woff2 +0 -0
- package/lib/assets/katex-fonts/KaTeX_Size3-Regular.woff2 +0 -0
- package/lib/assets/katex-fonts/KaTeX_Size4-Regular.woff2 +0 -0
- package/lib/assets/katex-fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
- package/lib/assets/katex.css +1 -0
- package/lib/assets/mermaid.js +3644 -0
- package/lib/assets/standalone-runtime.css +1 -0
- package/lib/assets/standalone-runtime.js +328 -0
- package/lib/assets/three.js +3842 -0
- package/lib/assets/visual.css +1 -0
- package/lib/assets/visual.js +414 -0
- package/lib/authoring-guide.js +2 -2
- package/lib/build-info.js +1 -1
- package/lib/canvas-system.js +3 -3
- package/lib/catalog.js +94 -92
- package/lib/components.js +9 -4
- package/lib/delivery.js +18 -0
- package/lib/diagnostics-route.js +6 -0
- package/lib/document-update.js +27 -0
- package/lib/export-runtime-bundle.js +1 -1
- package/lib/fence-feedback.js +61 -0
- package/lib/fence-route.js +14 -0
- package/lib/fences.js +9 -0
- package/lib/freeform.js +1 -1
- package/lib/inspection.js +3 -2
- package/lib/links.js +13 -0
- package/lib/normalize-authoring.js +46 -1
- package/lib/normalize-visual.js +36 -0
- package/lib/presentation.js +1 -1
- package/lib/protocol.js +348 -320
- package/lib/scene-library.js +13 -0
- package/lib/store.js +17 -2
- package/lib/stream.js +12 -0
- package/lib/text-document.js +25 -0
- package/lib/text-guide.js +13 -0
- package/lib/third-party/bundled/@braintree_sanitize-url-LICENSE +21 -0
- package/lib/third-party/bundled/@iconify_utils-license.txt +21 -0
- package/lib/third-party/bundled/@mermaid-js_parser-LICENSE +21 -0
- package/lib/third-party/bundled/@upsetjs_venn.js-LICENSE +22 -0
- package/lib/third-party/bundled/cose-base-LICENSE +21 -0
- package/lib/third-party/bundled/cytoscape-LICENSE +19 -0
- package/lib/third-party/bundled/cytoscape-cose-bilkent-LICENSE +21 -0
- package/lib/third-party/bundled/cytoscape-fcose-LICENSE +19 -0
- package/lib/third-party/bundled/cytoscape-license-update.mjs +32 -0
- package/lib/third-party/bundled/d3-LICENSE +13 -0
- package/lib/third-party/bundled/d3-array-LICENSE +27 -0
- package/lib/third-party/bundled/d3-axis-LICENSE +13 -0
- package/lib/third-party/bundled/d3-brush-LICENSE +13 -0
- package/lib/third-party/bundled/d3-chord-LICENSE +13 -0
- package/lib/third-party/bundled/d3-color-LICENSE +13 -0
- package/lib/third-party/bundled/d3-contour-LICENSE +13 -0
- package/lib/third-party/bundled/d3-delaunay-LICENSE +14 -0
- package/lib/third-party/bundled/d3-dispatch-LICENSE +13 -0
- package/lib/third-party/bundled/d3-drag-LICENSE +13 -0
- package/lib/third-party/bundled/d3-dsv-LICENSE +13 -0
- package/lib/third-party/bundled/d3-ease-LICENSE +28 -0
- package/lib/third-party/bundled/d3-fetch-LICENSE +13 -0
- package/lib/third-party/bundled/d3-force-LICENSE +13 -0
- package/lib/third-party/bundled/d3-format-LICENSE +13 -0
- package/lib/third-party/bundled/d3-geo-LICENSE +34 -0
- package/lib/third-party/bundled/d3-hierarchy-LICENSE +13 -0
- package/lib/third-party/bundled/d3-interpolate-LICENSE +13 -0
- package/lib/third-party/bundled/d3-path-LICENSE +27 -0
- package/lib/third-party/bundled/d3-polygon-LICENSE +13 -0
- package/lib/third-party/bundled/d3-quadtree-LICENSE +13 -0
- package/lib/third-party/bundled/d3-random-LICENSE +13 -0
- package/lib/third-party/bundled/d3-sankey-LICENSE +27 -0
- package/lib/third-party/bundled/d3-scale-LICENSE +13 -0
- package/lib/third-party/bundled/d3-scale-chromatic-LICENSE +28 -0
- package/lib/third-party/bundled/d3-selection-LICENSE +13 -0
- package/lib/third-party/bundled/d3-shape-LICENSE +13 -0
- package/lib/third-party/bundled/d3-time-LICENSE +13 -0
- package/lib/third-party/bundled/d3-time-format-LICENSE +13 -0
- package/lib/third-party/bundled/d3-timer-LICENSE +13 -0
- package/lib/third-party/bundled/d3-transition-LICENSE +13 -0
- package/lib/third-party/bundled/d3-zoom-LICENSE +13 -0
- package/lib/third-party/bundled/dagre-d3-es-LICENSE.md +23 -0
- package/lib/third-party/bundled/dayjs-LICENSE +21 -0
- package/lib/third-party/bundled/delaunator-LICENSE +15 -0
- package/lib/third-party/bundled/dompurify-LICENSE +202 -0
- package/lib/third-party/bundled/dompurify-LICENSE-MPL +373 -0
- package/lib/third-party/bundled/echarts-LICENSE +222 -0
- package/lib/third-party/bundled/echarts-NOTICE +5 -0
- package/lib/third-party/bundled/es-toolkit-LICENSE +21 -0
- package/lib/third-party/bundled/es-toolkit-NOTICE +39 -0
- package/lib/third-party/bundled/internmap-LICENSE +13 -0
- package/lib/third-party/bundled/katex-LICENSE +21 -0
- package/lib/third-party/bundled/khroma-license +21 -0
- package/lib/third-party/bundled/layout-base-LICENSE +21 -0
- package/lib/third-party/bundled/lodash-es-LICENSE +47 -0
- package/lib/third-party/bundled/marked-LICENSE.md +44 -0
- package/lib/third-party/bundled/mermaid-LICENSE +21 -0
- package/lib/third-party/bundled/react-LICENSE +21 -0
- package/lib/third-party/bundled/react-dom-LICENSE +21 -0
- package/lib/third-party/bundled/robust-predicates-LICENSE +24 -0
- package/lib/third-party/bundled/roughjs-LICENSE +21 -0
- package/lib/third-party/bundled/scheduler-LICENSE +21 -0
- package/lib/third-party/bundled/stylis-LICENSE +21 -0
- package/lib/third-party/bundled/three-LICENSE +21 -0
- package/lib/third-party/bundled/ts-dedent-LICENSE +21 -0
- package/lib/third-party/bundled/tslib-LICENSE.txt +12 -0
- package/lib/third-party/bundled/uuid-LICENSE.md +9 -0
- package/lib/third-party/bundled/zrender-LICENSE +29 -0
- package/lib/third-party/dsh-genui-LICENSE.txt +21 -0
- package/lib/third-party/dsh-genui-NOTICE.md +26 -0
- package/lib/third-party/echarts-LICENSE.txt +222 -0
- package/lib/third-party/echarts-NOTICE.txt +5 -0
- package/lib/third-party/katex-LICENSE.txt +21 -0
- package/lib/third-party/mermaid-LICENSE.txt +21 -0
- package/lib/third-party/three-LICENSE.txt +21 -0
- package/lib/tool-schema.js +17 -6
- package/lib/typography.js +16 -0
- package/lib/ui-intent.js +15 -14
- package/lib/ui-skill.js +53 -47
- package/lib/visual-assets.js +7 -0
- package/lib/visual-defaults.js +2 -0
- package/lib/visual-guard.js +2 -0
- package/lib/visual-styles.js +30 -0
- package/lib/visual.js +40 -0
- package/package.json +92 -77
- package/skills/intelligent-ui/SKILL.md +103 -96
package/index.js
CHANGED
|
@@ -1,83 +1,109 @@
|
|
|
1
|
-
import { defineTool } from '@deepseek-ai/dsh-tools';
|
|
2
|
-
import { dshHomePath } from '@deepseek-ai/dsh-home-paths';
|
|
3
|
-
import { validateDocument, fallbackText } from './lib/protocol.js';
|
|
4
|
-
import { UiStore, stateRoute, documentRoute, historyRoute } from './lib/store.js';
|
|
5
|
-
import { evaluate } from './lib/protocol.js';
|
|
6
|
-
import { componentCatalog } from './lib/components.js';
|
|
7
|
-
import { CANVAS_DESIGN_GUIDE } from './lib/canvas-design.js';
|
|
8
|
-
import { architectureExample, scatterExample } from './lib/visual-examples.js';
|
|
9
|
-
import { BUILD_INFO } from './lib/build-info.js';
|
|
10
|
-
import { UI_SKILL_SECTIONS, promptSections } from './lib/ui-skill.js';
|
|
11
|
-
import {
|
|
12
|
-
import
|
|
13
|
-
import
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
async execute({
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
}
|
|
69
|
-
})));
|
|
70
|
-
ctx.effect(()
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
1
|
+
import { defineTool } from '@deepseek-ai/dsh-tools';
|
|
2
|
+
import { dshHomePath } from '@deepseek-ai/dsh-home-paths';
|
|
3
|
+
import { validateDocument, fallbackText } from './lib/protocol.js';
|
|
4
|
+
import { UiStore, stateRoute, documentRoute, historyRoute } from './lib/store.js';
|
|
5
|
+
import { evaluate } from './lib/protocol.js';
|
|
6
|
+
import { componentCatalog } from './lib/components.js';
|
|
7
|
+
import { CANVAS_DESIGN_GUIDE } from './lib/canvas-design.js';
|
|
8
|
+
import { architectureExample, scatterExample } from './lib/visual-examples.js';
|
|
9
|
+
import { BUILD_INFO } from './lib/build-info.js';
|
|
10
|
+
import { UI_SKILL_SECTIONS, promptSections } from './lib/ui-skill.js';
|
|
11
|
+
import {DEFAULT_VISUAL_STYLE,VISUAL_STYLE_IDS} from './lib/visual-styles.js';
|
|
12
|
+
import { canvasDocument } from './lib/freeform.js';
|
|
13
|
+
import z from '@deepseek-ai/schemastery';
|
|
14
|
+
import { toolJson } from './lib/tool-json.js';
|
|
15
|
+
import { DOCUMENT_PARAMETER,TEXT_BLOCKS_PARAMETER } from './lib/tool-schema.js';
|
|
16
|
+
import {textDocument} from './lib/text-document.js';
|
|
17
|
+
import {TEXT_PRESETS} from './lib/typography.js';
|
|
18
|
+
import { inspectRecord } from './lib/inspection.js';
|
|
19
|
+
import {QUICK_EXAMPLES,QUICK_GUIDE} from './lib/quick-examples.js';
|
|
20
|
+
import { PROTOCOL_GUIDE, calculatorExample, comparisonExample, budgetExample, curveExample, sceneExamples, bicycleExample, oscillatorExample } from './lib/catalog.js';
|
|
21
|
+
import {VISUAL_GUIDE,VISUAL_EXAMPLES,visualCatalog} from './lib/visual.js';
|
|
22
|
+
import {registerVisualAssets} from './lib/visual-assets.js';
|
|
23
|
+
import {diagnosticsRoute} from './lib/diagnostics-route.js';
|
|
24
|
+
import {fenceRoute} from './lib/fence-route.js';
|
|
25
|
+
import {sceneCatalog,SCENE_GUIDE} from './lib/scene-library.js';
|
|
26
|
+
import {registerFenceFeedback} from './lib/fence-feedback.js';
|
|
27
|
+
import {diagnoseDelivery,deliveryDiagnostics} from './lib/delivery.js';
|
|
28
|
+
|
|
29
|
+
export const name = 'motion-ui';
|
|
30
|
+
export const inject = ['tools', 'connection', 'systemPrompt'];
|
|
31
|
+
function defineRenderTool(options) {
|
|
32
|
+
const tool=defineTool(options),execute=tool.execute;
|
|
33
|
+
return {...tool,async execute(args,exec){
|
|
34
|
+
// Legacy adapters may stringify JSON. Decode here, without advertising a
|
|
35
|
+
// string branch that encourages models to manually escape whole documents.
|
|
36
|
+
// Canonicalize adapter quirks before native schema checks, so a lossless
|
|
37
|
+
// items:{item:[...]} wrapper receives the same treatment as stored/replayed UI.
|
|
38
|
+
const normalized=args&&Object.hasOwn(args,'document')?{...args,document:validateDocument(toolJson(args.document,'document'))}:args&&Object.hasOwn(args,'blocks')?{...args,blocks:textDocument({...args,blocks:toolJson(args.blocks,'blocks')}).nodes}:args;
|
|
39
|
+
return execute(normalized,exec);
|
|
40
|
+
}};
|
|
41
|
+
}
|
|
42
|
+
export const Config=z.object({autoRepair:z.boolean().default(true).description('自动反馈无法交付的 UI 围栏、渲染失败及仅思考没有正文或工具的空交付,最多两次去重提醒;不限制模型思考。'),visualStyle:z.union(VISUAL_STYLE_IDS).default(DEFAULT_VISUAL_STYLE).description('引导模式的视觉风格;同步原生组件外观、风格提示词与案例,自由模式不应用。'),defaultPreset:z.union(TEXT_PRESETS).default('reading').description('兼容旧配置的保留字段,已停用;排版由模型按内容选择。'),designMode:z.union(['guided','free']).default('guided').description('guided:设计技能与示例引导;free:只注入画布接口与交互约束,由模型自主设计。'),displayMode:z.union(['tail','inline','sidebar']).default('inline').description('兼容旧配置的保留字段,已停用;统一使用正文标记,侧栏随时可打开。'),showDetails:z.boolean().default(false).description('显示参数状态、原始说明、视觉诊断和版本历史。默认关闭,保持界面简洁。')}).volatile();
|
|
43
|
+
export function apply(ctx,config={}) {
|
|
44
|
+
const store = new UiStore(dshHomePath('plugins', 'dsh-generative-ui'));
|
|
45
|
+
const settings=()=>typeof config.get==='function'?config.get():config;
|
|
46
|
+
const feedback=registerFenceFeedback(ctx,()=>settings().autoRepair!==false);
|
|
47
|
+
const placement=value=>`\nPlace this exact fenced marker in your answer at the intended UI position:\n\`\`\`dsh-ui\n${value.documentId}\n\`\`\``;
|
|
48
|
+
ctx.effect(()=>ctx.tools.register(defineRenderTool({
|
|
49
|
+
name:'render_text',description:'Quickly format everyday answers as readable native text, small comparisons, lists, callouts or link buttons. No HTML/CSS/script needed. Multiple calls in one answer create independent UIs; use separate successful IDs for inline markers. blocks accepts plain strings or native v1 nodes with optional IDs; a text block is {type:"text",text:"Your content"}. Extended title/items visuals use render_ui instead. Text supports size/weight/color/align/lineHeight and spans for inline emphasis. Prefer this short path for ordinary structured explanations.',
|
|
50
|
+
parameters:{title:{type:'string'},preset:{type:'string',enum:TEXT_PRESETS},accent:{type:'string',enum:['blue','teal','violet','amber','rose']},blocks:TEXT_BLOCKS_PARAMETER},
|
|
51
|
+
output:{schema:{type:'json'},render:(_a,v)=>[{type:'text',text:v.document.fallback+`\nUI documentId=${v.documentId}; documentRevision=${v.documentRevision??0}.`+placement(v)}],presentationMeta:(_a,v)=>({dshGenerativeUi:v})},
|
|
52
|
+
async execute(args,exec){exec.signal.throwIfAborted();for(const key of Object.keys(args))if(!['title','preset','accent','blocks'].includes(key))throw Error(`DSH UI: unknown render_text argument ${key}; put all content/styling inside blocks or children`);const document=textDocument({...args,blocks:toolJson(args.blocks,'blocks'),preset:args.preset??'reading'});fallbackText(document);const record=await store.create(document,{sessionId:exec.agent?.id??'unscoped',callId:exec.callId});exec.signal.throwIfAborted();return record;}
|
|
53
|
+
})));
|
|
54
|
+
ctx.effect(() => ctx.tools.register(defineRenderTool({
|
|
55
|
+
name: 'render_ui',
|
|
56
|
+
description: 'Render a static or interactive DSH UI v1 document in this conversation. Proactively use when visual relationships or changing parameters clearly explain the question better, even without an explicit UI request. For everyday styled text use render_text; simple facts can stay plain text. Deliver the smallest complete useful UI first. ui_catalog supplies optional details. Direct native calls only; PTC returns text. Calculations stay local. document accepts v1 {version:1,title,fallback,nodes} OR extended {title,items:[components]} for charts, plots, quiz, forms, diagrams and media. Repair errors at most twice or simplify/answer in text.',
|
|
57
|
+
parameters: { document: DOCUMENT_PARAMETER },
|
|
58
|
+
output: {
|
|
59
|
+
schema: { type: 'json' },
|
|
60
|
+
render: (_args, value) => [{ type: 'text', text: fallbackText(value.document)+`\nUI documentId=${value.documentId}; documentRevision=${value.documentRevision??0}. Use inspect_ui before refinements.`+placement(value)+(deliveryDiagnostics(value.document).length?'\nPARTIAL DELIVERY: '+JSON.stringify(deliveryDiagnostics(value.document))+'\nCorrect the rejected components using update_ui rather than generating another copy.':'') }],
|
|
61
|
+
presentationMeta: (_args, value) => ({ dshGenerativeUi: value })
|
|
62
|
+
},
|
|
63
|
+
async execute({ document }, exec) {
|
|
64
|
+
exec.signal.throwIfAborted();
|
|
65
|
+
const validated = validateDocument(toolJson(document,'document')); fallbackText(validated);
|
|
66
|
+
const record = await store.create(validated, { sessionId: exec.agent?.id ?? 'unscoped', callId: exec.callId });
|
|
67
|
+
exec.signal.throwIfAborted(); return record;
|
|
68
|
+
}
|
|
69
|
+
})));
|
|
70
|
+
ctx.effect(()=>ctx.tools.register(defineTool({
|
|
71
|
+
name:'render_canvas',description:'Create a static or interactive HTML/SVG/CSS/JavaScript canvas in the conversation. You design all content, controls, layout and motion. No fixed UI composition. Same persistence, isolation and inspect/patch support as render_ui. Use the injected canvas contract; no external resources or host APIs. Direct native calls only.',
|
|
72
|
+
parameters:{title:{type:'string',required:true},fallback:{type:'string',required:true},state:{type:'json'},data:{type:'json'},derived:{type:'json'},height:{type:'number'},css:{type:'string',description:'Canvas CSS; use an empty string when no custom styles are needed. Styled static previews appear progressively; interaction activates after the assistant turn ends.'},html:{type:'string',required:true},script:{type:'string'}},
|
|
73
|
+
output:{schema:{type:'json'},render:(_a,v)=>[{type:'text',text:fallbackText(v.document)+`\nUI documentId=${v.documentId}; documentRevision=${v.documentRevision??0}; canvas nodeId=canvas.`+placement(v)}],presentationMeta:(_a,v)=>({dshGenerativeUi:v})},
|
|
74
|
+
async execute(args,exec){exec.signal.throwIfAborted();const record=await store.create(canvasDocument(args),{sessionId:exec.agent?.id??'unscoped',callId:exec.callId});exec.signal.throwIfAborted();return record;}
|
|
75
|
+
})));
|
|
76
|
+
ctx.effect(() => ctx.tools.register(defineTool({
|
|
77
|
+
name: 'ui_catalog', description: 'Read the DSH UI protocol and registered components. Optional topic: templates (eight short scene summaries; add scene to retrieve one), visual (extended component fields), overview (default, compact static examples), quick (four minimal static examples), canvas (freeform design guide and four visual examples), data, scenes, all (fourteen examples). Prefer targeted topics to avoid unnecessary context. Read-only; omit for ordinary text answers.',
|
|
78
|
+
parameters: { topic: { type: 'string', enum: ['overview', 'quick', 'visual', 'templates', 'canvas', 'data', 'scenes', 'all'], description: 'overview, quick (four lightweight static layouts), canvas, data, scenes or all; default overview' },scene:{type:'string',description:'templates only: brief, comparison, flow, dashboard, quiz, form, plot, diagram'} }, output: { schema: { type: 'json' }, render: (_args, value) => [{ type: 'text', text: JSON.stringify(value) }] },
|
|
79
|
+
isConcurrencySafe: () => true,
|
|
80
|
+
async execute({ topic = 'overview',scene } = {}) {
|
|
81
|
+
if(topic==='templates')return sceneCatalog(scene);
|
|
82
|
+
const groups = { overview: [calculatorExample, oscillatorExample], canvas: [bicycleExample, oscillatorExample, architectureExample, scatterExample], data: [calculatorExample, comparisonExample, budgetExample, curveExample, scatterExample], scenes: sceneExamples, all: [calculatorExample, comparisonExample, budgetExample, curveExample, ...sceneExamples, bicycleExample, oscillatorExample, architectureExample, scatterExample] };
|
|
83
|
+
groups.quick=QUICK_EXAMPLES;groups.overview=QUICK_EXAMPLES.slice(0,2);
|
|
84
|
+
groups.visual=VISUAL_EXAMPLES;
|
|
85
|
+
if (!Object.hasOwn(groups, topic)) throw new Error('Unknown ui_catalog topic; use templates, overview, quick, visual, canvas, data, scenes or all');
|
|
86
|
+
if(topic==='visual')return{build:BUILD_INFO,topic,protocol:VISUAL_GUIDE,components:visualCatalog(),examples:VISUAL_EXAMPLES};
|
|
87
|
+
return { build: BUILD_INFO, topic, protocol: PROTOCOL_GUIDE, components: componentCatalog(), design: topic === 'quick' ? QUICK_GUIDE : topic === 'canvas' || topic === 'all' ? CANVAS_DESIGN_GUIDE : 'Choose composition by the question: editorial reading, technical relationships, analytical data, exploratory objects, aligned comparisons or ordered instruction. Keep theme, accessible labels and readable Chinese. Use topic=canvas for the full visual design guide.', examples: groups[topic] };
|
|
88
|
+
}
|
|
89
|
+
})));
|
|
90
|
+
ctx.effect(() => ctx.connection.fetch.register({ path: '/api/plugins/dsh-generative-ui/state', methods: ['GET', 'POST'], requestBody: 'buffered', fetch: stateRoute(store) }));
|
|
91
|
+
ctx.effect(() => ctx.connection.fetch.register({ path: '/api/plugins/dsh-generative-ui/document', methods: ['GET', 'POST'], requestBody: 'buffered', fetch: documentRoute(store) }));
|
|
92
|
+
ctx.effect(() => ctx.connection.fetch.register({ path: '/api/plugins/dsh-generative-ui/history', methods: ['GET', 'POST'], requestBody: 'buffered', fetch: historyRoute(store) }));
|
|
93
|
+
registerVisualAssets(ctx);
|
|
94
|
+
ctx.effect(()=>ctx.connection.fetch.register({path:'/api/plugins/dsh-generative-ui/diagnostics',methods:['GET'],requestBody:'buffered',fetch:diagnosticsRoute(feedback)}));
|
|
95
|
+
ctx.effect(()=>ctx.connection.fetch.register({path:'/api/plugins/dsh-generative-ui/fence',methods:['POST'],requestBody:'buffered',fetch:fenceRoute(store)}));
|
|
96
|
+
ctx.effect(()=>ctx.tools.register(defineTool({name:'validate_ui',description:'Read-only validation for Motion UI v1 or extended title/items visuals. Returns valid, complete, canonical document and precise diagnostics without saving or displaying a UI. valid=true with complete=false means rejected components, not complete delivery. Use when unsure about a complex schema; ordinary minimal UIs can render directly.',parameters:{document:{type:'json',required:true}},output:{schema:{type:'json'},render:(_a,v)=>[{type:'text',text:JSON.stringify(v)}]},isConcurrencySafe:()=>true,async execute({document}){try{const report=diagnoseDelivery(toolJson(document,'document'));return {...report,...(report.valid?{fallback:fallbackText(report.document)}:{error:report.diagnostics[0].message})}}catch(e){return{valid:false,complete:false,error:e.message}}}})));
|
|
97
|
+
ctx.effect(()=>ctx.tools.register(defineTool({
|
|
98
|
+
name:'inspect_ui',description:'Read the current UI revision, saved state/derived and heuristic visual observations. Default summary omits source. Use detail=nodes to read exact nodes before code edits; omitted nodeIds selects the first 16 nodes, or full only when needed. No report means unobserved, not a pass. Do not poll empty reports; automatic repair is at most two rounds per user request.',
|
|
99
|
+
parameters:{documentId:{type:'string',required:true},detail:{type:'string',enum:['summary','nodes','full']},nodeIds:{type:'json',description:'For nodes detail: up to 16 existing node IDs.'}},
|
|
100
|
+
output:{schema:{type:'json'},render:(_args,value)=>[{type:'text',text:JSON.stringify(value)}]},isConcurrencySafe:()=>true,
|
|
101
|
+
async execute({documentId,detail='summary',nodeIds=[]},exec){const record=await store.owned(documentId,exec.agent?.id);const saved=await store.readState(documentId,record.sessionId);return inspectRecord(record,saved.state,evaluate(record.document,saved.state).derived,await store.audits(documentId),{detail,nodeIds:toolJson(nodeIds,'nodeIds')});}
|
|
102
|
+
})));
|
|
103
|
+
ctx.effect(()=>ctx.tools.register(defineTool({name:'patch_ui',description:'Refine existing UI nodes without changing their IDs, structure, input bindings or actions. First inspect_ui for current documentRevision. changes is [{id,props}], with registered properties only. Replacing canvas html/css/script restarts that canvas; saved parameters and unaffected live nodes remain. Revision conflicts require inspect and retry. No partial scripts execute.',parameters:{documentId:{type:'string',required:true},documentRevision:{type:'number',required:true},changes:{type:'json',required:true}},output:{schema:{type:'json'},render:(_a,v)=>[{type:'text',text:`Updated ${v.document.title}; documentId=${v.documentId}; documentRevision=${v.documentRevision}. Saved parameters retained.`}],presentationMeta:(_a,v)=>({dshGenerativeUiPatch:v})},async execute({documentId,documentRevision,changes},exec){exec.signal.throwIfAborted();return store.refine(documentId,exec.agent?.id,documentRevision,toolJson(changes,'changes'));}})));
|
|
104
|
+
ctx.effect(()=>ctx.tools.register(defineTool({name:'update_ui',description:'Append or replace content of an existing UI without generating a duplicate document. Inspect its revision first. Use targetId to modify an existing native node; visual targetId accepts an extended title/items document. Without targetId, an extended fragment appends to the only root visual when unambiguous; otherwise append adds root nodes (IDs must be unique). replace updates the root content. Preserve existing state/derived definitions; new inputs receive defaults. operationId is a stable unique edit name, reuse it only for an identical retry; replay is idempotent for the latest 64 edits.',parameters:{documentId:{type:'string',required:true},documentRevision:{type:'number',required:true},operationId:{type:'string',required:true},mode:{type:'string',enum:['append','replace'],required:true},targetId:{type:'string'},document:{type:'json',required:true}},output:{schema:{type:'json'},render:(_a,v)=>[{type:'text',text:'Updated existing UI '+v.documentId+'; documentRevision='+v.documentRevision+'. Keep its existing inline marker; do not duplicate it.'}],presentationMeta:(_a,v)=>({dshGenerativeUiPatch:v})},async execute({documentId,documentRevision,operationId,mode,targetId,document},exec){exec.signal.throwIfAborted();return store.update(documentId,exec.agent?.id,documentRevision,operationId,{mode,...(targetId?{targetId}:{}),document:toolJson(document,'document')})}})));
|
|
105
|
+
for (const [i,section] of UI_SKILL_SECTIONS.entries())ctx.effect(()=>ctx.systemPrompt.section({...section,text:()=>promptSections(settings().designMode??'guided',settings().visualStyle??DEFAULT_VISUAL_STYLE)[i].text+(i===0&&settings().designMode!=='free'?'\n'+SCENE_GUIDE:'')+(i===0?'\nFor changes to an existing UI, inspect_ui then update_ui with its current revision and a stable operationId; preserve the original marker and user values. Never create a second copy for an edit. Read delivery diagnostics and correct rejected components before claiming the UI is complete.\nPresentation mode: inline. After a successful render_text/render_ui/render_canvas, put a fenced dsh-ui block containing only its documentId in your answer at the best explanatory position. Never invent an ID or put source inside the marker. If omitted, the interface remains below the answer.':'')}));
|
|
106
|
+
}
|
|
107
|
+
|
|
82
108
|
|
|
83
109
|
|