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 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
- ![A calculator rendered inside a DSH conversation](./public/computer.png)
23
+ ![A calculator rendered inside a DSH conversation](./public/computer.webp)
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
- ![A project proposal form rendered inside a DSH conversation](./public/form.png)
29
+ ![A project proposal form rendered inside a DSH conversation](./public/form.webp)
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
- ![A traffic line chart rendered inside a DSH conversation](./public/chat.png)
37
+ ![A traffic line chart rendered inside a DSH conversation](./public/chat.webp)
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
- ### Turn the authoring prompt on
158
+ ### GenUI authoring prompt
159
159
 
160
- Click the sparkle button in the composer tool row to turn GenUI authoring on. The toggle starts off after DSH restarts or the plugin reloads, and it only controls the authoring guidance sent to the model. Card rendering stays installed either way.
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: when the composer toggle is enabled, the plugin adds a prompt section teaching the model to emit structured JSON (inside a `schemaJson` code block) when an interface would help. The DSH web client picks up that 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.
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
- ![DSH 对话里渲染出的计算器](./public/computer.png)
23
+ ![DSH 对话里渲染出的计算器](./public/computer.webp)
24
24
 
25
25
  数字键、四则运算、括号、退格、清空,全都能按。算出来的 666 是真按出来的,不是 AI 写在文字里的。
26
26
 
27
27
  ### 说「生成一个表单」
28
28
 
29
- ![DSH 对话里渲染出的项目立项申请表](./public/form.png)
29
+ ![DSH 对话里渲染出的项目立项申请表](./public/form.webp)
30
30
 
31
31
  一句话生成一整张立项申请表:必填校验、单选按钮组、下拉框、人数步进器、日期选择、开关、多选框、长文本,一次到位。
32
32
 
@@ -34,7 +34,7 @@
34
34
 
35
35
  ### 说「用折线图展示最近 7 天访问量」
36
36
 
37
- ![DSH 对话里渲染出的访问量折线图](./public/chat.png)
37
+ ![DSH 对话里渲染出的访问量折线图](./public/chat.webp)
38
38
 
39
39
  双折线、图例、坐标轴、网格线,都是渲染出来的图,不是字符画。
40
40
 
@@ -155,9 +155,9 @@ DSH 在启动时就锁定了当前的插件集合,所以**装完插件不重
155
155
  3. 浏览器刷新一下页面
156
156
  4. **开一个新会话**
157
157
 
158
- ### 打开 GenUI 提示词
158
+ ### GenUI 提示词
159
159
 
160
- 点击输入框工具行里的星形按钮,开启 GenUI 授权提示词。DSH 重启或插件重新加载后,开关默认关闭;它只控制发给模型的提示词,卡片渲染能力始终保留。
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
- 具体一点:输入框开关打开时,插件给模型加一段提示词,教它在需要的时候输出一段结构化的 JSON(写在 `schemaJson` 代码块里);DSH 网页端拿到这段 JSON 后,交给渲染器变成实际组件。整个过程是流式的,AI 写到哪、界面就渲染到哪,不用等它把话说完。
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, { enabled: control.isEnabled() });
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 on-demand authoring prompt toggle.
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
- ctx.effect(() => () => promptControl.set(false), "dsh-genui: prompt toggle state");
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(promptControl)
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.0",
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/*.png website/public/"
59
+ "sync:website-assets": "mkdir -p website/public && cp public/*.webp website/public/"
60
60
  },
61
61
  "dsh": {
62
62
  "bundle": {