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.
Files changed (159) hide show
  1. package/LICENSE +21 -0
  2. package/README.i18n.yaml +6 -0
  3. package/README.md +183 -0
  4. package/README.zh.md +183 -0
  5. package/THIRD_PARTY_NOTICES.md +199 -0
  6. package/dist/_headers +3 -0
  7. package/dist/assets/fonts/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  8. package/dist/assets/fonts/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  9. package/dist/assets/fonts/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  10. package/dist/assets/fonts/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  11. package/dist/assets/fonts/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  12. package/dist/assets/fonts/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  13. package/dist/assets/fonts/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  14. package/dist/assets/fonts/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  15. package/dist/assets/fonts/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  16. package/dist/assets/fonts/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  17. package/dist/assets/fonts/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  18. package/dist/assets/fonts/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  19. package/dist/assets/fonts/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  20. package/dist/assets/fonts/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  21. package/dist/assets/fonts/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  22. package/dist/assets/fonts/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  23. package/dist/assets/fonts/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  24. package/dist/assets/fonts/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  25. package/dist/assets/fonts/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  26. package/dist/assets/fonts/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  27. package/dist/assets/fonts/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  28. package/dist/assets/fonts/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  29. package/dist/assets/fonts/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  30. package/dist/assets/fonts/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  31. package/dist/assets/fonts/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  32. package/dist/assets/fonts/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  33. package/dist/assets/fonts/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  34. package/dist/assets/fonts/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  35. package/dist/assets/fonts/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  36. package/dist/assets/fonts/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  37. package/dist/assets/fonts/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  38. package/dist/assets/fonts/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  39. package/dist/assets/fonts/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  40. package/dist/assets/fonts/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  41. package/dist/assets/fonts/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  42. package/dist/assets/fonts/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  43. package/dist/assets/fonts/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  44. package/dist/assets/fonts/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  45. package/dist/assets/fonts/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  46. package/dist/assets/fonts/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  47. package/dist/assets/fonts/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  48. package/dist/assets/fonts/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  49. package/dist/assets/fonts/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  50. package/dist/assets/fonts/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  51. package/dist/assets/fonts/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  52. package/dist/assets/fonts/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  53. package/dist/assets/fonts/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  54. package/dist/assets/fonts/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  55. package/dist/assets/fonts/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  56. package/dist/assets/fonts/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  57. package/dist/assets/fonts/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  58. package/dist/assets/fonts/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  59. package/dist/assets/fonts/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  60. package/dist/assets/fonts/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  61. package/dist/assets/fonts/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  62. package/dist/assets/fonts/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  63. package/dist/assets/fonts/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  64. package/dist/assets/fonts/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  65. package/dist/assets/fonts/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  66. package/dist/assets/index-C-1AiF3k.js +112 -0
  67. package/dist/assets/index-CSGf6Qzd.css +1 -0
  68. package/dist/assets/langs/c-BIGW1oBm.js +2 -0
  69. package/dist/assets/langs/cpp-DIPi6g--.js +2 -0
  70. package/dist/assets/langs/csharp-DSvCPggb.js +2 -0
  71. package/dist/assets/langs/css-CLj8gQPS.js +2 -0
  72. package/dist/assets/langs/go-C27-OAKa.js +2 -0
  73. package/dist/assets/langs/html-CfGypltT.js +2 -0
  74. package/dist/assets/langs/ini-BEwlwnbL.js +2 -0
  75. package/dist/assets/langs/java-CylS5w8V.js +2 -0
  76. package/dist/assets/langs/kotlin-BdnUsdx6.js +2 -0
  77. package/dist/assets/langs/less-B1dDrJ26.js +2 -0
  78. package/dist/assets/langs/lua-BaeVxFsk.js +2 -0
  79. package/dist/assets/langs/markdown-Cvjx9yec.js +2 -0
  80. package/dist/assets/langs/mdx-Cmh6b_Ma.js +2 -0
  81. package/dist/assets/langs/php-D-uCvoST.js +2 -0
  82. package/dist/assets/langs/python-B6aJPvgy.js +2 -0
  83. package/dist/assets/langs/ruby-DEItuUFs.js +2 -0
  84. package/dist/assets/langs/rust-B1yitclQ.js +2 -0
  85. package/dist/assets/langs/scss-D5BDwBP9.js +2 -0
  86. package/dist/assets/langs/sql-CRqJ_cUM.js +2 -0
  87. package/dist/assets/langs/swift-D82vCrfD.js +2 -0
  88. package/dist/assets/langs/toml-vGWfd6FD.js +2 -0
  89. package/dist/assets/langs/xml-sdJ4AIDG.js +2 -0
  90. package/dist/assets/langs/yaml-Buea-lGh.js +2 -0
  91. package/dist/assets/vendor-Cjbwl5VI.js +411 -0
  92. package/dist/assets/vendor-CjyC-hUb.css +1 -0
  93. package/dist/favicon.svg +8 -0
  94. package/dist/index.html +35 -0
  95. package/dist/manifest.webmanifest +16 -0
  96. package/dist/plugins/@deepseek-ai/dsh-api-gateway/client.js +420 -0
  97. package/dist/plugins/@deepseek-ai/dsh-api-remotes/client.js +5937 -0
  98. package/dist/plugins/@deepseek-ai/dsh-client-connection/client.js +10207 -0
  99. package/dist/plugins/@deepseek-ai/dsh-client-locale/client.js +1231 -0
  100. package/dist/plugins/@deepseek-ai/dsh-client-modules/client.js +259 -0
  101. package/dist/plugins/@deepseek-ai/dsh-client-runtime/client.js +10539 -0
  102. package/dist/plugins/@deepseek-ai/dsh-client-ui-agent-preset/client.js +1725 -0
  103. package/dist/plugins/@deepseek-ai/dsh-client-ui-commands/client.js +1116 -0
  104. package/dist/plugins/@deepseek-ai/dsh-client-ui-conversation/client.js +9832 -0
  105. package/dist/plugins/@deepseek-ai/dsh-client-ui-deliverables/client.js +373 -0
  106. package/dist/plugins/@deepseek-ai/dsh-client-ui-edge/client.js +549 -0
  107. package/dist/plugins/@deepseek-ai/dsh-client-ui-input-trigger/client.js +859 -0
  108. package/dist/plugins/@deepseek-ai/dsh-client-ui-jobs/client.js +280 -0
  109. package/dist/plugins/@deepseek-ai/dsh-client-ui-layout/client.js +456 -0
  110. package/dist/plugins/@deepseek-ai/dsh-client-ui-model-selection/client.js +804 -0
  111. package/dist/plugins/@deepseek-ai/dsh-client-ui-permission-presets/client.js +461 -0
  112. package/dist/plugins/@deepseek-ai/dsh-client-ui-settings/client.js +254 -0
  113. package/dist/plugins/@deepseek-ai/dsh-client-ui-settings-general/client.js +609 -0
  114. package/dist/plugins/@deepseek-ai/dsh-client-ui-sidebar/client.js +292 -0
  115. package/dist/plugins/@deepseek-ai/dsh-client-ui-skill/client.js +327 -0
  116. package/dist/plugins/@deepseek-ai/dsh-client-ui-subagent/client.js +710 -0
  117. package/dist/plugins/@deepseek-ai/dsh-client-ui-theme/client.js +1312 -0
  118. package/dist/plugins/@deepseek-ai/dsh-client-ui-tool/client.js +1630 -0
  119. package/dist/plugins/@deepseek-ai/dsh-client-ui-trajectory/client.js +7370 -0
  120. package/dist/plugins/@deepseek-ai/dsh-client-ui-user-questions/client.js +700 -0
  121. package/dist/plugins/@deepseek-ai/dsh-client-ui-workflow-run/client.js +474 -0
  122. package/dist/plugins/@deepseek-ai/dsh-client-ui-workspace/client.js +2426 -0
  123. package/dist/plugins/@deepseek-ai/dsh-typert-registry/client.js +1372 -0
  124. package/package.json +97 -0
  125. package/scripts/assemble-web.mjs +230 -0
  126. package/scripts/bundle-size.d.mts +2 -0
  127. package/scripts/bundle-size.mjs +26 -0
  128. package/scripts/bundle.mjs +53 -0
  129. package/scripts/cli.d.mts +39 -0
  130. package/scripts/cli.mjs +496 -0
  131. package/scripts/install.d.mts +149 -0
  132. package/scripts/install.mjs +989 -0
  133. package/scripts/legal-files.mjs +24 -0
  134. package/scripts/verify-packed.mjs +32 -0
  135. package/scripts/wrangler-config.d.mts +18 -0
  136. package/scripts/wrangler-config.mjs +84 -0
  137. package/src/agent.ts +119 -0
  138. package/src/auth.ts +352 -0
  139. package/src/deepseek.ts +231 -0
  140. package/src/deployment.ts +147 -0
  141. package/src/direct-shell-core-empty.ts +10 -0
  142. package/src/direct-shell-protocol.ts +5 -0
  143. package/src/direct-shell.ts +341 -0
  144. package/src/do-session-persistence.ts +1064 -0
  145. package/src/edge-api.ts +796 -0
  146. package/src/edge-credentials.ts +56 -0
  147. package/src/edge-remotes.ts +41 -0
  148. package/src/edge-workspace-store.ts +339 -0
  149. package/src/http.ts +212 -0
  150. package/src/index.ts +196 -0
  151. package/src/instance.ts +1007 -0
  152. package/src/isolated-direct-shell-unavailable.ts +11 -0
  153. package/src/protocol.ts +39 -0
  154. package/src/release.ts +9 -0
  155. package/src/session-store.ts +1110 -0
  156. package/src/sse.ts +86 -0
  157. package/src/web-search.ts +38 -0
  158. package/src/workspace.ts +270 -0
  159. 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