@deepseek-ai/dsh-client-ui-user-questions 0.1.6-alpha.1 → 0.1.7-alpha.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.i18n.yaml +2 -2
- package/README.md +6 -4
- package/README.zh.md +6 -4
- package/lib/client.js +78 -75
- package/lib/types/client/PlanReviewPanel.d.ts +3 -3
- package/lib/types/client/contract/slots.d.ts +22 -12
- package/package.json +20 -19
package/README.i18n.yaml
CHANGED
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
|
3
3
|
# after editing either side, bring the other along and re-record with:
|
|
4
4
|
# pnpm run verify-translation-pairing --write packages/client/ui-user-questions/README.md
|
|
5
|
-
README.md:
|
|
6
|
-
README.zh.md:
|
|
5
|
+
README.md: 929494485b5ca1c0afb6fa3d24f59627136cc915
|
|
6
|
+
README.zh.md: 0269998b744e020bd9d58b8f919626297cd94f7f
|
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@ English | [中文](README.zh.md)
|
|
|
9
9
|
|
|
10
10
|
## Summary
|
|
11
11
|
|
|
12
|
-
When an agent asks a question in the Web client, this package replaces the chat composer with an interactive question surface. Users can move through questions, choose one or multiple options, enter custom answers, skip items, and submit one structured answer batch. Single-choice selections advance immediately, while drafts survive Session navigation for the lifetime of the page. A single question with a supported presentation intent can use a dedicated surface, including the plan-review card with `
|
|
12
|
+
When an agent asks a question in the Web client, this package replaces the chat composer with an interactive question surface. Users can move through questions, choose one or multiple options, enter custom answers, skip items, and submit one structured answer batch. Single-choice selections advance immediately, while drafts survive Session navigation for the lifetime of the page. A single question with a supported presentation intent can use a dedicated surface, including the plan-review card with `Request changes` and `Approve` actions.
|
|
13
13
|
|
|
14
14
|
## Table of Contents
|
|
15
15
|
|
|
@@ -33,11 +33,11 @@ A multi-select draft keeps its selected labels while the user opens or edits the
|
|
|
33
33
|
|
|
34
34
|
### The plan-review card
|
|
35
35
|
|
|
36
|
-
A `plan-review` intent — set by `dsh-plan-mode` on the `exit_plan_mode` review — renders
|
|
36
|
+
A `plan-review` intent — set by `dsh-plan-mode` on the `exit_plan_mode` review — renders a compact approval card: a `Plan review` strip with a `View full plan` link, the plan title and a two-line plain-text summary, and `Request changes` / `Approve` actions. The strip uses the shared warning dot and changes it to the ongoing loader while either action settles. The complete plan opens in the sidebar through the link or its permanent Chat card. Approve answers with the asker's approval label; `Request changes` rejects the wait as `ASK_CANCELLED`, returning the composer for the user's feedback without submitting an approval. The card has no separate refusal button.
|
|
37
37
|
|
|
38
38
|
### Failure and recovery
|
|
39
39
|
|
|
40
|
-
The generic question flow keeps its current page, selected labels, custom text, and explicit skips in a non-persisted Slot store scoped to the owning Session and keyed by the pending request's local render identity. Switching from Session A to B
|
|
40
|
+
The generic question flow keeps its current page, selected labels, custom text, and explicit skips in a non-persisted Slot store scoped to the owning Session generation and keyed by the pending request's local render identity. Switching from Session A to B retires A when no other reference owns it, so returning to A starts an empty question draft; another reference that keeps A's generation alive also keeps that draft. A different request identity reads an empty draft and replaces the previous value on its first edit; a successful answer or cancellation clears the matching value. The host remains authoritative for whether the request is pending.
|
|
41
41
|
|
|
42
42
|
-----
|
|
43
43
|
|
|
@@ -51,12 +51,14 @@ The package is one ownership rule: rendering a question is a host UI capability,
|
|
|
51
51
|
|
|
52
52
|
### Intent surface election
|
|
53
53
|
|
|
54
|
-
The card
|
|
54
|
+
The card accepts one question declaring the intent, carrying the plan as `detail`, and offering the named approve label, with at most one alternative and no multi-select. Its secondary action returns to the composer for change requests. Larger choices and multi-select questions remain in the generic flow.
|
|
55
55
|
|
|
56
56
|
### Copy and locale
|
|
57
57
|
|
|
58
58
|
Composer chrome copy (pager, buttons, placeholders, validation feedback) is bilingual: the plugin registers zh/en dictionaries under the `question` namespace of `dsh-client-locale` and hands the entry its bound translator plus the locale snapshot source through the inject face, so a locale switch re-renders a mounted composer. Question and option text arrives from the model and renders verbatim; carrier failure messages also display untranslated.
|
|
59
59
|
|
|
60
|
+
A plan review exposes `conversation.plan-review.actions` with its request key, full text, and optional invocation identity. The plan plugin opens logged plans from history and unlogged reviews as temporary sidebar previews. Opening a document does not answer or dismiss the review.
|
|
61
|
+
|
|
60
62
|
</details>
|
|
61
63
|
|
|
62
64
|
-----
|
package/README.zh.md
CHANGED
|
@@ -9,7 +9,7 @@ kind: "package-reference"
|
|
|
9
9
|
|
|
10
10
|
## 概述
|
|
11
11
|
|
|
12
|
-
当 agent(智能体)在 Web 客户端中提问时,本包会用交互式提问界面接管聊天编辑器。用户可以在问题之间导航、选择一个或多个选项、输入自定义答案、跳过问题,并提交一批结构化答案。选择单选项后会立即前进,而草稿会在当前页面的生命周期内跨会话导航保留。若唯一的问题声明了受支持的呈现意图,则可使用专用界面,包括带 `
|
|
12
|
+
当 agent(智能体)在 Web 客户端中提问时,本包会用交互式提问界面接管聊天编辑器。用户可以在问题之间导航、选择一个或多个选项、输入自定义答案、跳过问题,并提交一批结构化答案。选择单选项后会立即前进,而草稿会在当前页面的生命周期内跨会话导航保留。若唯一的问题声明了受支持的呈现意图,则可使用专用界面,包括带 `Request changes` 和 `Approve` 操作的 plan-review 卡片。
|
|
13
13
|
|
|
14
14
|
## 目录
|
|
15
15
|
|
|
@@ -33,11 +33,11 @@ kind: "package-reference"
|
|
|
33
33
|
|
|
34
34
|
### plan-review 卡片
|
|
35
35
|
|
|
36
|
-
`plan-review` 意图——由 `dsh-plan-mode` 在 `exit_plan_mode`
|
|
36
|
+
`plan-review` 意图——由 `dsh-plan-mode` 在 `exit_plan_mode` 审阅上设置——渲染紧凑审批卡片:顶部为带“查看全文”链接的“计划待审”条带,正文显示计划标题和两行纯文本摘要,底部提供“要求修改”和“同意执行”。条带使用共享 warning 状态点,并在任一操作结算期间切换为 ongoing loading。通过链接或聊天历史中的常驻卡片可在侧边栏阅读完整计划。“同意执行”用提问方的批准标签回答;“要求修改”以 `ASK_CANCELLED` 拒绝等待,让编辑器归位供用户输入反馈,不会提交批准。卡片不单列拒绝按钮。
|
|
37
37
|
|
|
38
38
|
### 失败与恢复
|
|
39
39
|
|
|
40
|
-
通用提问流程把当前题号、已选标签、自定义文本和显式跳过状态保存在非持久化 slot
|
|
40
|
+
通用提问流程把当前题号、已选标签、自定义文本和显式跳过状态保存在非持久化 slot 存储中;该存储归属对应 Session generation,并以待处理请求的本地渲染标识为键。从 Session A 切换到 B 时,如果没有其他引用持有 A,A 就会结束,因此返回 A 时会得到空的问题草稿;如果另一个引用继续持有 A 的 generation,该草稿也会保留。不同的请求标识读取空草稿,并在首次编辑时替换旧值;成功回答或取消会清除相符的值。请求是否仍在等待由主机保持权威。
|
|
41
41
|
|
|
42
42
|
-----
|
|
43
43
|
|
|
@@ -51,12 +51,14 @@ kind: "package-reference"
|
|
|
51
51
|
|
|
52
52
|
### 意图界面选择
|
|
53
53
|
|
|
54
|
-
|
|
54
|
+
卡片接管声明了意图、以 `detail` 携带计划、提供了被指名的批准标签的单个问题,要求除批准外最多一个选项,且非多选。次要操作返回编辑器供用户提出修改要求。更多选项或多选问题仍由通用流程处理。
|
|
55
55
|
|
|
56
56
|
### 文案与 locale
|
|
57
57
|
|
|
58
58
|
编辑器外框文案(翻页器、按钮、占位符、校验提示)是双语的:插件在 `dsh-client-locale` 的 `question` 命名空间下注册 zh/en 词典,并通过 inject face 把绑定的翻译函数和 locale 快照源交给该条目,因此切换语言会重新渲染已挂载的编辑器。问题与选项文本来自模型并原样渲染;载体失败消息也不经翻译直接显示。
|
|
59
59
|
|
|
60
|
+
计划审批通过 `conversation.plan-review.actions` 插槽提供请求键、完整正文和可选的调用标识。计划插件从历史中打开已记录计划,并把没有调用标识的审批作为临时侧边栏预览打开。打开文档不会回答或关闭审批。
|
|
61
|
+
|
|
60
62
|
</details>
|
|
61
63
|
|
|
62
64
|
-----
|
package/lib/client.js
CHANGED
|
@@ -21,16 +21,10 @@ window.__ModuleLoader__.load({
|
|
|
21
21
|
* Narrow a request to a renderable plan review, or return undefined to leave it
|
|
22
22
|
* to the generic question flow.
|
|
23
23
|
*
|
|
24
|
-
* The card
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
* label the intent names, and is a binary single choice: at most one option
|
|
29
|
-
* besides approve, and not multi-select. A third option or a multi-select batch
|
|
30
|
-
* has answers two buttons cannot express, so the generic flow keeps it — as it
|
|
31
|
-
* keeps any request whose intent the asker's own service would have rejected,
|
|
32
|
-
* because the client sits downstream of a wire boundary and every request must
|
|
33
|
-
* stay answerable.
|
|
24
|
+
* The card offers approval and a return to the composer for change requests.
|
|
25
|
+
* It accepts one question carrying the plan as detail and the named approve
|
|
26
|
+
* option, with at most one alternative and no multi-select. Larger choices
|
|
27
|
+
* remain in the generic question flow.
|
|
34
28
|
*
|
|
35
29
|
* @param questions - the request's whole question batch.
|
|
36
30
|
* @returns The narrowed review, or undefined when the generic flow owns it.
|
|
@@ -50,6 +44,7 @@ window.__ModuleLoader__.load({
|
|
|
50
44
|
id: question.id,
|
|
51
45
|
question: question.question,
|
|
52
46
|
plan: question.detail,
|
|
47
|
+
...intent.callId === void 0 ? {} : { callId: intent.callId },
|
|
53
48
|
approve,
|
|
54
49
|
...decline === void 0 ? {} : { decline }
|
|
55
50
|
};
|
|
@@ -205,7 +200,7 @@ window.__ModuleLoader__.load({
|
|
|
205
200
|
}
|
|
206
201
|
//#endregion
|
|
207
202
|
//#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-user-questions/src/client/PlanReviewPanel.module.css.mjs
|
|
208
|
-
const css$1 = ".LVzXQa_frame{padding:6px calc(var(--dsh-composer-side-clearance) + 16px) 10px;justify-content:center;display:flex}.LVzXQa_card{width:100%;max-width:var(--dsh-chat-content-width)
|
|
203
|
+
const css$1 = ".LVzXQa_frame{padding:6px calc(var(--dsh-composer-side-clearance) + 16px) 10px;justify-content:center;display:flex}.LVzXQa_card{width:100%;max-width:var(--dsh-chat-content-width);--dsw-elevation-stroke-color:var(--dsw-alias-border-l2);background:var(--dsw-specific-input-major);box-shadow:var(--dsw-elevation-panel);color:var(--dsw-alias-label-primary);border:0;border-radius:20px;flex-direction:column;display:flex;overflow:hidden}.LVzXQa_card,.LVzXQa_card *{box-sizing:border-box}.LVzXQa_strip{background:var(--dsw-alias-state-warn-tertiary);color:var(--dsw-alias-state-warn-primary);flex-shrink:0;align-items:center;gap:8px;padding:12px 16px;font-size:14px;line-height:20px;display:flex}.LVzXQa_footer{flex-shrink:0;justify-content:space-between;align-items:center;gap:12px;padding:8px 16px 12px;display:flex}.LVzXQa_feedback{min-height:16px;color:var(--dsw-alias-state-error-primary);font-size:11px;line-height:16px}.LVzXQa_actions{flex-shrink:0;align-items:center;gap:8px;display:flex}.LVzXQa_summary{min-width:0;padding:14px 16px 12px}.LVzXQa_title{text-overflow:ellipsis;white-space:nowrap;margin:0;font-size:15px;font-weight:500;line-height:22px;overflow:hidden}.LVzXQa_description{-webkit-line-clamp:2;color:var(--dsw-alias-label-secondary);-webkit-box-orient:vertical;margin:8px 0 0;font-size:14px;line-height:24px;display:-webkit-box;overflow:hidden}.LVzXQa_discuss{gap:6px}@media (width<=720px){.LVzXQa_card{border-radius:16px}.LVzXQa_footer{align-items:flex-end;padding:8px 12px 10px}}.LVzXQa_previewActions{align-items:center;margin-left:auto;display:flex}";
|
|
209
204
|
const tagId$1 = "@deepseek-ai/dsh-client-ui-user-questions/PlanReviewPanel.module.css";
|
|
210
205
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
|
|
211
206
|
const tag = document.createElement("style");
|
|
@@ -216,14 +211,16 @@ window.__ModuleLoader__.load({
|
|
|
216
211
|
}
|
|
217
212
|
var PlanReviewPanel_module_css_default = {
|
|
218
213
|
"actions": "LVzXQa_actions",
|
|
219
|
-
"body": "LVzXQa_body",
|
|
220
214
|
"card": "LVzXQa_card",
|
|
215
|
+
"description": "LVzXQa_description",
|
|
221
216
|
"discuss": "LVzXQa_discuss",
|
|
222
|
-
"dot": "LVzXQa_dot",
|
|
223
217
|
"feedback": "LVzXQa_feedback",
|
|
224
218
|
"footer": "LVzXQa_footer",
|
|
225
219
|
"frame": "LVzXQa_frame",
|
|
226
|
-
"
|
|
220
|
+
"previewActions": "LVzXQa_previewActions",
|
|
221
|
+
"strip": "LVzXQa_strip",
|
|
222
|
+
"summary": "LVzXQa_summary",
|
|
223
|
+
"title": "LVzXQa_title"
|
|
227
224
|
};
|
|
228
225
|
//#endregion
|
|
229
226
|
//#region lib/types/client/PlanReviewPanel.js
|
|
@@ -238,19 +235,12 @@ window.__ModuleLoader__.load({
|
|
|
238
235
|
return description === void 0 ? {} : { title: description };
|
|
239
236
|
}
|
|
240
237
|
/**
|
|
241
|
-
* Render
|
|
238
|
+
* Render plan review controls; the submitted document opens in the sidebar.
|
|
242
239
|
*
|
|
243
240
|
* @param props - the question domain face, the narrowed plan review, and `t`.
|
|
244
241
|
* @returns The plan-review takeover for this request.
|
|
245
242
|
*/
|
|
246
|
-
function PlanReviewPanel({ pending, review, t }) {
|
|
247
|
-
const markdownLabels = (0, react.useMemo)(() => ({
|
|
248
|
-
code: {
|
|
249
|
-
copyLabel: t("copy"),
|
|
250
|
-
copiedLabel: t("copied")
|
|
251
|
-
},
|
|
252
|
-
footnotes: t("markdown.footnotes")
|
|
253
|
-
}), [t]);
|
|
243
|
+
function PlanReviewPanel({ pending, review, t, renderSlot }) {
|
|
254
244
|
const [busy, setBusy] = (0, react.useState)(false);
|
|
255
245
|
const [error, setError] = (0, react.useState)(null);
|
|
256
246
|
const settle = (send) => {
|
|
@@ -267,25 +257,45 @@ window.__ModuleLoader__.load({
|
|
|
267
257
|
selected: [label]
|
|
268
258
|
}] }));
|
|
269
259
|
};
|
|
270
|
-
const
|
|
260
|
+
const summary = (0, react.useMemo)(() => {
|
|
261
|
+
const title = (0, _deepseek_ai_dsh_client_ui_primitives.extractMarkdownPlainText)(review.plan, { mode: "first-line" });
|
|
262
|
+
const description = (0, _deepseek_ai_dsh_client_ui_primitives.extractMarkdownPlainText)(review.plan, { mode: "first-paragraph" });
|
|
263
|
+
return {
|
|
264
|
+
title,
|
|
265
|
+
description: description === title ? "" : description
|
|
266
|
+
};
|
|
267
|
+
}, [review.plan]);
|
|
271
268
|
return (0, react_jsx_runtime.jsx)("div", {
|
|
272
269
|
className: PlanReviewPanel_module_css_default.frame,
|
|
273
270
|
"data-plan-review-key": pending.key,
|
|
274
271
|
children: (0, react_jsx_runtime.jsxs)("section", {
|
|
275
272
|
className: PlanReviewPanel_module_css_default.card,
|
|
276
273
|
"aria-label": review.question,
|
|
274
|
+
"aria-busy": busy,
|
|
277
275
|
children: [
|
|
278
276
|
(0, react_jsx_runtime.jsxs)("div", {
|
|
279
277
|
className: PlanReviewPanel_module_css_default.strip,
|
|
280
|
-
children: [
|
|
278
|
+
children: [
|
|
279
|
+
(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.StateDot, { state: busy ? "ongoing" : "warning" }),
|
|
280
|
+
t("plan.header"),
|
|
281
|
+
(0, react_jsx_runtime.jsx)("div", {
|
|
282
|
+
className: PlanReviewPanel_module_css_default.previewActions,
|
|
283
|
+
children: renderSlot("conversation.plan-review.actions", {
|
|
284
|
+
review,
|
|
285
|
+
requestKey: pending.key
|
|
286
|
+
})
|
|
287
|
+
})
|
|
288
|
+
]
|
|
281
289
|
}),
|
|
282
|
-
(0, react_jsx_runtime.
|
|
283
|
-
className: PlanReviewPanel_module_css_default.
|
|
284
|
-
"
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
290
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
291
|
+
className: PlanReviewPanel_module_css_default.summary,
|
|
292
|
+
children: [(0, react_jsx_runtime.jsx)("h3", {
|
|
293
|
+
className: PlanReviewPanel_module_css_default.title,
|
|
294
|
+
children: summary.title
|
|
295
|
+
}), summary.description !== "" && (0, react_jsx_runtime.jsx)("p", {
|
|
296
|
+
className: PlanReviewPanel_module_css_default.description,
|
|
297
|
+
children: summary.description
|
|
298
|
+
})]
|
|
289
299
|
}),
|
|
290
300
|
(0, react_jsx_runtime.jsxs)("div", {
|
|
291
301
|
className: PlanReviewPanel_module_css_default.footer,
|
|
@@ -295,36 +305,24 @@ window.__ModuleLoader__.load({
|
|
|
295
305
|
children: error
|
|
296
306
|
}), (0, react_jsx_runtime.jsxs)("div", {
|
|
297
307
|
className: PlanReviewPanel_module_css_default.actions,
|
|
298
|
-
children: [
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
children: t("plan.decline")
|
|
317
|
-
}),
|
|
318
|
-
(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
319
|
-
variant: "primary",
|
|
320
|
-
...tooltip(review.approve.description),
|
|
321
|
-
disabled: busy,
|
|
322
|
-
onClick: () => {
|
|
323
|
-
decide(review.approve.label);
|
|
324
|
-
},
|
|
325
|
-
children: t("plan.approve")
|
|
326
|
-
})
|
|
327
|
-
]
|
|
308
|
+
children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
309
|
+
variant: "outline",
|
|
310
|
+
className: PlanReviewPanel_module_css_default.discuss,
|
|
311
|
+
icon: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconEditOutlineRegular, { size: 14 }),
|
|
312
|
+
disabled: busy,
|
|
313
|
+
onClick: () => {
|
|
314
|
+
settle(() => pending.cancel());
|
|
315
|
+
},
|
|
316
|
+
children: t("plan.discuss")
|
|
317
|
+
}), (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
318
|
+
variant: "primary",
|
|
319
|
+
...tooltip(review.approve.description),
|
|
320
|
+
disabled: busy,
|
|
321
|
+
onClick: () => {
|
|
322
|
+
decide(review.approve.label);
|
|
323
|
+
},
|
|
324
|
+
children: t("plan.approve")
|
|
325
|
+
})]
|
|
328
326
|
})]
|
|
329
327
|
})
|
|
330
328
|
]
|
|
@@ -397,7 +395,7 @@ window.__ModuleLoader__.load({
|
|
|
397
395
|
}
|
|
398
396
|
/** Return whether a text-field key event belongs to an active IME composition. */
|
|
399
397
|
function isComposing(event) {
|
|
400
|
-
return event.nativeEvent.isComposing || event.nativeEvent
|
|
398
|
+
return event.nativeEvent.isComposing || Reflect.get(event.nativeEvent, "keyCode") === 229;
|
|
401
399
|
}
|
|
402
400
|
/**
|
|
403
401
|
* Auto-growing free-text answer: a textarea, so a long answer soft-wraps and
|
|
@@ -460,7 +458,8 @@ window.__ModuleLoader__.load({
|
|
|
460
458
|
}, question.key) : (0, react_jsx_runtime.jsx)(PlanReviewPanel, {
|
|
461
459
|
pending: question,
|
|
462
460
|
review,
|
|
463
|
-
t: props.t
|
|
461
|
+
t: props.t,
|
|
462
|
+
renderSlot: props.renderSlot
|
|
464
463
|
}, question.key);
|
|
465
464
|
}
|
|
466
465
|
function QuestionFlow({ pending, t, useStore, actions }) {
|
|
@@ -623,7 +622,7 @@ window.__ModuleLoader__.load({
|
|
|
623
622
|
onClick: () => {
|
|
624
623
|
setMinimized((current) => !current);
|
|
625
624
|
},
|
|
626
|
-
children: minimized ? (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.
|
|
625
|
+
children: minimized ? (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronUpOutlineRegular, {}) : (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutlineRegular, {})
|
|
627
626
|
}), (0, react_jsx_runtime.jsx)("button", {
|
|
628
627
|
type: "button",
|
|
629
628
|
className: QuestionComposer_module_css_default.iconButton,
|
|
@@ -631,7 +630,7 @@ window.__ModuleLoader__.load({
|
|
|
631
630
|
title: t("nav.cancel"),
|
|
632
631
|
disabled: busy !== null,
|
|
633
632
|
onClick: cancelFlow,
|
|
634
|
-
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.
|
|
633
|
+
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconCloseOutlineRegular, {})
|
|
635
634
|
})]
|
|
636
635
|
})]
|
|
637
636
|
}), !minimized && (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -667,7 +666,7 @@ window.__ModuleLoader__.load({
|
|
|
667
666
|
children: [question.multiSelect === true ? (0, react_jsx_runtime.jsx)("span", {
|
|
668
667
|
className: clsx(QuestionComposer_module_css_default.checkbox, selected && QuestionComposer_module_css_default.checkboxChecked),
|
|
669
668
|
"aria-hidden": "true",
|
|
670
|
-
children: selected && (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.
|
|
669
|
+
children: selected && (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconCheckOutlineRegular, { size: 12 })
|
|
671
670
|
}) : (0, react_jsx_runtime.jsx)("span", {
|
|
672
671
|
className: QuestionComposer_module_css_default.number,
|
|
673
672
|
children: optionIndex + 1
|
|
@@ -697,11 +696,11 @@ window.__ModuleLoader__.load({
|
|
|
697
696
|
children: [question.multiSelect === true ? (0, react_jsx_runtime.jsx)("span", {
|
|
698
697
|
className: clsx(QuestionComposer_module_css_default.checkbox, draft.custom !== "" && QuestionComposer_module_css_default.checkboxChecked),
|
|
699
698
|
"aria-hidden": "true",
|
|
700
|
-
children: draft.custom !== "" && (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.
|
|
699
|
+
children: draft.custom !== "" && (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconCheckOutlineRegular, { size: 12 })
|
|
701
700
|
}) : (0, react_jsx_runtime.jsx)("span", {
|
|
702
701
|
className: QuestionComposer_module_css_default.number,
|
|
703
702
|
"aria-hidden": "true",
|
|
704
|
-
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.
|
|
703
|
+
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconEditOutlineRegular, { size: 12 })
|
|
705
704
|
}), (0, react_jsx_runtime.jsx)(AnswerField, {
|
|
706
705
|
variant: "inline",
|
|
707
706
|
value: draft.custom,
|
|
@@ -738,7 +737,7 @@ window.__ModuleLoader__.load({
|
|
|
738
737
|
replaceProgress(index - 1, drafts);
|
|
739
738
|
setError(null);
|
|
740
739
|
},
|
|
741
|
-
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.
|
|
740
|
+
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronLeftOutlineRegular, {})
|
|
742
741
|
}),
|
|
743
742
|
(0, react_jsx_runtime.jsxs)("span", {
|
|
744
743
|
className: QuestionComposer_module_css_default.progress,
|
|
@@ -757,7 +756,7 @@ window.__ModuleLoader__.load({
|
|
|
757
756
|
replaceProgress(index + 1, drafts);
|
|
758
757
|
setError(null);
|
|
759
758
|
},
|
|
760
|
-
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.
|
|
759
|
+
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronRightOutlineRegular, {})
|
|
761
760
|
})
|
|
762
761
|
]
|
|
763
762
|
}),
|
|
@@ -802,9 +801,9 @@ window.__ModuleLoader__.load({
|
|
|
802
801
|
"action.skip": "跳过",
|
|
803
802
|
"action.next": "下一题",
|
|
804
803
|
"plan.header": "计划待审",
|
|
805
|
-
"plan.approve": "
|
|
804
|
+
"plan.approve": "同意执行",
|
|
806
805
|
"plan.decline": "拒绝",
|
|
807
|
-
"plan.discuss": "
|
|
806
|
+
"plan.discuss": "要求修改"
|
|
808
807
|
};
|
|
809
808
|
/** English dictionary, checked complete against the zh key set. */
|
|
810
809
|
const en = {
|
|
@@ -822,7 +821,7 @@ window.__ModuleLoader__.load({
|
|
|
822
821
|
"plan.header": "Plan review",
|
|
823
822
|
"plan.approve": "Approve",
|
|
824
823
|
"plan.decline": "Refuse",
|
|
825
|
-
"plan.discuss": "
|
|
824
|
+
"plan.discuss": "Request changes"
|
|
826
825
|
};
|
|
827
826
|
//#endregion
|
|
828
827
|
//#region lib/types/client/index.js
|
|
@@ -875,7 +874,11 @@ window.__ModuleLoader__.load({
|
|
|
875
874
|
name: "conversation.composer",
|
|
876
875
|
select: ({ pendingInteraction }) => pendingInteraction instanceof PendingQuestion ? pendingInteraction : null,
|
|
877
876
|
locale: NS,
|
|
878
|
-
store: questionDraftStore
|
|
877
|
+
store: questionDraftStore,
|
|
878
|
+
children: { "conversation.plan-review.actions": {
|
|
879
|
+
kind: "list",
|
|
880
|
+
scope: "session"
|
|
881
|
+
} }
|
|
879
882
|
}, QuestionComposer));
|
|
880
883
|
ctx.remote.$on("user-questions/request", function(request, next) {
|
|
881
884
|
return answerQuestion(ctx, this, request, next, registerPendingInteraction);
|
|
@@ -3,12 +3,12 @@ import type { PendingQuestion, PlanReview, QuestionComposerProps } from './contr
|
|
|
3
3
|
export type PlanReviewPanelProps = {
|
|
4
4
|
pending: PendingQuestion;
|
|
5
5
|
review: PlanReview;
|
|
6
|
-
} & Pick<QuestionComposerProps, 't'>;
|
|
6
|
+
} & Pick<QuestionComposerProps, 't' | 'renderSlot'>;
|
|
7
7
|
/**
|
|
8
|
-
* Render
|
|
8
|
+
* Render plan review controls; the submitted document opens in the sidebar.
|
|
9
9
|
*
|
|
10
10
|
* @param props - the question domain face, the narrowed plan review, and `t`.
|
|
11
11
|
* @returns The plan-review takeover for this request.
|
|
12
12
|
*/
|
|
13
|
-
export declare function PlanReviewPanel({ pending, review, t }: PlanReviewPanelProps): import("react").JSX.Element;
|
|
13
|
+
export declare function PlanReviewPanel({ pending, review, t, renderSlot }: PlanReviewPanelProps): import("react").JSX.Element;
|
|
14
14
|
//# sourceMappingURL=PlanReviewPanel.d.ts.map
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/** Question composer props and one pending Remote waterfall response. */
|
|
2
|
-
import type { PropsLocale, PropsRuntime, PropsStore } from '@deepseek-ai/dsh-client-ui-slots';
|
|
2
|
+
import type { PropsLocale, PropsRenderSlots, PropsRuntime, PropsStore } from '@deepseek-ai/dsh-client-ui-slots';
|
|
3
|
+
import type { ToolCallId } from '@deepseek-ai/dsh-llm/brand';
|
|
3
4
|
import type { SessionId } from '@deepseek-ai/dsh-session/types';
|
|
4
5
|
import type { AskUserQuestionAnswer, AskUserQuestionItem } from '@deepseek-ai/dsh-user-questions';
|
|
5
6
|
import type { createQuestionDraftStore } from '../draft-store.ts';
|
|
@@ -9,6 +10,19 @@ declare module '@deepseek-ai/dsh-client-ui-session/client' {
|
|
|
9
10
|
question: PendingQuestion;
|
|
10
11
|
}
|
|
11
12
|
}
|
|
13
|
+
declare module '@deepseek-ai/dsh-client-ui-slots' {
|
|
14
|
+
interface SlotMap {
|
|
15
|
+
/** Actions for the exact plan under review; approval remains with the question composer. */
|
|
16
|
+
'conversation.plan-review.actions': {
|
|
17
|
+
kind: 'list';
|
|
18
|
+
scope: 'session';
|
|
19
|
+
owner: {
|
|
20
|
+
review: PlanReview;
|
|
21
|
+
requestKey: PendingQuestion['key'];
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
}
|
|
12
26
|
/** One structured answer batch covering every question of the request. */
|
|
13
27
|
export type QuestionAnswer = AskUserQuestionAnswer;
|
|
14
28
|
/** One question of the request. */
|
|
@@ -29,6 +43,8 @@ export interface PlanReview {
|
|
|
29
43
|
question: string;
|
|
30
44
|
/** The plan markdown under review. */
|
|
31
45
|
plan: string;
|
|
46
|
+
/** Logged tool invocation used to reopen this plan. */
|
|
47
|
+
callId?: ToolCallId;
|
|
32
48
|
/** The option that approves the plan. */
|
|
33
49
|
approve: QuestionOption;
|
|
34
50
|
/** The option that declines it; absent when the asker offered no other option. */
|
|
@@ -38,16 +54,10 @@ export interface PlanReview {
|
|
|
38
54
|
* Narrow a request to a renderable plan review, or return undefined to leave it
|
|
39
55
|
* to the generic question flow.
|
|
40
56
|
*
|
|
41
|
-
* The card
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
* label the intent names, and is a binary single choice: at most one option
|
|
46
|
-
* besides approve, and not multi-select. A third option or a multi-select batch
|
|
47
|
-
* has answers two buttons cannot express, so the generic flow keeps it — as it
|
|
48
|
-
* keeps any request whose intent the asker's own service would have rejected,
|
|
49
|
-
* because the client sits downstream of a wire boundary and every request must
|
|
50
|
-
* stay answerable.
|
|
57
|
+
* The card offers approval and a return to the composer for change requests.
|
|
58
|
+
* It accepts one question carrying the plan as detail and the named approve
|
|
59
|
+
* option, with at most one alternative and no multi-select. Larger choices
|
|
60
|
+
* remain in the generic question flow.
|
|
51
61
|
*
|
|
52
62
|
* @param questions - the request's whole question batch.
|
|
53
63
|
* @returns The narrowed review, or undefined when the generic flow owns it.
|
|
@@ -102,7 +112,7 @@ export type QuestionWait = PendingQuestion;
|
|
|
102
112
|
* standard locale seat; the carrier plus the domain face above carry the
|
|
103
113
|
* whole behavior surface.
|
|
104
114
|
*/
|
|
105
|
-
export type QuestionComposerProps = PropsRuntime<'conversation.composer'> & PropsStore<ReturnType<typeof createQuestionDraftStore>> & {
|
|
115
|
+
export type QuestionComposerProps = PropsRuntime<'conversation.composer'> & PropsStore<ReturnType<typeof createQuestionDraftStore>> & PropsRenderSlots<'conversation.plan-review.actions'> & {
|
|
106
116
|
matched: QuestionWait;
|
|
107
117
|
} & PropsLocale<'question'>;
|
|
108
118
|
export {};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deepseek-ai/dsh-client-ui-user-questions",
|
|
3
3
|
"description": "Web ask_user_question composer takeover and plan-review presentation UI",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.7-alpha.1",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -40,29 +40,30 @@
|
|
|
40
40
|
},
|
|
41
41
|
"license": "MIT",
|
|
42
42
|
"peerDependencies": {
|
|
43
|
-
"@deepseek-ai/cordis": "^4.0.
|
|
43
|
+
"@deepseek-ai/cordis": "^4.0.3"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@types/react": "~18.3.1",
|
|
47
47
|
"react": "^18.2.0",
|
|
48
48
|
"clsx": "^2.0.0",
|
|
49
|
-
"@deepseek-ai/cordis": "^4.0.
|
|
50
|
-
"@deepseek-ai/dsh-
|
|
51
|
-
"@deepseek-ai/dsh-api-session-controller": "^0.1.
|
|
52
|
-
"@deepseek-ai/dsh-
|
|
53
|
-
"@deepseek-ai/dsh-client-
|
|
54
|
-
"@deepseek-ai/dsh-
|
|
55
|
-
"@deepseek-ai/dsh-
|
|
56
|
-
"@deepseek-ai/dsh-tools": "^0.1.
|
|
57
|
-
"@deepseek-ai/dsh-
|
|
58
|
-
"@deepseek-ai/dsh-client-ui-
|
|
59
|
-
"@deepseek-ai/dsh-client-ui-
|
|
60
|
-
"@deepseek-ai/dsh-client-ui-
|
|
61
|
-
"@deepseek-ai/dsh-
|
|
62
|
-
"@deepseek-ai/dsh-client-
|
|
63
|
-
"@deepseek-ai/dsh-
|
|
64
|
-
"@deepseek-ai/dsh-
|
|
65
|
-
"@deepseek-ai/dsh-
|
|
49
|
+
"@deepseek-ai/cordis": "^4.0.3",
|
|
50
|
+
"@deepseek-ai/dsh-agent": "^0.1.7-alpha.1",
|
|
51
|
+
"@deepseek-ai/dsh-api-session-controller": "^0.1.7-alpha.1",
|
|
52
|
+
"@deepseek-ai/dsh-client-locale": "^0.1.7-alpha.1",
|
|
53
|
+
"@deepseek-ai/dsh-client-store": "^0.1.7-alpha.1",
|
|
54
|
+
"@deepseek-ai/dsh-api-remotes": "^0.1.7-alpha.1",
|
|
55
|
+
"@deepseek-ai/dsh-system-prompt": "^0.1.7-alpha.1",
|
|
56
|
+
"@deepseek-ai/dsh-tools": "^0.1.7-alpha.1",
|
|
57
|
+
"@deepseek-ai/dsh-user-questions": "^0.1.7-alpha.1",
|
|
58
|
+
"@deepseek-ai/dsh-client-ui-primitives": "^0.1.7-alpha.1",
|
|
59
|
+
"@deepseek-ai/dsh-client-ui-slots": "^0.1.7-alpha.1",
|
|
60
|
+
"@deepseek-ai/dsh-client-ui-renderer": "^0.1.7-alpha.1",
|
|
61
|
+
"@deepseek-ai/dsh-client-ui-session": "^0.1.7-alpha.1",
|
|
62
|
+
"@deepseek-ai/dsh-client-ui-conversation": "^0.1.7-alpha.1",
|
|
63
|
+
"@deepseek-ai/dsh-client-connection": "^0.1.7-alpha.1",
|
|
64
|
+
"@deepseek-ai/dsh-session": "^0.1.7-alpha.1",
|
|
65
|
+
"@deepseek-ai/dsh-typert-protocol": "^0.1.7-alpha.1",
|
|
66
|
+
"@deepseek-ai/dsh-llm": "^0.1.7-alpha.1"
|
|
66
67
|
},
|
|
67
68
|
"files": [
|
|
68
69
|
"lib/index.js",
|