dsh-edge 0.1.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/LICENSE +21 -0
- package/README.i18n.yaml +6 -0
- package/README.md +183 -0
- package/README.zh.md +183 -0
- package/THIRD_PARTY_NOTICES.md +199 -0
- package/dist/_headers +3 -0
- package/dist/assets/fonts/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
- package/dist/assets/fonts/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
- package/dist/assets/fonts/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
- package/dist/assets/fonts/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
- package/dist/assets/fonts/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
- package/dist/assets/fonts/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
- package/dist/assets/fonts/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
- package/dist/assets/fonts/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
- package/dist/assets/fonts/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
- package/dist/assets/fonts/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
- package/dist/assets/fonts/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
- package/dist/assets/fonts/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
- package/dist/assets/fonts/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
- package/dist/assets/fonts/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
- package/dist/assets/fonts/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
- package/dist/assets/fonts/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
- package/dist/assets/fonts/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
- package/dist/assets/fonts/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
- package/dist/assets/fonts/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
- package/dist/assets/fonts/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
- package/dist/assets/fonts/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
- package/dist/assets/fonts/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
- package/dist/assets/fonts/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
- package/dist/assets/fonts/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
- package/dist/assets/fonts/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
- package/dist/assets/fonts/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
- package/dist/assets/fonts/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
- package/dist/assets/fonts/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
- package/dist/assets/fonts/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
- package/dist/assets/fonts/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
- package/dist/assets/fonts/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
- package/dist/assets/fonts/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
- package/dist/assets/fonts/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
- package/dist/assets/fonts/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
- package/dist/assets/fonts/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
- package/dist/assets/fonts/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
- package/dist/assets/fonts/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
- package/dist/assets/fonts/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
- package/dist/assets/fonts/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
- package/dist/assets/fonts/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
- package/dist/assets/fonts/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
- package/dist/assets/fonts/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
- package/dist/assets/fonts/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
- package/dist/assets/fonts/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
- package/dist/assets/fonts/KaTeX_Script-Regular-D5yQViql.woff +0 -0
- package/dist/assets/fonts/KaTeX_Size1-Regular-C195tn64.woff +0 -0
- package/dist/assets/fonts/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
- package/dist/assets/fonts/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
- package/dist/assets/fonts/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
- package/dist/assets/fonts/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
- package/dist/assets/fonts/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
- package/dist/assets/fonts/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
- package/dist/assets/fonts/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
- package/dist/assets/fonts/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
- package/dist/assets/fonts/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
- package/dist/assets/fonts/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
- package/dist/assets/fonts/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
- package/dist/assets/fonts/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
- package/dist/assets/fonts/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
- package/dist/assets/index-C-1AiF3k.js +112 -0
- package/dist/assets/index-CSGf6Qzd.css +1 -0
- package/dist/assets/langs/c-BIGW1oBm.js +2 -0
- package/dist/assets/langs/cpp-DIPi6g--.js +2 -0
- package/dist/assets/langs/csharp-DSvCPggb.js +2 -0
- package/dist/assets/langs/css-CLj8gQPS.js +2 -0
- package/dist/assets/langs/go-C27-OAKa.js +2 -0
- package/dist/assets/langs/html-CfGypltT.js +2 -0
- package/dist/assets/langs/ini-BEwlwnbL.js +2 -0
- package/dist/assets/langs/java-CylS5w8V.js +2 -0
- package/dist/assets/langs/kotlin-BdnUsdx6.js +2 -0
- package/dist/assets/langs/less-B1dDrJ26.js +2 -0
- package/dist/assets/langs/lua-BaeVxFsk.js +2 -0
- package/dist/assets/langs/markdown-Cvjx9yec.js +2 -0
- package/dist/assets/langs/mdx-Cmh6b_Ma.js +2 -0
- package/dist/assets/langs/php-D-uCvoST.js +2 -0
- package/dist/assets/langs/python-B6aJPvgy.js +2 -0
- package/dist/assets/langs/ruby-DEItuUFs.js +2 -0
- package/dist/assets/langs/rust-B1yitclQ.js +2 -0
- package/dist/assets/langs/scss-D5BDwBP9.js +2 -0
- package/dist/assets/langs/sql-CRqJ_cUM.js +2 -0
- package/dist/assets/langs/swift-D82vCrfD.js +2 -0
- package/dist/assets/langs/toml-vGWfd6FD.js +2 -0
- package/dist/assets/langs/xml-sdJ4AIDG.js +2 -0
- package/dist/assets/langs/yaml-Buea-lGh.js +2 -0
- package/dist/assets/vendor-Cjbwl5VI.js +411 -0
- package/dist/assets/vendor-CjyC-hUb.css +1 -0
- package/dist/favicon.svg +8 -0
- package/dist/index.html +35 -0
- package/dist/manifest.webmanifest +16 -0
- package/dist/plugins/@deepseek-ai/dsh-api-gateway/client.js +420 -0
- package/dist/plugins/@deepseek-ai/dsh-api-remotes/client.js +5937 -0
- package/dist/plugins/@deepseek-ai/dsh-client-connection/client.js +10207 -0
- package/dist/plugins/@deepseek-ai/dsh-client-locale/client.js +1231 -0
- package/dist/plugins/@deepseek-ai/dsh-client-modules/client.js +259 -0
- package/dist/plugins/@deepseek-ai/dsh-client-runtime/client.js +10539 -0
- package/dist/plugins/@deepseek-ai/dsh-client-ui-agent-preset/client.js +1725 -0
- package/dist/plugins/@deepseek-ai/dsh-client-ui-commands/client.js +1116 -0
- package/dist/plugins/@deepseek-ai/dsh-client-ui-conversation/client.js +9832 -0
- package/dist/plugins/@deepseek-ai/dsh-client-ui-deliverables/client.js +373 -0
- package/dist/plugins/@deepseek-ai/dsh-client-ui-edge/client.js +549 -0
- package/dist/plugins/@deepseek-ai/dsh-client-ui-input-trigger/client.js +859 -0
- package/dist/plugins/@deepseek-ai/dsh-client-ui-jobs/client.js +280 -0
- package/dist/plugins/@deepseek-ai/dsh-client-ui-layout/client.js +456 -0
- package/dist/plugins/@deepseek-ai/dsh-client-ui-model-selection/client.js +804 -0
- package/dist/plugins/@deepseek-ai/dsh-client-ui-permission-presets/client.js +461 -0
- package/dist/plugins/@deepseek-ai/dsh-client-ui-settings/client.js +254 -0
- package/dist/plugins/@deepseek-ai/dsh-client-ui-settings-general/client.js +609 -0
- package/dist/plugins/@deepseek-ai/dsh-client-ui-sidebar/client.js +292 -0
- package/dist/plugins/@deepseek-ai/dsh-client-ui-skill/client.js +327 -0
- package/dist/plugins/@deepseek-ai/dsh-client-ui-subagent/client.js +710 -0
- package/dist/plugins/@deepseek-ai/dsh-client-ui-theme/client.js +1312 -0
- package/dist/plugins/@deepseek-ai/dsh-client-ui-tool/client.js +1630 -0
- package/dist/plugins/@deepseek-ai/dsh-client-ui-trajectory/client.js +7370 -0
- package/dist/plugins/@deepseek-ai/dsh-client-ui-user-questions/client.js +700 -0
- package/dist/plugins/@deepseek-ai/dsh-client-ui-workflow-run/client.js +474 -0
- package/dist/plugins/@deepseek-ai/dsh-client-ui-workspace/client.js +2426 -0
- package/dist/plugins/@deepseek-ai/dsh-typert-registry/client.js +1372 -0
- package/package.json +97 -0
- package/scripts/assemble-web.mjs +230 -0
- package/scripts/bundle-size.d.mts +2 -0
- package/scripts/bundle-size.mjs +26 -0
- package/scripts/bundle.mjs +53 -0
- package/scripts/cli.d.mts +39 -0
- package/scripts/cli.mjs +496 -0
- package/scripts/install.d.mts +149 -0
- package/scripts/install.mjs +989 -0
- package/scripts/legal-files.mjs +24 -0
- package/scripts/verify-packed.mjs +32 -0
- package/scripts/wrangler-config.d.mts +18 -0
- package/scripts/wrangler-config.mjs +84 -0
- package/src/agent.ts +119 -0
- package/src/auth.ts +352 -0
- package/src/deepseek.ts +231 -0
- package/src/deployment.ts +147 -0
- package/src/direct-shell-core-empty.ts +10 -0
- package/src/direct-shell-protocol.ts +5 -0
- package/src/direct-shell.ts +341 -0
- package/src/do-session-persistence.ts +1064 -0
- package/src/edge-api.ts +796 -0
- package/src/edge-credentials.ts +56 -0
- package/src/edge-remotes.ts +41 -0
- package/src/edge-workspace-store.ts +339 -0
- package/src/http.ts +212 -0
- package/src/index.ts +196 -0
- package/src/instance.ts +1007 -0
- package/src/isolated-direct-shell-unavailable.ts +11 -0
- package/src/protocol.ts +39 -0
- package/src/release.ts +9 -0
- package/src/session-store.ts +1110 -0
- package/src/sse.ts +86 -0
- package/src/web-search.ts +38 -0
- package/src/workspace.ts +270 -0
- package/wrangler.jsonc +56 -0
|
@@ -0,0 +1,700 @@
|
|
|
1
|
+
window.__ModuleLoader__.load({
|
|
2
|
+
id: "@deepseek-ai/dsh-client-ui-user-questions",
|
|
3
|
+
factory: (require) => {
|
|
4
|
+
var module = { exports: {} };
|
|
5
|
+
var exports = module.exports;
|
|
6
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
7
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
8
|
+
let react = require("react");
|
|
9
|
+
let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
10
|
+
//#region ../../../node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.mjs
|
|
11
|
+
function r(e) {
|
|
12
|
+
var t, f, n = "";
|
|
13
|
+
if ("string" == typeof e || "number" == typeof e) n += e;
|
|
14
|
+
else if ("object" == typeof e) if (Array.isArray(e)) {
|
|
15
|
+
var o = e.length;
|
|
16
|
+
for (t = 0; t < o; t++) e[t] && (f = r(e[t])) && (n && (n += " "), n += f);
|
|
17
|
+
} else for (f in e) e[f] && (n && (n += " "), n += f);
|
|
18
|
+
return n;
|
|
19
|
+
}
|
|
20
|
+
function clsx() {
|
|
21
|
+
for (var e, t, f = 0, n = "", o = arguments.length; f < o; f++) (e = arguments[f]) && (t = r(e)) && (n && (n += " "), n += t);
|
|
22
|
+
return n;
|
|
23
|
+
}
|
|
24
|
+
//#endregion
|
|
25
|
+
//#region lib/types/client/contract/slots.js
|
|
26
|
+
/**
|
|
27
|
+
* Narrow a request to a renderable plan review, or return undefined to leave it
|
|
28
|
+
* to the generic question flow.
|
|
29
|
+
*
|
|
30
|
+
* The card is one decision over one plan, and it claims a request only when it
|
|
31
|
+
* can send every answer that request allows — an intent changes the layout,
|
|
32
|
+
* never which answers are reachable. So the batch must be a single question
|
|
33
|
+
* that declares the intent, carries the plan as its detail, offers the approve
|
|
34
|
+
* label the intent names, and is a binary single choice: at most one option
|
|
35
|
+
* besides approve, and not multi-select. A third option or a multi-select batch
|
|
36
|
+
* has answers two buttons cannot express, so the generic flow keeps it — as it
|
|
37
|
+
* keeps any request whose intent the asker's own service would have rejected,
|
|
38
|
+
* because the client sits downstream of a wire boundary and every request must
|
|
39
|
+
* stay answerable.
|
|
40
|
+
*
|
|
41
|
+
* @param questions - the request's whole question batch.
|
|
42
|
+
* @returns The narrowed review, or undefined when the generic flow owns it.
|
|
43
|
+
*/
|
|
44
|
+
function planReviewOf(questions) {
|
|
45
|
+
if (questions.length !== 1) return void 0;
|
|
46
|
+
const question = questions[0];
|
|
47
|
+
const intent = question.intent;
|
|
48
|
+
if (intent?.kind !== "plan-review" || question.detail === void 0) return void 0;
|
|
49
|
+
if (question.multiSelect === true) return void 0;
|
|
50
|
+
const options = question.options ?? [];
|
|
51
|
+
if (options.length > 2) return void 0;
|
|
52
|
+
const approve = options.find((option) => option.label === intent.approve);
|
|
53
|
+
if (approve === void 0) return void 0;
|
|
54
|
+
const decline = options.find((option) => option.label !== intent.approve);
|
|
55
|
+
return {
|
|
56
|
+
id: question.id,
|
|
57
|
+
question: question.question,
|
|
58
|
+
plan: question.detail,
|
|
59
|
+
approve,
|
|
60
|
+
...decline === void 0 ? {} : { decline }
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Question domain face over the carrier: render identity and questions
|
|
65
|
+
* transparently forwarded; answer/cancel own the wire encoding (the success
|
|
66
|
+
* fields and the cancelled error) and turn a rejected carrier receipt into a
|
|
67
|
+
* thrown error. Components mint one per carrier via useMemo (never inside a
|
|
68
|
+
* select — a per-dispatch mint would churn identity and break memoization).
|
|
69
|
+
*/
|
|
70
|
+
var PendingQuestion = class {
|
|
71
|
+
wait;
|
|
72
|
+
/**
|
|
73
|
+
* @param wait - the runtime carrier for one pending question request.
|
|
74
|
+
*/
|
|
75
|
+
constructor(wait) {
|
|
76
|
+
this.wait = wait;
|
|
77
|
+
}
|
|
78
|
+
/** Opaque render identity (React key / draft remount axis), forwarded from the carrier. */
|
|
79
|
+
get key() {
|
|
80
|
+
return this.wait.key;
|
|
81
|
+
}
|
|
82
|
+
/** The request's question list, forwarded from the carrier payload. */
|
|
83
|
+
get questions() {
|
|
84
|
+
return this.wait.payload.questions;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Deliver the whole answer batch; a rejected carrier receipt throws.
|
|
88
|
+
* @param answer - complete structured answer batch.
|
|
89
|
+
*/
|
|
90
|
+
async answer(answer) {
|
|
91
|
+
const receipt = await this.wait.respond({
|
|
92
|
+
ok: true,
|
|
93
|
+
value: {
|
|
94
|
+
sessionId: this.wait.sessionId,
|
|
95
|
+
answer
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
if (!receipt.accepted) throw new Error(`question response rejected: ${receipt.reason}`);
|
|
99
|
+
}
|
|
100
|
+
/** Reject the whole wait (the host resolves the tool call as cancelled); a rejected receipt throws. */
|
|
101
|
+
async cancel() {
|
|
102
|
+
const receipt = await this.wait.respond({
|
|
103
|
+
ok: false,
|
|
104
|
+
error: {
|
|
105
|
+
code: "cancelled",
|
|
106
|
+
message: "the user closed this question request",
|
|
107
|
+
details: {}
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
if (!receipt.accepted) throw new Error(`question cancellation rejected: ${receipt.reason}`);
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
//#endregion
|
|
114
|
+
//#region \0dsh-css:/private/var/folders/nm/n5smty9962gf5rhjc5855kt80000gn/T/dsh-edge-release-worktree.XXXXXX.RcJjogaGt4/repo/packages/client/ui-user-questions/src/client/PlanReviewPanel.module.css.mjs
|
|
115
|
+
const css$1 = ".rVSvAG_frame{padding:6px calc(var(--dsh-composer-side-clearance) + 16px) 10px;justify-content:center;display:flex}.rVSvAG_card{width:100%;max-width:var(--dsh-chat-content-width);border:1px solid var(--dsw-alias-state-warn-secondary);background:var(--dsw-specific-input-major);max-height:min(60vh,520px);box-shadow:var(--dsw-shadow-lv2);color:var(--dsw-alias-label-primary);--dsh-scrollbar-thumb:var(--dsw-alias-scrollbar-bg-l2);--dsh-scrollbar-thumb-hover:var(--dsw-alias-scrollbar-hover-l2);border-radius:20px;flex-direction:column;display:flex;overflow:hidden}.rVSvAG_card,.rVSvAG_card *{box-sizing:border-box}.rVSvAG_strip{background:var(--dsw-alias-state-warn-tertiary);color:var(--dsw-alias-state-warn-primary);flex-shrink:0;align-items:center;gap:8px;padding:10px 16px;font-size:13px;line-height:18px;display:flex}.rVSvAG_dot{background:var(--dsw-alias-state-warn-primary);border-radius:50%;width:8px;height:8px}.rVSvAG_body{overscroll-behavior:contain;flex:auto;min-height:0;padding:12px 16px 4px;font-size:14px;line-height:22px;overflow-y:auto}.rVSvAG_footer{flex-shrink:0;justify-content:space-between;align-items:center;gap:12px;padding:8px 16px 12px;display:flex}.rVSvAG_feedback{min-height:16px;color:var(--dsw-alias-state-error-primary);font-size:11px;line-height:16px}.rVSvAG_actions{flex-shrink:0;align-items:center;gap:8px;display:flex}.rVSvAG_discuss{color:var(--dsw-alias-label-secondary);gap:6px}.rVSvAG_discuss:hover:not(:disabled){color:var(--dsw-alias-label-primary)}@media (width<=720px){.rVSvAG_card{border-radius:16px}.rVSvAG_body{padding:10px 12px 4px}.rVSvAG_footer{align-items:flex-end;padding:8px 12px 10px}}";
|
|
116
|
+
const tagId$1 = "@deepseek-ai/dsh-client-ui-user-questions/PlanReviewPanel.module.css";
|
|
117
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
|
|
118
|
+
const tag = document.createElement("style");
|
|
119
|
+
tag.dataset.plugin = "@deepseek-ai/dsh-client-ui-user-questions";
|
|
120
|
+
tag.dataset.pluginCss = tagId$1;
|
|
121
|
+
tag.textContent = css$1;
|
|
122
|
+
document.head.appendChild(tag);
|
|
123
|
+
}
|
|
124
|
+
var PlanReviewPanel_module_css_default = {
|
|
125
|
+
"card": "rVSvAG_card",
|
|
126
|
+
"actions": "rVSvAG_actions",
|
|
127
|
+
"footer": "rVSvAG_footer",
|
|
128
|
+
"body": "rVSvAG_body",
|
|
129
|
+
"discuss": "rVSvAG_discuss",
|
|
130
|
+
"feedback": "rVSvAG_feedback",
|
|
131
|
+
"dot": "rVSvAG_dot",
|
|
132
|
+
"strip": "rVSvAG_strip",
|
|
133
|
+
"frame": "rVSvAG_frame"
|
|
134
|
+
};
|
|
135
|
+
//#endregion
|
|
136
|
+
//#region lib/types/client/PlanReviewPanel.js
|
|
137
|
+
/**
|
|
138
|
+
* Optional-prop spread for a decision button's tooltip: `title` is optional on
|
|
139
|
+
* the DOM props, and exactOptionalPropertyTypes rejects an explicit undefined.
|
|
140
|
+
*
|
|
141
|
+
* @param description - the asker's option description, when it carries one.
|
|
142
|
+
* @returns The `title` prop to spread, or nothing.
|
|
143
|
+
*/
|
|
144
|
+
function tooltip(description) {
|
|
145
|
+
return description === void 0 ? {} : { title: description };
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Render a plan review as a decision card.
|
|
149
|
+
*
|
|
150
|
+
* @param props - the question domain face, the narrowed plan review, and `t`.
|
|
151
|
+
* @returns The plan-review takeover for this request.
|
|
152
|
+
*/
|
|
153
|
+
function PlanReviewPanel({ pending, review, t }) {
|
|
154
|
+
const [busy, setBusy] = (0, react.useState)(false);
|
|
155
|
+
const [error, setError] = (0, react.useState)(null);
|
|
156
|
+
const settle = (send) => {
|
|
157
|
+
setBusy(true);
|
|
158
|
+
setError(null);
|
|
159
|
+
send().catch((cause) => {
|
|
160
|
+
setBusy(false);
|
|
161
|
+
setError(cause instanceof Error ? cause.message : String(cause));
|
|
162
|
+
});
|
|
163
|
+
};
|
|
164
|
+
const decide = (label) => {
|
|
165
|
+
settle(() => pending.answer({ answers: [{
|
|
166
|
+
id: review.id,
|
|
167
|
+
selected: [label]
|
|
168
|
+
}] }));
|
|
169
|
+
};
|
|
170
|
+
const decline = review.decline;
|
|
171
|
+
return (0, react_jsx_runtime.jsx)("div", {
|
|
172
|
+
className: PlanReviewPanel_module_css_default.frame,
|
|
173
|
+
"data-plan-review-key": pending.key,
|
|
174
|
+
children: (0, react_jsx_runtime.jsxs)("section", {
|
|
175
|
+
className: PlanReviewPanel_module_css_default.card,
|
|
176
|
+
"aria-label": review.question,
|
|
177
|
+
children: [
|
|
178
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
179
|
+
className: PlanReviewPanel_module_css_default.strip,
|
|
180
|
+
children: [(0, react_jsx_runtime.jsx)("span", { className: PlanReviewPanel_module_css_default.dot }), t("plan.header")]
|
|
181
|
+
}),
|
|
182
|
+
(0, react_jsx_runtime.jsx)("div", {
|
|
183
|
+
className: PlanReviewPanel_module_css_default.body,
|
|
184
|
+
"data-plan-review-scroll": true,
|
|
185
|
+
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.MarkdownText, { text: review.plan })
|
|
186
|
+
}),
|
|
187
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
188
|
+
className: PlanReviewPanel_module_css_default.footer,
|
|
189
|
+
children: [(0, react_jsx_runtime.jsx)("div", {
|
|
190
|
+
className: PlanReviewPanel_module_css_default.feedback,
|
|
191
|
+
role: "status",
|
|
192
|
+
children: error
|
|
193
|
+
}), (0, react_jsx_runtime.jsxs)("div", {
|
|
194
|
+
className: PlanReviewPanel_module_css_default.actions,
|
|
195
|
+
children: [
|
|
196
|
+
(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
197
|
+
variant: "ghost",
|
|
198
|
+
className: PlanReviewPanel_module_css_default.discuss,
|
|
199
|
+
icon: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconEditOutline16, { size: 14 }),
|
|
200
|
+
disabled: busy,
|
|
201
|
+
onClick: () => {
|
|
202
|
+
settle(() => pending.cancel());
|
|
203
|
+
},
|
|
204
|
+
children: t("plan.discuss")
|
|
205
|
+
}),
|
|
206
|
+
decline !== void 0 && (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
207
|
+
variant: "outline",
|
|
208
|
+
...tooltip(decline.description),
|
|
209
|
+
disabled: busy,
|
|
210
|
+
onClick: () => {
|
|
211
|
+
decide(decline.label);
|
|
212
|
+
},
|
|
213
|
+
children: t("plan.decline")
|
|
214
|
+
}),
|
|
215
|
+
(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
216
|
+
variant: "primary",
|
|
217
|
+
...tooltip(review.approve.description),
|
|
218
|
+
disabled: busy,
|
|
219
|
+
onClick: () => {
|
|
220
|
+
decide(review.approve.label);
|
|
221
|
+
},
|
|
222
|
+
children: t("plan.approve")
|
|
223
|
+
})
|
|
224
|
+
]
|
|
225
|
+
})]
|
|
226
|
+
})
|
|
227
|
+
]
|
|
228
|
+
})
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
//#endregion
|
|
232
|
+
//#region \0dsh-css:/private/var/folders/nm/n5smty9962gf5rhjc5855kt80000gn/T/dsh-edge-release-worktree.XXXXXX.RcJjogaGt4/repo/packages/client/ui-user-questions/src/client/QuestionComposer.module.css.mjs
|
|
233
|
+
const css = ".Fjs5Aa_frame{padding:6px calc(var(--dsh-composer-side-clearance) + 16px) 10px;justify-content:center;display:flex}.Fjs5Aa_card{width:100%;max-width:var(--dsh-chat-content-width);border:1px solid var(--dsw-alias-border-l2-darkmode-thin);background:var(--dsw-specific-input-major);max-height:min(60vh,520px);box-shadow:var(--dsw-shadow-lv2);color:var(--dsw-alias-label-primary);--dsh-scrollbar-thumb:var(--dsw-alias-scrollbar-bg-l2);--dsh-scrollbar-thumb-hover:var(--dsw-alias-scrollbar-hover-l2);border-radius:20px;flex-direction:column;padding:0 0 10px;display:flex;overflow:hidden}.Fjs5Aa_card,.Fjs5Aa_card *{box-sizing:border-box}.Fjs5Aa_cardMinimized{max-height:none}.Fjs5Aa_cardMinimized .Fjs5Aa_header{padding-bottom:14px}.Fjs5Aa_headerActions{flex-shrink:0;align-items:center;gap:4px;display:flex}.Fjs5Aa_header{flex-shrink:0;justify-content:space-between;align-items:flex-start;gap:16px;padding:20px 16px 0 24px;display:flex}.Fjs5Aa_headingBlock{min-width:0}.Fjs5Aa_eyebrow{color:var(--dsw-alias-label-tertiary);margin-bottom:5px;font-size:11px;line-height:16px}.Fjs5Aa_title{margin:0;font-size:16px;font-weight:500;line-height:22px}.Fjs5Aa_detail{margin:0 2px 8px}.Fjs5Aa_footerActions{flex-shrink:0;align-items:center;gap:12px;display:flex}.Fjs5Aa_pager{flex-shrink:0;align-items:center;gap:6px;display:flex}.Fjs5Aa_progress{color:var(--dsw-alias-label-secondary);white-space:nowrap;word-spacing:-2px;padding:0 4px;font-size:14px;font-weight:500;line-height:24px}.Fjs5Aa_iconButton{width:24px;height:24px;color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:none;border-radius:999px;place-items:center;padding:0;display:grid}.Fjs5Aa_iconButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.Fjs5Aa_iconButton:disabled{color:var(--dsw-alias-label-dimmed);cursor:default}.Fjs5Aa_body{overscroll-behavior:contain;flex-direction:column;flex:auto;min-height:0;display:flex;overflow-y:auto}.Fjs5Aa_options{flex-direction:column;gap:1px;margin:8px 0 0;padding:4px 12px;display:flex}.Fjs5Aa_option{width:100%;min-height:40px;color:inherit;text-align:left;cursor:pointer;background:0 0;border:1px solid #0000;border-radius:12px;flex-shrink:0;align-items:flex-start;gap:8px;padding:8px 12px 8px 8px;transition:background-color .12s,border-color .12s;display:flex}.Fjs5Aa_option:hover:not(:disabled),.Fjs5Aa_optionSelected{background:var(--dsw-alias-interactive-bg-hover)}.Fjs5Aa_optionSelected{border-color:var(--dsw-alias-border-l2)}.Fjs5Aa_option:disabled{cursor:default}.Fjs5Aa_number{background:var(--dsw-alias-bg-overlay);width:20px;height:20px;color:var(--dsw-alias-label-secondary);border-radius:6px;flex:0 0 20px;place-items:center;margin-top:2px;font-size:12px;font-weight:500;line-height:18px;display:grid}.Fjs5Aa_checkbox{flex:0 0 20px;place-items:center;width:20px;height:20px;margin-top:2px;display:grid}.Fjs5Aa_checkbox:before{content:\"\";border:1px solid var(--dsw-alias-border-l4);border-radius:4px;grid-area:1/1;width:14px;height:14px;transition:background-color .12s,border-color .12s}.Fjs5Aa_checkbox>svg{grid-area:1/1}.Fjs5Aa_checkboxChecked{color:var(--dsw-alias-label-primary-foreground)}.Fjs5Aa_checkboxChecked:before{border-color:var(--dsw-alias-label-primary);background:var(--dsw-alias-label-primary)}.Fjs5Aa_optionCopy{flex:1;min-width:0}.Fjs5Aa_optionLine{flex-wrap:wrap;align-items:baseline;gap:2px 6px;display:flex}.Fjs5Aa_optionLabel{font-size:14px;font-weight:500;line-height:24px}.Fjs5Aa_badge{background:var(--dsw-specific-sidebar-nav-item-active-accent);color:var(--dsw-alias-button-info-fill);border-radius:6px;padding:0 4px;font-size:11px;font-weight:600;line-height:18px}.Fjs5Aa_description{color:var(--dsw-alias-label-tertiary);font-size:14px;font-weight:400;line-height:24px}.Fjs5Aa_customRow{border:1px solid #0000;border-radius:12px;flex-shrink:0;align-items:flex-start;gap:8px;width:100%;min-height:40px;padding:8px 12px 8px 8px;transition:background-color .12s,border-color .12s;display:flex}.Fjs5Aa_customRow:hover,.Fjs5Aa_customRow:focus-within,.Fjs5Aa_customRowActive{background:var(--dsw-alias-interactive-bg-hover)}.Fjs5Aa_customRow:focus-within,.Fjs5Aa_customRowActive{border-color:var(--dsw-alias-border-l2)}.Fjs5Aa_customInput{min-width:0;color:var(--dsw-alias-label-primary);caret-color:var(--dsw-alias-state-business-primary);font:inherit;background:0 0;border:none;outline:none;flex:1;padding:0;font-size:14px;line-height:24px}.Fjs5Aa_customInput::placeholder{color:var(--dsw-alias-label-caption)}.Fjs5Aa_customTextarea{resize:none;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-module-platform);min-height:64px;max-height:140px;color:var(--dsw-alias-label-primary);caret-color:var(--dsw-alias-state-business-primary);font:inherit;border-radius:10px;outline:none;flex-shrink:0;margin:0 12px;padding:8px 12px;font-size:14px;line-height:24px;display:block}.Fjs5Aa_customTextarea:focus{border-color:var(--dsw-alias-state-business-primary)}.Fjs5Aa_customTextarea::placeholder{color:var(--dsw-alias-label-caption)}.Fjs5Aa_footer{flex-shrink:0;justify-content:space-between;align-items:center;gap:12px;margin-top:12px;padding:0 10px 0 18px;display:flex}.Fjs5Aa_feedback{min-height:16px;color:var(--dsw-alias-state-error-primary);text-align:right;flex:1;font-size:11px;line-height:16px}@media (width<=720px){.Fjs5Aa_card{border-radius:16px}.Fjs5Aa_header{padding:10px 12px 0 18px}.Fjs5Aa_options{padding:4px 8px}.Fjs5Aa_title{font-size:15px;line-height:21px}.Fjs5Aa_option,.Fjs5Aa_customRow{padding:8px 6px}.Fjs5Aa_footer{align-items:flex-end;padding:0 10px}.Fjs5Aa_footerActions{flex-shrink:0}}@media (prefers-reduced-motion:reduce){.Fjs5Aa_option,.Fjs5Aa_customRow{transition:none}}";
|
|
234
|
+
const tagId = "@deepseek-ai/dsh-client-ui-user-questions/QuestionComposer.module.css";
|
|
235
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
|
|
236
|
+
const tag = document.createElement("style");
|
|
237
|
+
tag.dataset.plugin = "@deepseek-ai/dsh-client-ui-user-questions";
|
|
238
|
+
tag.dataset.pluginCss = tagId;
|
|
239
|
+
tag.textContent = css;
|
|
240
|
+
document.head.appendChild(tag);
|
|
241
|
+
}
|
|
242
|
+
var QuestionComposer_module_css_default = {
|
|
243
|
+
"body": "Fjs5Aa_body",
|
|
244
|
+
"options": "Fjs5Aa_options",
|
|
245
|
+
"header": "Fjs5Aa_header",
|
|
246
|
+
"headerActions": "Fjs5Aa_headerActions",
|
|
247
|
+
"optionLine": "Fjs5Aa_optionLine",
|
|
248
|
+
"eyebrow": "Fjs5Aa_eyebrow",
|
|
249
|
+
"number": "Fjs5Aa_number",
|
|
250
|
+
"cardMinimized": "Fjs5Aa_cardMinimized",
|
|
251
|
+
"iconButton": "Fjs5Aa_iconButton",
|
|
252
|
+
"headingBlock": "Fjs5Aa_headingBlock",
|
|
253
|
+
"customInput": "Fjs5Aa_customInput",
|
|
254
|
+
"feedback": "Fjs5Aa_feedback",
|
|
255
|
+
"description": "Fjs5Aa_description",
|
|
256
|
+
"customRowActive": "Fjs5Aa_customRowActive",
|
|
257
|
+
"option": "Fjs5Aa_option",
|
|
258
|
+
"optionSelected": "Fjs5Aa_optionSelected",
|
|
259
|
+
"title": "Fjs5Aa_title",
|
|
260
|
+
"pager": "Fjs5Aa_pager",
|
|
261
|
+
"checkbox": "Fjs5Aa_checkbox",
|
|
262
|
+
"customTextarea": "Fjs5Aa_customTextarea",
|
|
263
|
+
"badge": "Fjs5Aa_badge",
|
|
264
|
+
"optionLabel": "Fjs5Aa_optionLabel",
|
|
265
|
+
"optionCopy": "Fjs5Aa_optionCopy",
|
|
266
|
+
"detail": "Fjs5Aa_detail",
|
|
267
|
+
"checkboxChecked": "Fjs5Aa_checkboxChecked",
|
|
268
|
+
"frame": "Fjs5Aa_frame",
|
|
269
|
+
"progress": "Fjs5Aa_progress",
|
|
270
|
+
"footerActions": "Fjs5Aa_footerActions",
|
|
271
|
+
"footer": "Fjs5Aa_footer",
|
|
272
|
+
"card": "Fjs5Aa_card",
|
|
273
|
+
"customRow": "Fjs5Aa_customRow"
|
|
274
|
+
};
|
|
275
|
+
//#endregion
|
|
276
|
+
//#region lib/types/client/QuestionComposer.js
|
|
277
|
+
/**
|
|
278
|
+
* Split the conventional recommendation suffix without changing the answer value.
|
|
279
|
+
* @param label - Original option label returned if selected.
|
|
280
|
+
* @returns Display label plus recommendation state.
|
|
281
|
+
*/
|
|
282
|
+
function parseRecommendedLabel(label) {
|
|
283
|
+
const suffix = /\s*(?:\((?:recommended|推荐)\)|((?:recommended|推荐)))\s*$/i;
|
|
284
|
+
return suffix.test(label) ? {
|
|
285
|
+
label: label.replace(suffix, ""),
|
|
286
|
+
recommended: true
|
|
287
|
+
} : {
|
|
288
|
+
label,
|
|
289
|
+
recommended: false
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
/** Return whether a text-field key event belongs to an active IME composition. */
|
|
293
|
+
function isComposing(event) {
|
|
294
|
+
return event.nativeEvent.isComposing || event.nativeEvent.keyCode === 229;
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Composer takeover boundary; the carrier key keys local drafts, so a
|
|
298
|
+
* same-request replay (same key, new carrier object) preserves them.
|
|
299
|
+
*
|
|
300
|
+
* One takeover, two shapes: a request that declares a presentation intent this
|
|
301
|
+
* package renders takes that shape (a plan review is one decision over one
|
|
302
|
+
* plan, not a question set), and every other request takes the generic flow.
|
|
303
|
+
* The routing lives here, at the one entry that owns the composer seat, so
|
|
304
|
+
* neither shape can claim a request the other is already rendering.
|
|
305
|
+
*
|
|
306
|
+
* @param props - the selector-matched pending question carrier plus the framework standard kit.
|
|
307
|
+
* @returns The question flow, or the intent's own surface, for this request.
|
|
308
|
+
*/
|
|
309
|
+
function QuestionComposer(props) {
|
|
310
|
+
const question = (0, react.useMemo)(() => new PendingQuestion(props.matched), [props.matched]);
|
|
311
|
+
const review = (0, react.useMemo)(() => planReviewOf(question.questions), [question]);
|
|
312
|
+
return review === void 0 ? (0, react_jsx_runtime.jsx)(QuestionFlow, {
|
|
313
|
+
pending: question,
|
|
314
|
+
t: props.t
|
|
315
|
+
}, question.key) : (0, react_jsx_runtime.jsx)(PlanReviewPanel, {
|
|
316
|
+
pending: question,
|
|
317
|
+
review,
|
|
318
|
+
t: props.t
|
|
319
|
+
}, question.key);
|
|
320
|
+
}
|
|
321
|
+
function QuestionFlow({ pending, t }) {
|
|
322
|
+
const questions = pending.questions;
|
|
323
|
+
const [index, setIndex] = (0, react.useState)(0);
|
|
324
|
+
const [drafts, setDrafts] = (0, react.useState)(() => questions.map(() => ({
|
|
325
|
+
selected: [],
|
|
326
|
+
custom: "",
|
|
327
|
+
skipped: false
|
|
328
|
+
})));
|
|
329
|
+
const [busy, setBusy] = (0, react.useState)(null);
|
|
330
|
+
const [error, setError] = (0, react.useState)(null);
|
|
331
|
+
const [minimized, setMinimized] = (0, react.useState)(false);
|
|
332
|
+
const focusedQuestions = (0, react.useRef)(/* @__PURE__ */ new Set());
|
|
333
|
+
const question = questions[index];
|
|
334
|
+
const draft = drafts[index];
|
|
335
|
+
const hasOptions = (question.options?.length ?? 0) > 0;
|
|
336
|
+
const cancelFlow = () => {
|
|
337
|
+
setBusy("cancel");
|
|
338
|
+
setError(null);
|
|
339
|
+
pending.cancel().catch((cause) => {
|
|
340
|
+
setBusy(null);
|
|
341
|
+
setError({ text: cause instanceof Error ? cause.message : String(cause) });
|
|
342
|
+
});
|
|
343
|
+
};
|
|
344
|
+
const updateDraft = (update) => {
|
|
345
|
+
setDrafts((current) => current.map((item, itemIndex) => itemIndex === index ? update(item) : item));
|
|
346
|
+
setError(null);
|
|
347
|
+
};
|
|
348
|
+
const choose = (label) => {
|
|
349
|
+
updateDraft((current) => {
|
|
350
|
+
if (question.multiSelect === true) {
|
|
351
|
+
const selected = current.selected.includes(label) ? current.selected.filter((item) => item !== label) : [...current.selected, label];
|
|
352
|
+
return {
|
|
353
|
+
...current,
|
|
354
|
+
selected,
|
|
355
|
+
skipped: false
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
return {
|
|
359
|
+
selected: [label],
|
|
360
|
+
custom: "",
|
|
361
|
+
skipped: false
|
|
362
|
+
};
|
|
363
|
+
});
|
|
364
|
+
if (question.multiSelect !== true && index < questions.length - 1) setIndex((current) => current + 1);
|
|
365
|
+
};
|
|
366
|
+
const answered = (item) => item.selected.length > 0 || item.custom.trim() !== "";
|
|
367
|
+
const completed = (item) => answered(item) || item.skipped;
|
|
368
|
+
const submitDrafts = (values) => {
|
|
369
|
+
const missing = values.findIndex((item) => !completed(item));
|
|
370
|
+
if (missing >= 0) {
|
|
371
|
+
setIndex(missing);
|
|
372
|
+
setError({ key: "error.incomplete" });
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
375
|
+
const answer = { answers: questions.map((item, itemIndex) => {
|
|
376
|
+
const value = values[itemIndex];
|
|
377
|
+
if (value.skipped) return {
|
|
378
|
+
id: item.id,
|
|
379
|
+
selected: []
|
|
380
|
+
};
|
|
381
|
+
const custom = value.custom.trim();
|
|
382
|
+
return {
|
|
383
|
+
id: item.id,
|
|
384
|
+
selected: custom === "" || item.multiSelect === true ? value.selected : [],
|
|
385
|
+
...custom === "" ? {} : { custom }
|
|
386
|
+
};
|
|
387
|
+
}) };
|
|
388
|
+
setBusy("answer");
|
|
389
|
+
setError(null);
|
|
390
|
+
pending.answer(answer).catch((cause) => {
|
|
391
|
+
setBusy(null);
|
|
392
|
+
setError({ text: cause instanceof Error ? cause.message : String(cause) });
|
|
393
|
+
});
|
|
394
|
+
};
|
|
395
|
+
const continueFlow = () => {
|
|
396
|
+
if (!answered(draft)) {
|
|
397
|
+
setError({ key: "error.unanswered" });
|
|
398
|
+
return;
|
|
399
|
+
}
|
|
400
|
+
if (index < questions.length - 1) {
|
|
401
|
+
setIndex((current) => current + 1);
|
|
402
|
+
setError(null);
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
submitDrafts(drafts);
|
|
406
|
+
};
|
|
407
|
+
const draftCustom = (event) => {
|
|
408
|
+
const value = event.target.value;
|
|
409
|
+
updateDraft((current) => ({
|
|
410
|
+
...current,
|
|
411
|
+
selected: question.multiSelect === true ? current.selected : [],
|
|
412
|
+
custom: value,
|
|
413
|
+
skipped: false
|
|
414
|
+
}));
|
|
415
|
+
};
|
|
416
|
+
const continueFromCustom = (event) => {
|
|
417
|
+
if (event.key !== "Enter" || event.shiftKey || isComposing(event)) return;
|
|
418
|
+
event.preventDefault();
|
|
419
|
+
continueFlow();
|
|
420
|
+
};
|
|
421
|
+
const skipQuestion = () => {
|
|
422
|
+
const nextDrafts = drafts.map((item, itemIndex) => itemIndex === index ? {
|
|
423
|
+
selected: [],
|
|
424
|
+
custom: "",
|
|
425
|
+
skipped: true
|
|
426
|
+
} : item);
|
|
427
|
+
setDrafts(nextDrafts);
|
|
428
|
+
setError(null);
|
|
429
|
+
if (index < questions.length - 1) {
|
|
430
|
+
setIndex((current) => current + 1);
|
|
431
|
+
return;
|
|
432
|
+
}
|
|
433
|
+
submitDrafts(nextDrafts);
|
|
434
|
+
};
|
|
435
|
+
return (0, react_jsx_runtime.jsx)("div", {
|
|
436
|
+
className: QuestionComposer_module_css_default.frame,
|
|
437
|
+
"data-question-key": pending.key,
|
|
438
|
+
children: (0, react_jsx_runtime.jsxs)("section", {
|
|
439
|
+
className: clsx(QuestionComposer_module_css_default.card, minimized && QuestionComposer_module_css_default.cardMinimized),
|
|
440
|
+
"aria-labelledby": `question-${pending.key}-${String(index)}`,
|
|
441
|
+
children: [(0, react_jsx_runtime.jsxs)("header", {
|
|
442
|
+
className: QuestionComposer_module_css_default.header,
|
|
443
|
+
children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
444
|
+
className: QuestionComposer_module_css_default.headingBlock,
|
|
445
|
+
children: [question.header !== void 0 && (0, react_jsx_runtime.jsx)("div", {
|
|
446
|
+
className: QuestionComposer_module_css_default.eyebrow,
|
|
447
|
+
children: question.header
|
|
448
|
+
}), (0, react_jsx_runtime.jsx)("h2", {
|
|
449
|
+
className: QuestionComposer_module_css_default.title,
|
|
450
|
+
id: `question-${pending.key}-${String(index)}`,
|
|
451
|
+
children: question.question
|
|
452
|
+
})]
|
|
453
|
+
}), (0, react_jsx_runtime.jsxs)("div", {
|
|
454
|
+
className: QuestionComposer_module_css_default.headerActions,
|
|
455
|
+
children: [(0, react_jsx_runtime.jsx)("button", {
|
|
456
|
+
type: "button",
|
|
457
|
+
className: QuestionComposer_module_css_default.iconButton,
|
|
458
|
+
"aria-label": t(minimized ? "nav.maximize" : "nav.minimize"),
|
|
459
|
+
title: t(minimized ? "nav.maximize" : "nav.minimize"),
|
|
460
|
+
"aria-expanded": !minimized,
|
|
461
|
+
disabled: busy !== null,
|
|
462
|
+
onClick: () => {
|
|
463
|
+
setMinimized((current) => !current);
|
|
464
|
+
},
|
|
465
|
+
children: minimized ? (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronUpOutline14, {}) : (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutline14, {})
|
|
466
|
+
}), (0, react_jsx_runtime.jsx)("button", {
|
|
467
|
+
type: "button",
|
|
468
|
+
className: QuestionComposer_module_css_default.iconButton,
|
|
469
|
+
"aria-label": t("nav.cancel"),
|
|
470
|
+
title: t("nav.cancel"),
|
|
471
|
+
disabled: busy !== null,
|
|
472
|
+
onClick: cancelFlow,
|
|
473
|
+
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconCloseOutline16, {})
|
|
474
|
+
})]
|
|
475
|
+
})]
|
|
476
|
+
}), !minimized && (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
477
|
+
className: QuestionComposer_module_css_default.body,
|
|
478
|
+
"data-question-scroll": true,
|
|
479
|
+
children: [question.detail !== void 0 && (0, react_jsx_runtime.jsx)("div", {
|
|
480
|
+
className: QuestionComposer_module_css_default.detail,
|
|
481
|
+
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.MarkdownText, { text: question.detail })
|
|
482
|
+
}), (0, react_jsx_runtime.jsxs)("div", {
|
|
483
|
+
className: QuestionComposer_module_css_default.options,
|
|
484
|
+
role: question.multiSelect === true ? "group" : "radiogroup",
|
|
485
|
+
children: [(question.options ?? []).map((option, optionIndex) => {
|
|
486
|
+
const selected = draft.selected.includes(option.label);
|
|
487
|
+
const display = parseRecommendedLabel(option.label);
|
|
488
|
+
return (0, react_jsx_runtime.jsxs)("button", {
|
|
489
|
+
type: "button",
|
|
490
|
+
className: clsx(QuestionComposer_module_css_default.option, selected && question.multiSelect !== true && QuestionComposer_module_css_default.optionSelected),
|
|
491
|
+
role: question.multiSelect === true ? "checkbox" : "radio",
|
|
492
|
+
"aria-checked": selected,
|
|
493
|
+
"aria-label": display.label,
|
|
494
|
+
disabled: busy !== null,
|
|
495
|
+
onClick: () => {
|
|
496
|
+
choose(option.label);
|
|
497
|
+
},
|
|
498
|
+
onKeyDown: (event) => {
|
|
499
|
+
if (event.key !== "Enter" || !drafts.every(completed)) return;
|
|
500
|
+
event.preventDefault();
|
|
501
|
+
submitDrafts(drafts);
|
|
502
|
+
},
|
|
503
|
+
children: [question.multiSelect === true ? (0, react_jsx_runtime.jsx)("span", {
|
|
504
|
+
className: clsx(QuestionComposer_module_css_default.checkbox, selected && QuestionComposer_module_css_default.checkboxChecked),
|
|
505
|
+
"aria-hidden": "true",
|
|
506
|
+
children: selected && (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconCheckOutline14, { size: 12 })
|
|
507
|
+
}) : (0, react_jsx_runtime.jsx)("span", {
|
|
508
|
+
className: QuestionComposer_module_css_default.number,
|
|
509
|
+
children: optionIndex + 1
|
|
510
|
+
}), (0, react_jsx_runtime.jsx)("span", {
|
|
511
|
+
className: QuestionComposer_module_css_default.optionCopy,
|
|
512
|
+
children: (0, react_jsx_runtime.jsxs)("span", {
|
|
513
|
+
className: QuestionComposer_module_css_default.optionLine,
|
|
514
|
+
children: [
|
|
515
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
516
|
+
className: QuestionComposer_module_css_default.optionLabel,
|
|
517
|
+
children: display.label
|
|
518
|
+
}),
|
|
519
|
+
display.recommended && (0, react_jsx_runtime.jsx)("span", {
|
|
520
|
+
className: QuestionComposer_module_css_default.badge,
|
|
521
|
+
children: t("option.recommended")
|
|
522
|
+
}),
|
|
523
|
+
option.description !== void 0 && (0, react_jsx_runtime.jsx)("span", {
|
|
524
|
+
className: QuestionComposer_module_css_default.description,
|
|
525
|
+
children: option.description
|
|
526
|
+
})
|
|
527
|
+
]
|
|
528
|
+
})
|
|
529
|
+
})]
|
|
530
|
+
}, `${option.label}-${String(optionIndex)}`);
|
|
531
|
+
}), hasOptions ? (0, react_jsx_runtime.jsxs)("div", {
|
|
532
|
+
className: clsx(QuestionComposer_module_css_default.customRow, draft.custom !== "" && QuestionComposer_module_css_default.customRowActive),
|
|
533
|
+
children: [question.multiSelect === true ? (0, react_jsx_runtime.jsx)("span", {
|
|
534
|
+
className: clsx(QuestionComposer_module_css_default.checkbox, draft.custom !== "" && QuestionComposer_module_css_default.checkboxChecked),
|
|
535
|
+
"aria-hidden": "true",
|
|
536
|
+
children: draft.custom !== "" && (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconCheckOutline14, { size: 12 })
|
|
537
|
+
}) : (0, react_jsx_runtime.jsx)("span", {
|
|
538
|
+
className: QuestionComposer_module_css_default.number,
|
|
539
|
+
"aria-hidden": "true",
|
|
540
|
+
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconEditOutline16, { size: 12 })
|
|
541
|
+
}), (0, react_jsx_runtime.jsx)("input", {
|
|
542
|
+
type: "text",
|
|
543
|
+
className: QuestionComposer_module_css_default.customInput,
|
|
544
|
+
value: draft.custom,
|
|
545
|
+
disabled: busy !== null,
|
|
546
|
+
placeholder: t("custom.placeholder"),
|
|
547
|
+
onChange: draftCustom,
|
|
548
|
+
onKeyDown: continueFromCustom
|
|
549
|
+
})]
|
|
550
|
+
}) : (0, react_jsx_runtime.jsx)("textarea", {
|
|
551
|
+
autoFocus: !focusedQuestions.current.has(index),
|
|
552
|
+
className: QuestionComposer_module_css_default.customTextarea,
|
|
553
|
+
value: draft.custom,
|
|
554
|
+
disabled: busy !== null,
|
|
555
|
+
rows: 2,
|
|
556
|
+
placeholder: t("custom.placeholder"),
|
|
557
|
+
onFocus: () => {
|
|
558
|
+
focusedQuestions.current.add(index);
|
|
559
|
+
},
|
|
560
|
+
onChange: draftCustom,
|
|
561
|
+
onKeyDown: continueFromCustom
|
|
562
|
+
})]
|
|
563
|
+
})]
|
|
564
|
+
}), (0, react_jsx_runtime.jsxs)("footer", {
|
|
565
|
+
className: QuestionComposer_module_css_default.footer,
|
|
566
|
+
children: [
|
|
567
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
568
|
+
className: QuestionComposer_module_css_default.pager,
|
|
569
|
+
children: [
|
|
570
|
+
(0, react_jsx_runtime.jsx)("button", {
|
|
571
|
+
type: "button",
|
|
572
|
+
className: QuestionComposer_module_css_default.iconButton,
|
|
573
|
+
"aria-label": t("nav.prev"),
|
|
574
|
+
disabled: index === 0 || busy !== null,
|
|
575
|
+
onClick: () => {
|
|
576
|
+
setIndex(index - 1);
|
|
577
|
+
setError(null);
|
|
578
|
+
},
|
|
579
|
+
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronLeftOutline14, {})
|
|
580
|
+
}),
|
|
581
|
+
(0, react_jsx_runtime.jsxs)("span", {
|
|
582
|
+
className: QuestionComposer_module_css_default.progress,
|
|
583
|
+
children: [
|
|
584
|
+
index + 1,
|
|
585
|
+
" / ",
|
|
586
|
+
questions.length
|
|
587
|
+
]
|
|
588
|
+
}),
|
|
589
|
+
(0, react_jsx_runtime.jsx)("button", {
|
|
590
|
+
type: "button",
|
|
591
|
+
className: QuestionComposer_module_css_default.iconButton,
|
|
592
|
+
"aria-label": t("nav.next"),
|
|
593
|
+
disabled: index === questions.length - 1 || busy !== null,
|
|
594
|
+
onClick: () => {
|
|
595
|
+
setIndex(index + 1);
|
|
596
|
+
setError(null);
|
|
597
|
+
},
|
|
598
|
+
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronRightOutline14, {})
|
|
599
|
+
})
|
|
600
|
+
]
|
|
601
|
+
}),
|
|
602
|
+
(0, react_jsx_runtime.jsx)("div", {
|
|
603
|
+
className: QuestionComposer_module_css_default.feedback,
|
|
604
|
+
role: "status",
|
|
605
|
+
children: error === null ? null : "key" in error ? t(error.key) : error.text
|
|
606
|
+
}),
|
|
607
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
608
|
+
className: QuestionComposer_module_css_default.footerActions,
|
|
609
|
+
children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
610
|
+
variant: "outline",
|
|
611
|
+
disabled: busy !== null,
|
|
612
|
+
onClick: skipQuestion,
|
|
613
|
+
children: t("action.skip")
|
|
614
|
+
}), (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
615
|
+
variant: "primary",
|
|
616
|
+
disabled: busy !== null || !answered(draft),
|
|
617
|
+
onClick: continueFlow,
|
|
618
|
+
children: busy === "answer" ? t("submitting") : index === questions.length - 1 ? t("submit") : t("action.next")
|
|
619
|
+
})]
|
|
620
|
+
})
|
|
621
|
+
]
|
|
622
|
+
})] })]
|
|
623
|
+
})
|
|
624
|
+
});
|
|
625
|
+
}
|
|
626
|
+
//#endregion
|
|
627
|
+
//#region lib/types/client/locales.js
|
|
628
|
+
/** `question` namespace dictionaries. */
|
|
629
|
+
/** Simplified Chinese dictionary (the key-set source of truth). */
|
|
630
|
+
const zh = {
|
|
631
|
+
"error.incomplete": "请先完成这道问题。",
|
|
632
|
+
"error.unanswered": "请选择一个选项或填写自定义答案。",
|
|
633
|
+
"nav.prev": "上一题",
|
|
634
|
+
"nav.next": "下一题",
|
|
635
|
+
"nav.minimize": "收起问题卡片",
|
|
636
|
+
"nav.maximize": "展开问题卡片",
|
|
637
|
+
"nav.cancel": "放弃整组问题",
|
|
638
|
+
"option.recommended": "推荐",
|
|
639
|
+
"custom.placeholder": "输入你的答案",
|
|
640
|
+
"action.skip": "跳过本题",
|
|
641
|
+
"action.next": "下一题",
|
|
642
|
+
"plan.header": "计划待审",
|
|
643
|
+
"plan.approve": "确认执行",
|
|
644
|
+
"plan.decline": "拒绝",
|
|
645
|
+
"plan.discuss": "去聊天里说"
|
|
646
|
+
};
|
|
647
|
+
/** English dictionary, checked complete against the zh key set. */
|
|
648
|
+
const en = {
|
|
649
|
+
"error.incomplete": "Please complete this question first.",
|
|
650
|
+
"error.unanswered": "Please select an option or enter a custom answer.",
|
|
651
|
+
"nav.prev": "Previous question",
|
|
652
|
+
"nav.next": "Next question",
|
|
653
|
+
"nav.minimize": "Collapse the question card",
|
|
654
|
+
"nav.maximize": "Expand the question card",
|
|
655
|
+
"nav.cancel": "Dismiss all questions",
|
|
656
|
+
"option.recommended": "Recommended",
|
|
657
|
+
"custom.placeholder": "Type your answer",
|
|
658
|
+
"action.skip": "Skip this question",
|
|
659
|
+
"action.next": "Next",
|
|
660
|
+
"plan.header": "Plan review",
|
|
661
|
+
"plan.approve": "Approve",
|
|
662
|
+
"plan.decline": "Refuse",
|
|
663
|
+
"plan.discuss": "Chat about it"
|
|
664
|
+
};
|
|
665
|
+
//#endregion
|
|
666
|
+
//#region lib/types/client/index.js
|
|
667
|
+
/** Dictionary namespace owned by this plugin. */
|
|
668
|
+
const NS = "question";
|
|
669
|
+
/** Required services: the slot registry and the question composer's copy. */
|
|
670
|
+
const inject = ["slots", "locale"];
|
|
671
|
+
/** Chain routing: claim the composer while a question wait is pending (pure — owner props only). */
|
|
672
|
+
function selectQuestion({ interactions }) {
|
|
673
|
+
return interactions.find((i) => i.kind === "question") ?? null;
|
|
674
|
+
}
|
|
675
|
+
/**
|
|
676
|
+
* Client plugin body: register the `question` dictionaries and the question
|
|
677
|
+
* composer into the composer chain. Zero business face — data and verbs live
|
|
678
|
+
* on the matched carrier; t rides the standard locale seat.
|
|
679
|
+
* @param ctx - client root context.
|
|
680
|
+
*/
|
|
681
|
+
function apply(ctx) {
|
|
682
|
+
ctx.effect(() => ctx.locale.register(NS, {
|
|
683
|
+
zh,
|
|
684
|
+
en
|
|
685
|
+
}), "ui-user-questions: dictionaries");
|
|
686
|
+
ctx.slots.inject("conversation.composer", () => ctx.slots.register({
|
|
687
|
+
name: "conversation.composer",
|
|
688
|
+
select: selectQuestion,
|
|
689
|
+
locale: NS
|
|
690
|
+
}, QuestionComposer));
|
|
691
|
+
}
|
|
692
|
+
//#endregion
|
|
693
|
+
exports.PendingQuestion = PendingQuestion;
|
|
694
|
+
exports.apply = apply;
|
|
695
|
+
exports.inject = inject;
|
|
696
|
+
return module.exports;
|
|
697
|
+
}
|
|
698
|
+
});
|
|
699
|
+
|
|
700
|
+
//# sourceMappingURL=client.js.map
|