dsh-genui 0.2.0 → 0.2.1
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/README.md +7 -7
- package/README.zh-CN.md +7 -7
- package/lib/index.js +56 -5
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -20,13 +20,13 @@ All three screenshots are from a live DSH session — not mockups.
|
|
|
20
20
|
|
|
21
21
|
### "Generate a calculator"
|
|
22
22
|
|
|
23
|
-

|
|
24
24
|
|
|
25
25
|
Digits, operators, parentheses, backspace, clear — every key works. That 666 was typed on the keypad, not written into the text by the model.
|
|
26
26
|
|
|
27
27
|
### "Generate a form"
|
|
28
28
|
|
|
29
|
-

|
|
30
30
|
|
|
31
31
|
One sentence produces a full project proposal form: required-field validation, radio group, dropdown, headcount stepper, date picker, toggle, checkboxes, long text.
|
|
32
32
|
|
|
@@ -34,7 +34,7 @@ Hit **Submit** and your answers go back into the conversation, so the AI can ran
|
|
|
34
34
|
|
|
35
35
|
### "Show the last 7 days of traffic as a line chart"
|
|
36
36
|
|
|
37
|
-

|
|
38
38
|
|
|
39
39
|
Two series, legend, axes, gridlines — a rendered chart, not ASCII art.
|
|
40
40
|
|
|
@@ -155,9 +155,9 @@ DSH locks in its plugin set at startup, so **nothing changes in the UI until you
|
|
|
155
155
|
3. Refresh the browser
|
|
156
156
|
4. **Start a new conversation**
|
|
157
157
|
|
|
158
|
-
###
|
|
158
|
+
### GenUI authoring prompt
|
|
159
159
|
|
|
160
|
-
|
|
160
|
+
GenUI authoring starts on by default and remembers your last choice across DSH restarts. Use the sparkle button in the composer tool row if you want to turn the authoring guidance off. Card rendering stays installed either way.
|
|
161
161
|
|
|
162
162
|
### Check that it worked
|
|
163
163
|
|
|
@@ -197,7 +197,7 @@ DSH needs pnpm to manage plugins. Run `corepack enable` (or `npm i -g pnpm`), th
|
|
|
197
197
|
|
|
198
198
|
**The AI doesn't use interfaces on its own?**
|
|
199
199
|
|
|
200
|
-
If the sparkle toggle is off, the model has no GenUI authoring guidance. Turn it on, then say something like "give me a form / chart / interface."
|
|
200
|
+
If the sparkle toggle is off, the model has no GenUI authoring guidance. Turn it back on, then say something like "give me a form / chart / interface."
|
|
201
201
|
|
|
202
202
|
**Does this change how DSH normally works?**
|
|
203
203
|
|
|
@@ -213,7 +213,7 @@ Yes. Run `dsh plugin remove`, restart, and DSH is back to its original state wit
|
|
|
213
213
|
|
|
214
214
|
In short: the model no longer writes only text — it also writes a *description of an interface*, and the browser renders that description into real components.
|
|
215
215
|
|
|
216
|
-
A bit more detail:
|
|
216
|
+
A bit more detail: the plugin adds a prompt section teaching the model to emit structured JSON (inside a `schemaJson` code block) when an interface would help. The composer sparkle toggle controls that section and is enabled by default. The DSH web client picks up the JSON and hands it to a renderer. It's streaming, so the interface appears as the model writes it — no waiting for the full reply.
|
|
217
217
|
|
|
218
218
|
The components come from [OpenTiny GenUI SDK](https://opentiny.design/genui-sdk) and the OpenTiny Vue library — OpenTiny's generative-UI stack, a spec plus rendering engine for letting LLMs produce interfaces. dsh-genui wires that into the DSH conversation flow.
|
|
219
219
|
|
package/README.zh-CN.md
CHANGED
|
@@ -20,13 +20,13 @@
|
|
|
20
20
|
|
|
21
21
|
### 说「生成一个计算器」
|
|
22
22
|
|
|
23
|
-

|
|
24
24
|
|
|
25
25
|
数字键、四则运算、括号、退格、清空,全都能按。算出来的 666 是真按出来的,不是 AI 写在文字里的。
|
|
26
26
|
|
|
27
27
|
### 说「生成一个表单」
|
|
28
28
|
|
|
29
|
-

|
|
30
30
|
|
|
31
31
|
一句话生成一整张立项申请表:必填校验、单选按钮组、下拉框、人数步进器、日期选择、开关、多选框、长文本,一次到位。
|
|
32
32
|
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
|
|
35
35
|
### 说「用折线图展示最近 7 天访问量」
|
|
36
36
|
|
|
37
|
-

|
|
38
38
|
|
|
39
39
|
双折线、图例、坐标轴、网格线,都是渲染出来的图,不是字符画。
|
|
40
40
|
|
|
@@ -155,9 +155,9 @@ DSH 在启动时就锁定了当前的插件集合,所以**装完插件不重
|
|
|
155
155
|
3. 浏览器刷新一下页面
|
|
156
156
|
4. **开一个新会话**
|
|
157
157
|
|
|
158
|
-
###
|
|
158
|
+
### GenUI 提示词
|
|
159
159
|
|
|
160
|
-
|
|
160
|
+
GenUI 授权提示词默认开启,并且会记住你上一次的选择:DSH 重启后保持关闭或开启。想临时关闭时,点击输入框工具行里的星形按钮即可;它只控制发给模型的提示词,卡片渲染能力始终保留。
|
|
161
161
|
|
|
162
162
|
### 验证装好了没
|
|
163
163
|
|
|
@@ -197,7 +197,7 @@ DSH 管理插件依赖 pnpm。执行 `corepack enable`(或 `npm i -g pnpm`)
|
|
|
197
197
|
|
|
198
198
|
**AI 不主动用界面回答?**
|
|
199
199
|
|
|
200
|
-
如果星形开关是关闭的,模型不会收到 GenUI
|
|
200
|
+
如果星形开关是关闭的,模型不会收到 GenUI 提示词。重新打开开关,再说一句「用界面/表单/图表的方式给我」就行。
|
|
201
201
|
|
|
202
202
|
**会不会影响原来的用法?**
|
|
203
203
|
|
|
@@ -213,7 +213,7 @@ DSH 管理插件依赖 pnpm。执行 `corepack enable`(或 `npm i -g pnpm`)
|
|
|
213
213
|
|
|
214
214
|
一句话:AI 不再只写文字,它还会写一段「界面描述」,浏览器把这段描述渲染成真正的组件。
|
|
215
215
|
|
|
216
|
-
|
|
216
|
+
具体一点:插件默认给模型加一段提示词,教它在需要的时候输出一段结构化的 JSON(写在 `schemaJson` 代码块里);输入框里的星形开关控制是否加这段提示词。DSH 网页端拿到 JSON 后,交给渲染器变成实际组件。整个过程是流式的,AI 写到哪、界面就渲染到哪,不用等它把话说完。
|
|
217
217
|
|
|
218
218
|
组件本身来自 [OpenTiny GenUI SDK](https://opentiny.design/genui-sdk) 和 OpenTiny Vue 组件库——这是 OpenTiny 团队做的生成式 UI 方案,一整套「让大模型输出界面」的规范和渲染引擎。dsh-genui 做的事情,是把它接到了 DSH 的对话流里。
|
|
219
219
|
|
package/lib/index.js
CHANGED
|
@@ -6102,6 +6102,26 @@ function He(r, e, t, s) {
|
|
|
6102
6102
|
//#endregion
|
|
6103
6103
|
//#region src/prompt-control.ts
|
|
6104
6104
|
/**
|
|
6105
|
+
* Mirror prompt-toggle changes into DSH settings without delaying the UI.
|
|
6106
|
+
* @param control - the in-memory prompt section control.
|
|
6107
|
+
* @param settings - the registered settings scope.
|
|
6108
|
+
* @param initialEnabled - fallback when settings contains no stored value.
|
|
6109
|
+
* @param onError - called when persisting a user choice fails.
|
|
6110
|
+
*/
|
|
6111
|
+
function createPersistedPromptControl(control, settings, initialEnabled, onError, onPersist) {
|
|
6112
|
+
const stored = settings.get().enabled;
|
|
6113
|
+
control.set(typeof stored === "boolean" ? stored : initialEnabled);
|
|
6114
|
+
return {
|
|
6115
|
+
isEnabled: control.isEnabled,
|
|
6116
|
+
set(enabled) {
|
|
6117
|
+
const next = control.set(enabled);
|
|
6118
|
+
onPersist?.(next);
|
|
6119
|
+
settings.update({ enabled: next }).catch((error) => onError?.(error));
|
|
6120
|
+
return next;
|
|
6121
|
+
}
|
|
6122
|
+
};
|
|
6123
|
+
}
|
|
6124
|
+
/**
|
|
6105
6125
|
* Create the host-side on/off state for the GenUI authoring section.
|
|
6106
6126
|
* @param section - stable prompt section values.
|
|
6107
6127
|
* @param systemPrompt - host system-prompt registry.
|
|
@@ -6129,7 +6149,10 @@ function createGenuiPromptControl(section, systemPrompt) {
|
|
|
6129
6149
|
function createGenuiPromptControlHandler(control) {
|
|
6130
6150
|
return async (req, res) => {
|
|
6131
6151
|
if (req.method === "GET") {
|
|
6132
|
-
respond(res, 200, {
|
|
6152
|
+
respond(res, 200, {
|
|
6153
|
+
enabled: control.isEnabled(),
|
|
6154
|
+
...control.persisted === void 0 ? {} : { persisted: control.persisted() }
|
|
6155
|
+
});
|
|
6133
6156
|
return;
|
|
6134
6157
|
}
|
|
6135
6158
|
if (req.method !== "POST") {
|
|
@@ -6225,6 +6248,8 @@ const Config = z.object({
|
|
|
6225
6248
|
sectionOrder: z.number().default(80),
|
|
6226
6249
|
sectionName: z.string().default("genui:cards")
|
|
6227
6250
|
});
|
|
6251
|
+
/** Settings schema for the user's last prompt-toggle choice. */
|
|
6252
|
+
const PromptSettings = z.object({ enabled: z.boolean().default(true) });
|
|
6228
6253
|
/**
|
|
6229
6254
|
* Create the GenUI authoring guidance for the host system-prompt registry.
|
|
6230
6255
|
* @returns The prompt text to register while the composer toggle is enabled.
|
|
@@ -6244,7 +6269,7 @@ function genuiPromptText() {
|
|
|
6244
6269
|
}] });
|
|
6245
6270
|
}
|
|
6246
6271
|
/**
|
|
6247
|
-
* Register the GenUI runtime and the
|
|
6272
|
+
* Register the GenUI runtime and the authoring prompt toggle.
|
|
6248
6273
|
* @param ctx - Cordis context with `systemPrompt` injected.
|
|
6249
6274
|
* @param config - validated plugin config.
|
|
6250
6275
|
*/
|
|
@@ -6255,13 +6280,39 @@ function apply(ctx, config) {
|
|
|
6255
6280
|
order: config.sectionOrder,
|
|
6256
6281
|
text: genuiPromptText()
|
|
6257
6282
|
}, systemPrompt);
|
|
6258
|
-
|
|
6283
|
+
let currentControl = promptControl;
|
|
6284
|
+
let persistedAttached = false;
|
|
6285
|
+
const endpointControl = {
|
|
6286
|
+
isEnabled: () => currentControl.isEnabled(),
|
|
6287
|
+
set: (enabled) => currentControl.set(enabled),
|
|
6288
|
+
persisted: () => persistedAttached
|
|
6289
|
+
};
|
|
6290
|
+
ctx.effect(() => {
|
|
6291
|
+
promptControl.set(true);
|
|
6292
|
+
return () => promptControl.set(false);
|
|
6293
|
+
}, "dsh-genui: prompt toggle state");
|
|
6294
|
+
ctx.inject(["settings"], (settingsCtx) => {
|
|
6295
|
+
const scope = settingsCtx.settings.register("dsh-genui", PromptSettings);
|
|
6296
|
+
ctx.logger.debug("dsh-genui: settings service attached");
|
|
6297
|
+
settingsCtx.effect(() => {
|
|
6298
|
+
currentControl = createPersistedPromptControl(promptControl, scope, true, (error) => {
|
|
6299
|
+
ctx.logger.warn("dsh-genui: failed to persist prompt state", error);
|
|
6300
|
+
}, (enabled) => {
|
|
6301
|
+
ctx.logger.debug("dsh-genui: persisting prompt state enabled=%s", String(enabled));
|
|
6302
|
+
});
|
|
6303
|
+
persistedAttached = true;
|
|
6304
|
+
return () => {
|
|
6305
|
+
currentControl = promptControl;
|
|
6306
|
+
persistedAttached = false;
|
|
6307
|
+
};
|
|
6308
|
+
}, "dsh-genui: persisted prompt control");
|
|
6309
|
+
});
|
|
6259
6310
|
const artifacts = genuiRuntimeArtifactPaths();
|
|
6260
6311
|
const webServer = ctx.webServer;
|
|
6261
6312
|
ctx.effect(() => webServer.register({
|
|
6262
6313
|
kind: "exact",
|
|
6263
6314
|
path: GENUI_PROMPT_CONTROL_URL,
|
|
6264
|
-
handler: createGenuiPromptControlHandler(
|
|
6315
|
+
handler: createGenuiPromptControlHandler(endpointControl)
|
|
6265
6316
|
}), "dsh-genui: prompt toggle state endpoint");
|
|
6266
6317
|
ctx.effect(() => webServer.register({
|
|
6267
6318
|
kind: "exact",
|
|
@@ -6275,4 +6326,4 @@ function apply(ctx, config) {
|
|
|
6275
6326
|
}), "dsh-genui: runtime.js.map");
|
|
6276
6327
|
}
|
|
6277
6328
|
//#endregion
|
|
6278
|
-
export { Config, apply, inject, name };
|
|
6329
|
+
export { Config, PromptSettings, apply, inject, name };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-genui",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"packageManager": "pnpm@11.21.0",
|
|
5
5
|
"description": "GenUI for DeepSeek Harness: interactive charts, forms, calculators, dashboards, and mini apps rendered inline in assistant replies, with actions that flow back to the model.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"prepublishOnly": "pnpm build && pnpm test",
|
|
57
57
|
"website:dev": "pnpm --filter dsh-genui-website dev",
|
|
58
58
|
"website:build": "pnpm sync:website-assets && pnpm --filter dsh-genui-website build",
|
|
59
|
-
"sync:website-assets": "mkdir -p website/public && cp public/*.
|
|
59
|
+
"sync:website-assets": "mkdir -p website/public && cp public/*.webp website/public/"
|
|
60
60
|
},
|
|
61
61
|
"dsh": {
|
|
62
62
|
"bundle": {
|