dsh-motion-ui 0.6.0 → 0.7.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 +66 -0
- package/README.md +37 -1
- package/VERIFICATION.md +36 -0
- package/client.js +1856 -984
- package/examples/mechanism-assembly.json +50 -0
- package/examples/mechanism-crank.json +103 -0
- package/examples/mechanism-gears.json +103 -0
- package/index.js +115 -104
- package/lib/assets/standalone-runtime.js +3 -1
- package/lib/assets/visual.js +3 -1
- package/lib/author-expression.js +3 -2
- package/lib/authoring-guide.js +2 -1
- package/lib/build-info.js +1 -1
- package/lib/catalog.js +4 -4
- package/lib/components.js +2 -2
- package/lib/export-runtime-bundle.js +1 -1
- package/lib/expressive-examples.js +6 -0
- package/lib/fence-feedback.js +1 -1
- package/lib/freeform.js +4 -3
- package/lib/mechanism-catalog.js +24 -0
- package/lib/mechanism-css.js +13 -0
- package/lib/mechanism-entry.js +20 -0
- package/lib/mechanism-geometry.js +62 -0
- package/lib/mechanism-render.js +24 -0
- package/lib/mechanism-runtime-bundle.js +2 -0
- package/lib/mechanism-scenes.js +20 -0
- package/lib/motion-library.js +18 -0
- package/lib/normalize-authoring.js +6 -2
- package/lib/protocol.js +23 -8
- package/lib/sandbox.js +2 -0
- package/lib/style-system.js +28 -0
- package/lib/third-party/anatomy-LICENSE.txt +21 -0
- package/lib/third-party/anatomy-NOTICE.md +13 -0
- package/lib/third-party/anatomy-iso.mjs +674 -0
- package/lib/third-party/lucian-uxui-LICENSE.txt +21 -0
- package/lib/third-party/lucian-uxui-NOTICE.md +1 -0
- package/lib/tool-schema.js +5 -5
- package/lib/ui-intent.js +1 -1
- package/lib/ui-skill.js +3 -2
- package/lib/visual-styles.js +134 -22
- package/package.json +92 -92
- package/skills/intelligent-ui/SKILL.md +113 -100
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 1,
|
|
3
|
+
"title": "分层结构 · 示意装配",
|
|
4
|
+
"fallback": "底座支撑功能板,处理模块上方为散热层,外壳保护内部。拆解表示装配关系,不表示受力运动。",
|
|
5
|
+
"state": {
|
|
6
|
+
"explode": {
|
|
7
|
+
"type": "number",
|
|
8
|
+
"default": 0.45,
|
|
9
|
+
"min": 0,
|
|
10
|
+
"max": 1,
|
|
11
|
+
"step": 0.01
|
|
12
|
+
},
|
|
13
|
+
"selected": {
|
|
14
|
+
"type": "string",
|
|
15
|
+
"default": "all"
|
|
16
|
+
},
|
|
17
|
+
"cutaway": {
|
|
18
|
+
"type": "boolean",
|
|
19
|
+
"default": false
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"nodes": [
|
|
23
|
+
{
|
|
24
|
+
"id": "mechanism",
|
|
25
|
+
"type": "sandbox",
|
|
26
|
+
"title": "分层结构 · 示意装配",
|
|
27
|
+
"fallback": "底座支撑功能板,处理模块上方为散热层,外壳保护内部。拆解表示装配关系,不表示受力运动。",
|
|
28
|
+
"height": 560,
|
|
29
|
+
"libraries": [
|
|
30
|
+
"mechanism"
|
|
31
|
+
],
|
|
32
|
+
"stateKeys": [
|
|
33
|
+
"explode",
|
|
34
|
+
"selected",
|
|
35
|
+
"cutaway"
|
|
36
|
+
],
|
|
37
|
+
"html": "<div id=\"diagram\"><section class=\"mui-mechanism\"><svg class=\"mui-mechanism-svg\" viewBox=\"0 0 600 340\" role=\"img\" aria-label=\"结构轮廓预览;完成后显示立体细节\"><path data-material=\"dark\" data-tone=\"0\" d=\"M272.4 206.9L270.2 207.7L267.6 208.3L264.8 208.4L262 208.3L259.4 207.7L257.2 206.9L255.5 205.7L254.4 204.4L254 203L254.4 201.6L255.5 200.3L257.2 199.2L259.4 198.4L262 197.8L264.8 197.6L267.6 197.8L270.2 198.4L272.4 199.2L274.2 200.3L275.2 201.6L275.6 203L275.2 204.4L274.2 205.7ZM196.1 245L193.9 245.9L191.3 246.4L188.5 246.6L185.7 246.4L183.1 245.9L180.9 245L179.2 243.9L178.1 242.6L177.7 241.2L178.1 239.8L179.2 238.5L180.9 237.4L183.1 236.5L185.7 236L188.5 235.8L191.3 236L193.9 236.5L196.1 237.4L197.8 238.5L198.9 239.8L199.3 241.2L198.9 242.6L197.8 243.9ZM389.4 265.4L387.2 266.2L384.6 266.8L381.8 266.9L379 266.8L376.4 266.2L374.2 265.4L372.5 264.2L371.4 262.9L371 261.5L371.4 260.1L372.5 258.8L374.2 257.7L376.4 256.9L379 256.3L381.8 256.2L384.6 256.3L387.2 256.9L389.4 257.7L391.2 258.8L392.2 260.1L392.6 261.5L392.2 262.9L391.2 264.2ZM313.1 303.5L310.9 304.4L308.3 304.9L305.5 305.1L302.7 304.9L300.1 304.4L297.9 303.5L296.2 302.4L295.1 301.1L294.7 299.7L295.1 298.3L296.2 297L297.9 295.9L300.1 295L302.7 294.5L305.5 294.3L308.3 294.5L310.9 295L313.1 295.9L314.9 297L315.9 298.3L316.3 299.7L315.9 301.1L314.9 302.4Z\" fill-rule=\"evenodd\"/><path data-material=\"metal\" data-tone=\"0\" d=\"M407.9 243.9L410.7 246.3L410.7 249.1L407.9 251.5L315 297.9L310.2 299.3L304.6 299.3L299.8 297.9L162.4 229.3L159.6 226.8L159.6 224L162.4 221.6L255.3 175.2L260.1 173.8L265.7 173.8L270.5 175.2ZM439.4 120.3L440.4 121.1L440.4 122.1L439.4 122.9L439.4 122.9L437.8 123.3L436 123.3L434.3 122.9L281.7 46.6L280.8 45.8L280.8 44.8L281.7 44L281.7 44L283.3 43.6L285.2 43.6L286.8 44Z\" fill-rule=\"evenodd\"/><path data-material=\"cool\" data-tone=\"0\" d=\"M381.8 202.3L383.2 203.5L383.2 204.9L381.8 206.1L310.6 241.7L308.2 242.4L305.4 242.4L303 241.7L188.5 184.4L187.1 183.2L187.1 181.8L188.5 180.6L259.7 145L262.1 144.3L264.9 144.3L267.4 145Z\" fill-rule=\"evenodd\"/><path data-material=\"dark\" data-tone=\"0\" d=\"M287.7 163.4L287 163.7L286.1 163.9L285.2 163.9L284.2 163.9L283.4 163.7L282.6 163.4L282 163L281.7 162.6L281.6 162.1L281.7 161.7L282 161.2L282.6 160.9L283.4 160.6L284.2 160.4L285.2 160.3L286.1 160.4L287 160.6L287.7 160.9L288.3 161.2L288.6 161.7L288.8 162.1L288.6 162.6L288.3 163ZM226.7 193.9L225.9 194.2L225 194.4L224.1 194.4L223.2 194.4L222.3 194.2L221.6 193.9L221 193.5L220.6 193.1L220.5 192.6L220.6 192.2L221 191.7L221.6 191.4L222.3 191.1L223.2 190.9L224.1 190.8L225 190.9L225.9 191.1L226.7 191.4L227.2 191.7L227.6 192.2L227.7 192.6L227.6 193.1L227.2 193.5ZM348.8 193.9L348 194.2L347.1 194.4L346.2 194.4L345.3 194.4L344.4 194.2L343.7 193.9L343.1 193.5L342.7 193.1L342.6 192.6L342.7 192.2L343.1 191.7L343.7 191.4L344.4 191.1L345.3 190.9L346.2 190.8L347.1 190.9L348 191.1L348.8 191.4L349.3 191.7L349.7 192.2L349.8 192.6L349.7 193.1L349.3 193.5ZM287.7 224.4L287 224.7L286.1 224.9L285.2 225L284.2 224.9L283.4 224.7L282.6 224.4L282 224.1L281.7 223.6L281.6 223.2L281.7 222.7L282 222.3L282.6 221.9L283.4 221.6L284.2 221.4L285.2 221.4L286.1 221.4L287 221.6L287.7 221.9L288.3 222.3L288.6 222.7L288.8 223.2L288.6 223.6L288.3 224.1ZM293.4 166.6L294.4 167.5L294.4 168.4L293.4 169.2L268 181.9L266.4 182.4L264.5 182.4L262.9 181.9L236.2 168.6L235.3 167.7L235.3 166.8L236.2 166L261.6 153.3L263.2 152.8L265.1 152.8L266.7 153.3Z\" fill-rule=\"evenodd\"/><path data-material=\"warm\" data-tone=\"0\" d=\"M356.4 184.3L357.3 185.1L357.3 186L356.4 186.8L315.7 207.2L314.1 207.6L312.2 207.6L310.6 207.2L295.3 199.5L294.4 198.7L294.4 197.8L295.3 197L336 176.6L337.6 176.2L339.5 176.2L341.1 176.6Z\" fill-rule=\"evenodd\"/><path data-material=\"metal\" data-tone=\"0\" d=\"M311.2 131.4L312.2 132.2L312.2 133.1L311.2 133.9L262.9 158.1L261.3 158.6L259.4 158.6L257.8 158.1L206.9 132.7L206 131.9L206 130.9L206.9 130.1L255.3 106L256.9 105.5L258.7 105.5L260.4 106ZM261.9 77.6L262.4 78L262.4 78.5L261.9 78.9L213.6 103.1L212.8 103.3L211.8 103.3L211 103.1L210.5 102.8L210 102.4L210 101.9L210.5 101.5L258.8 77.4L259.6 77.1L260.6 77.1L261.4 77.4ZM269.5 81.4L270 81.8L270 82.3L269.5 82.7L221.2 106.9L220.4 107.1L219.5 107.1L218.6 106.9L218.1 106.6L217.7 106.2L217.7 105.7L218.1 105.3L266.5 81.2L267.3 80.9L268.2 80.9L269 81.2ZM277.1 85.2L277.6 85.6L277.6 86.1L277.1 86.5L228.8 110.7L228 110.9L227.1 110.9L226.3 110.7L225.8 110.4L225.3 110L225.3 109.6L225.8 109.2L274.1 85L274.9 84.8L275.8 84.8L276.6 85ZM284.8 89.1L285.2 89.5L285.2 89.9L284.8 90.3L236.4 114.5L235.6 114.7L234.7 114.7L233.9 114.5L233.4 114.2L232.9 113.8L232.9 113.4L233.4 113L281.7 88.8L282.5 88.6L283.5 88.6L284.3 88.8ZM292.4 92.9L292.9 93.3L292.9 93.7L292.4 94.1L244.1 118.3L243.3 118.5L242.3 118.5L241.5 118.3L241 118.1L240.6 117.7L240.6 117.2L241 116.8L289.4 92.6L290.2 92.4L291.1 92.4L291.9 92.6ZM300 96.7L300.5 97.1L300.5 97.6L300 98L251.7 122.1L250.9 122.4L250 122.4L249.2 122.1L248.7 121.9L248.2 121.5L248.2 121L248.7 120.6L297 96.4L297.8 96.2L298.7 96.2L299.5 96.4ZM307.7 100.5L308.1 100.9L308.1 101.4L307.7 101.8L259.3 125.9L258.5 126.2L257.6 126.2L256.8 125.9L256.3 125.7L255.8 125.3L255.8 124.8L256.3 124.4L304.6 100.3L305.4 100L306.4 100L307.2 100.3ZM419.8 96.6L422.6 99L422.6 101.8L419.8 104.2L321.9 153.2L317.1 154.6L311.5 154.6L306.7 153.2L164.2 82L161.4 79.6L161.4 76.8L164.2 74.4L262.1 25.4L267 24L272.6 24L277.4 25.4Z\" fill-rule=\"evenodd\"/></svg><p>底座支撑功能板,处理模块上方为散热层,外壳保护内部。拆解表示装配关系,不表示受力运动。</p></section></div>",
|
|
38
|
+
"css": "\n.mui-mechanism{font:15px/1.7 system-ui,sans-serif;color:var(--canvas-ink);background:var(--canvas-bg);border:1px solid var(--canvas-line);border-radius:24px;padding:20px;max-width:100%;box-sizing:border-box}.mui-mechanism *{box-sizing:border-box}.mui-mechanism h2{font-size:22px;line-height:1.35;margin:0 0 8px;font-weight:750}.mui-mechanism p{margin:0;color:var(--canvas-muted)}\n.mui-mechanism-svg{display:block;width:100%;height:auto;max-height:420px;touch-action:pan-y}.mui-mechanism-svg path{stroke:color-mix(in srgb,var(--canvas-ink) 38%,var(--canvas-bg));stroke-width:.8;stroke-linejoin:round;vector-effect:non-scaling-stroke;cursor:pointer;fill:var(--mech-base,var(--canvas-soft))}.mui-mechanism-svg [data-material=metal]{--mech-base:color-mix(in srgb,var(--canvas-muted) 32%,var(--canvas-bg))}.mui-mechanism-svg [data-material=dark]{--mech-base:color-mix(in srgb,var(--canvas-ink) 78%,var(--canvas-bg))}.mui-mechanism-svg [data-material=accent]{--mech-base:var(--canvas-accent)}.mui-mechanism-svg [data-material=cool]{--mech-base:color-mix(in srgb,#22998a 70%,var(--canvas-bg))}.mui-mechanism-svg [data-material=warm]{--mech-base:color-mix(in srgb,#dd9c42 75%,var(--canvas-bg))}\n.mui-mechanism-svg [data-tone=\"0\"]{fill:color-mix(in srgb,var(--mech-base) 74%,var(--canvas-bg))}.mui-mechanism-svg [data-tone=\"1\"]{fill:var(--mech-base)}.mui-mechanism-svg [data-tone=\"2\"]{fill:color-mix(in srgb,var(--mech-base) 85%,var(--canvas-ink))}.mui-mechanism-svg [data-tone=\"3\"]{fill:color-mix(in srgb,var(--mech-base) 68%,var(--canvas-ink))}.mui-mechanism-svg [data-line]{fill:none;stroke:var(--mech-base);stroke-width:2}.mui-mechanism-svg [data-active=false]{opacity:.2}.mui-mechanism-svg [data-active=true]{opacity:1}\n.mui-mechanism-nav{display:flex;flex-wrap:wrap;gap:7px;margin:8px 0 12px}.mui-mechanism button{font:inherit;color:var(--canvas-ink);background:var(--canvas-bg);border:1px solid var(--canvas-line);border-radius:999px;padding:6px 13px;cursor:pointer;min-height:36px}.mui-mechanism button[aria-pressed=true]{color:var(--canvas-bg);background:var(--canvas-ink);border-color:var(--canvas-ink)}.mui-mechanism button:focus-visible,.mui-mechanism input:focus-visible{outline:2px solid var(--canvas-accent);outline-offset:3px}.mui-mechanism button:disabled{opacity:.5;cursor:default}\n.mui-mechanism-controls{display:flex;align-items:center;flex-wrap:wrap;gap:14px;padding:12px 14px;border-radius:16px;background:var(--canvas-soft);margin:8px 0}.mui-mechanism-controls label{display:flex;align-items:center;gap:9px;flex:1 1 180px;min-width:0}.mui-mechanism-controls input[type=range]{flex:1;min-width:70px;accent-color:var(--canvas-accent)}.mui-mechanism-controls input[type=checkbox]{accent-color:var(--canvas-accent)}.mui-mechanism-controls output{font-variant-numeric:tabular-nums;min-width:40px;text-align:right;font-weight:650}.mui-mechanism-readout{display:block;padding:10px 0;font-weight:700;font-variant-numeric:tabular-nums;color:var(--canvas-ink)}.mui-mechanism-description{min-height:0;font-size:14px}\n.mui-mechanism[data-style=editorial]{border:0;border-top:1px solid var(--canvas-line);border-radius:0;padding:16px 0}.mui-mechanism[data-style=editorial] h2{font-family:ui-serif,Georgia,serif;font-weight:650}.mui-mechanism[data-style=editorial] .mui-mechanism-controls{border-radius:0;background:transparent;border-block:1px solid var(--canvas-line)}\n.mui-mechanism[data-style=technical]{border-radius:10px}.mui-mechanism[data-style=technical] button,.mui-mechanism[data-style=technical] .mui-mechanism-controls{border-radius:6px}.mui-mechanism[data-style=technical] .mui-mechanism-readout{font-family:ui-monospace,Consolas,monospace}\n.mui-mechanism[data-style=soft]{border:0;background:var(--canvas-soft);border-radius:28px 28px 28px 10px}.mui-mechanism[data-style=soft] .mui-mechanism-controls{background:var(--canvas-bg);border-radius:22px}.mui-mechanism[data-style=expressive] h2{font-size:28px;font-weight:850;border-left:5px solid var(--canvas-accent);padding-left:14px}.mui-mechanism[data-style=expressive]{border:0;border-radius:0}.mui-mechanism[data-style=prismframe]{border:1.5px solid var(--canvas-line);box-shadow:4px 5px 0 color-mix(in srgb,var(--canvas-accent) 14%,var(--canvas-bg))}.mui-mechanism[data-style=aurora]{border-radius:28px;box-shadow:0 16px 30px -25px #30204d66}.mui-mechanism[data-style=aurora] .mui-mechanism-controls{border-radius:24px}\n@media(max-width:500px){.mui-mechanism{padding:14px;border-radius:20px}.mui-mechanism h2{font-size:20px}.mui-mechanism-controls{padding:10px}.mui-mechanism-nav{gap:5px}.mui-mechanism button{padding:6px 10px;font-size:14px}}\n@media(prefers-reduced-motion:reduce){.mui-mechanism *{animation:none!important;transition:none!important}}\n@media(forced-colors:active){.mui-mechanism-svg path{fill:Canvas;stroke:CanvasText}.mui-mechanism button[aria-pressed=true]{background:Highlight;color:HighlightText}}\n",
|
|
39
|
+
"script": "const diagram=DSHUI.mechanism.mountDemo(\"#diagram\",\"assembly\",{title:\"\",bind:{\"explode\":\"explode\",\"selected\":\"selected\",\"cutaway\":\"cutaway\"}});addEventListener(\"pagehide\",()=>diagram.destroy(),{once:true});"
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"id": "accuracy",
|
|
43
|
+
"type": "text",
|
|
44
|
+
"text": "底座支撑功能板,处理模块上方为散热层,外壳保护内部。拆解表示装配关系,不表示受力运动。"
|
|
45
|
+
}
|
|
46
|
+
],
|
|
47
|
+
"data": {},
|
|
48
|
+
"derived": {},
|
|
49
|
+
"actions": {}
|
|
50
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 1,
|
|
3
|
+
"title": "曲柄连杆 · 旋转转为往复",
|
|
4
|
+
"fallback": "旋转曲柄带动定长连杆,滑块沿导轨往复。默认半径20、杆长70,完整行程40,位置由几何约束计算。非动力学仿真。",
|
|
5
|
+
"state": {
|
|
6
|
+
"explode": {
|
|
7
|
+
"type": "number",
|
|
8
|
+
"default": 0,
|
|
9
|
+
"min": 0,
|
|
10
|
+
"max": 1,
|
|
11
|
+
"step": 0.01
|
|
12
|
+
},
|
|
13
|
+
"selected": {
|
|
14
|
+
"type": "string",
|
|
15
|
+
"default": "all"
|
|
16
|
+
},
|
|
17
|
+
"cutaway": {
|
|
18
|
+
"type": "boolean",
|
|
19
|
+
"default": false
|
|
20
|
+
},
|
|
21
|
+
"rpm": {
|
|
22
|
+
"type": "number",
|
|
23
|
+
"default": 20,
|
|
24
|
+
"min": 0,
|
|
25
|
+
"max": 90,
|
|
26
|
+
"step": 1
|
|
27
|
+
},
|
|
28
|
+
"running": {
|
|
29
|
+
"type": "boolean",
|
|
30
|
+
"default": false
|
|
31
|
+
},
|
|
32
|
+
"angle": {
|
|
33
|
+
"type": "number",
|
|
34
|
+
"default": 0,
|
|
35
|
+
"min": 0,
|
|
36
|
+
"max": 360,
|
|
37
|
+
"step": 1
|
|
38
|
+
},
|
|
39
|
+
"radius": {
|
|
40
|
+
"type": "number",
|
|
41
|
+
"default": 20,
|
|
42
|
+
"min": 10,
|
|
43
|
+
"max": 28,
|
|
44
|
+
"step": 1
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
"nodes": [
|
|
48
|
+
{
|
|
49
|
+
"id": "mechanism",
|
|
50
|
+
"type": "sandbox",
|
|
51
|
+
"title": "曲柄连杆 · 旋转转为往复",
|
|
52
|
+
"fallback": "旋转曲柄带动定长连杆,滑块沿导轨往复。默认半径20、杆长70,完整行程40,位置由几何约束计算。非动力学仿真。",
|
|
53
|
+
"height": 560,
|
|
54
|
+
"libraries": [
|
|
55
|
+
"mechanism"
|
|
56
|
+
],
|
|
57
|
+
"stateKeys": [
|
|
58
|
+
"explode",
|
|
59
|
+
"selected",
|
|
60
|
+
"cutaway",
|
|
61
|
+
"rpm",
|
|
62
|
+
"running",
|
|
63
|
+
"angle",
|
|
64
|
+
"radius"
|
|
65
|
+
],
|
|
66
|
+
"html": "<div id=\"diagram\"><section class=\"mui-mechanism\"><svg class=\"mui-mechanism-svg\" viewBox=\"0 0 600 340\" role=\"img\" aria-label=\"结构轮廓预览;完成后显示立体细节\"><path data-material=\"metal\" data-tone=\"0\" d=\"M554.6 204.2L559.2 208.2L559.2 212.8L554.6 216.8L412.1 288L404.1 290.3L394.9 290.3L386.9 288L45.4 117.3L40.8 113.3L40.8 108.7L45.4 104.7L187.9 33.5L195.9 31.2L205.1 31.2L213.1 33.5Z\" fill-rule=\"evenodd\"/><path data-material=\"dark\" data-tone=\"0\" d=\"M306.3 92.1L304.4 92.8L302.3 93.2L300 93.4L297.7 93.2L295.6 92.8L293.7 92.1L292.3 91.2L291.4 90.1L291.1 88.9L291.4 87.8L292.3 86.7L293.7 85.8L295.6 85.1L297.7 84.6L300 84.5L302.3 84.6L304.4 85.1L306.3 85.8L307.7 86.7L308.6 87.8L308.9 88.9L308.6 90.1L307.7 91.2ZM249.7 95.9L243 98.4L235.1 100.1L226.7 100.6L218.2 100.1L210.4 98.4L203.6 95.9L198.4 92.5L195.2 88.5L194.1 84.3L195.2 80.1L198.4 76.2L203.6 72.8L210.4 70.2L218.2 68.6L226.7 68L235.1 68.6L243 70.2L249.7 72.8L254.9 76.2L258.2 80.1L259.3 84.3L258.2 88.5L254.9 92.5ZM236.9 87.3L238.1 85.9L238.5 84.3L238.1 82.8L236.9 81.4L235.1 80.1L232.6 79.2L229.7 78.6L226.7 78.4L223.6 78.6L220.7 79.2L218.3 80.1L216.4 81.4L215.2 82.8L214.8 84.3L215.2 85.9L216.4 87.3L218.3 88.5L220.7 89.5L223.6 90.1L226.7 90.3L229.7 90.1L232.6 89.5L235.1 88.5ZM180.6 154.9L178.7 155.6L176.6 156.1L174.3 156.2L172 156.1L169.9 155.6L168 154.9L166.6 154L165.7 152.9L165.4 151.8L165.7 150.6L166.6 149.6L168 148.6L169.9 147.9L172 147.5L174.3 147.3L176.6 147.5L178.7 147.9L180.6 148.6L182 149.6L182.9 150.6L183.2 151.8L182.9 152.9L182 154ZM432 154.9L430.1 155.6L428 156.1L425.7 156.2L423.4 156.1L421.3 155.6L419.4 154.9L418 154L417.1 152.9L416.8 151.8L417.1 150.6L418 149.6L419.4 148.6L421.3 147.9L423.4 147.5L425.7 147.3L428 147.5L430.1 147.9L432 148.6L433.4 149.6L434.3 150.6L434.6 151.8L434.3 152.9L433.4 154ZM306.3 217.8L304.4 218.5L302.3 218.9L300 219.1L297.7 218.9L295.6 218.5L293.7 217.8L292.3 216.9L291.4 215.8L291.1 214.6L291.4 213.5L292.3 212.4L293.7 211.5L295.6 210.8L297.7 210.3L300 210.2L302.3 210.3L304.4 210.8L306.3 211.5L307.7 212.4L308.6 213.5L308.9 214.6L308.6 215.8L307.7 216.9Z\" fill-rule=\"evenodd\"/><path data-material=\"metal\" data-tone=\"0\" d=\"M234.6 53.7L232.3 54.6L229.6 55.1L226.7 55.3L223.8 55.1L221 54.6L218.7 53.7L216.9 52.5L215.8 51.1L215.4 49.7L215.8 48.2L216.9 46.9L218.7 45.7L221 44.8L223.8 44.3L226.7 44.1L229.6 44.3L232.3 44.8L234.6 45.7L236.4 46.9L237.5 48.2L237.9 49.7L237.5 51.1L236.4 52.5Z\" fill-rule=\"evenodd\"/><path data-material=\"dark\" data-tone=\"0\" d=\"M507.4 182.1L508.2 182.8L508.2 183.5L507.4 184.2L501.1 187.3L499.8 187.7L498.3 187.7L496.9 187.3L323 100.4L322.3 99.7L322.3 99L323 98.3L329.3 95.1L330.7 94.8L332.2 94.8L333.5 95.1ZM440.4 215.6L441.1 216.3L441.1 217L440.4 217.7L434.1 220.8L432.8 221.2L431.2 221.2L429.9 220.8L256 133.9L255.2 133.2L255.2 132.5L256 131.8L262.3 128.7L263.6 128.3L265.2 128.3L266.5 128.7Z\" fill-rule=\"evenodd\"/><path data-material=\"cool\" data-tone=\"0\" d=\"M452.9 132.5L455.2 134.5L455.2 136.8L452.9 138.8L415.2 157.7L411.2 158.8L406.6 158.8L402.7 157.7L377.5 145.1L375.2 143.1L375.2 140.8L377.5 138.8L415.2 120L419.2 118.8L423.8 118.8L427.8 120Z\" fill-rule=\"evenodd\"/><path data-material=\"accent\" data-tone=\"0\" d=\"M281.1 89.8L265.2 95.9L246.6 99.7L226.7 101L206.7 99.7L188.2 95.9L172.2 89.8L160 81.8L152.3 72.5L149.6 62.5L152.3 52.5L160 43.3L172.2 35.3L188.2 29.2L206.7 25.3L226.7 24L246.6 25.3L265.2 29.2L281.1 35.3L293.4 43.3L301.1 52.5L303.7 62.5L301.1 72.5L293.4 81.8ZM236.9 65.5L238.1 64.1L238.5 62.5L238.1 61L236.9 59.6L235.1 58.3L232.6 57.4L229.7 56.8L226.7 56.6L223.6 56.8L220.7 57.4L218.3 58.3L216.4 59.6L215.2 61L214.8 62.5L215.2 64.1L216.4 65.5L218.3 66.7L220.7 67.6L223.6 68.2L226.7 68.4L229.7 68.2L232.6 67.6L235.1 66.7Z\" fill-rule=\"evenodd\"/><path data-material=\"warm\" data-tone=\"0\" d=\"M274.9 58.4L273 59.1L270.9 59.5L268.6 59.7L266.3 59.5L264.1 59.1L262.3 58.4L260.9 57.5L260 56.4L259.7 55.2L260 54.1L260.9 53L262.3 52.1L264.1 51.4L266.3 51L268.6 50.8L270.9 51L273 51.4L274.9 52.1L276.3 53L277.2 54.1L277.5 55.2L277.2 56.4L276.3 57.5ZM421.5 134.3L419.7 135L417.5 135.4L415.2 135.6L412.9 135.4L410.8 135L408.9 134.3L407.5 133.4L406.6 132.3L406.3 131.1L406.6 130L407.5 128.9L408.9 128L410.8 127.3L412.9 126.8L415.2 126.7L417.5 126.8L419.7 127.3L421.5 128L422.9 128.9L423.8 130L424.1 131.1L423.8 132.3L422.9 133.4Z\" fill-rule=\"evenodd\"/><path data-material=\"metal\" data-tone=\"0\" d=\"M270.5 64L272.1 64.5L418.8 137.8L417.2 137.3ZM268.6 64.5L270.5 64L417.2 137.3L415.2 137.8ZM266.6 65.9L268.6 64.5L415.2 137.8L413.3 139.2ZM265 68.1L266.6 65.9L413.3 139.2L411.7 141.4Z\" fill-rule=\"evenodd\"/></svg><p>旋转曲柄带动定长连杆,滑块沿导轨往复。默认半径20、杆长70,完整行程40,位置由几何约束计算。非动力学仿真。</p></section></div>",
|
|
67
|
+
"css": "\n.mui-mechanism{font:15px/1.7 system-ui,sans-serif;color:var(--canvas-ink);background:var(--canvas-bg);border:1px solid var(--canvas-line);border-radius:24px;padding:20px;max-width:100%;box-sizing:border-box}.mui-mechanism *{box-sizing:border-box}.mui-mechanism h2{font-size:22px;line-height:1.35;margin:0 0 8px;font-weight:750}.mui-mechanism p{margin:0;color:var(--canvas-muted)}\n.mui-mechanism-svg{display:block;width:100%;height:auto;max-height:420px;touch-action:pan-y}.mui-mechanism-svg path{stroke:color-mix(in srgb,var(--canvas-ink) 38%,var(--canvas-bg));stroke-width:.8;stroke-linejoin:round;vector-effect:non-scaling-stroke;cursor:pointer;fill:var(--mech-base,var(--canvas-soft))}.mui-mechanism-svg [data-material=metal]{--mech-base:color-mix(in srgb,var(--canvas-muted) 32%,var(--canvas-bg))}.mui-mechanism-svg [data-material=dark]{--mech-base:color-mix(in srgb,var(--canvas-ink) 78%,var(--canvas-bg))}.mui-mechanism-svg [data-material=accent]{--mech-base:var(--canvas-accent)}.mui-mechanism-svg [data-material=cool]{--mech-base:color-mix(in srgb,#22998a 70%,var(--canvas-bg))}.mui-mechanism-svg [data-material=warm]{--mech-base:color-mix(in srgb,#dd9c42 75%,var(--canvas-bg))}\n.mui-mechanism-svg [data-tone=\"0\"]{fill:color-mix(in srgb,var(--mech-base) 74%,var(--canvas-bg))}.mui-mechanism-svg [data-tone=\"1\"]{fill:var(--mech-base)}.mui-mechanism-svg [data-tone=\"2\"]{fill:color-mix(in srgb,var(--mech-base) 85%,var(--canvas-ink))}.mui-mechanism-svg [data-tone=\"3\"]{fill:color-mix(in srgb,var(--mech-base) 68%,var(--canvas-ink))}.mui-mechanism-svg [data-line]{fill:none;stroke:var(--mech-base);stroke-width:2}.mui-mechanism-svg [data-active=false]{opacity:.2}.mui-mechanism-svg [data-active=true]{opacity:1}\n.mui-mechanism-nav{display:flex;flex-wrap:wrap;gap:7px;margin:8px 0 12px}.mui-mechanism button{font:inherit;color:var(--canvas-ink);background:var(--canvas-bg);border:1px solid var(--canvas-line);border-radius:999px;padding:6px 13px;cursor:pointer;min-height:36px}.mui-mechanism button[aria-pressed=true]{color:var(--canvas-bg);background:var(--canvas-ink);border-color:var(--canvas-ink)}.mui-mechanism button:focus-visible,.mui-mechanism input:focus-visible{outline:2px solid var(--canvas-accent);outline-offset:3px}.mui-mechanism button:disabled{opacity:.5;cursor:default}\n.mui-mechanism-controls{display:flex;align-items:center;flex-wrap:wrap;gap:14px;padding:12px 14px;border-radius:16px;background:var(--canvas-soft);margin:8px 0}.mui-mechanism-controls label{display:flex;align-items:center;gap:9px;flex:1 1 180px;min-width:0}.mui-mechanism-controls input[type=range]{flex:1;min-width:70px;accent-color:var(--canvas-accent)}.mui-mechanism-controls input[type=checkbox]{accent-color:var(--canvas-accent)}.mui-mechanism-controls output{font-variant-numeric:tabular-nums;min-width:40px;text-align:right;font-weight:650}.mui-mechanism-readout{display:block;padding:10px 0;font-weight:700;font-variant-numeric:tabular-nums;color:var(--canvas-ink)}.mui-mechanism-description{min-height:0;font-size:14px}\n.mui-mechanism[data-style=editorial]{border:0;border-top:1px solid var(--canvas-line);border-radius:0;padding:16px 0}.mui-mechanism[data-style=editorial] h2{font-family:ui-serif,Georgia,serif;font-weight:650}.mui-mechanism[data-style=editorial] .mui-mechanism-controls{border-radius:0;background:transparent;border-block:1px solid var(--canvas-line)}\n.mui-mechanism[data-style=technical]{border-radius:10px}.mui-mechanism[data-style=technical] button,.mui-mechanism[data-style=technical] .mui-mechanism-controls{border-radius:6px}.mui-mechanism[data-style=technical] .mui-mechanism-readout{font-family:ui-monospace,Consolas,monospace}\n.mui-mechanism[data-style=soft]{border:0;background:var(--canvas-soft);border-radius:28px 28px 28px 10px}.mui-mechanism[data-style=soft] .mui-mechanism-controls{background:var(--canvas-bg);border-radius:22px}.mui-mechanism[data-style=expressive] h2{font-size:28px;font-weight:850;border-left:5px solid var(--canvas-accent);padding-left:14px}.mui-mechanism[data-style=expressive]{border:0;border-radius:0}.mui-mechanism[data-style=prismframe]{border:1.5px solid var(--canvas-line);box-shadow:4px 5px 0 color-mix(in srgb,var(--canvas-accent) 14%,var(--canvas-bg))}.mui-mechanism[data-style=aurora]{border-radius:28px;box-shadow:0 16px 30px -25px #30204d66}.mui-mechanism[data-style=aurora] .mui-mechanism-controls{border-radius:24px}\n@media(max-width:500px){.mui-mechanism{padding:14px;border-radius:20px}.mui-mechanism h2{font-size:20px}.mui-mechanism-controls{padding:10px}.mui-mechanism-nav{gap:5px}.mui-mechanism button{padding:6px 10px;font-size:14px}}\n@media(prefers-reduced-motion:reduce){.mui-mechanism *{animation:none!important;transition:none!important}}\n@media(forced-colors:active){.mui-mechanism-svg path{fill:Canvas;stroke:CanvasText}.mui-mechanism button[aria-pressed=true]{background:Highlight;color:HighlightText}}\n",
|
|
68
|
+
"script": "const diagram=DSHUI.mechanism.mountDemo(\"#diagram\",\"crank\",{title:\"\",bind:{\"explode\":\"explode\",\"selected\":\"selected\",\"cutaway\":\"cutaway\",\"rpm\":\"rpm\",\"running\":\"running\",\"angle\":\"angle\",\"radius\":\"radius\"}});addEventListener(\"pagehide\",()=>diagram.destroy(),{once:true});"
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"id": "radius",
|
|
72
|
+
"type": "slider",
|
|
73
|
+
"label": "曲柄半径(示意长度单位)",
|
|
74
|
+
"bind": "state.radius"
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"id": "rpm",
|
|
78
|
+
"type": "slider",
|
|
79
|
+
"label": "输入转速(rpm)",
|
|
80
|
+
"bind": "state.rpm"
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"id": "angle",
|
|
84
|
+
"type": "slider",
|
|
85
|
+
"label": "手动角度(°,暂停时调节)",
|
|
86
|
+
"bind": "state.angle"
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
"id": "running",
|
|
90
|
+
"type": "toggle",
|
|
91
|
+
"label": "运行机械示意",
|
|
92
|
+
"bind": "state.running"
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
"id": "accuracy",
|
|
96
|
+
"type": "text",
|
|
97
|
+
"text": "旋转曲柄带动定长连杆,滑块沿导轨往复。默认半径20、杆长70,完整行程40,位置由几何约束计算。非动力学仿真。"
|
|
98
|
+
}
|
|
99
|
+
],
|
|
100
|
+
"data": {},
|
|
101
|
+
"derived": {},
|
|
102
|
+
"actions": {}
|
|
103
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 1,
|
|
3
|
+
"title": "齿轮传动 · 简化直齿轮示意",
|
|
4
|
+
"fallback": "外啮合齿轮反向转动。主动轮16齿、20 rpm,从动轮默认32齿、-10 rpm,中心距由模数和齿数确定。齿形为简化示意,不用于加工。",
|
|
5
|
+
"state": {
|
|
6
|
+
"explode": {
|
|
7
|
+
"type": "number",
|
|
8
|
+
"default": 0,
|
|
9
|
+
"min": 0,
|
|
10
|
+
"max": 1,
|
|
11
|
+
"step": 0.01
|
|
12
|
+
},
|
|
13
|
+
"selected": {
|
|
14
|
+
"type": "string",
|
|
15
|
+
"default": "all"
|
|
16
|
+
},
|
|
17
|
+
"cutaway": {
|
|
18
|
+
"type": "boolean",
|
|
19
|
+
"default": true
|
|
20
|
+
},
|
|
21
|
+
"rpm": {
|
|
22
|
+
"type": "number",
|
|
23
|
+
"default": 20,
|
|
24
|
+
"min": 0,
|
|
25
|
+
"max": 90,
|
|
26
|
+
"step": 1
|
|
27
|
+
},
|
|
28
|
+
"running": {
|
|
29
|
+
"type": "boolean",
|
|
30
|
+
"default": false
|
|
31
|
+
},
|
|
32
|
+
"angle": {
|
|
33
|
+
"type": "number",
|
|
34
|
+
"default": 0,
|
|
35
|
+
"min": 0,
|
|
36
|
+
"max": 360,
|
|
37
|
+
"step": 1
|
|
38
|
+
},
|
|
39
|
+
"teeth": {
|
|
40
|
+
"type": "number",
|
|
41
|
+
"default": 32,
|
|
42
|
+
"min": 16,
|
|
43
|
+
"max": 48,
|
|
44
|
+
"step": 1
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
"nodes": [
|
|
48
|
+
{
|
|
49
|
+
"id": "mechanism",
|
|
50
|
+
"type": "sandbox",
|
|
51
|
+
"title": "齿轮传动 · 简化直齿轮示意",
|
|
52
|
+
"fallback": "外啮合齿轮反向转动。主动轮16齿、20 rpm,从动轮默认32齿、-10 rpm,中心距由模数和齿数确定。齿形为简化示意,不用于加工。",
|
|
53
|
+
"height": 560,
|
|
54
|
+
"libraries": [
|
|
55
|
+
"mechanism"
|
|
56
|
+
],
|
|
57
|
+
"stateKeys": [
|
|
58
|
+
"explode",
|
|
59
|
+
"selected",
|
|
60
|
+
"cutaway",
|
|
61
|
+
"rpm",
|
|
62
|
+
"running",
|
|
63
|
+
"angle",
|
|
64
|
+
"teeth"
|
|
65
|
+
],
|
|
66
|
+
"html": "<div id=\"diagram\"><section class=\"mui-mechanism\"><svg class=\"mui-mechanism-svg\" viewBox=\"0 0 600 340\" role=\"img\" aria-label=\"结构轮廓预览;完成后显示立体细节\"><path data-material=\"metal\" data-tone=\"0\" d=\"M498.1 118.6L504.8 122.5L508.2 128.5L507.5 135.2L437.6 292.7L432.9 298.1L425.5 301L417.4 300.4L101.9 206.3L95.2 202.5L91.8 196.4L92.5 189.8L162.4 32.3L167.1 26.8L174.5 24L182.6 24.6Z\" fill-rule=\"evenodd\"/><path data-material=\"dark\" data-tone=\"0\" d=\"M250.7 128.2L247.5 133.2L242.9 137.3L237.1 140.3L230.6 142L223.8 142.3L217.1 141.1L211 138.5L206 134.7L202.3 130L200.2 124.6L199.9 119L201.4 113.5L204.6 108.5L209.2 104.4L215 101.4L221.5 99.7L228.3 99.5L235 100.7L241.1 103.3L246.1 107.1L249.8 111.8L251.9 117.1L252.2 122.7ZM236.5 121.6L236.4 119.4L235.6 117.2L234.1 115.3L232.1 113.8L229.6 112.8L227 112.3L224.2 112.4L221.6 113.1L219.3 114.3L217.5 115.9L216.2 117.9L215.6 120.1L215.7 122.4L216.5 124.5L218 126.4L220 127.9L222.5 128.9L225.1 129.4L227.9 129.3L230.5 128.7L232.8 127.5L234.6 125.8L235.9 123.8ZM339.4 154.7L336.3 159.7L331.7 163.8L325.9 166.8L319.3 168.5L312.5 168.7L305.8 167.5L299.7 164.9L294.7 161.1L291 156.4L289 151.1L288.7 145.5L290.1 140L293.3 135L297.9 130.9L303.7 127.9L310.2 126.2L317.1 125.9L323.8 127.1L329.8 129.7L334.9 133.5L338.6 138.2L340.6 143.6L340.9 149.2ZM325.2 148.1L325.1 145.8L324.3 143.7L322.8 141.8L320.8 140.3L318.4 139.3L315.7 138.8L313 138.9L310.4 139.5L308 140.7L306.2 142.4L304.9 144.4L304.3 146.6L304.5 148.8L305.3 151L306.8 152.9L308.8 154.4L311.2 155.4L313.9 155.9L316.6 155.8L319.2 155.1L321.5 153.9L323.4 152.3L324.6 150.3ZM257.2 69.8L256.3 71.3L254.9 72.5L253.2 73.4L251.2 73.9L249.1 74L247.1 73.6L245.3 72.9L243.8 71.7L242.7 70.3L242.1 68.7L242 67L242.4 65.4L243.4 63.9L244.8 62.6L246.5 61.7L248.5 61.2L250.5 61.2L252.5 61.5L254.3 62.3L255.9 63.4L257 64.9L257.6 66.5L257.7 68.1ZM415 116.8L414 118.3L412.6 119.5L410.9 120.5L409 121L406.9 121L404.9 120.7L403.1 119.9L401.6 118.8L400.5 117.3L399.8 115.7L399.7 114L400.2 112.4L401.1 110.9L402.5 109.7L404.3 108.8L406.2 108.3L408.3 108.2L410.3 108.6L412.1 109.3L413.6 110.5L414.7 111.9L415.3 113.5L415.4 115.2ZM199.8 199L198.9 200.5L197.5 201.7L195.7 202.6L193.8 203.2L191.7 203.2L189.7 202.9L187.9 202.1L186.4 200.9L185.3 199.5L184.7 197.9L184.6 196.2L185 194.6L186 193.1L187.4 191.9L189.1 191L191 190.5L193.1 190.4L195.1 190.7L196.9 191.5L198.4 192.7L199.5 194.1L200.2 195.7L200.3 197.4ZM357.6 246L356.6 247.5L355.2 248.8L353.5 249.7L351.5 250.2L349.5 250.3L347.5 249.9L345.7 249.1L344.1 248L343 246.6L342.4 245L342.3 243.3L342.8 241.6L343.7 240.1L345.1 238.9L346.8 238L348.8 237.5L350.9 237.4L352.9 237.8L354.7 238.6L356.2 239.7L357.3 241.1L357.9 242.7L358 244.4Z\" fill-rule=\"evenodd\"/><path data-material=\"metal\" data-tone=\"0\" d=\"M235.4 93.6L234.2 95.5L232.5 97L230.3 98.2L227.8 98.8L225.2 98.9L222.6 98.5L220.3 97.5L218.4 96L217 94.2L216.2 92.2L216.1 90.1L216.7 88L217.9 86.1L219.6 84.5L221.8 83.4L224.3 82.7L226.9 82.6L229.5 83.1L231.8 84.1L233.7 85.5L235.1 87.3L235.9 89.4L236 91.5ZM324.2 120L323 121.9L321.2 123.5L319 124.6L316.5 125.3L313.9 125.4L311.4 124.9L309.1 123.9L307.2 122.5L305.8 120.7L305 118.7L304.9 116.5L305.4 114.4L306.6 112.6L308.4 111L310.6 109.8L313.1 109.2L315.7 109.1L318.2 109.6L320.5 110.5L322.4 112L323.8 113.8L324.6 115.8L324.7 117.9Z\" fill-rule=\"evenodd\"/><path data-material=\"accent\" data-tone=\"0\" d=\"M253.9 104.1L253.5 105.7L258.9 108.4L257.4 111.9L251.1 111.1L250.1 112.5L249 113.9L252.8 118.1L249.7 120.8L244.2 118.1L242.7 119.1L241 120.1L242.6 125.1L238.4 126.7L234.7 122.5L232.7 122.9L230.8 123.3L229.8 128.4L225.3 128.6L223.7 123.5L221.8 123.3L219.8 123L216.5 127.5L212.2 126.2L213.2 121.1L211.5 120.3L209.8 119.4L204.7 122.5L201.3 119.9L204.6 115.5L203.4 114.2L202.2 112.8L196.1 114.1L194.1 110.7L199.3 107.6L198.7 106L198.3 104.4L192 103.6L191.8 99.9L198 98.7L198.2 97.1L198.6 95.5L193.2 92.7L194.7 89.2L201 90L202 88.6L203.1 87.2L199.3 83L202.4 80.3L207.9 83L209.4 82L211.1 81.1L209.5 76L213.7 74.4L217.5 78.6L219.4 78.2L221.3 77.8L222.3 72.7L226.8 72.5L228.4 77.6L230.3 77.8L232.3 78.1L235.6 73.6L239.9 74.9L238.9 80.1L240.6 80.9L242.3 81.8L247.4 78.7L250.8 81.2L247.5 85.7L248.7 86.9L249.9 88.3L256 87L258 90.4L252.8 93.5L253.4 95.1L253.8 96.7L260.1 97.5L260.3 101.2L254.1 102.4ZM236.5 101.3L236.5 100.8L236.5 99.6L236.4 99.1L236.2 98.5L236 97.9L235.8 97.5L235.2 96.4L234.9 96L234.5 95.5L234.1 95L233.6 94.6L232.6 93.8L232.1 93.5L231.5 93.2L230.8 92.9L230.3 92.7L229 92.3L228.4 92.2L227.6 92.1L226.9 92L226.3 92L224.9 92L224.3 92.1L223.6 92.2L222.8 92.4L222.3 92.5L221 93L220.5 93.3L219.8 93.6L219.3 94L218.8 94.3L217.9 95.2L217.5 95.6L217.1 96.1L216.7 96.6L216.5 97.1L216 98.2L215.8 98.7L215.7 99.3L215.6 99.9L215.6 100.4L215.6 101.5L215.7 102L215.9 102.6L216.1 103.2L216.3 103.7L216.9 104.7L217.2 105.1L217.6 105.6L218.1 106.1L218.5 106.5L219.5 107.3L220 107.6L220.6 107.9L221.3 108.2L221.8 108.4L223.1 108.8L223.7 108.9L224.5 109.1L225.2 109.1L225.8 109.2L227.2 109.1L227.8 109L228.5 108.9L229.3 108.7L229.8 108.6L231.1 108.1L231.6 107.8L232.3 107.5L232.8 107.1L233.3 106.8L234.2 105.9L234.6 105.5L235 105L235.4 104.5L235.7 104L236.1 103L236.3 102.5L236.4 101.9Z\" fill-rule=\"evenodd\"/><path data-material=\"cool\" data-tone=\"0\" d=\"M255.9 119.6L256.2 117.9L250.6 115.4L251.7 111.9L258.1 111.9L258.8 110.3L259.5 108.7L254.6 105.4L256.5 102.1L262.8 103.2L263.8 101.7L265 100.2L260.9 96.2L263.6 93.3L269.4 95.3L270.8 94L272.3 92.8L269.3 88.2L272.6 85.8L277.9 88.7L279.5 87.6L281.3 86.6L279.4 81.6L283.2 79.8L287.7 83.5L289.6 82.8L291.5 82.1L290.9 76.9L295.1 75.7L298.6 80L300.6 79.6L302.7 79.2L303.3 74L307.7 73.5L310.1 78.3L312.2 78.2L314.3 78.2L316.2 73.2L320.6 73.4L321.8 78.5L323.9 78.8L325.9 79L329 74.5L333.2 75.4L333.2 80.6L335.2 81.1L337.1 81.7L341.2 77.7L345.2 79.3L343.9 84.4L345.7 85.3L347.5 86.2L352.4 82.9L356 85.1L353.5 89.9L355.1 91L356.6 92.2L362.2 89.8L365.2 92.4L361.6 96.8L362.9 98.1L364.1 99.6L370.2 98.1L372.4 101.2L367.9 104.8L368.8 106.4L369.7 108L376 107.5L377.5 110.9L372.2 113.7L372.7 115.4L373.2 117.1L379.5 117.6L380.1 121.2L374.2 123.2L374.3 124.9L374.4 126.6L380.5 128.2L380.2 131.7L374 132.7L373.7 134.4L373.3 136.1L379 138.6L377.9 142.1L371.5 142.1L370.8 143.7L370 145.3L375 148.7L373.1 151.9L366.8 150.9L365.8 152.3L364.6 153.8L368.6 157.9L366 160.7L360.1 158.7L358.7 160L357.3 161.3L360.3 165.9L357 168.3L351.7 165.3L350 166.4L348.3 167.4L350.1 172.4L346.4 174.2L341.9 170.5L340 171.3L338.1 172L338.6 177.2L334.5 178.4L331 174L329 174.4L326.9 174.8L326.2 180L321.9 180.5L319.5 175.7L317.4 175.8L315.3 175.8L313.4 180.8L309 180.6L307.8 175.5L305.7 175.3L303.6 175L300.6 179.6L296.4 178.7L296.4 173.5L294.4 172.9L292.4 172.3L288.4 176.3L284.4 174.7L285.7 169.6L283.9 168.8L282.1 167.8L277.1 171.1L273.6 169L276.1 164.2L274.5 163L273 161.8L267.4 164.3L264.4 161.6L268 157.3L266.7 155.9L265.5 154.5L259.4 156L257.2 152.9L261.7 149.2L260.8 147.7L259.9 146.1L253.6 146.6L252.1 143.2L257.4 140.3L256.9 138.6L256.4 136.9L250.1 136.4L249.5 132.8L255.4 130.9L255.2 129.1L255.2 127.4L249.1 125.9L249.3 122.3L255.6 121.3ZM304.4 126L304.3 126.3L304.3 126.8L304.3 127.1L304.3 127.4L304.3 127.7L304.4 127.9L304.5 128.5L304.5 128.8L304.6 129.1L304.7 129.4L304.8 129.6L305 130.1L305.1 130.4L305.3 130.6L305.4 130.9L305.6 131.1L305.9 131.6L306.1 131.9L306.3 132.1L306.6 132.3L306.7 132.5L307.2 133L307.4 133.1L307.7 133.4L308 133.6L308.2 133.7L308.8 134.1L309 134.2L309.3 134.4L309.7 134.5L309.9 134.6L310.6 134.9L310.9 135L311.2 135.1L311.6 135.2L311.8 135.3L312.5 135.4L312.8 135.5L313.2 135.5L313.6 135.6L313.9 135.6L314.6 135.6L314.9 135.6L315.2 135.6L315.6 135.6L315.9 135.6L316.6 135.5L316.9 135.4L317.3 135.4L317.6 135.3L317.9 135.2L318.6 135L318.9 134.9L319.2 134.8L319.6 134.7L319.8 134.6L320.4 134.3L320.7 134.1L321 133.9L321.3 133.8L321.5 133.6L322.1 133.2L322.3 133L322.5 132.8L322.8 132.6L323 132.4L323.4 131.9L323.6 131.7L323.8 131.5L323.9 131.2L324.1 131L324.4 130.5L324.5 130.2L324.6 130L324.8 129.7L324.9 129.4L325 128.9L325.1 128.6L325.2 128.3L325.2 128L325.2 127.8L325.3 127.2L325.3 126.9L325.3 126.6L325.2 126.3L325.2 126.1L325.1 125.5L325.1 125.3L325 125L324.9 124.7L324.8 124.4L324.6 123.9L324.4 123.7L324.3 123.4L324.1 123.1L324 122.9L323.6 122.4L323.5 122.2L323.3 121.9L323 121.7L322.8 121.5L322.4 121.1L322.1 120.9L321.9 120.7L321.6 120.5L321.4 120.3L320.8 120L320.5 119.8L320.2 119.7L319.9 119.5L319.6 119.4L319 119.1L318.7 119L318.4 118.9L318 118.8L317.7 118.8L317.1 118.6L316.8 118.6L316.4 118.5L316 118.5L315.7 118.5L315 118.4L314.7 118.4L314.3 118.4L314 118.4L313.7 118.5L313 118.6L312.7 118.6L312.3 118.7L311.9 118.7L311.6 118.8L311 119L310.7 119.1L310.4 119.2L310 119.4L309.7 119.5L309.1 119.8L308.9 119.9L308.6 120.1L308.3 120.3L308.1 120.4L307.5 120.8L307.3 121L307.1 121.2L306.8 121.4L306.6 121.6L306.2 122.1L306 122.3L305.8 122.6L305.6 122.8L305.5 123L305.2 123.6L305.1 123.8L304.9 124.1L304.8 124.4L304.7 124.6L304.5 125.2L304.5 125.4L304.4 125.7Z\" fill-rule=\"evenodd\"/><path data-material=\"warm\" data-tone=\"0\" d=\"M240.8 95.2L238.9 98.2L236.2 100.7L232.7 102.5L228.8 103.5L224.7 103.6L220.7 102.9L217 101.3L214 99.1L211.8 96.2L210.6 93L210.4 89.7L211.3 86.4L213.2 83.4L215.9 80.9L219.4 79.1L223.3 78.1L227.4 77.9L231.4 78.7L235.1 80.2L238.1 82.5L240.3 85.3L241.6 88.5L241.7 91.9ZM236 91.5L235.9 89.4L235.1 87.3L233.7 85.5L231.8 84.1L229.5 83.1L226.9 82.6L224.3 82.7L221.8 83.4L219.6 84.5L217.9 86.1L216.7 88L216.1 90.1L216.2 92.2L217 94.2L218.4 96L220.3 97.5L222.6 98.5L225.2 98.9L227.8 98.8L230.3 98.2L232.5 97L234.2 95.5L235.4 93.6ZM329.6 121.6L327.7 124.6L324.9 127.1L321.4 128.9L317.5 129.9L313.4 130.1L309.4 129.4L305.8 127.8L302.7 125.5L300.5 122.7L299.3 119.5L299.1 116.1L300 112.8L301.9 109.8L304.7 107.4L308.1 105.6L312.1 104.5L316.2 104.4L320.2 105.1L323.8 106.7L326.8 108.9L329.1 111.8L330.3 115L330.5 118.4ZM324.7 117.9L324.6 115.8L323.8 113.8L322.4 112L320.5 110.5L318.2 109.6L315.7 109.1L313.1 109.2L310.6 109.8L308.4 111L306.6 112.6L305.4 114.4L304.9 116.5L305 118.7L305.8 120.7L307.2 122.5L309.1 123.9L311.4 124.9L313.9 125.4L316.5 125.3L319 124.6L321.2 123.5L323 121.9L324.2 120Z\" fill-rule=\"evenodd\"/></svg><p>外啮合齿轮反向转动。主动轮16齿、20 rpm,从动轮默认32齿、-10 rpm,中心距由模数和齿数确定。齿形为简化示意,不用于加工。</p></section></div>",
|
|
67
|
+
"css": "\n.mui-mechanism{font:15px/1.7 system-ui,sans-serif;color:var(--canvas-ink);background:var(--canvas-bg);border:1px solid var(--canvas-line);border-radius:24px;padding:20px;max-width:100%;box-sizing:border-box}.mui-mechanism *{box-sizing:border-box}.mui-mechanism h2{font-size:22px;line-height:1.35;margin:0 0 8px;font-weight:750}.mui-mechanism p{margin:0;color:var(--canvas-muted)}\n.mui-mechanism-svg{display:block;width:100%;height:auto;max-height:420px;touch-action:pan-y}.mui-mechanism-svg path{stroke:color-mix(in srgb,var(--canvas-ink) 38%,var(--canvas-bg));stroke-width:.8;stroke-linejoin:round;vector-effect:non-scaling-stroke;cursor:pointer;fill:var(--mech-base,var(--canvas-soft))}.mui-mechanism-svg [data-material=metal]{--mech-base:color-mix(in srgb,var(--canvas-muted) 32%,var(--canvas-bg))}.mui-mechanism-svg [data-material=dark]{--mech-base:color-mix(in srgb,var(--canvas-ink) 78%,var(--canvas-bg))}.mui-mechanism-svg [data-material=accent]{--mech-base:var(--canvas-accent)}.mui-mechanism-svg [data-material=cool]{--mech-base:color-mix(in srgb,#22998a 70%,var(--canvas-bg))}.mui-mechanism-svg [data-material=warm]{--mech-base:color-mix(in srgb,#dd9c42 75%,var(--canvas-bg))}\n.mui-mechanism-svg [data-tone=\"0\"]{fill:color-mix(in srgb,var(--mech-base) 74%,var(--canvas-bg))}.mui-mechanism-svg [data-tone=\"1\"]{fill:var(--mech-base)}.mui-mechanism-svg [data-tone=\"2\"]{fill:color-mix(in srgb,var(--mech-base) 85%,var(--canvas-ink))}.mui-mechanism-svg [data-tone=\"3\"]{fill:color-mix(in srgb,var(--mech-base) 68%,var(--canvas-ink))}.mui-mechanism-svg [data-line]{fill:none;stroke:var(--mech-base);stroke-width:2}.mui-mechanism-svg [data-active=false]{opacity:.2}.mui-mechanism-svg [data-active=true]{opacity:1}\n.mui-mechanism-nav{display:flex;flex-wrap:wrap;gap:7px;margin:8px 0 12px}.mui-mechanism button{font:inherit;color:var(--canvas-ink);background:var(--canvas-bg);border:1px solid var(--canvas-line);border-radius:999px;padding:6px 13px;cursor:pointer;min-height:36px}.mui-mechanism button[aria-pressed=true]{color:var(--canvas-bg);background:var(--canvas-ink);border-color:var(--canvas-ink)}.mui-mechanism button:focus-visible,.mui-mechanism input:focus-visible{outline:2px solid var(--canvas-accent);outline-offset:3px}.mui-mechanism button:disabled{opacity:.5;cursor:default}\n.mui-mechanism-controls{display:flex;align-items:center;flex-wrap:wrap;gap:14px;padding:12px 14px;border-radius:16px;background:var(--canvas-soft);margin:8px 0}.mui-mechanism-controls label{display:flex;align-items:center;gap:9px;flex:1 1 180px;min-width:0}.mui-mechanism-controls input[type=range]{flex:1;min-width:70px;accent-color:var(--canvas-accent)}.mui-mechanism-controls input[type=checkbox]{accent-color:var(--canvas-accent)}.mui-mechanism-controls output{font-variant-numeric:tabular-nums;min-width:40px;text-align:right;font-weight:650}.mui-mechanism-readout{display:block;padding:10px 0;font-weight:700;font-variant-numeric:tabular-nums;color:var(--canvas-ink)}.mui-mechanism-description{min-height:0;font-size:14px}\n.mui-mechanism[data-style=editorial]{border:0;border-top:1px solid var(--canvas-line);border-radius:0;padding:16px 0}.mui-mechanism[data-style=editorial] h2{font-family:ui-serif,Georgia,serif;font-weight:650}.mui-mechanism[data-style=editorial] .mui-mechanism-controls{border-radius:0;background:transparent;border-block:1px solid var(--canvas-line)}\n.mui-mechanism[data-style=technical]{border-radius:10px}.mui-mechanism[data-style=technical] button,.mui-mechanism[data-style=technical] .mui-mechanism-controls{border-radius:6px}.mui-mechanism[data-style=technical] .mui-mechanism-readout{font-family:ui-monospace,Consolas,monospace}\n.mui-mechanism[data-style=soft]{border:0;background:var(--canvas-soft);border-radius:28px 28px 28px 10px}.mui-mechanism[data-style=soft] .mui-mechanism-controls{background:var(--canvas-bg);border-radius:22px}.mui-mechanism[data-style=expressive] h2{font-size:28px;font-weight:850;border-left:5px solid var(--canvas-accent);padding-left:14px}.mui-mechanism[data-style=expressive]{border:0;border-radius:0}.mui-mechanism[data-style=prismframe]{border:1.5px solid var(--canvas-line);box-shadow:4px 5px 0 color-mix(in srgb,var(--canvas-accent) 14%,var(--canvas-bg))}.mui-mechanism[data-style=aurora]{border-radius:28px;box-shadow:0 16px 30px -25px #30204d66}.mui-mechanism[data-style=aurora] .mui-mechanism-controls{border-radius:24px}\n@media(max-width:500px){.mui-mechanism{padding:14px;border-radius:20px}.mui-mechanism h2{font-size:20px}.mui-mechanism-controls{padding:10px}.mui-mechanism-nav{gap:5px}.mui-mechanism button{padding:6px 10px;font-size:14px}}\n@media(prefers-reduced-motion:reduce){.mui-mechanism *{animation:none!important;transition:none!important}}\n@media(forced-colors:active){.mui-mechanism-svg path{fill:Canvas;stroke:CanvasText}.mui-mechanism button[aria-pressed=true]{background:Highlight;color:HighlightText}}\n",
|
|
68
|
+
"script": "const diagram=DSHUI.mechanism.mountDemo(\"#diagram\",\"gears\",{title:\"\",bind:{\"explode\":\"explode\",\"selected\":\"selected\",\"cutaway\":\"cutaway\",\"rpm\":\"rpm\",\"running\":\"running\",\"angle\":\"angle\",\"teeth\":\"teeth\"}});addEventListener(\"pagehide\",()=>diagram.destroy(),{once:true});"
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"id": "teeth",
|
|
72
|
+
"type": "slider",
|
|
73
|
+
"label": "从动轮齿数(主动轮16齿)",
|
|
74
|
+
"bind": "state.teeth"
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"id": "rpm",
|
|
78
|
+
"type": "slider",
|
|
79
|
+
"label": "输入转速(rpm)",
|
|
80
|
+
"bind": "state.rpm"
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"id": "angle",
|
|
84
|
+
"type": "slider",
|
|
85
|
+
"label": "手动角度(°,暂停时调节)",
|
|
86
|
+
"bind": "state.angle"
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
"id": "running",
|
|
90
|
+
"type": "toggle",
|
|
91
|
+
"label": "运行机械示意",
|
|
92
|
+
"bind": "state.running"
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
"id": "accuracy",
|
|
96
|
+
"type": "text",
|
|
97
|
+
"text": "外啮合齿轮反向转动。主动轮16齿、20 rpm,从动轮默认32齿、-10 rpm,中心距由模数和齿数确定。齿形为简化示意,不用于加工。"
|
|
98
|
+
}
|
|
99
|
+
],
|
|
100
|
+
"data": {},
|
|
101
|
+
"derived": {},
|
|
102
|
+
"actions": {}
|
|
103
|
+
}
|
package/index.js
CHANGED
|
@@ -1,109 +1,120 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
1
|
+
import {mechanismDocument} from './lib/mechanism-entry.js';
|
|
2
|
+
import {mechanismCatalog} from './lib/mechanism-catalog.js';
|
|
3
|
+
import {motionCatalog} from './lib/motion-library.js';
|
|
4
|
+
import { defineTool } from '@deepseek-ai/dsh-tools';
|
|
5
|
+
import { dshHomePath } from '@deepseek-ai/dsh-home-paths';
|
|
6
|
+
import { validateDocument, fallbackText } from './lib/protocol.js';
|
|
7
|
+
import { UiStore, stateRoute, documentRoute, historyRoute } from './lib/store.js';
|
|
8
|
+
import { evaluate } from './lib/protocol.js';
|
|
9
|
+
import { componentCatalog } from './lib/components.js';
|
|
10
|
+
import { CANVAS_DESIGN_GUIDE } from './lib/canvas-design.js';
|
|
11
|
+
import { architectureExample, scatterExample } from './lib/visual-examples.js';
|
|
12
|
+
import { BUILD_INFO } from './lib/build-info.js';
|
|
13
|
+
import { UI_SKILL_SECTIONS, promptSections } from './lib/ui-skill.js';
|
|
14
|
+
import {DEFAULT_VISUAL_STYLE,VISUAL_STYLE_IDS} from './lib/visual-styles.js';
|
|
15
|
+
import { canvasDocument } from './lib/freeform.js';
|
|
16
|
+
import z from '@deepseek-ai/schemastery';
|
|
17
|
+
import { toolJson } from './lib/tool-json.js';
|
|
18
|
+
import { DOCUMENT_PARAMETER,TEXT_BLOCKS_PARAMETER } from './lib/tool-schema.js';
|
|
19
|
+
import {textDocument} from './lib/text-document.js';
|
|
20
|
+
import {TEXT_PRESETS} from './lib/typography.js';
|
|
21
|
+
import { inspectRecord } from './lib/inspection.js';
|
|
22
|
+
import {QUICK_EXAMPLES,QUICK_GUIDE} from './lib/quick-examples.js';
|
|
23
|
+
import { PROTOCOL_GUIDE, calculatorExample, comparisonExample, budgetExample, curveExample, sceneExamples, bicycleExample, oscillatorExample } from './lib/catalog.js';
|
|
24
|
+
import {VISUAL_GUIDE,VISUAL_EXAMPLES,visualCatalog} from './lib/visual.js';
|
|
25
|
+
import {registerVisualAssets} from './lib/visual-assets.js';
|
|
23
26
|
import {diagnosticsRoute} from './lib/diagnostics-route.js';
|
|
24
|
-
import {fenceRoute} from './lib/fence-route.js';
|
|
27
|
+
import {fenceRoute} from './lib/fence-route.js';
|
|
25
28
|
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(()
|
|
77
|
-
name:
|
|
78
|
-
parameters:
|
|
79
|
-
|
|
29
|
+
import {registerFenceFeedback} from './lib/fence-feedback.js';
|
|
30
|
+
import {diagnoseDelivery,deliveryDiagnostics} from './lib/delivery.js';
|
|
31
|
+
|
|
32
|
+
export const name = 'motion-ui';
|
|
33
|
+
export const inject = ['tools', 'connection', 'systemPrompt'];
|
|
34
|
+
function defineRenderTool(options) {
|
|
35
|
+
const tool=defineTool(options),execute=tool.execute;
|
|
36
|
+
return {...tool,async execute(args,exec){
|
|
37
|
+
// Legacy adapters may stringify JSON. Decode here, without advertising a
|
|
38
|
+
// string branch that encourages models to manually escape whole documents.
|
|
39
|
+
// Canonicalize adapter quirks before native schema checks, so a lossless
|
|
40
|
+
// items:{item:[...]} wrapper receives the same treatment as stored/replayed UI.
|
|
41
|
+
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;
|
|
42
|
+
return execute(normalized,exec);
|
|
43
|
+
}};
|
|
44
|
+
}
|
|
45
|
+
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();
|
|
46
|
+
export function apply(ctx,config={}) {
|
|
47
|
+
const store = new UiStore(dshHomePath('plugins', 'dsh-generative-ui'));
|
|
48
|
+
const settings=()=>typeof config.get==='function'?config.get():config;
|
|
49
|
+
const feedback=registerFenceFeedback(ctx,()=>settings().autoRepair!==false);
|
|
50
|
+
const placement=value=>`\nPlace this exact fenced marker in your answer at the intended UI position:\n\`\`\`dsh-ui\n${value.documentId}\n\`\`\``;
|
|
51
|
+
ctx.effect(()=>ctx.tools.register(defineRenderTool({
|
|
52
|
+
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.',
|
|
53
|
+
parameters:{title:{type:'string'},preset:{type:'string',enum:TEXT_PRESETS},accent:{type:'string',enum:['blue','teal','violet','amber','rose']},blocks:TEXT_BLOCKS_PARAMETER},
|
|
54
|
+
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})},
|
|
55
|
+
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;}
|
|
56
|
+
})));
|
|
57
|
+
ctx.effect(() => ctx.tools.register(defineRenderTool({
|
|
58
|
+
name: 'render_ui',
|
|
59
|
+
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.',
|
|
60
|
+
parameters: { document: DOCUMENT_PARAMETER },
|
|
61
|
+
output: {
|
|
62
|
+
schema: { type: 'json' },
|
|
63
|
+
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.':'') }],
|
|
64
|
+
presentationMeta: (_args, value) => ({ dshGenerativeUi: value })
|
|
65
|
+
},
|
|
66
|
+
async execute({ document }, exec) {
|
|
67
|
+
exec.signal.throwIfAborted();
|
|
68
|
+
const validated = validateDocument(toolJson(document,'document')); fallbackText(validated);
|
|
69
|
+
const record = await store.create(validated, { sessionId: exec.agent?.id ?? 'unscoped', callId: exec.callId });
|
|
70
|
+
exec.signal.throwIfAborted(); return record;
|
|
71
|
+
}
|
|
72
|
+
})));
|
|
73
|
+
ctx.effect(()=>ctx.tools.register(defineTool({
|
|
74
|
+
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.',
|
|
75
|
+
parameters:{title:{type:'string',required:true},fallback:{type:'string',required:true},state:{type:'json'},data:{type:'json'},derived:{type:'json'},libraries:{type:'array',items:{type:'string',enum:['mechanism']}},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'}},
|
|
76
|
+
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})},
|
|
77
|
+
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;}
|
|
78
|
+
})));
|
|
79
|
+
ctx.effect(()=>ctx.tools.register(defineTool({
|
|
80
|
+
name:'render_mechanism',description:'Fast path for an educational exploded assembly, external gear pair or slider-crank mechanism. Delivers the complete interactive diagram, controls, accurate local kinematics and persisted parameters from a few arguments. Proactively useful for internal structure and working principles. No SVG/CSS/script or catalog lookup needed. scene=assembly/gears/crank. Gears use a fixed 16-tooth driver; crank uses a fixed connecting rod length70. For other geometry use render_canvas with libraries:["mechanism"] and ui_catalog topic=mechanism. Illustrative shapes, not engineering simulation. Direct native calls only.',
|
|
81
|
+
parameters:{scene:{type:'string',required:true,enum:['assembly','gears','crank']},title:{type:'string'},rpm:{type:'number',description:'gears/crank: 0..90, default20'},teeth:{type:'number',description:'gears only: driven integer16..48, default32'},radius:{type:'number',description:'crank only: integer10..28, default20'},running:{type:'boolean',description:'gears/crank: defaultfalse'},angle:{type:'number',description:'gears/crank: integer0..360 degrees, default0'},explode:{type:'number',description:'0..1 in steps0.01; assembly default0.45, others0'}},
|
|
82
|
+
output:{schema:{type:'json'},render:(_a,v)=>[{type:'text',text:fallbackText(v.document)+'\nUI documentId='+v.documentId+'; documentRevision='+v.documentRevision+'.'+placement(v)}],presentationMeta:(_a,v)=>({dshGenerativeUi:v})},
|
|
83
|
+
async execute(args,exec){exec.signal.throwIfAborted();const record=await store.create(mechanismDocument(args),{sessionId:exec.agent?.id??'unscoped',callId:exec.callId});exec.signal.throwIfAborted();return record;}
|
|
84
|
+
})));
|
|
85
|
+
ctx.effect(() => ctx.tools.register(defineTool({
|
|
86
|
+
name: 'ui_catalog', description: 'Read the DSH UI protocol and registered components. Optional topic: mechanism (assembly/gears/crank structure and kinematics; add scene for one complete example), templates (eight short scene summaries; add scene to retrieve one), motion (seven interactive recipe summaries; add scene for 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.',
|
|
87
|
+
parameters: { topic: { type: 'string', enum: ['overview', 'quick', 'visual', 'motion', 'mechanism', 'templates', 'canvas', 'data', 'scenes', 'all'], description: 'overview, quick (four lightweight static layouts), canvas, data, scenes or all; default overview' },scene:{type:'string',description:'templates: brief, comparison, flow, dashboard, quiz, form, plot, diagram; mechanism: assembly, gears, crank; motion: action, quantity, elastic, plan, checklist, copy, plot'} }, output: { schema: { type: 'json' }, render: (_args, value) => [{ type: 'text', text: JSON.stringify(value) }] },
|
|
88
|
+
isConcurrencySafe: () => true,
|
|
80
89
|
async execute({ topic = 'overview',scene } = {}) {
|
|
81
|
-
if(topic==='templates')return sceneCatalog(scene);
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
groups
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
ctx.effect(() => ctx.connection.fetch.register({ path: '/api/plugins/dsh-generative-ui/
|
|
90
|
+
if(topic==='templates')return sceneCatalog(scene);
|
|
91
|
+
if(topic==='mechanism')return mechanismCatalog(scene);
|
|
92
|
+
if(topic==='motion')return motionCatalog(scene);
|
|
93
|
+
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] };
|
|
94
|
+
groups.quick=QUICK_EXAMPLES;groups.overview=QUICK_EXAMPLES.slice(0,2);
|
|
95
|
+
groups.visual=VISUAL_EXAMPLES;
|
|
96
|
+
if (!Object.hasOwn(groups, topic)) throw new Error('Unknown ui_catalog topic; use templates, overview, quick, visual, canvas, data, scenes or all');
|
|
97
|
+
if(topic==='visual')return{build:BUILD_INFO,topic,protocol:VISUAL_GUIDE,components:visualCatalog(),examples:VISUAL_EXAMPLES};
|
|
98
|
+
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] };
|
|
99
|
+
}
|
|
100
|
+
})));
|
|
101
|
+
ctx.effect(() => ctx.connection.fetch.register({ path: '/api/plugins/dsh-generative-ui/state', methods: ['GET', 'POST'], requestBody: 'buffered', fetch: stateRoute(store) }));
|
|
102
|
+
ctx.effect(() => ctx.connection.fetch.register({ path: '/api/plugins/dsh-generative-ui/document', methods: ['GET', 'POST'], requestBody: 'buffered', fetch: documentRoute(store) }));
|
|
103
|
+
ctx.effect(() => ctx.connection.fetch.register({ path: '/api/plugins/dsh-generative-ui/history', methods: ['GET', 'POST'], requestBody: 'buffered', fetch: historyRoute(store) }));
|
|
93
104
|
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'));}})));
|
|
105
|
+
ctx.effect(()=>ctx.connection.fetch.register({path:'/api/plugins/dsh-generative-ui/diagnostics',methods:['GET'],requestBody:'buffered',fetch:diagnosticsRoute(feedback)}));
|
|
106
|
+
ctx.effect(()=>ctx.connection.fetch.register({path:'/api/plugins/dsh-generative-ui/fence',methods:['POST'],requestBody:'buffered',fetch:fenceRoute(store)}));
|
|
107
|
+
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}}}})));
|
|
108
|
+
ctx.effect(()=>ctx.tools.register(defineTool({
|
|
109
|
+
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.',
|
|
110
|
+
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.'}},
|
|
111
|
+
output:{schema:{type:'json'},render:(_args,value)=>[{type:'text',text:JSON.stringify(value)}]},isConcurrencySafe:()=>true,
|
|
112
|
+
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')});}
|
|
113
|
+
})));
|
|
114
|
+
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
115
|
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
|
-
|
|
108
|
-
|
|
109
|
-
|
|
116
|
+
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/render_mechanism, 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.':'')}));
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
|