@lynn123411/dsh-ask-user-grilling 0.6.1 → 0.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -25,11 +25,11 @@ DSH 原生 `ask_user_question`([`@deepseek-ai/dsh-tool-ask-user`](https://www.
25
25
 
26
26
  - `scripts/test-recommendation.mjs`:推荐标记的归一化;
27
27
  - `scripts/test-card.mjs`:卡片模型(轮末补充题、`detail`、被拒、取消/中断、结果里多出来的 id、流式半截 JSON);
28
- - `scripts/smoke-host.mjs`:用真 `defineTool` + 假 seam 跑 `execute()`,逐条断言上面的转换与拒绝,另断言载体行的 config 门禁与 config 校验;
28
+ - `scripts/smoke-host.mjs`:真 cordis `Context`、真 `ctx.tools`(工具经真工具表注册并取回)、真 `ctx.userQuestions`(`ask()` 真走服务校验与 waterfall),只有「人怎么答」是假应答者;逐条断言上面的转换与拒绝,另断言工具描述与共有参数描述仍与原生逐字相同、载体行的 config 门禁与 config 校验;
29
29
  - `scripts/test-render.mjs`:用真 react 渲染构建出来的行组件,断言卡片的结构与文案(取词走真字典,缺键或缺参数即失败);`ui-primitives` 是替身,真组件的外观在浏览器里看;
30
- - `scripts/smoke-client.mjs`:按 Web shell 的方式加载构建出来的 `lib/client.js`(`window.__ModuleLoader__.load` 桩件),用带内核 inject 守卫的假上下文断言 `tool.call.toolview` 的 keyed 注册与字典,并守住 `dsg-*` class 名在 JSX 与 CSS 之间不单边漂移。
30
+ - `scripts/smoke-client.mjs`:按 Web shell 的方式加载构建出来的 `lib/client.js`(`window.__ModuleLoader__.load` 桩件),用带内核 inject 守卫的假上下文断言 `tool.call.toolview` 的 keyed 注册与字典,守住 `dsg-*` class 名在 JSX 与 CSS 之间不单边漂移,并核对客户端半边引的 ui-primitives 名字都在安装副本的导出表里。
31
31
 
32
- 内核包(`@deepseek-ai/dsh-tools` / `@deepseek-ai/dsh-user-questions`)与界面侧副本从 DSH 运行副本 `~/.dsh/profiles/node_modules/` 解析(可用 `DSH_HOME` 改主目录);`scripts/recommended-label-rule.mjs` 抄着界面侧「哪个 label 算推荐」那条正则,`smoke-host.mjs` 断言它仍与安装副本逐字相同,上游一改就当场失败。`src/` 是源码,`lib/` 是构建镜像、不入库(`pnpm build` 现打,`prepack` 在发布前打一次)。
32
+ 自检要的内核包与界面侧副本是本插件的 devDependencies(与 `engines.dsh` 同版本),`pnpm install` 后离线可跑、不指向任何 DSH 安装副本;`scripts/recommended-label-rule.mjs` 抄着界面侧「哪个 label 算推荐」那条正则,`smoke-host.mjs` 断言它仍与安装副本逐字相同,并断言工具描述与共有参数描述仍与原生 `ask_user_question` 逐字相同,上游一改就当场失败。`src/` 是源码,`lib/` 是构建镜像、不入库(`pnpm build` 现打,`prepack` 在发布前打一次)。
33
33
 
34
34
  ## 安装
35
35
 
@@ -44,6 +44,6 @@ dsh plugin --profile web add @lynn123411/dsh-ask-user-grilling
44
44
  **profile 侧两处登记,缺一不可**:
45
45
 
46
46
  1. `dsh.profile.bundles` 里有 `@lynn123411/dsh-ask-user-grilling`。包内 `cordis.patch.yml` 会在 bundle 层插入一条 `id: lynn-ask-user-grilling-carrier`、`config: { carrier: true }` 的行;宿主半边在那条行下什么都不注册。这一条只为让 Web shell 服务本包的浏览器半边:客户端 bundle 只对 root loader 的 **enabled entry** 服务,而 preset 工具行是 `ctx.plugin` 直接挂的子树、不是 Loader entry。位置决定功能——少了它工具照常可用,只是 transcript 那一行退回原始 JSON;`carrier` 之外的 config 键或错类型当场抛,免得拼错的载体行静默把工具注册成 root layer 的全局工具。
47
- 2. preset 的 `agent.cordis.yml` 里有工具行(`- id: tool-ask-user-grilling` / `name: '@lynn123411/dsh-ask-user-grilling'`)。工具与它的作用域由这一行注册。
47
+ 2. preset 的组合里有工具行(`- id: tool-ask-user-grilling` / `name: '@lynn123411/dsh-ask-user-grilling'`)。preset 由组合包的 patch 声明,这一行放在 `@deepseek-ai/dsh-agent-preset` 的 `config.plugins` 里;工具与它的作用域由这一行注册。
48
48
 
49
49
  改完 `src/` 必须重新 `pnpm build`:宿主半边与**新加入 profile bundle 层的这一行**要重启 DSH 实例(bundle 层在启动时组装);已经在图里的客户端 bundle 由 `dsh-client-hmr` 轮询到改动后热换,页面自行重载,必要时硬刷新一次。
package/lib/client.js CHANGED
@@ -205,7 +205,7 @@ function AskGrillingRow({ block, toolName, inspect, t }) {
205
205
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dsg-bodyWrap", children: [
206
206
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CardBody, { model, argsRaw, resultText, failure, t }),
207
207
  inspect === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", { type: "button", className: "dsg-inspectButton", onClick: inspect, children: [
208
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconInspectOutline12, {}),
208
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconInspectOutlineRegular, {}),
209
209
  t("row.inspect")
210
210
  ] })
211
211
  ] })
@@ -226,7 +226,7 @@ function failureText(resultText, error) {
226
226
  function leadingFor(state) {
227
227
  if (state === "error" || state === "rejected") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.StateDot, { state: "error" });
228
228
  if (state === "cancelled" || state === "interrupted") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.StateDot, { state: "warning" });
229
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconQuestionOutline14, {});
229
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconQuestionOutlineRegular, {});
230
230
  }
231
231
  function statusLabel(state, t) {
232
232
  switch (state) {
package/lib/client.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/client/index.js", "../src/client/AskGrillingRow.jsx", "../src/contract.js", "../src/card.js", "../src/client/AskGrillingRow.css", "../src/client/locales.js"],
4
- "sourcesContent": ["import { AskGrillingRow } from './AskGrillingRow.jsx';\nimport css from './AskGrillingRow.css';\nimport { NS, en, zh } from './locales.js';\n\n/** \u6D4F\u89C8\u5668\u534A\u8FB9\u7684\u5305\u8EAB\u4EFD\uFF0C\u4E5F\u662F bundle \u91CC <style> \u7684\u5F52\u5C5E\u6807\u8BB0\u3002 */\nconst PACKAGE_ID = '@lynn123411/dsh-ask-user-grilling';\nconst CSS_TAG = `${PACKAGE_ID}/AskGrillingRow.css`;\n\n/**\n * \u6D4F\u89C8\u5668\u534A\u8FB9\u8981\u7684 cordis \u670D\u52A1\u3002`locale` \u88C5\u5B57\u5178\uFF0C`slots` \u6CE8\u518C\u884C\uFF1B\n * \u5C11\u58F0\u660E\u4E00\u4E2A\u4E0D\u4F1A\u5F53\u573A\u62A5\u9519\uFF0C\u63D2\u4EF6\u4F1A\u6574\u6761 entry \u53D8 failed\u3001\u4ECE\u9875\u9762\u4E0A\u6D88\u5931\uFF08\u89C1 docs/rules/client-wiring.md\uFF09\u3002\n */\nexport const inject = ['locale', 'slots'];\n\n/** \u6CE8\u5165\u672C\u63D2\u4EF6\u7684\u6837\u5F0F\u8868\uFF1A\u6309\u6807\u7B7E\u952E\u590D\u7528\u540C\u4E00\u4E2A <style>\uFF0CHMR \u91CD\u8DD1\u65F6\u66FF\u6362\u5185\u5BB9\u800C\u4E0D\u662F\u53E0\u4E00\u4EFD\u3002 */\nfunction injectStyles() {\n if (typeof document === 'undefined') return;\n let tag = document.querySelector('style[data-plugin-css=' + JSON.stringify(CSS_TAG) + ']');\n if (tag === null) {\n tag = document.createElement('style');\n tag.dataset.plugin = PACKAGE_ID;\n tag.dataset.pluginCss = CSS_TAG;\n document.head.appendChild(tag);\n }\n tag.textContent = css;\n}\n\n/**\n * \u6D4F\u89C8\u5668\u534A\u8FB9\uFF1A\u88C5\u672C\u63D2\u4EF6\u7684\u5B57\u5178\uFF0C\u7136\u540E\u6309 wire \u5DE5\u5177\u540D\u6CE8\u518C `ask_user_grilling` \u7684\u884C\u3002\n * \u6CE8\u518C\u7684\u662F\u81EA\u6709 key\uFF0C\u5B98\u65B9 `ask_user_question` \u90A3\u5F20\u5361\u4E0D\u53D7\u5F71\u54CD\u3002\n * @param {object} ctx - \u5BA2\u6237\u7AEF\u6839\u4E0A\u4E0B\u6587\u3002\n */\nexport function apply(ctx) {\n injectStyles();\n ctx.effect(() => ctx.locale.register(NS, { zh, en }), 'dsh-ask-user-grilling: dictionaries');\n ctx.slots.inject('tool.call.toolview', () => ctx.slots.register({\n name: 'tool.call.toolview',\n key: 'ask_user_grilling',\n locale: NS,\n }, AskGrillingRow));\n}\n", "import { useMemo, useState } from 'react';\nimport {\n DisclosureRow,\n IconInspectOutline12,\n IconQuestionOutline14,\n MarkdownText,\n StateDot,\n} from '@deepseek-ai/dsh-client-ui-primitives';\nimport { readAskCard } from '../card.js';\n\n/**\n * `ask_user_grilling` \u7684 transcript \u884C\uFF1A\u6309 wire \u5DE5\u5177\u540D\u6CE8\u518C\u8FDB `tool.call.toolview`\uFF0C\n * \u4E0E\u5B98\u65B9 `ask_user_question` \u90A3\u5F20\u5361\u5E76\u5217\uFF08\u6CE8\u518C\u81EA\u6709\u7684 key\uFF0C\u4E0D\u63A5\u7BA1\u5B98\u65B9\u90A3\u5F20\uFF09\u3002\n *\n * \u5B98\u65B9\u5361\u7684\u53D6\u6570\u6B62\u4E8E argsRaw \u7684 id/question \u4E0E\u7ED3\u679C\u7684 answers\uFF0C\u8F6E\u672B\u8865\u5145\u9898\u4E0D\u5728 argsRaw \u91CC\u3001\n * detail \u4E5F\u4E0D\u5728\u8303\u56F4\u5185\uFF0C\u4E8E\u662F\u914D\u4E0D\u4E0A\u5BF9\u5C31\u9000\u56DE\u539F\u59CB JSON\u3002\u8FD9\u91CC\u6362\u6210\u8BFB\u5361\u6A21\u578B\uFF1AargsRaw \u91CC\u6CA1\u6709\u7684\n * \u7B54\u6848\u6309\u8865\u5145\u9898\u53E6\u5217\uFF0Cdetail \u8D70 markdown\u3002\n *\n * @param {{ block: object, toolName: string, inspect?: () => void, t: Function }} props - \u69FD\u4F4D\u7ED9\u7684\u884C\u6570\u636E\u3002\n * @returns {import('react').JSX.Element} \u8FD9\u4E00\u884C\u7684\u5361\u7247\u3002\n */\nexport function AskGrillingRow({ block, toolName, inspect, t }) {\n const [expanded, setExpanded] = useState(false);\n const toggle = () => setExpanded((value) => !value);\n const settled = 'kind' in block;\n const argsRaw = (settled ? block.call?.argsRaw : block.argsRaw) ?? '';\n const resultText = settled ? firstText(block.content) : undefined;\n const model = readAskCard({\n argsRaw,\n resultText,\n errorCode: settled ? block.error?.code : undefined,\n failed: settled && block.isError === true,\n });\n const failure = settled && block.isError === true ? failureText(resultText, block.error) : undefined;\n const expandable = argsRaw !== '' || resultText !== undefined || model.questions.length > 0;\n const open = expanded && expandable;\n const status = statusLabel(model.state, t);\n\n return (\n <div className=\"dsg-root\" data-tool={toolName} data-state={model.state}>\n {status === null ? null : <span className=\"dsg-visuallyHidden\">{status}</span>}\n <DisclosureRow\n icon={leadingFor(model.state)}\n title={t('row.title')}\n open={open}\n expandable={expandable}\n onToggle={toggle}\n expandOnRowClick\n keepContentWhenOpen\n rowClassName=\"dsg-row\"\n leadingClassName=\"dsg-leading\"\n chevronClassName=\"dsg-chevron\"\n titleClassName=\"dsg-title\"\n collapsedContent={\n <>\n <span className=\"dsg-sep\" aria-hidden=\"true\" />\n <span className=\"dsg-summary\">{summaryFor(model, t)}</span>\n </>\n }\n >\n <div className=\"dsg-bodyWrap\">\n <CardBody model={model} argsRaw={argsRaw} resultText={resultText} failure={failure} t={t} />\n {inspect === undefined ? null : (\n <button type=\"button\" className=\"dsg-inspectButton\" onClick={inspect}>\n <IconInspectOutline12 />\n {t('row.inspect')}\n </button>\n )}\n </div>\n </DisclosureRow>\n </div>\n );\n}\n\n/**\n * \u7ED3\u679C\u91CC\u7684\u7B2C\u4E00\u6BB5\u6587\u672C\u3002\u672C\u5DE5\u5177\u53EA\u6E32\u67D3\u4E00\u6BB5\uFF0C\u5F62\u72B6\u4E0D\u5BF9\u5C31\u5F53\u6CA1\u6709\u7ED3\u679C\u3002\n * @param {unknown} content - \u7ED3\u679C content \u6570\u7EC4\u3002\n * @returns {string|undefined} \u6587\u672C\u3002\n */\nfunction firstText(content) {\n if (!Array.isArray(content)) return undefined;\n const text = content.find((block) => block?.type === 'text');\n return typeof text?.text === 'string' ? text.text : undefined;\n}\n\n/**\n * \u5931\u8D25\u884C\u8981\u663E\u793A\u7684\u6587\u5B57\uFF1A\u7ED3\u679C\u91CC\u90A3\u6BB5\u6587\u672C\u4F18\u5148\uFF0C\u6CA1\u6709\u5C31\u7528\u9519\u8BEF\u7684 name/code \u62FC\u4E00\u884C\u3002\n * @param {string|undefined} resultText - \u7ED3\u679C\u6587\u672C\u3002\n * @param {{name?: string, code?: string}|undefined} error - \u7ED3\u679C\u8282\u70B9\u4E0A\u7684\u9519\u8BEF\u3002\n * @returns {string|undefined} \u5931\u8D25\u8BF4\u660E\u3002\n */\nfunction failureText(resultText, error) {\n if (resultText !== undefined && resultText !== '') return resultText;\n const parts = [error?.name, error?.code].filter((part) => typeof part === 'string' && part !== '');\n return parts.length === 0 ? undefined : parts.join(': ');\n}\n\n/**\n * \u884C\u7684\u524D\u5BFC\u56FE\u6807\uFF1A\u5931\u8D25\u4E0E\u62D2\u7EDD\u7528\u72B6\u6001\u70B9\uFF0C\u5176\u4F59\u7528\u95EE\u53F7\u56FE\u6807\uFF08\u4E0E\u5B98\u65B9\u884C\u540C\u4E00\u5957\u8BED\u4E49\uFF09\u3002\n * @param {string} state - \u5361\u7247\u72B6\u6001\u3002\n * @returns {import('react').ReactNode} \u524D\u5BFC\u8282\u70B9\u3002\n */\nfunction leadingFor(state) {\n if (state === 'error' || state === 'rejected') return <StateDot state=\"error\" />;\n if (state === 'cancelled' || state === 'interrupted') return <StateDot state=\"warning\" />;\n return <IconQuestionOutline14 />;\n}\n\n/**\n * \u5C4F\u5E55\u9605\u8BFB\u5668\u7528\u7684\u72B6\u6001\u6587\u5B57\u3002\u626B\u63CF\u5149\u4E0E\u72B6\u6001\u70B9\u90FD\u662F\u7EAF\u89C6\u89C9\u7684\u3002\n * @param {string} state - \u5361\u7247\u72B6\u6001\u3002\n * @param {Function} t - \u672C\u63D2\u4EF6\u7684\u53D6\u8BCD\u51FD\u6570\u3002\n * @returns {string|null} \u72B6\u6001\u6587\u5B57\uFF0C\u6B63\u5E38\u6001\u4E3A null\u3002\n */\nfunction statusLabel(state, t) {\n switch (state) {\n case 'running':\n return t('row.waiting');\n case 'error':\n return t('row.failed');\n case 'cancelled':\n return t('row.cancelled');\n case 'interrupted':\n return t('row.interrupted');\n default:\n return null;\n }\n}\n\n/**\n * \u6298\u53E0\u884C\u53F3\u4FA7\u7684\u6458\u8981\u3002\n * @param {object} model - \u5361\u7247\u6A21\u578B\u3002\n * @param {Function} t - \u672C\u63D2\u4EF6\u7684\u53D6\u8BCD\u51FD\u6570\u3002\n * @returns {string} \u6458\u8981\u6587\u5B57\u3002\n */\nfunction summaryFor(model, t) {\n switch (model.state) {\n case 'running':\n return t('row.waiting');\n case 'answered':\n return t('row.answered', { answered: model.answered, total: model.total });\n case 'rejected':\n return t('row.rejected');\n case 'cancelled':\n return t('row.cancelled');\n case 'interrupted':\n return t('row.interrupted');\n default:\n return t('row.failed');\n }\n}\n\n/**\n * \u6B63\u6587\uFF1A\u62D2\u7EDD\u65F6\u5148\u7ED9\u8FDD\u89C4\u6E05\u5355\uFF0C\u53D6\u6D88/\u4E2D\u65AD\u65F6\u7ED9\u8BF4\u660E\u52A0\u9898\u76EE\uFF0C\u5931\u8D25\u7ED9\u5931\u8D25\u8BF4\u660E\uFF0C\u5176\u4F59\u6309\u95EE\u7B54\u5217\u8868\u753B\u3002\n * @param {{ model: object, argsRaw: string, resultText: string|undefined, failure: string|undefined, t: Function }} props - \u5361\u7247\u6A21\u578B\u4E0E\u539F\u59CB\u6587\u672C\u3002\n * @returns {import('react').ReactNode} \u6B63\u6587\u3002\n */\nfunction CardBody({ model, argsRaw, resultText, failure, t }) {\n if (model.state === 'rejected') {\n return (\n <div className=\"dsg-card\" role=\"group\" aria-label={t('row.violations')}>\n <p className=\"dsg-verdict\">{model.error ?? t('row.rejected')}</p>\n <ul className=\"dsg-violations\">\n {model.violations.map((violation, index) => (\n <li key={String(index)}>{violation}</li>\n ))}\n </ul>\n <QuestionEntries questions={model.questions} showAnswers={false} t={t} />\n </div>\n );\n }\n if (model.questions.length === 0) {\n // \u8FD0\u884C\u4E2D\u7684\u534A\u622A JSON\u3001\u6216\u4E0D\u662F\u672C\u63D2\u4EF6\u5F62\u72B6\u7684\u7ED3\u679C\uFF1A\u539F\u6837\u7ED9\u51FA\uFF0C\u522B\u88C5\u4F5C\u8BFB\u61C2\u4E86\n const raw = model.state === 'running' ? argsRaw : resultText;\n return raw === undefined || raw === '' ? null : <pre className=\"dsg-raw\">{raw}</pre>;\n }\n if (model.state === 'cancelled' || model.state === 'interrupted') {\n return (\n <div className=\"dsg-card\">\n <p className=\"dsg-verdict\">\n {model.state === 'cancelled' ? t('row.cancelledDetail') : t('row.interruptedDetail')}\n </p>\n <QuestionEntries questions={model.questions} showAnswers={false} t={t} />\n </div>\n );\n }\n if (model.state === 'error') {\n return (\n <div className=\"dsg-card\">\n {failure === undefined ? null : <p className=\"dsg-failure\">{failure}</p>}\n <QuestionEntries questions={model.questions} showAnswers={false} t={t} />\n </div>\n );\n }\n return (\n <div className=\"dsg-card\">\n <QuestionEntries questions={model.questions} showAnswers={model.state === 'answered'} t={t} />\n </div>\n );\n}\n\n/**\n * \u9898\u76EE\u5217\u8868\uFF1A\u6709\u7B54\u6848\u7684\u753B dt/dd\uFF0C\u6CA1\u7B54\u6848\u7684\u53EA\u753B\u9898\u5E72\uFF1Bdetail \u8D70 markdown\u3002\n * @param {{ questions: object[], showAnswers: boolean, t: Function }} props - \u9898\u76EE\u4E0E\u662F\u5426\u753B\u7B54\u6848\u3002\n * @returns {import('react').JSX.Element} \u5217\u8868\u3002\n */\nfunction QuestionEntries({ questions, showAnswers, t }) {\n const labels = useMemo(() => markdownLabels(t), [t]);\n return (\n <dl className=\"dsg-list\">\n {questions.map((question) => (\n <div className=\"dsg-item\" key={question.id}>\n <dt className=\"dsg-question\">\n {question.header === '' ? null : <span className=\"dsg-header\">{question.header}</span>}\n {question.question}\n </dt>\n {question.detail === undefined ? null : (\n <div className=\"dsg-detail\">\n <MarkdownText text={question.detail} labels={labels} />\n </div>\n )}\n {showAnswers ? <AnswerLine question={question} t={t} /> : null}\n </div>\n ))}\n </dl>\n );\n}\n\n/**\n * \u4E00\u9053\u9898\u7684\u7B54\u6848\u884C\uFF1A\u9009\u4E2D\u9879\u9010\u884C\u5217\u51FA\uFF0C\u81EA\u7531\u6587\u672C\u63A5\u5728\u540E\u9762\uFF0C\u4E00\u6761\u90FD\u6CA1\u6709\u5C31\u662F\u300C\u672A\u56DE\u7B54\u300D\u3002\n * @param {{ question: object, t: Function }} props - \u9898\u76EE\u4E0E\u53D6\u8BCD\u51FD\u6570\u3002\n * @returns {import('react').JSX.Element} \u7B54\u6848\u884C\u3002\n */\nfunction AnswerLine({ question, t }) {\n return (\n <dd className=\"dsg-answer\">\n {question.answers.length === 0 ? (\n <span className=\"dsg-skipped\">{t('row.skipped')}</span>\n ) : (\n question.answers.map((answer, index) => (\n <span className=\"dsg-answerLine\" key={`${question.id}-${String(index)}`}>\n {answer}\n </span>\n ))\n )}\n </dd>\n );\n}\n\n/**\n * `MarkdownText` \u8981\u7684\u90A3\u4EFD chrome \u6807\u7B7E\uFF0C\u53D6\u81EA\u672C\u63D2\u4EF6\u7684\u5B57\u5178\u3002\n * @param {Function} t - \u672C\u63D2\u4EF6\u7684\u53D6\u8BCD\u51FD\u6570\u3002\n * @returns {{ code: { copyLabel: string, copiedLabel: string }, footnotes: string }} \u6807\u7B7E\u3002\n */\nfunction markdownLabels(t) {\n return {\n code: { copyLabel: t('copy'), copiedLabel: t('copied') },\n footnotes: t('markdown.footnotes'),\n };\n}\n", "// \u5BBF\u4E3B\u534A\u8FB9\u4E0E\u754C\u9762\u534A\u8FB9\u5171\u7528\u7684\u7EAF\u5951\u7EA6\uFF1A\u9898\u76EE\u5B57\u6BB5\u7684\u62FC\u6CD5\uFF0C\u52A0\u8F6E\u672B\u8865\u5145\u9898\u8FD9\u4E00\u9053\u7531\u4EE3\u7801\u8FFD\u52A0\u7684\u9898\u3002\n//\n// \u4E24\u5904\u5FC5\u987B\u4E00\u81F4\uFF0C\u6240\u4EE5\u53EA\u6709\u8FD9\u4E00\u4EFD\uFF1A\u8868\u5355\u9875\u6807\u9898\u4E0E transcript \u5361\u7247\u6807\u9898\u90FD\u6309\n// mergeNumberIntoHeader \u62FC\uFF1B\u754C\u9762\u6309 id \u8BA4\u51FA\u8F6E\u672B\u8865\u5145\u9898\uFF0C\u4E5F\u6309 ROUND_END_QUESTION \u62FF\u5B83\u7684\u9898\u5E72\u3002\n// \u5404\u5199\u4E00\u4EFD\u5FC5\u7136\u6F02\u3002\n\n/** \u8F6E\u672B\u8865\u5145\u9898\u7684 id \u524D\u7F00\uFF0C\u540C\u65F6\u662F\u6A21\u578B\u4E0D\u5F97\u5360\u7528\u7684\u4FDD\u7559\u524D\u7F00\u3002 */\nexport const RESERVED_ID_PREFIX = '__grill_';\n\n/**\n * \u6BCF\u6B21\u8C03\u7528\u7531\u4EE3\u7801\u8FFD\u52A0\u5728\u672B\u5C3E\u7684\u8865\u5145\u9898\u3002\u754C\u9762\u534A\u8FB9\u6309 id \u8BA4\u51FA\u5B83\uFF0C\u5BBF\u4E3B\u534A\u8FB9\u628A\u5B83\u9001\u8FDB seam\u3002\n * \u9009\u9879\u6570\u7EC4\u7684\u6D45\u62F7\u8D1D\u7531\u5BBF\u4E3B\u5728\u6295\u9012\u524D\u505A\uFF08seam \u4FA7\u4E0D\u518D\u6539\u5B83\uFF0C\u4F46\u522B\u628A\u8FD9\u4EFD\u5E38\u91CF\u4EA4\u51FA\u53BB\uFF09\u3002\n */\nexport const ROUND_END_QUESTION = Object.freeze({\n id: `${RESERVED_ID_PREFIX}round_supplement__`,\n question: '\u8FD9\u8F6E\u8FD8\u6709\u4EC0\u4E48\u8981\u8865\u5145\u6216\u8C03\u6574\u7684\u5417\uFF1F',\n header: '\u8F6E\u672B\u8865\u5145',\n options: Object.freeze([Object.freeze({ label: '\u65E0\u9700\u8865\u5145' })]),\n});\n\n/**\n * \u53BB\u6389\u9996\u5C3E\u7A7A\u767D\u540E\u662F\u5426\u4E3A\u7A7A\u3002\u7A7A\u4E32\u4E0E\u7EAF\u7A7A\u767D\u90FD\u4E0D\u503C\u5F97\u9001\u8FDB\u8868\u5355\u3002\n * @param {unknown} value - \u5F85\u5224\u5B9A\u7684\u503C\u3002\n * @returns {boolean} \u975E\u5B57\u7B26\u4E32\u6216\u53BB\u7A7A\u767D\u540E\u4E3A\u7A7A\u65F6\u4E3A true\u3002\n */\nexport function isBlank(value) {\n return typeof value !== 'string' || value.trim() === '';\n}\n\n/**\n * \u628A\u9898\u53F7\u5E76\u8FDB\u6807\u9898\uFF1A\u4E24\u8005\u90FD\u7ED9\u5199\u4F5C `<number> \u00B7 <header>`\uFF0C\u53EA\u7ED9\u4E00\u4E2A\u5C31\u662F\u90A3\u4E00\u4E2A\uFF1B\n * \u6807\u9898\u5DF2\u7ECF\u4EE5\u8BE5\u9898\u53F7\u5F00\u5934\u65F6\u539F\u6837\u9001\u51FA\u53BB\uFF08\u6A21\u578B\u5E38\u81EA\u5DF1\u5199\u6210 \"Q2 \u00B7 Deadline\"\uFF09\u3002\n * @param {string} [number] - \u9898\u53F7\u3002\n * @param {string} [header] - \u6807\u9898\u3002\n * @returns {string} \u4EA4\u7ED9\u754C\u9762\u7684\u6807\u9898\uFF1B\u4E24\u8005\u90FD\u7F3A\u65F6\u4E3A\u7A7A\u4E32\uFF08\u8C03\u7528\u65B9\u636E\u6B64\u7701\u7565\u8BE5\u5B57\u6BB5\uFF09\u3002\n */\nexport function mergeNumberIntoHeader(number, header) {\n const num = isBlank(number) ? undefined : number;\n const head = isBlank(header) ? undefined : header;\n if (num === undefined) return head ?? '';\n if (head === undefined) return num;\n return head.startsWith(num) ? head : `${num} \u00B7 ${head}`;\n}\n", "// \u4E00\u6B21 ask_user_grilling \u8C03\u7528\u7684\u5361\u7247\u6A21\u578B\uFF1A\u628A\u7EBF\u4E0A\u90A3\u4E24\u4EFD JSON\uFF08\u8C03\u7528\u7684 argsRaw\u3001\u7ED3\u679C\u7684\u6587\u672C\uFF09\n// \u7FFB\u6210\u754C\u9762\u76F4\u63A5\u80FD\u753B\u7684\u7ED3\u6784\u3002\u7EAF\u51FD\u6570\uFF1A\u4E0D\u78B0 React\u3001\u4E0D\u8BFB\u65F6\u949F\u3001\u4E0D\u8BFB\u4F1A\u8BDD\uFF0C\u5B9E\u65F6\u6E32\u67D3\u4E0E\u65E5\u5FD7\u91CD\u653E\u540C\u4E00\u6761\u8DEF\u5F84\u3002\n//\n// \u4E0E\u5B98\u65B9\u5361\uFF08@deepseek-ai/dsh-client-ui-tool \u7684 AskQuestionRow\uFF09\u7684\u53D6\u6570\u5DEE\u522B\u6709\u4E24\u5904\uFF0C\u90FD\u662F\u672C\u63D2\u4EF6\n// \u81EA\u5DF1\u9020\u6210\u7684\uFF1A\u8F6E\u672B\u8865\u5145\u9898\u662F\u5BBF\u4E3B\u8FFD\u52A0\u7684\uFF0C\u4E0D\u5728 argsRaw \u91CC\uFF1Bdetail \u4E5F\u4E0D\u5728\u5B98\u65B9\u5361\u7684\u53D6\u6570\u8303\u56F4\u5185\u3002\n// \u6240\u4EE5\u8FD9\u91CC\u6309 id \u914D\u5BF9\u4E4B\u540E\uFF0C\u628A argsRaw \u91CC\u6CA1\u6709\u7684\u7B54\u6848\u6309\u8F6E\u672B\u8865\u5145\u9898\u53E6\u884C\u5217\u51FA\uFF0C\u5E76\u628A detail \u4E00\u8D77\u5E26\u51FA\u53BB\u3002\n\nimport { ROUND_END_QUESTION, isBlank, mergeNumberIntoHeader } from './contract.js';\n\n/** \u7528\u6237\u53D6\u6D88 / \u4E2D\u65AD\u65F6\u5BBF\u4E3B\u5DE5\u5177\u6536\u5230\u7684\u9519\u8BEF\u7801\uFF0C\u754C\u9762\u636E\u6B64\u7ED9\u51FA\u672A\u4F5C\u7B54\u7684\u8BF4\u660E\u3002 */\nconst CANCELLED_CODE = 'ASK_CANCELLED';\nconst INTERRUPTED_CODE = 'ASK_ABORTED';\n\nfunction isRecord(value) {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/**\n * JSON.parse\uFF0C\u5931\u8D25\u8FD4\u56DE undefined\u3002running \u65F6 argsRaw \u662F\u534A\u622A JSON\uFF0C\u89E3\u6790\u5931\u8D25\u662F\u6B63\u5E38\u6001\u3002\n * @param {unknown} text - \u539F\u59CB\u6587\u672C\u3002\n * @returns {unknown} \u89E3\u6790\u7ED3\u679C\uFF0C\u6216 undefined\u3002\n */\nfunction parseJson(text) {\n if (typeof text !== 'string' || text === '') return undefined;\n try {\n return JSON.parse(text);\n } catch {\n return undefined;\n }\n}\n\nfunction stringList(value) {\n return Array.isArray(value) ? value.filter((item) => typeof item === 'string') : [];\n}\n\n/**\n * argsRaw \u2192 \u6A21\u578B\u51FA\u7684\u9898\u3002\u89E3\u6790\u5931\u8D25\u3001\u6CA1\u6709 questions\u3001\u6216 id \u91CD\u590D\uFF08\u754C\u9762\u6309 id \u914D\u5BF9\uFF0C\u91CD\u590D\u5373\u65E0\u4ECE\u914D\u5BF9\uFF09\u65F6\u8FD4\u56DE\u7A7A\u6570\u7EC4\u3002\n * @param {unknown} argsRaw - \u8C03\u7528\u7684\u539F\u59CB\u53C2\u6570\u6587\u672C\u3002\n * @returns {object[]} \u9898\u76EE\u6761\u76EE\u3002\n */\nfunction readQuestions(argsRaw) {\n const parsed = parseJson(argsRaw);\n if (!isRecord(parsed) || !Array.isArray(parsed.questions)) return [];\n const questions = [];\n const ids = new Set();\n for (const question of parsed.questions) {\n if (!isRecord(question) || typeof question.id !== 'string' || ids.has(question.id)) return [];\n ids.add(question.id);\n questions.push({\n id: question.id,\n header: mergeNumberIntoHeader(question.number, question.header),\n question: typeof question.question === 'string' ? question.question : '',\n detail: isBlank(question.detail) ? undefined : question.detail,\n answers: [],\n supplement: false,\n });\n }\n return questions;\n}\n\n/**\n * \u7ED3\u679C\u6587\u672C \u2192 \u7B54\u6848\u8BB0\u5F55\u3002\u5F62\u72B6\u4E0D\u8BA4\u8BC6\u65F6\u8FD4\u56DE undefined\uFF08\u8C03\u7528\u65B9\u6309\u8C03\u7528\u5931\u8D25\u5904\u7406\uFF09\u3002\n * @param {unknown} resultText - \u5DE5\u5177\u7ED3\u679C\u91CC\u7684\u6587\u672C\u3002\n * @returns {{rejected: boolean, violations: string[], error: string|undefined, answers: object[]}|undefined}\n */\nfunction readResult(resultText) {\n const parsed = parseJson(resultText);\n if (!isRecord(parsed)) return undefined;\n if (parsed.rejected === true) {\n return {\n rejected: true,\n violations: stringList(parsed.violations),\n error: typeof parsed.error === 'string' ? parsed.error : undefined,\n answers: [],\n };\n }\n if (!Array.isArray(parsed.answers)) return undefined;\n const answers = [];\n for (const entry of parsed.answers) {\n if (!isRecord(entry) || typeof entry.id !== 'string') return undefined;\n answers.push({\n id: entry.id,\n selected: stringList(entry.selected),\n custom: typeof entry.custom === 'string' ? entry.custom : undefined,\n });\n }\n return { rejected: false, violations: [], error: undefined, answers };\n}\n\n/**\n * \u8BFB\u51FA\u4E00\u5F20\u5361\u7684\u6A21\u578B\u3002\n * @param {{ argsRaw?: unknown, resultText?: unknown, errorCode?: unknown, failed?: boolean }} input\n * argsRaw\uFF1A\u8C03\u7528\u7684\u539F\u59CB\u53C2\u6570\uFF1BresultText\uFF1A\u7ED3\u679C\u6587\u672C\uFF08running \u65F6\u4E3A\u7A7A\uFF09\uFF1BerrorCode\uFF1A\u5931\u8D25\u7684 code\uFF1B\n * failed\uFF1A\u8FD9\u6B21\u8C03\u7528\u662F\u5426\u4EE5\u5931\u8D25\u6536\u573A\uFF08\u7ED3\u679C\u65E2\u6CA1\u6709\u7B54\u6848\u4E5F\u4E0D\u662F\u62D2\u7EDD\u65F6\u7528\u6765\u533A\u5206\u300C\u8FD0\u884C\u4E2D\u300D\u4E0E\u300C\u5931\u8D25\u300D\uFF09\u3002\n * @returns {{\n * state: 'running'|'answered'|'rejected'|'cancelled'|'interrupted'|'error',\n * questions: object[], answered: number, total: number,\n * violations: string[], error: string|undefined,\n * }} \u5361\u7247\u6A21\u578B\uFF1Bquestions \u4E3A\u7A7A\u8868\u793A\u53C2\u6570\u8FD8\u89E3\u6790\u4E0D\u51FA\u6765\uFF08\u8FD0\u884C\u4E2D\u6216\u4E0D\u662F\u672C\u63D2\u4EF6\u7684\u5F62\u72B6\uFF09\u3002\n */\nexport function readAskCard({ argsRaw, resultText, errorCode, failed = false }) {\n const questions = readQuestions(argsRaw);\n const known = new Set(questions.map((question) => question.id));\n const result = readResult(resultText);\n\n let state;\n if (errorCode === CANCELLED_CODE) state = 'cancelled';\n else if (errorCode === INTERRUPTED_CODE) state = 'interrupted';\n else if (result !== undefined) state = result.rejected ? 'rejected' : 'answered';\n else if (failed) state = 'error';\n else if (typeof resultText === 'string' && resultText !== '') state = 'error';\n else state = 'running';\n\n if (state === 'answered') {\n for (const answer of result.answers) {\n const lines = [\n ...answer.selected,\n ...answer.custom === undefined || answer.custom === '' ? [] : [answer.custom],\n ];\n const entry = questions.find((question) => question.id === answer.id);\n if (entry !== undefined) {\n entry.answers = lines;\n continue;\n }\n const supplement = answer.id === ROUND_END_QUESTION.id;\n questions.push({\n id: answer.id,\n header: supplement ? ROUND_END_QUESTION.header : '',\n question: supplement ? ROUND_END_QUESTION.question : answer.id,\n detail: undefined,\n answers: lines,\n supplement: true,\n });\n }\n } else if ((state === 'running' || state === 'cancelled' || state === 'interrupted') && questions.length > 0) {\n // \u8FD9\u4E00\u8F6E\u771F\u7684\u8FDB\u8FC7\u8868\u5355\uFF08\u6B63\u5728\u56DE\u7B54 / \u88AB\u53D6\u6D88 / \u88AB\u4E2D\u65AD\uFF09\uFF1A\u8865\u5145\u9898\u4E5F\u5728\u8868\u5355\u91CC\uFF0C\u6309\u5E38\u91CF\u8865\u4E00\u6761\u51FA\u6765\u3002\n // \u88AB\u62D2\u4E0E\u8C03\u7528\u5931\u8D25\u90FD\u6CA1\u8D70\u5230\u8868\u5355\uFF0C\u8865\u4E0A\u53BB\u7B49\u4E8E\u62A5\u544A\u4E00\u9053\u6CA1\u95EE\u8FC7\u7684\u9898\uFF1B\u53C2\u6570\u8FD8\u89E3\u6790\u4E0D\u51FA\u6765\u65F6\u540C\u7406\u2014\u2014\n // \u90A3\u662F argsRaw \u8FD8\u5728\u6D41\u5F0F\u4F20\u8F93\uFF0C\u754C\u9762\u9000\u56DE\u539F\u59CB\u6587\u672C\uFF0C\u4E0D\u5047\u88C5\u8BFB\u61C2\u4E86\u8FD9\u4E00\u8F6E\u3002\n if (!known.has(ROUND_END_QUESTION.id)) {\n questions.push({\n id: ROUND_END_QUESTION.id,\n header: ROUND_END_QUESTION.header,\n question: ROUND_END_QUESTION.question,\n detail: undefined,\n answers: [],\n supplement: true,\n });\n }\n }\n\n return finish(state, questions, result);\n}\n\n/**\n * \u6536\u53E3\uFF1A\u7B97\u5DF2\u7B54\u6570\u5E76\u5E26\u4E0A\u62D2\u7EDD\u4FE1\u606F\u3002\n * @param {string} state - \u5361\u7247\u72B6\u6001\u3002\n * @param {object[]} questions - \u6761\u76EE\u5217\u8868\u3002\n * @param {object|undefined} result - \u89E3\u6790\u51FA\u7684\u7ED3\u679C\u8BB0\u5F55\u3002\n * @returns {object} \u5361\u7247\u6A21\u578B\u3002\n */\nfunction finish(state, questions, result) {\n return {\n state,\n questions,\n answered: questions.filter((question) => question.answers.length > 0).length,\n total: questions.length,\n violations: result === undefined ? [] : result.violations,\n error: result === undefined ? undefined : result.error,\n };\n}\n", "export default \"/* ask_user_grilling \u7684 transcript \u5361\u7247\u3002\\n *\\n * \u4E0E\u5B98\u65B9 @deepseek-ai/dsh-client-ui-tool \u7684 ToolRow / AskQuestionCard \u540C\u4E00\u5957 token \u4E0E\u6570\u503C\uFF1A\\n * \u8FD9\u91CC\u53EA\u662F\u628A\u7C7B\u540D\u6362\u6210 dsg- \u524D\u7F00\uFF08\u8DE8\u63D2\u4EF6\u503C\u5BFC\u5165\u88AB\u5BA2\u6237\u7AEF bundle \u7684\u7EAF\u51C0\u5EA6\u95E8\u7981\u6321\u4F4F\uFF0C\u6240\u4EE5\u884C\u5916\u58F3\\n * \u53EA\u80FD\u81EA\u5DF1\u62FC\uFF09\uFF0C\u5F62\u72B6\u3001\u5B57\u53F7\u3001\u884C\u9AD8\u30010.5px \u53D1\u4E1D\u7EBF\u90FD\u7167\u6284\uFF0C\u907F\u514D\u540C\u4E00\u9875\u51FA\u73B0\u4E24\u5957\u89C6\u89C9\u3002 */\\n\\n.dsg-root {\\n display: flex;\\n flex-direction: column;\\n}\\n\\n.dsg-row {\\n position: relative;\\n overflow: hidden;\\n}\\n\\n/* \u8FD0\u884C\u4E2D\uFF1A\u4E0E\u5B98\u65B9\u884C\u540C\u4E00\u6761\u626B\u5149\u3002 */\\n.dsg-root[data-state='running'] .dsg-row::after {\\n content: '';\\n position: absolute;\\n top: 0;\\n bottom: 0;\\n left: 0;\\n width: 300px;\\n pointer-events: none;\\n background: linear-gradient(\\n 90deg,\\n transparent 0%,\\n color-mix(in srgb, var(--dsw-alias-bg-base) 60%, transparent) 55%,\\n transparent 100%\\n );\\n animation: 2.6s ease-out infinite dsg-tool-row-sweep;\\n}\\n\\n@keyframes dsg-tool-row-sweep {\\n 0% {\\n left: -300px;\\n }\\n 90%,\\n 100% {\\n left: 100%;\\n }\\n}\\n\\n.dsg-leading {\\n flex-shrink: 0;\\n}\\n\\n.dsg-chevron {\\n color: var(--dsw-alias-label-secondary);\\n}\\n\\n.dsg-title {\\n font-weight: 400;\\n}\\n\\n.dsg-sep {\\n flex: none;\\n width: 2px;\\n height: 2px;\\n margin: 0 8px;\\n border-radius: 1px;\\n background: var(--dsw-alias-label-caption);\\n}\\n\\n.dsg-summary {\\n flex: auto;\\n min-width: 0;\\n overflow: hidden;\\n text-overflow: ellipsis;\\n white-space: nowrap;\\n font-size: var(--dsh-content-font-size-secondary, 13px);\\n line-height: calc(24px + var(--dsh-content-font-delta, 0px));\\n color: var(--dsw-alias-label-tertiary);\\n}\\n\\n.dsg-bodyWrap {\\n display: flex;\\n flex-direction: column;\\n}\\n\\n.dsg-card {\\n display: flex;\\n flex-direction: column;\\n gap: 16px;\\n max-height: 360px;\\n margin: 4px 0 4px 4px;\\n padding: 16px 20px;\\n overflow-y: auto;\\n border: 0.5px solid var(--dsw-alias-border-l1);\\n border-radius: 12px;\\n background: var(--dsw-alias-bg-base);\\n}\\n\\n.dsg-list {\\n display: flex;\\n flex-direction: column;\\n gap: 16px;\\n margin: 0;\\n}\\n\\n.dsg-item {\\n display: flex;\\n flex-direction: column;\\n gap: 2px;\\n min-width: 0;\\n}\\n\\n.dsg-question,\\n.dsg-answer,\\n.dsg-verdict {\\n margin: 0;\\n white-space: pre-wrap;\\n overflow-wrap: anywhere;\\n font-size: var(--dsh-content-font-size, 14px);\\n line-height: calc(24px + var(--dsh-content-font-delta, 0px));\\n}\\n\\n.dsg-question {\\n color: var(--dsw-alias-label-tertiary);\\n}\\n\\n.dsg-answer,\\n.dsg-verdict {\\n color: var(--dsw-alias-label-primary);\\n}\\n\\n.dsg-failure {\\n margin: 0;\\n white-space: pre-wrap;\\n overflow-wrap: anywhere;\\n font-size: var(--dsh-content-font-size, 14px);\\n line-height: calc(24px + var(--dsh-content-font-delta, 0px));\\n color: var(--dsw-alias-state-error-primary);\\n}\\n\\n.dsg-answerLine {\\n display: block;\\n}\\n\\n.dsg-skipped {\\n color: var(--dsw-alias-label-tertiary);\\n}\\n\\n.dsg-header {\\n display: block;\\n font-size: var(--dsh-content-font-size-secondary, 13px);\\n color: var(--dsw-alias-label-caption);\\n}\\n\\n.dsg-detail {\\n margin: 2px 0 0;\\n font-size: var(--dsh-content-font-size-secondary, 13px);\\n color: var(--dsw-alias-label-secondary);\\n}\\n\\n.dsg-violations {\\n display: flex;\\n flex-direction: column;\\n gap: 8px;\\n margin: 0;\\n padding-left: 20px;\\n font-size: var(--dsh-content-font-size, 14px);\\n line-height: calc(24px + var(--dsh-content-font-delta, 0px));\\n color: var(--dsw-alias-state-error-primary);\\n}\\n\\n.dsg-raw {\\n max-height: 360px;\\n margin: 4px 0 4px 4px;\\n padding: 12px 16px;\\n overflow: auto;\\n border: 0.5px solid var(--dsw-alias-border-l1);\\n border-radius: 12px;\\n background: var(--dsw-alias-markdown-code-block);\\n font: var(--dsw-font-markdown-code-block-small);\\n white-space: pre-wrap;\\n overflow-wrap: anywhere;\\n color: var(--dsw-alias-label-secondary);\\n}\\n\\n.dsg-inspectButton {\\n display: inline-flex;\\n align-self: flex-start;\\n align-items: center;\\n gap: 4px;\\n margin: 4px 0 2px 4px;\\n padding: 2px 8px;\\n border: 0.5px solid var(--dsw-alias-border-l4);\\n border-radius: 999px;\\n corner-shape: round;\\n background: var(--dsw-alias-bg-base);\\n color: var(--dsw-alias-label-secondary);\\n font-size: 11px;\\n line-height: 16px;\\n opacity: 0;\\n cursor: pointer;\\n transition: opacity 100ms ease;\\n}\\n\\n.dsg-bodyWrap:hover .dsg-inspectButton,\\n.dsg-inspectButton:focus-visible {\\n opacity: 1;\\n}\\n\\n.dsg-inspectButton:hover {\\n background: var(--dsw-alias-interactive-bg-hover-solid);\\n color: var(--dsw-alias-label-primary);\\n}\\n\\n.dsg-visuallyHidden {\\n position: absolute;\\n width: 1px;\\n height: 1px;\\n overflow: hidden;\\n clip: rect(0 0 0 0);\\n white-space: nowrap;\\n}\\n\\n@media (prefers-reduced-motion: reduce) {\\n .dsg-root[data-state='running'] .dsg-row::after {\\n animation: none;\\n }\\n\\n .dsg-inspectButton {\\n transition: none;\\n }\\n}\\n\";", "/** \u672C\u63D2\u4EF6\u5361\u7247\u81EA\u5DF1\u7684\u6587\u6848\u5B57\u5178\u3002\u540D\u5B57\u7A7A\u95F4\u5F52\u672C\u63D2\u4EF6\uFF0C\u590D\u7528\u522B\u4EBA\u7684\u540D\u5B57\u7A7A\u95F4\u4F1A\u5728\u5BF9\u65B9\u6539\u952E\u65F6\u9759\u9ED8\u5931\u6548\u3002 */\n\n/** \u5B57\u5178\u540D\u5B57\u7A7A\u95F4\u3002 */\nexport const NS = 'askGrilling';\n\n/** \u7B80\u4F53\u4E2D\u6587\uFF08\u952E\u96C6\u7684\u4E8B\u5B9E\u6765\u6E90\uFF09\u3002 */\nexport const zh = {\n 'row.title': '\u63D0\u95EE',\n 'row.waiting': '\u7B49\u5F85\u56DE\u7B54',\n 'row.answered': '{answered}/{total} \u5DF2\u56DE\u7B54',\n 'row.skipped': '\u672A\u56DE\u7B54',\n 'row.rejected': '\u5165\u53C2\u88AB\u62D2\u7EDD',\n 'row.cancelled': '\u5DF2\u53D6\u6D88',\n 'row.cancelledDetail': '\u672C\u8F6E\u5DF2\u53D6\u6D88\uFF0C\u672A\u63D0\u4EA4\u56DE\u7B54\u3002',\n 'row.interrupted': '\u5DF2\u4E2D\u65AD',\n 'row.interruptedDetail': '\u672C\u8F6E\u5DF2\u4E2D\u65AD\uFF0C\u672A\u63D0\u4EA4\u56DE\u7B54\u3002',\n 'row.failed': '\u8C03\u7528\u5931\u8D25',\n 'row.violations': '\u6821\u9A8C\u5931\u8D25',\n 'row.inspect': '\u67E5\u770B',\n 'copy': '\u590D\u5236',\n 'copied': '\u5DF2\u590D\u5236',\n 'markdown.footnotes': '\u811A\u6CE8',\n};\n\n/** \u82F1\u6587\uFF0C\u952E\u96C6\u4E0E\u4E2D\u6587\u9010\u6761\u5BF9\u9F50\u3002 */\nexport const en = {\n 'row.title': 'Ask question',\n 'row.waiting': 'waiting for the answer',\n 'row.answered': '{answered}/{total} answered',\n 'row.skipped': 'Not answered',\n 'row.rejected': 'Rejected before asking',\n 'row.cancelled': 'cancelled',\n 'row.cancelledDetail': 'This round was cancelled before answers were submitted.',\n 'row.interrupted': 'interrupted',\n 'row.interruptedDetail': 'This round was interrupted before answers were submitted.',\n 'row.failed': 'Tool call failed',\n 'row.violations': 'Rejected input',\n 'row.inspect': 'Inspect',\n 'copy': 'Copy',\n 'copied': 'Copied',\n 'markdown.footnotes': 'Footnotes',\n};\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { AskGrillingRow } from './AskGrillingRow.jsx';\nimport css from './AskGrillingRow.css';\nimport { NS, en, zh } from './locales.js';\n\n/** \u6D4F\u89C8\u5668\u534A\u8FB9\u7684\u5305\u8EAB\u4EFD\uFF0C\u4E5F\u662F bundle \u91CC <style> \u7684\u5F52\u5C5E\u6807\u8BB0\u3002 */\nconst PACKAGE_ID = '@lynn123411/dsh-ask-user-grilling';\nconst CSS_TAG = `${PACKAGE_ID}/AskGrillingRow.css`;\n\n/**\n * \u6D4F\u89C8\u5668\u534A\u8FB9\u8981\u7684 cordis \u670D\u52A1\u3002`locale` \u88C5\u5B57\u5178\uFF0C`slots` \u6CE8\u518C\u884C\uFF1B\n * \u5C11\u58F0\u660E\u4E00\u4E2A\u4E0D\u4F1A\u5F53\u573A\u62A5\u9519\uFF0C\u63D2\u4EF6\u4F1A\u6574\u6761 entry \u53D8 failed\u3001\u4ECE\u9875\u9762\u4E0A\u6D88\u5931\uFF08\u89C1 docs/rules/client-wiring.md\uFF09\u3002\n */\nexport const inject = ['locale', 'slots'];\n\n/** \u6CE8\u5165\u672C\u63D2\u4EF6\u7684\u6837\u5F0F\u8868\uFF1A\u6309\u6807\u7B7E\u952E\u590D\u7528\u540C\u4E00\u4E2A <style>\uFF0CHMR \u91CD\u8DD1\u65F6\u66FF\u6362\u5185\u5BB9\u800C\u4E0D\u662F\u53E0\u4E00\u4EFD\u3002 */\nfunction injectStyles() {\n if (typeof document === 'undefined') return;\n let tag = document.querySelector('style[data-plugin-css=' + JSON.stringify(CSS_TAG) + ']');\n if (tag === null) {\n tag = document.createElement('style');\n tag.dataset.plugin = PACKAGE_ID;\n tag.dataset.pluginCss = CSS_TAG;\n document.head.appendChild(tag);\n }\n tag.textContent = css;\n}\n\n/**\n * \u6D4F\u89C8\u5668\u534A\u8FB9\uFF1A\u88C5\u672C\u63D2\u4EF6\u7684\u5B57\u5178\uFF0C\u7136\u540E\u6309 wire \u5DE5\u5177\u540D\u6CE8\u518C `ask_user_grilling` \u7684\u884C\u3002\n * \u6CE8\u518C\u7684\u662F\u81EA\u6709 key\uFF0C\u5B98\u65B9 `ask_user_question` \u90A3\u5F20\u5361\u4E0D\u53D7\u5F71\u54CD\u3002\n * @param {object} ctx - \u5BA2\u6237\u7AEF\u6839\u4E0A\u4E0B\u6587\u3002\n */\nexport function apply(ctx) {\n injectStyles();\n ctx.effect(() => ctx.locale.register(NS, { zh, en }), 'dsh-ask-user-grilling: dictionaries');\n ctx.slots.inject('tool.call.toolview', () => ctx.slots.register({\n name: 'tool.call.toolview',\n key: 'ask_user_grilling',\n locale: NS,\n }, AskGrillingRow));\n}\n", "import { useMemo, useState } from 'react';\nimport {\n DisclosureRow,\n IconInspectOutlineRegular,\n IconQuestionOutlineRegular,\n MarkdownText,\n StateDot,\n} from '@deepseek-ai/dsh-client-ui-primitives';\nimport { readAskCard } from '../card.js';\n\n/**\n * `ask_user_grilling` \u7684 transcript \u884C\uFF1A\u6309 wire \u5DE5\u5177\u540D\u6CE8\u518C\u8FDB `tool.call.toolview`\uFF0C\n * \u4E0E\u5B98\u65B9 `ask_user_question` \u90A3\u5F20\u5361\u5E76\u5217\uFF08\u6CE8\u518C\u81EA\u6709\u7684 key\uFF0C\u4E0D\u63A5\u7BA1\u5B98\u65B9\u90A3\u5F20\uFF09\u3002\n *\n * \u5B98\u65B9\u5361\u7684\u53D6\u6570\u6B62\u4E8E argsRaw \u7684 id/question \u4E0E\u7ED3\u679C\u7684 answers\uFF0C\u8F6E\u672B\u8865\u5145\u9898\u4E0D\u5728 argsRaw \u91CC\u3001\n * detail \u4E5F\u4E0D\u5728\u8303\u56F4\u5185\uFF0C\u4E8E\u662F\u914D\u4E0D\u4E0A\u5BF9\u5C31\u9000\u56DE\u539F\u59CB JSON\u3002\u8FD9\u91CC\u6362\u6210\u8BFB\u5361\u6A21\u578B\uFF1AargsRaw \u91CC\u6CA1\u6709\u7684\n * \u7B54\u6848\u6309\u8865\u5145\u9898\u53E6\u5217\uFF0Cdetail \u8D70 markdown\u3002\n *\n * @param {{ block: object, toolName: string, inspect?: () => void, t: Function }} props - \u69FD\u4F4D\u7ED9\u7684\u884C\u6570\u636E\u3002\n * @returns {import('react').JSX.Element} \u8FD9\u4E00\u884C\u7684\u5361\u7247\u3002\n */\nexport function AskGrillingRow({ block, toolName, inspect, t }) {\n const [expanded, setExpanded] = useState(false);\n const toggle = () => setExpanded((value) => !value);\n const settled = 'kind' in block;\n const argsRaw = (settled ? block.call?.argsRaw : block.argsRaw) ?? '';\n const resultText = settled ? firstText(block.content) : undefined;\n const model = readAskCard({\n argsRaw,\n resultText,\n errorCode: settled ? block.error?.code : undefined,\n failed: settled && block.isError === true,\n });\n const failure = settled && block.isError === true ? failureText(resultText, block.error) : undefined;\n const expandable = argsRaw !== '' || resultText !== undefined || model.questions.length > 0;\n const open = expanded && expandable;\n const status = statusLabel(model.state, t);\n\n return (\n <div className=\"dsg-root\" data-tool={toolName} data-state={model.state}>\n {status === null ? null : <span className=\"dsg-visuallyHidden\">{status}</span>}\n <DisclosureRow\n icon={leadingFor(model.state)}\n title={t('row.title')}\n open={open}\n expandable={expandable}\n onToggle={toggle}\n expandOnRowClick\n keepContentWhenOpen\n rowClassName=\"dsg-row\"\n leadingClassName=\"dsg-leading\"\n chevronClassName=\"dsg-chevron\"\n titleClassName=\"dsg-title\"\n collapsedContent={\n <>\n <span className=\"dsg-sep\" aria-hidden=\"true\" />\n <span className=\"dsg-summary\">{summaryFor(model, t)}</span>\n </>\n }\n >\n <div className=\"dsg-bodyWrap\">\n <CardBody model={model} argsRaw={argsRaw} resultText={resultText} failure={failure} t={t} />\n {inspect === undefined ? null : (\n <button type=\"button\" className=\"dsg-inspectButton\" onClick={inspect}>\n <IconInspectOutlineRegular />\n {t('row.inspect')}\n </button>\n )}\n </div>\n </DisclosureRow>\n </div>\n );\n}\n\n/**\n * \u7ED3\u679C\u91CC\u7684\u7B2C\u4E00\u6BB5\u6587\u672C\u3002\u672C\u5DE5\u5177\u53EA\u6E32\u67D3\u4E00\u6BB5\uFF0C\u5F62\u72B6\u4E0D\u5BF9\u5C31\u5F53\u6CA1\u6709\u7ED3\u679C\u3002\n * @param {unknown} content - \u7ED3\u679C content \u6570\u7EC4\u3002\n * @returns {string|undefined} \u6587\u672C\u3002\n */\nfunction firstText(content) {\n if (!Array.isArray(content)) return undefined;\n const text = content.find((block) => block?.type === 'text');\n return typeof text?.text === 'string' ? text.text : undefined;\n}\n\n/**\n * \u5931\u8D25\u884C\u8981\u663E\u793A\u7684\u6587\u5B57\uFF1A\u7ED3\u679C\u91CC\u90A3\u6BB5\u6587\u672C\u4F18\u5148\uFF0C\u6CA1\u6709\u5C31\u7528\u9519\u8BEF\u7684 name/code \u62FC\u4E00\u884C\u3002\n * @param {string|undefined} resultText - \u7ED3\u679C\u6587\u672C\u3002\n * @param {{name?: string, code?: string}|undefined} error - \u7ED3\u679C\u8282\u70B9\u4E0A\u7684\u9519\u8BEF\u3002\n * @returns {string|undefined} \u5931\u8D25\u8BF4\u660E\u3002\n */\nfunction failureText(resultText, error) {\n if (resultText !== undefined && resultText !== '') return resultText;\n const parts = [error?.name, error?.code].filter((part) => typeof part === 'string' && part !== '');\n return parts.length === 0 ? undefined : parts.join(': ');\n}\n\n/**\n * \u884C\u7684\u524D\u5BFC\u56FE\u6807\uFF1A\u5931\u8D25\u4E0E\u62D2\u7EDD\u7528\u72B6\u6001\u70B9\uFF0C\u5176\u4F59\u7528\u95EE\u53F7\u56FE\u6807\uFF08\u4E0E\u5B98\u65B9\u884C\u540C\u4E00\u5957\u8BED\u4E49\uFF09\u3002\n * @param {string} state - \u5361\u7247\u72B6\u6001\u3002\n * @returns {import('react').ReactNode} \u524D\u5BFC\u8282\u70B9\u3002\n */\nfunction leadingFor(state) {\n if (state === 'error' || state === 'rejected') return <StateDot state=\"error\" />;\n if (state === 'cancelled' || state === 'interrupted') return <StateDot state=\"warning\" />;\n return <IconQuestionOutlineRegular />;\n}\n\n/**\n * \u5C4F\u5E55\u9605\u8BFB\u5668\u7528\u7684\u72B6\u6001\u6587\u5B57\u3002\u626B\u63CF\u5149\u4E0E\u72B6\u6001\u70B9\u90FD\u662F\u7EAF\u89C6\u89C9\u7684\u3002\n * @param {string} state - \u5361\u7247\u72B6\u6001\u3002\n * @param {Function} t - \u672C\u63D2\u4EF6\u7684\u53D6\u8BCD\u51FD\u6570\u3002\n * @returns {string|null} \u72B6\u6001\u6587\u5B57\uFF0C\u6B63\u5E38\u6001\u4E3A null\u3002\n */\nfunction statusLabel(state, t) {\n switch (state) {\n case 'running':\n return t('row.waiting');\n case 'error':\n return t('row.failed');\n case 'cancelled':\n return t('row.cancelled');\n case 'interrupted':\n return t('row.interrupted');\n default:\n return null;\n }\n}\n\n/**\n * \u6298\u53E0\u884C\u53F3\u4FA7\u7684\u6458\u8981\u3002\n * @param {object} model - \u5361\u7247\u6A21\u578B\u3002\n * @param {Function} t - \u672C\u63D2\u4EF6\u7684\u53D6\u8BCD\u51FD\u6570\u3002\n * @returns {string} \u6458\u8981\u6587\u5B57\u3002\n */\nfunction summaryFor(model, t) {\n switch (model.state) {\n case 'running':\n return t('row.waiting');\n case 'answered':\n return t('row.answered', { answered: model.answered, total: model.total });\n case 'rejected':\n return t('row.rejected');\n case 'cancelled':\n return t('row.cancelled');\n case 'interrupted':\n return t('row.interrupted');\n default:\n return t('row.failed');\n }\n}\n\n/**\n * \u6B63\u6587\uFF1A\u62D2\u7EDD\u65F6\u5148\u7ED9\u8FDD\u89C4\u6E05\u5355\uFF0C\u53D6\u6D88/\u4E2D\u65AD\u65F6\u7ED9\u8BF4\u660E\u52A0\u9898\u76EE\uFF0C\u5931\u8D25\u7ED9\u5931\u8D25\u8BF4\u660E\uFF0C\u5176\u4F59\u6309\u95EE\u7B54\u5217\u8868\u753B\u3002\n * @param {{ model: object, argsRaw: string, resultText: string|undefined, failure: string|undefined, t: Function }} props - \u5361\u7247\u6A21\u578B\u4E0E\u539F\u59CB\u6587\u672C\u3002\n * @returns {import('react').ReactNode} \u6B63\u6587\u3002\n */\nfunction CardBody({ model, argsRaw, resultText, failure, t }) {\n if (model.state === 'rejected') {\n return (\n <div className=\"dsg-card\" role=\"group\" aria-label={t('row.violations')}>\n <p className=\"dsg-verdict\">{model.error ?? t('row.rejected')}</p>\n <ul className=\"dsg-violations\">\n {model.violations.map((violation, index) => (\n <li key={String(index)}>{violation}</li>\n ))}\n </ul>\n <QuestionEntries questions={model.questions} showAnswers={false} t={t} />\n </div>\n );\n }\n if (model.questions.length === 0) {\n // \u8FD0\u884C\u4E2D\u7684\u534A\u622A JSON\u3001\u6216\u4E0D\u662F\u672C\u63D2\u4EF6\u5F62\u72B6\u7684\u7ED3\u679C\uFF1A\u539F\u6837\u7ED9\u51FA\uFF0C\u522B\u88C5\u4F5C\u8BFB\u61C2\u4E86\n const raw = model.state === 'running' ? argsRaw : resultText;\n return raw === undefined || raw === '' ? null : <pre className=\"dsg-raw\">{raw}</pre>;\n }\n if (model.state === 'cancelled' || model.state === 'interrupted') {\n return (\n <div className=\"dsg-card\">\n <p className=\"dsg-verdict\">\n {model.state === 'cancelled' ? t('row.cancelledDetail') : t('row.interruptedDetail')}\n </p>\n <QuestionEntries questions={model.questions} showAnswers={false} t={t} />\n </div>\n );\n }\n if (model.state === 'error') {\n return (\n <div className=\"dsg-card\">\n {failure === undefined ? null : <p className=\"dsg-failure\">{failure}</p>}\n <QuestionEntries questions={model.questions} showAnswers={false} t={t} />\n </div>\n );\n }\n return (\n <div className=\"dsg-card\">\n <QuestionEntries questions={model.questions} showAnswers={model.state === 'answered'} t={t} />\n </div>\n );\n}\n\n/**\n * \u9898\u76EE\u5217\u8868\uFF1A\u6709\u7B54\u6848\u7684\u753B dt/dd\uFF0C\u6CA1\u7B54\u6848\u7684\u53EA\u753B\u9898\u5E72\uFF1Bdetail \u8D70 markdown\u3002\n * @param {{ questions: object[], showAnswers: boolean, t: Function }} props - \u9898\u76EE\u4E0E\u662F\u5426\u753B\u7B54\u6848\u3002\n * @returns {import('react').JSX.Element} \u5217\u8868\u3002\n */\nfunction QuestionEntries({ questions, showAnswers, t }) {\n const labels = useMemo(() => markdownLabels(t), [t]);\n return (\n <dl className=\"dsg-list\">\n {questions.map((question) => (\n <div className=\"dsg-item\" key={question.id}>\n <dt className=\"dsg-question\">\n {question.header === '' ? null : <span className=\"dsg-header\">{question.header}</span>}\n {question.question}\n </dt>\n {question.detail === undefined ? null : (\n <div className=\"dsg-detail\">\n <MarkdownText text={question.detail} labels={labels} />\n </div>\n )}\n {showAnswers ? <AnswerLine question={question} t={t} /> : null}\n </div>\n ))}\n </dl>\n );\n}\n\n/**\n * \u4E00\u9053\u9898\u7684\u7B54\u6848\u884C\uFF1A\u9009\u4E2D\u9879\u9010\u884C\u5217\u51FA\uFF0C\u81EA\u7531\u6587\u672C\u63A5\u5728\u540E\u9762\uFF0C\u4E00\u6761\u90FD\u6CA1\u6709\u5C31\u662F\u300C\u672A\u56DE\u7B54\u300D\u3002\n * @param {{ question: object, t: Function }} props - \u9898\u76EE\u4E0E\u53D6\u8BCD\u51FD\u6570\u3002\n * @returns {import('react').JSX.Element} \u7B54\u6848\u884C\u3002\n */\nfunction AnswerLine({ question, t }) {\n return (\n <dd className=\"dsg-answer\">\n {question.answers.length === 0 ? (\n <span className=\"dsg-skipped\">{t('row.skipped')}</span>\n ) : (\n question.answers.map((answer, index) => (\n <span className=\"dsg-answerLine\" key={`${question.id}-${String(index)}`}>\n {answer}\n </span>\n ))\n )}\n </dd>\n );\n}\n\n/**\n * `MarkdownText` \u8981\u7684\u90A3\u4EFD chrome \u6807\u7B7E\uFF0C\u53D6\u81EA\u672C\u63D2\u4EF6\u7684\u5B57\u5178\u3002\n * @param {Function} t - \u672C\u63D2\u4EF6\u7684\u53D6\u8BCD\u51FD\u6570\u3002\n * @returns {{ code: { copyLabel: string, copiedLabel: string }, footnotes: string }} \u6807\u7B7E\u3002\n */\nfunction markdownLabels(t) {\n return {\n code: { copyLabel: t('copy'), copiedLabel: t('copied') },\n footnotes: t('markdown.footnotes'),\n };\n}\n", "// \u5BBF\u4E3B\u534A\u8FB9\u4E0E\u754C\u9762\u534A\u8FB9\u5171\u7528\u7684\u7EAF\u5951\u7EA6\uFF1A\u9898\u76EE\u5B57\u6BB5\u7684\u62FC\u6CD5\uFF0C\u52A0\u8F6E\u672B\u8865\u5145\u9898\u8FD9\u4E00\u9053\u7531\u4EE3\u7801\u8FFD\u52A0\u7684\u9898\u3002\n//\n// \u4E24\u5904\u5FC5\u987B\u4E00\u81F4\uFF0C\u6240\u4EE5\u53EA\u6709\u8FD9\u4E00\u4EFD\uFF1A\u8868\u5355\u9875\u6807\u9898\u4E0E transcript \u5361\u7247\u6807\u9898\u90FD\u6309\n// mergeNumberIntoHeader \u62FC\uFF1B\u754C\u9762\u6309 id \u8BA4\u51FA\u8F6E\u672B\u8865\u5145\u9898\uFF0C\u4E5F\u6309 ROUND_END_QUESTION \u62FF\u5B83\u7684\u9898\u5E72\u3002\n// \u5404\u5199\u4E00\u4EFD\u5FC5\u7136\u6F02\u3002\n\n/** \u8F6E\u672B\u8865\u5145\u9898\u7684 id \u524D\u7F00\uFF0C\u540C\u65F6\u662F\u6A21\u578B\u4E0D\u5F97\u5360\u7528\u7684\u4FDD\u7559\u524D\u7F00\u3002 */\nexport const RESERVED_ID_PREFIX = '__grill_';\n\n/**\n * \u6BCF\u6B21\u8C03\u7528\u7531\u4EE3\u7801\u8FFD\u52A0\u5728\u672B\u5C3E\u7684\u8865\u5145\u9898\u3002\u754C\u9762\u534A\u8FB9\u6309 id \u8BA4\u51FA\u5B83\uFF0C\u5BBF\u4E3B\u534A\u8FB9\u628A\u5B83\u9001\u8FDB seam\u3002\n * \u9009\u9879\u6570\u7EC4\u7684\u6D45\u62F7\u8D1D\u7531\u5BBF\u4E3B\u5728\u6295\u9012\u524D\u505A\uFF08seam \u4FA7\u4E0D\u518D\u6539\u5B83\uFF0C\u4F46\u522B\u628A\u8FD9\u4EFD\u5E38\u91CF\u4EA4\u51FA\u53BB\uFF09\u3002\n */\nexport const ROUND_END_QUESTION = Object.freeze({\n id: `${RESERVED_ID_PREFIX}round_supplement__`,\n question: '\u8FD9\u8F6E\u8FD8\u6709\u4EC0\u4E48\u8981\u8865\u5145\u6216\u8C03\u6574\u7684\u5417\uFF1F',\n header: '\u8F6E\u672B\u8865\u5145',\n options: Object.freeze([Object.freeze({ label: '\u65E0\u9700\u8865\u5145' })]),\n});\n\n/**\n * \u53BB\u6389\u9996\u5C3E\u7A7A\u767D\u540E\u662F\u5426\u4E3A\u7A7A\u3002\u7A7A\u4E32\u4E0E\u7EAF\u7A7A\u767D\u90FD\u4E0D\u503C\u5F97\u9001\u8FDB\u8868\u5355\u3002\n * @param {unknown} value - \u5F85\u5224\u5B9A\u7684\u503C\u3002\n * @returns {boolean} \u975E\u5B57\u7B26\u4E32\u6216\u53BB\u7A7A\u767D\u540E\u4E3A\u7A7A\u65F6\u4E3A true\u3002\n */\nexport function isBlank(value) {\n return typeof value !== 'string' || value.trim() === '';\n}\n\n/**\n * \u628A\u9898\u53F7\u5E76\u8FDB\u6807\u9898\uFF1A\u4E24\u8005\u90FD\u7ED9\u5199\u4F5C `<number> \u00B7 <header>`\uFF0C\u53EA\u7ED9\u4E00\u4E2A\u5C31\u662F\u90A3\u4E00\u4E2A\uFF1B\n * \u6807\u9898\u5DF2\u7ECF\u4EE5\u8BE5\u9898\u53F7\u5F00\u5934\u65F6\u539F\u6837\u9001\u51FA\u53BB\uFF08\u6A21\u578B\u5E38\u81EA\u5DF1\u5199\u6210 \"Q2 \u00B7 Deadline\"\uFF09\u3002\n * @param {string} [number] - \u9898\u53F7\u3002\n * @param {string} [header] - \u6807\u9898\u3002\n * @returns {string} \u4EA4\u7ED9\u754C\u9762\u7684\u6807\u9898\uFF1B\u4E24\u8005\u90FD\u7F3A\u65F6\u4E3A\u7A7A\u4E32\uFF08\u8C03\u7528\u65B9\u636E\u6B64\u7701\u7565\u8BE5\u5B57\u6BB5\uFF09\u3002\n */\nexport function mergeNumberIntoHeader(number, header) {\n const num = isBlank(number) ? undefined : number;\n const head = isBlank(header) ? undefined : header;\n if (num === undefined) return head ?? '';\n if (head === undefined) return num;\n return head.startsWith(num) ? head : `${num} \u00B7 ${head}`;\n}\n", "// \u4E00\u6B21 ask_user_grilling \u8C03\u7528\u7684\u5361\u7247\u6A21\u578B\uFF1A\u628A\u7EBF\u4E0A\u90A3\u4E24\u4EFD JSON\uFF08\u8C03\u7528\u7684 argsRaw\u3001\u7ED3\u679C\u7684\u6587\u672C\uFF09\n// \u7FFB\u6210\u754C\u9762\u76F4\u63A5\u80FD\u753B\u7684\u7ED3\u6784\u3002\u7EAF\u51FD\u6570\uFF1A\u4E0D\u78B0 React\u3001\u4E0D\u8BFB\u65F6\u949F\u3001\u4E0D\u8BFB\u4F1A\u8BDD\uFF0C\u5B9E\u65F6\u6E32\u67D3\u4E0E\u65E5\u5FD7\u91CD\u653E\u540C\u4E00\u6761\u8DEF\u5F84\u3002\n//\n// \u4E0E\u5B98\u65B9\u5361\uFF08@deepseek-ai/dsh-client-ui-tool \u7684 AskQuestionRow\uFF09\u7684\u53D6\u6570\u5DEE\u522B\u6709\u4E24\u5904\uFF0C\u90FD\u662F\u672C\u63D2\u4EF6\n// \u81EA\u5DF1\u9020\u6210\u7684\uFF1A\u8F6E\u672B\u8865\u5145\u9898\u662F\u5BBF\u4E3B\u8FFD\u52A0\u7684\uFF0C\u4E0D\u5728 argsRaw \u91CC\uFF1Bdetail \u4E5F\u4E0D\u5728\u5B98\u65B9\u5361\u7684\u53D6\u6570\u8303\u56F4\u5185\u3002\n// \u6240\u4EE5\u8FD9\u91CC\u6309 id \u914D\u5BF9\u4E4B\u540E\uFF0C\u628A argsRaw \u91CC\u6CA1\u6709\u7684\u7B54\u6848\u6309\u8F6E\u672B\u8865\u5145\u9898\u53E6\u884C\u5217\u51FA\uFF0C\u5E76\u628A detail \u4E00\u8D77\u5E26\u51FA\u53BB\u3002\n\nimport { ROUND_END_QUESTION, isBlank, mergeNumberIntoHeader } from './contract.js';\n\n/** \u7528\u6237\u53D6\u6D88 / \u4E2D\u65AD\u65F6\u5BBF\u4E3B\u5DE5\u5177\u6536\u5230\u7684\u9519\u8BEF\u7801\uFF0C\u754C\u9762\u636E\u6B64\u7ED9\u51FA\u672A\u4F5C\u7B54\u7684\u8BF4\u660E\u3002 */\nconst CANCELLED_CODE = 'ASK_CANCELLED';\nconst INTERRUPTED_CODE = 'ASK_ABORTED';\n\nfunction isRecord(value) {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/**\n * JSON.parse\uFF0C\u5931\u8D25\u8FD4\u56DE undefined\u3002running \u65F6 argsRaw \u662F\u534A\u622A JSON\uFF0C\u89E3\u6790\u5931\u8D25\u662F\u6B63\u5E38\u6001\u3002\n * @param {unknown} text - \u539F\u59CB\u6587\u672C\u3002\n * @returns {unknown} \u89E3\u6790\u7ED3\u679C\uFF0C\u6216 undefined\u3002\n */\nfunction parseJson(text) {\n if (typeof text !== 'string' || text === '') return undefined;\n try {\n return JSON.parse(text);\n } catch {\n return undefined;\n }\n}\n\nfunction stringList(value) {\n return Array.isArray(value) ? value.filter((item) => typeof item === 'string') : [];\n}\n\n/**\n * argsRaw \u2192 \u6A21\u578B\u51FA\u7684\u9898\u3002\u89E3\u6790\u5931\u8D25\u3001\u6CA1\u6709 questions\u3001\u6216 id \u91CD\u590D\uFF08\u754C\u9762\u6309 id \u914D\u5BF9\uFF0C\u91CD\u590D\u5373\u65E0\u4ECE\u914D\u5BF9\uFF09\u65F6\u8FD4\u56DE\u7A7A\u6570\u7EC4\u3002\n * @param {unknown} argsRaw - \u8C03\u7528\u7684\u539F\u59CB\u53C2\u6570\u6587\u672C\u3002\n * @returns {object[]} \u9898\u76EE\u6761\u76EE\u3002\n */\nfunction readQuestions(argsRaw) {\n const parsed = parseJson(argsRaw);\n if (!isRecord(parsed) || !Array.isArray(parsed.questions)) return [];\n const questions = [];\n const ids = new Set();\n for (const question of parsed.questions) {\n if (!isRecord(question) || typeof question.id !== 'string' || ids.has(question.id)) return [];\n ids.add(question.id);\n questions.push({\n id: question.id,\n header: mergeNumberIntoHeader(question.number, question.header),\n question: typeof question.question === 'string' ? question.question : '',\n detail: isBlank(question.detail) ? undefined : question.detail,\n answers: [],\n supplement: false,\n });\n }\n return questions;\n}\n\n/**\n * \u7ED3\u679C\u6587\u672C \u2192 \u7B54\u6848\u8BB0\u5F55\u3002\u5F62\u72B6\u4E0D\u8BA4\u8BC6\u65F6\u8FD4\u56DE undefined\uFF08\u8C03\u7528\u65B9\u6309\u8C03\u7528\u5931\u8D25\u5904\u7406\uFF09\u3002\n * @param {unknown} resultText - \u5DE5\u5177\u7ED3\u679C\u91CC\u7684\u6587\u672C\u3002\n * @returns {{rejected: boolean, violations: string[], error: string|undefined, answers: object[]}|undefined}\n */\nfunction readResult(resultText) {\n const parsed = parseJson(resultText);\n if (!isRecord(parsed)) return undefined;\n if (parsed.rejected === true) {\n return {\n rejected: true,\n violations: stringList(parsed.violations),\n error: typeof parsed.error === 'string' ? parsed.error : undefined,\n answers: [],\n };\n }\n if (!Array.isArray(parsed.answers)) return undefined;\n const answers = [];\n for (const entry of parsed.answers) {\n if (!isRecord(entry) || typeof entry.id !== 'string') return undefined;\n answers.push({\n id: entry.id,\n selected: stringList(entry.selected),\n custom: typeof entry.custom === 'string' ? entry.custom : undefined,\n });\n }\n return { rejected: false, violations: [], error: undefined, answers };\n}\n\n/**\n * \u8BFB\u51FA\u4E00\u5F20\u5361\u7684\u6A21\u578B\u3002\n * @param {{ argsRaw?: unknown, resultText?: unknown, errorCode?: unknown, failed?: boolean }} input\n * argsRaw\uFF1A\u8C03\u7528\u7684\u539F\u59CB\u53C2\u6570\uFF1BresultText\uFF1A\u7ED3\u679C\u6587\u672C\uFF08running \u65F6\u4E3A\u7A7A\uFF09\uFF1BerrorCode\uFF1A\u5931\u8D25\u7684 code\uFF1B\n * failed\uFF1A\u8FD9\u6B21\u8C03\u7528\u662F\u5426\u4EE5\u5931\u8D25\u6536\u573A\uFF08\u7ED3\u679C\u65E2\u6CA1\u6709\u7B54\u6848\u4E5F\u4E0D\u662F\u62D2\u7EDD\u65F6\u7528\u6765\u533A\u5206\u300C\u8FD0\u884C\u4E2D\u300D\u4E0E\u300C\u5931\u8D25\u300D\uFF09\u3002\n * @returns {{\n * state: 'running'|'answered'|'rejected'|'cancelled'|'interrupted'|'error',\n * questions: object[], answered: number, total: number,\n * violations: string[], error: string|undefined,\n * }} \u5361\u7247\u6A21\u578B\uFF1Bquestions \u4E3A\u7A7A\u8868\u793A\u53C2\u6570\u8FD8\u89E3\u6790\u4E0D\u51FA\u6765\uFF08\u8FD0\u884C\u4E2D\u6216\u4E0D\u662F\u672C\u63D2\u4EF6\u7684\u5F62\u72B6\uFF09\u3002\n */\nexport function readAskCard({ argsRaw, resultText, errorCode, failed = false }) {\n const questions = readQuestions(argsRaw);\n const known = new Set(questions.map((question) => question.id));\n const result = readResult(resultText);\n\n let state;\n if (errorCode === CANCELLED_CODE) state = 'cancelled';\n else if (errorCode === INTERRUPTED_CODE) state = 'interrupted';\n else if (result !== undefined) state = result.rejected ? 'rejected' : 'answered';\n else if (failed) state = 'error';\n else if (typeof resultText === 'string' && resultText !== '') state = 'error';\n else state = 'running';\n\n if (state === 'answered') {\n for (const answer of result.answers) {\n const lines = [\n ...answer.selected,\n ...answer.custom === undefined || answer.custom === '' ? [] : [answer.custom],\n ];\n const entry = questions.find((question) => question.id === answer.id);\n if (entry !== undefined) {\n entry.answers = lines;\n continue;\n }\n const supplement = answer.id === ROUND_END_QUESTION.id;\n questions.push({\n id: answer.id,\n header: supplement ? ROUND_END_QUESTION.header : '',\n question: supplement ? ROUND_END_QUESTION.question : answer.id,\n detail: undefined,\n answers: lines,\n supplement: true,\n });\n }\n } else if ((state === 'running' || state === 'cancelled' || state === 'interrupted') && questions.length > 0) {\n // \u8FD9\u4E00\u8F6E\u771F\u7684\u8FDB\u8FC7\u8868\u5355\uFF08\u6B63\u5728\u56DE\u7B54 / \u88AB\u53D6\u6D88 / \u88AB\u4E2D\u65AD\uFF09\uFF1A\u8865\u5145\u9898\u4E5F\u5728\u8868\u5355\u91CC\uFF0C\u6309\u5E38\u91CF\u8865\u4E00\u6761\u51FA\u6765\u3002\n // \u88AB\u62D2\u4E0E\u8C03\u7528\u5931\u8D25\u90FD\u6CA1\u8D70\u5230\u8868\u5355\uFF0C\u8865\u4E0A\u53BB\u7B49\u4E8E\u62A5\u544A\u4E00\u9053\u6CA1\u95EE\u8FC7\u7684\u9898\uFF1B\u53C2\u6570\u8FD8\u89E3\u6790\u4E0D\u51FA\u6765\u65F6\u540C\u7406\u2014\u2014\n // \u90A3\u662F argsRaw \u8FD8\u5728\u6D41\u5F0F\u4F20\u8F93\uFF0C\u754C\u9762\u9000\u56DE\u539F\u59CB\u6587\u672C\uFF0C\u4E0D\u5047\u88C5\u8BFB\u61C2\u4E86\u8FD9\u4E00\u8F6E\u3002\n if (!known.has(ROUND_END_QUESTION.id)) {\n questions.push({\n id: ROUND_END_QUESTION.id,\n header: ROUND_END_QUESTION.header,\n question: ROUND_END_QUESTION.question,\n detail: undefined,\n answers: [],\n supplement: true,\n });\n }\n }\n\n return finish(state, questions, result);\n}\n\n/**\n * \u6536\u53E3\uFF1A\u7B97\u5DF2\u7B54\u6570\u5E76\u5E26\u4E0A\u62D2\u7EDD\u4FE1\u606F\u3002\n * @param {string} state - \u5361\u7247\u72B6\u6001\u3002\n * @param {object[]} questions - \u6761\u76EE\u5217\u8868\u3002\n * @param {object|undefined} result - \u89E3\u6790\u51FA\u7684\u7ED3\u679C\u8BB0\u5F55\u3002\n * @returns {object} \u5361\u7247\u6A21\u578B\u3002\n */\nfunction finish(state, questions, result) {\n return {\n state,\n questions,\n answered: questions.filter((question) => question.answers.length > 0).length,\n total: questions.length,\n violations: result === undefined ? [] : result.violations,\n error: result === undefined ? undefined : result.error,\n };\n}\n", "export default \"/* ask_user_grilling \u7684 transcript \u5361\u7247\u3002\\n *\\n * \u4E0E\u5B98\u65B9 @deepseek-ai/dsh-client-ui-tool \u7684 ToolRow / AskQuestionCard \u540C\u4E00\u5957 token \u4E0E\u6570\u503C\uFF1A\\n * \u8FD9\u91CC\u53EA\u662F\u628A\u7C7B\u540D\u6362\u6210 dsg- \u524D\u7F00\uFF08\u8DE8\u63D2\u4EF6\u503C\u5BFC\u5165\u88AB\u5BA2\u6237\u7AEF bundle \u7684\u7EAF\u51C0\u5EA6\u95E8\u7981\u6321\u4F4F\uFF0C\u6240\u4EE5\u884C\u5916\u58F3\\n * \u53EA\u80FD\u81EA\u5DF1\u62FC\uFF09\uFF0C\u5F62\u72B6\u3001\u5B57\u53F7\u3001\u884C\u9AD8\u30010.5px \u53D1\u4E1D\u7EBF\u90FD\u7167\u6284\uFF0C\u907F\u514D\u540C\u4E00\u9875\u51FA\u73B0\u4E24\u5957\u89C6\u89C9\u3002 */\\n\\n.dsg-root {\\n display: flex;\\n flex-direction: column;\\n}\\n\\n.dsg-row {\\n position: relative;\\n overflow: hidden;\\n}\\n\\n/* \u8FD0\u884C\u4E2D\uFF1A\u4E0E\u5B98\u65B9\u884C\u540C\u4E00\u6761\u626B\u5149\u3002 */\\n.dsg-root[data-state='running'] .dsg-row::after {\\n content: '';\\n position: absolute;\\n top: 0;\\n bottom: 0;\\n left: 0;\\n width: 300px;\\n pointer-events: none;\\n background: linear-gradient(\\n 90deg,\\n transparent 0%,\\n color-mix(in srgb, var(--dsw-alias-bg-base) 60%, transparent) 55%,\\n transparent 100%\\n );\\n animation: 2.6s ease-out infinite dsg-tool-row-sweep;\\n}\\n\\n@keyframes dsg-tool-row-sweep {\\n 0% {\\n left: -300px;\\n }\\n 90%,\\n 100% {\\n left: 100%;\\n }\\n}\\n\\n.dsg-leading {\\n flex-shrink: 0;\\n}\\n\\n.dsg-chevron {\\n color: var(--dsw-alias-label-secondary);\\n}\\n\\n.dsg-title {\\n font-weight: 400;\\n}\\n\\n.dsg-sep {\\n flex: none;\\n width: 2px;\\n height: 2px;\\n margin: 0 8px;\\n border-radius: 1px;\\n background: var(--dsw-alias-label-caption);\\n}\\n\\n.dsg-summary {\\n flex: auto;\\n min-width: 0;\\n overflow: hidden;\\n text-overflow: ellipsis;\\n white-space: nowrap;\\n font-size: var(--dsh-content-font-size-secondary, 13px);\\n line-height: calc(24px + var(--dsh-content-font-delta, 0px));\\n color: var(--dsw-alias-label-tertiary);\\n}\\n\\n.dsg-bodyWrap {\\n display: flex;\\n flex-direction: column;\\n}\\n\\n.dsg-card {\\n display: flex;\\n flex-direction: column;\\n gap: 16px;\\n max-height: 360px;\\n margin: 4px 0 4px 4px;\\n padding: 16px 20px;\\n overflow-y: auto;\\n border: 0.5px solid var(--dsw-alias-border-l1);\\n border-radius: 12px;\\n background: var(--dsw-alias-bg-base);\\n}\\n\\n.dsg-list {\\n display: flex;\\n flex-direction: column;\\n gap: 16px;\\n margin: 0;\\n}\\n\\n.dsg-item {\\n display: flex;\\n flex-direction: column;\\n gap: 2px;\\n min-width: 0;\\n}\\n\\n.dsg-question,\\n.dsg-answer,\\n.dsg-verdict {\\n margin: 0;\\n white-space: pre-wrap;\\n overflow-wrap: anywhere;\\n font-size: var(--dsh-content-font-size, 14px);\\n line-height: calc(24px + var(--dsh-content-font-delta, 0px));\\n}\\n\\n.dsg-question {\\n color: var(--dsw-alias-label-tertiary);\\n}\\n\\n.dsg-answer,\\n.dsg-verdict {\\n color: var(--dsw-alias-label-primary);\\n}\\n\\n.dsg-failure {\\n margin: 0;\\n white-space: pre-wrap;\\n overflow-wrap: anywhere;\\n font-size: var(--dsh-content-font-size, 14px);\\n line-height: calc(24px + var(--dsh-content-font-delta, 0px));\\n color: var(--dsw-alias-state-error-primary);\\n}\\n\\n.dsg-answerLine {\\n display: block;\\n}\\n\\n.dsg-skipped {\\n color: var(--dsw-alias-label-tertiary);\\n}\\n\\n.dsg-header {\\n display: block;\\n font-size: var(--dsh-content-font-size-secondary, 13px);\\n color: var(--dsw-alias-label-caption);\\n}\\n\\n.dsg-detail {\\n margin: 2px 0 0;\\n font-size: var(--dsh-content-font-size-secondary, 13px);\\n color: var(--dsw-alias-label-secondary);\\n}\\n\\n.dsg-violations {\\n display: flex;\\n flex-direction: column;\\n gap: 8px;\\n margin: 0;\\n padding-left: 20px;\\n font-size: var(--dsh-content-font-size, 14px);\\n line-height: calc(24px + var(--dsh-content-font-delta, 0px));\\n color: var(--dsw-alias-state-error-primary);\\n}\\n\\n.dsg-raw {\\n max-height: 360px;\\n margin: 4px 0 4px 4px;\\n padding: 12px 16px;\\n overflow: auto;\\n border: 0.5px solid var(--dsw-alias-border-l1);\\n border-radius: 12px;\\n background: var(--dsw-alias-markdown-code-block);\\n font: var(--dsw-font-markdown-code-block-small);\\n white-space: pre-wrap;\\n overflow-wrap: anywhere;\\n color: var(--dsw-alias-label-secondary);\\n}\\n\\n.dsg-inspectButton {\\n display: inline-flex;\\n align-self: flex-start;\\n align-items: center;\\n gap: 4px;\\n margin: 4px 0 2px 4px;\\n padding: 2px 8px;\\n border: 0.5px solid var(--dsw-alias-border-l4);\\n border-radius: 999px;\\n corner-shape: round;\\n background: var(--dsw-alias-bg-base);\\n color: var(--dsw-alias-label-secondary);\\n font-size: 11px;\\n line-height: 16px;\\n opacity: 0;\\n cursor: pointer;\\n transition: opacity 100ms ease;\\n}\\n\\n.dsg-bodyWrap:hover .dsg-inspectButton,\\n.dsg-inspectButton:focus-visible {\\n opacity: 1;\\n}\\n\\n.dsg-inspectButton:hover {\\n background: var(--dsw-alias-interactive-bg-hover-solid);\\n color: var(--dsw-alias-label-primary);\\n}\\n\\n.dsg-visuallyHidden {\\n position: absolute;\\n width: 1px;\\n height: 1px;\\n overflow: hidden;\\n clip: rect(0 0 0 0);\\n white-space: nowrap;\\n}\\n\\n@media (prefers-reduced-motion: reduce) {\\n .dsg-root[data-state='running'] .dsg-row::after {\\n animation: none;\\n }\\n\\n .dsg-inspectButton {\\n transition: none;\\n }\\n}\\n\";", "/** \u672C\u63D2\u4EF6\u5361\u7247\u81EA\u5DF1\u7684\u6587\u6848\u5B57\u5178\u3002\u540D\u5B57\u7A7A\u95F4\u5F52\u672C\u63D2\u4EF6\uFF0C\u590D\u7528\u522B\u4EBA\u7684\u540D\u5B57\u7A7A\u95F4\u4F1A\u5728\u5BF9\u65B9\u6539\u952E\u65F6\u9759\u9ED8\u5931\u6548\u3002 */\n\n/** \u5B57\u5178\u540D\u5B57\u7A7A\u95F4\u3002 */\nexport const NS = 'askGrilling';\n\n/** \u7B80\u4F53\u4E2D\u6587\uFF08\u952E\u96C6\u7684\u4E8B\u5B9E\u6765\u6E90\uFF09\u3002 */\nexport const zh = {\n 'row.title': '\u63D0\u95EE',\n 'row.waiting': '\u7B49\u5F85\u56DE\u7B54',\n 'row.answered': '{answered}/{total} \u5DF2\u56DE\u7B54',\n 'row.skipped': '\u672A\u56DE\u7B54',\n 'row.rejected': '\u5165\u53C2\u88AB\u62D2\u7EDD',\n 'row.cancelled': '\u5DF2\u53D6\u6D88',\n 'row.cancelledDetail': '\u672C\u8F6E\u5DF2\u53D6\u6D88\uFF0C\u672A\u63D0\u4EA4\u56DE\u7B54\u3002',\n 'row.interrupted': '\u5DF2\u4E2D\u65AD',\n 'row.interruptedDetail': '\u672C\u8F6E\u5DF2\u4E2D\u65AD\uFF0C\u672A\u63D0\u4EA4\u56DE\u7B54\u3002',\n 'row.failed': '\u8C03\u7528\u5931\u8D25',\n 'row.violations': '\u6821\u9A8C\u5931\u8D25',\n 'row.inspect': '\u67E5\u770B',\n 'copy': '\u590D\u5236',\n 'copied': '\u5DF2\u590D\u5236',\n 'markdown.footnotes': '\u811A\u6CE8',\n};\n\n/** \u82F1\u6587\uFF0C\u952E\u96C6\u4E0E\u4E2D\u6587\u9010\u6761\u5BF9\u9F50\u3002 */\nexport const en = {\n 'row.title': 'Ask question',\n 'row.waiting': 'waiting for the answer',\n 'row.answered': '{answered}/{total} answered',\n 'row.skipped': 'Not answered',\n 'row.rejected': 'Rejected before asking',\n 'row.cancelled': 'cancelled',\n 'row.cancelledDetail': 'This round was cancelled before answers were submitted.',\n 'row.interrupted': 'interrupted',\n 'row.interruptedDetail': 'This round was interrupted before answers were submitted.',\n 'row.failed': 'Tool call failed',\n 'row.violations': 'Rejected input',\n 'row.inspect': 'Inspect',\n 'copy': 'Copy',\n 'copied': 'Copied',\n 'markdown.footnotes': 'Footnotes',\n};\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
package/lib/index.js CHANGED
@@ -70,7 +70,7 @@ function apply(ctx, config) {
70
70
  if (readConfig(config).carrier) return;
71
71
  ctx.tools.register(defineTool({
72
72
  name: "ask_user_grilling",
73
- description: "Ask the user a concise question when you need confirmation, a choice, or missing information before proceeding. Send one or more questions, each with a stable id that will be echoed in the answer.",
73
+ description: "Ask the user a concise question when you need confirmation, a choice, or missing information before proceeding.",
74
74
  parameters: {
75
75
  questions: {
76
76
  type: "array",
package/lib/index.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/index.js", "../src/contract.js", "../src/recommendation.js"],
4
- "sourcesContent": ["import { defineTool } from \"@deepseek-ai/dsh-tools\";\nimport \"@deepseek-ai/dsh-user-questions\";\nimport { RESERVED_ID_PREFIX, ROUND_END_QUESTION, isBlank, mergeNumberIntoHeader } from \"./contract.js\";\nimport { normalizeOption } from \"./recommendation.js\";\n\n/**\n * @lynn123411/dsh-ask-user-grilling \u2014 a presentation variant of the native\n * `ask_user_question` (`@deepseek-ai/dsh-tool-ask-user`). Same capability seam\n * (ctx.userQuestions), the same tool description and the same descriptions for\n * the shared parameters verbatim; only the rendered form differs.\n *\n * ask_user_grilling:\n * - forces multi-select on every question \u2014 the schema offers no opt-out\n * - merges the optional `number` into the header as \"<number> \u00B7 <header>\",\n * so a form page carries the same Q-number the round announced in prose;\n * a header that already opens with that number is sent as it is\n * - passes the optional `detail` through to the seam: the client renders it as\n * markdown under the question, while the question itself is a plain heading\n * with no markdown and no line breaks, so a multi-paragraph body belongs in\n * `detail`\n * - normalizes the recommendation marker into the one form the client renders,\n * a trailing \"\uFF08\u63A8\u8350\uFF09\" on the label: an explicit `recommended` flag, or a\n * loose marker at the end of the label or the description, is moved there \u2014\n * the client reads only the label and accepts only the bracketed suffix\n * - appends a round-end supplement question; per-question supplement goes\n * through the built-in custom input (\"Type your answer\" / \"\u8F93\u5165\u4F60\u7684\u7B54\u6848\"),\n * so no extra per-question option is added (it would duplicate that field)\n * - rejects what the form cannot carry: a question id under the reserved\n * `__grill_` prefix, a duplicate question id, a blank question text, a blank\n * option label, or two options of one question that end up with the same\n * label (the client keys selection by label, so a collision cannot be\n * restored or even clicked apart)\n *\n * Two rows mount this module. The preset tool row registers the tool (the\n * default). The profile bundle row, inserted by this package's\n * `cordis.patch.yml`, exists only so the Web client serves `lib/client.js` \u2014\n * the browser bundle is served for an enabled Loader entry, and a preset row is\n * a directly plugged subtree rather than a Loader entry, so the package must be\n * in `dsh.profile.bundles` for its card to reach the page. That row passes\n * `config.carrier: true` and registers nothing; without it the tool would also\n * become a root-layer tool, visible to agents on every other preset.\n */\nconst name = \"tool-ask-user-grilling\";\nconst inject = [\"tools\", \"userQuestions\"];\n\n/** \u8F7D\u4F53\u884C\u8BA4\u8FD9\u4E00\u4E2A\u952E\uFF0C\u8BA4\u5230\u5C31\u6574\u884C\u4EC0\u4E48\u90FD\u4E0D\u6CE8\u518C\uFF08\u6D4F\u89C8\u5668\u534A\u8FB9\u7684 servable entry\uFF0C\u89C1\u6587\u4EF6\u5934\uFF09\u3002 */\nconst CONFIG_KEY = \"carrier\";\n\n/**\n * \u8BFB\u8FD9\u4E00\u884C\u7684 config\u3002\u672A\u77E5\u952E\u4E0E\u9519\u7C7B\u578B\u5F53\u573A\u629B\uFF1A\u62FC\u9519\u7684\u8F7D\u4F53\u884C\u4F1A\u9759\u9ED8\u591A\u6CE8\u518C\u4E00\u4E2A\u5168\u5C40\u5DE5\u5177\uFF0C\n * \u90A3\u6BD4\u542F\u52A8\u5931\u8D25\u96BE\u67E5\u5F97\u591A\u3002\n * @param {unknown} config - loader \u4EA4\u7ED9\u63D2\u4EF6\u884C\u7684 config\u3002\n * @returns {{ carrier: boolean }} \u5F52\u4E00\u5316\u540E\u7684\u914D\u7F6E\u3002\n */\nfunction readConfig(config) {\n if (config === undefined || config === null) return { carrier: false };\n if (typeof config !== \"object\" || Array.isArray(config)) {\n throw new TypeError(`${name}: config must be an object with an optional boolean \"${CONFIG_KEY}\"`);\n }\n const unknown = Object.keys(config).filter((key) => key !== CONFIG_KEY);\n if (unknown.length > 0) {\n throw new TypeError(`${name}: unknown config key(s) ${unknown.map((key) => JSON.stringify(key)).join(\", \")}; the only accepted key is \"${CONFIG_KEY}\"`);\n }\n if (config[CONFIG_KEY] !== undefined && typeof config[CONFIG_KEY] !== \"boolean\") {\n throw new TypeError(`${name}: config.${CONFIG_KEY} must be a boolean`);\n }\n return { carrier: config[CONFIG_KEY] === true };\n}\n\nfunction apply(ctx, config) {\n if (readConfig(config).carrier) return;\n ctx.tools.register(defineTool({\n name: \"ask_user_grilling\",\n description: \"Ask the user a concise question when you need confirmation, a choice, or missing information before proceeding. Send one or more questions, each with a stable id that will be echoed in the answer.\",\n parameters: {\n questions: {\n type: \"array\",\n required: true,\n description: \"Questions to ask the user before continuing.\",\n items: {\n type: \"object\",\n additionalProperties: true,\n properties: {\n id: {\n type: \"string\",\n required: true,\n description: \"Stable id for this question; echoed in the answer.\",\n },\n question: {\n type: \"string\",\n required: true,\n description: \"The specific question to ask the user.\",\n },\n header: {\n type: \"string\",\n description: \"Optional short heading for the question, such as \\\"Confirm\\\" or \\\"Choose Mode\\\".\",\n },\n number: {\n type: \"string\",\n description: \"Optional question number, e.g. \\\"Q2\\\". Rendered before the header as \\\"Q2 \u00B7 <header>\\\"; use the same Q-number you announced in the message text.\",\n },\n detail: {\n type: \"string\",\n description: \"Optional supporting body for this question. Rendered as markdown under the question, so put multi-paragraph context here and keep question to the one line that asks.\",\n },\n options: {\n type: \"array\",\n description: \"Optional choices to show the user. If you recommend one, put it first and append \\\"(Recommended)\\\" to that label.\",\n items: {\n type: \"object\",\n additionalProperties: true,\n properties: {\n label: {\n type: \"string\",\n required: true,\n description: \"Short user-facing option label.\",\n },\n description: {\n type: \"string\",\n description: \"One sentence explaining the tradeoff or impact.\",\n },\n recommended: {\n type: \"boolean\",\n description: \"Set true on the option you recommend (alternative to the \\\"(Recommended)\\\" label suffix).\",\n },\n },\n },\n },\n },\n },\n },\n },\n output: {\n schema: {\n type: \"object\",\n additionalProperties: false,\n properties: {\n rejected: {\n type: \"boolean\",\n description: \"True when input validation failed and the round was not asked.\",\n },\n violations: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"Validation violations when rejected.\",\n },\n error: {\n type: \"string\",\n description: \"Human-readable error when rejected.\",\n },\n answers: {\n type: \"array\",\n required: true,\n description: \"One entry per question, in the order asked.\",\n items: {\n type: \"object\",\n additionalProperties: false,\n properties: {\n id: {\n type: \"string\",\n required: true,\n description: \"The question id you supplied.\",\n },\n selected: {\n type: \"array\",\n required: true,\n items: { type: \"string\" },\n description: \"Labels of the options the user picked (may be empty if skipped).\",\n },\n custom: {\n type: \"string\",\n description: \"User-typed free text for this question, if any.\",\n },\n },\n },\n },\n },\n },\n render: (_args, value) => [{ type: \"text\", text: JSON.stringify(value) }],\n },\n async execute(args, exec) {\n // 1. input validation: only what the form cannot represent at all. Stem /\n // option separation stays guidance, NOT enforced: substring matching\n // would reject legitimate stems (e.g. a stem that naturally mentions an\n // option name), so no stem check may refuse a round \u2014 a bad stem is\n // preferable to a false rejection.\n const violations = [];\n const seenIds = new Set();\n args.questions.forEach((question, questionIndex) => {\n const where = `Question ${questionIndex + 1} (id ${JSON.stringify(question.id)})`;\n if (typeof question.id === \"string\" && question.id.startsWith(RESERVED_ID_PREFIX)) {\n violations.push(`${where} uses the reserved prefix ${RESERVED_ID_PREFIX} (owned by the round-end supplement question)`);\n }\n if (typeof question.id === \"string\") {\n if (seenIds.has(question.id)) violations.push(`${where} repeats an id already used in this round; ids must be unique because the answer is keyed by id`);\n seenIds.add(question.id);\n }\n if (isBlank(question.question)) {\n violations.push(`${where} has an empty question text; write the question itself in question and its body in detail`);\n }\n const seenLabels = new Set();\n (question.options ?? []).forEach((option, optionIndex) => {\n const label = normalizeOption(option).label;\n if (isBlank(label)) {\n violations.push(`${where}, option ${optionIndex + 1} has an empty label; every option needs a label the user can read and pick`);\n return;\n }\n if (seenLabels.has(label)) {\n violations.push(`${where} has two options that render with the same label ${JSON.stringify(label)}; the form identifies a choice by its label, so make them differ`);\n return;\n }\n seenLabels.add(label);\n });\n });\n if (violations.length > 0) {\n return {\n rejected: true,\n violations,\n error: `${violations.length} violation(s) in this round: ids must be unique and must not use the reserved ${RESERVED_ID_PREFIX} prefix, question text must not be blank, and the options of one question must not share a label. Fix them and call this tool again.`,\n answers: [],\n };\n }\n\n // 2. transform: force multi-select; merge the optional number into the\n // header; hand detail to the field the client renders as markdown; move\n // the recommendation marker to the label suffix the client renders;\n // per-question supplement is via the built-in custom input (\"Type your\n // answer\"/\"\u8F93\u5165\u4F60\u7684\u7B54\u6848\") \u2014 no extra option is added to avoid\n // duplication with that field\n const labelRestore = new Map();\n const questions = args.questions.map((question) => {\n const header = mergeNumberIntoHeader(question.number, question.header);\n const restore = new Map();\n const options = (question.options ?? []).map((option) => {\n const normalized = normalizeOption(option);\n if (normalized.label !== normalized.originalLabel) {\n restore.set(normalized.label, normalized.originalLabel);\n }\n return {\n label: normalized.label,\n ...(normalized.description !== undefined ? { description: normalized.description } : {}),\n };\n });\n labelRestore.set(question.id, restore);\n return {\n id: question.id,\n question: question.question,\n ...(header !== \"\" ? { header } : {}),\n ...(isBlank(question.detail) ? {} : { detail: question.detail }),\n options,\n multiSelect: true,\n };\n });\n\n // 3. round-end supplement question \u2014 single \"\u65E0\u9700\u8865\u5145\" option; supplement is via custom input, so no \"I have something to add\" option (duplicates that field)\n questions.push({\n ...ROUND_END_QUESTION,\n options: ROUND_END_QUESTION.options.map((option) => ({ ...option })),\n multiSelect: true,\n });\n\n // 4. ask through the userQuestions seam (UI renders from the service)\n const answer = await ctx.userQuestions.ask({\n questions,\n ...(exec.agent !== undefined ? { agent: exec.agent } : {}),\n signal: exec.signal,\n });\n return {\n answers: answer.answers.map((entry) => {\n const restore = labelRestore.get(entry.id);\n return {\n id: entry.id,\n selected: entry.selected.map((label) => restore?.get(label) ?? label),\n ...(entry.custom !== undefined ? { custom: entry.custom } : {}),\n };\n }),\n };\n },\n }));\n}\n\nexport { apply, inject, name };\n", "// \u5BBF\u4E3B\u534A\u8FB9\u4E0E\u754C\u9762\u534A\u8FB9\u5171\u7528\u7684\u7EAF\u5951\u7EA6\uFF1A\u9898\u76EE\u5B57\u6BB5\u7684\u62FC\u6CD5\uFF0C\u52A0\u8F6E\u672B\u8865\u5145\u9898\u8FD9\u4E00\u9053\u7531\u4EE3\u7801\u8FFD\u52A0\u7684\u9898\u3002\n//\n// \u4E24\u5904\u5FC5\u987B\u4E00\u81F4\uFF0C\u6240\u4EE5\u53EA\u6709\u8FD9\u4E00\u4EFD\uFF1A\u8868\u5355\u9875\u6807\u9898\u4E0E transcript \u5361\u7247\u6807\u9898\u90FD\u6309\n// mergeNumberIntoHeader \u62FC\uFF1B\u754C\u9762\u6309 id \u8BA4\u51FA\u8F6E\u672B\u8865\u5145\u9898\uFF0C\u4E5F\u6309 ROUND_END_QUESTION \u62FF\u5B83\u7684\u9898\u5E72\u3002\n// \u5404\u5199\u4E00\u4EFD\u5FC5\u7136\u6F02\u3002\n\n/** \u8F6E\u672B\u8865\u5145\u9898\u7684 id \u524D\u7F00\uFF0C\u540C\u65F6\u662F\u6A21\u578B\u4E0D\u5F97\u5360\u7528\u7684\u4FDD\u7559\u524D\u7F00\u3002 */\nexport const RESERVED_ID_PREFIX = '__grill_';\n\n/**\n * \u6BCF\u6B21\u8C03\u7528\u7531\u4EE3\u7801\u8FFD\u52A0\u5728\u672B\u5C3E\u7684\u8865\u5145\u9898\u3002\u754C\u9762\u534A\u8FB9\u6309 id \u8BA4\u51FA\u5B83\uFF0C\u5BBF\u4E3B\u534A\u8FB9\u628A\u5B83\u9001\u8FDB seam\u3002\n * \u9009\u9879\u6570\u7EC4\u7684\u6D45\u62F7\u8D1D\u7531\u5BBF\u4E3B\u5728\u6295\u9012\u524D\u505A\uFF08seam \u4FA7\u4E0D\u518D\u6539\u5B83\uFF0C\u4F46\u522B\u628A\u8FD9\u4EFD\u5E38\u91CF\u4EA4\u51FA\u53BB\uFF09\u3002\n */\nexport const ROUND_END_QUESTION = Object.freeze({\n id: `${RESERVED_ID_PREFIX}round_supplement__`,\n question: '\u8FD9\u8F6E\u8FD8\u6709\u4EC0\u4E48\u8981\u8865\u5145\u6216\u8C03\u6574\u7684\u5417\uFF1F',\n header: '\u8F6E\u672B\u8865\u5145',\n options: Object.freeze([Object.freeze({ label: '\u65E0\u9700\u8865\u5145' })]),\n});\n\n/**\n * \u53BB\u6389\u9996\u5C3E\u7A7A\u767D\u540E\u662F\u5426\u4E3A\u7A7A\u3002\u7A7A\u4E32\u4E0E\u7EAF\u7A7A\u767D\u90FD\u4E0D\u503C\u5F97\u9001\u8FDB\u8868\u5355\u3002\n * @param {unknown} value - \u5F85\u5224\u5B9A\u7684\u503C\u3002\n * @returns {boolean} \u975E\u5B57\u7B26\u4E32\u6216\u53BB\u7A7A\u767D\u540E\u4E3A\u7A7A\u65F6\u4E3A true\u3002\n */\nexport function isBlank(value) {\n return typeof value !== 'string' || value.trim() === '';\n}\n\n/**\n * \u628A\u9898\u53F7\u5E76\u8FDB\u6807\u9898\uFF1A\u4E24\u8005\u90FD\u7ED9\u5199\u4F5C `<number> \u00B7 <header>`\uFF0C\u53EA\u7ED9\u4E00\u4E2A\u5C31\u662F\u90A3\u4E00\u4E2A\uFF1B\n * \u6807\u9898\u5DF2\u7ECF\u4EE5\u8BE5\u9898\u53F7\u5F00\u5934\u65F6\u539F\u6837\u9001\u51FA\u53BB\uFF08\u6A21\u578B\u5E38\u81EA\u5DF1\u5199\u6210 \"Q2 \u00B7 Deadline\"\uFF09\u3002\n * @param {string} [number] - \u9898\u53F7\u3002\n * @param {string} [header] - \u6807\u9898\u3002\n * @returns {string} \u4EA4\u7ED9\u754C\u9762\u7684\u6807\u9898\uFF1B\u4E24\u8005\u90FD\u7F3A\u65F6\u4E3A\u7A7A\u4E32\uFF08\u8C03\u7528\u65B9\u636E\u6B64\u7701\u7565\u8BE5\u5B57\u6BB5\uFF09\u3002\n */\nexport function mergeNumberIntoHeader(number, header) {\n const num = isBlank(number) ? undefined : number;\n const head = isBlank(header) ? undefined : header;\n if (num === undefined) return head ?? '';\n if (head === undefined) return num;\n return head.startsWith(num) ? head : `${num} \u00B7 ${head}`;\n}\n", "// \u63A8\u8350\u6807\u8BB0\u7684\u5F52\u4E00\u5316\u3002\n//\n// \u5BA2\u6237\u7AEF\uFF08@deepseek-ai/dsh-client-ui-user-questions \u7684 parseRecommendedLabel\uFF09\n// \u53EA\u6709\u4E00\u4E2A\u5224\u5B9A\u4F9D\u636E\uFF1Aoption.label \u5FC5\u987B\u4EE5\u534A\u89D2\u6216\u5168\u89D2\u7684\u62EC\u53F7\u63A8\u8350\u5B57\u6837\u6536\u5C3E\uFF1Boption.description\n// \u5B8C\u5168\u4E0D\u53C2\u4E0E\u3002\u6A21\u578B\u7ECF\u5E38\u628A\u63A8\u8350\u5199\u6210 description \u672B\u5C3E\u7684\u300C\uFF1B\u63A8\u8350\u300D\uFF0C\u6216\u8005\u5199\u6210 label \u91CC\u4E0D\u5E26\n// \u62EC\u53F7\u7684\u5F62\u5F0F\uFF0C\u4E8E\u662F\u5FBD\u6807\u4E0D\u6E32\u67D3\u3001\u6807\u8BB0\u539F\u6837\u663E\u793A\u6210\u6587\u5B57\u3002\n//\n// \u8FD9\u91CC\u5728\u9898\u76EE\u4EA4\u7ED9 ctx.userQuestions.ask \u4E4B\u524D\u628A\u6807\u8BB0\u7EDF\u4E00\u642C\u5230 label \u672B\u5C3E\u7684\u300C\uFF08\u63A8\u8350\uFF09\u300D\uFF0C\n// \u5BA2\u6237\u7AEF\u5C31\u80FD\u8BA4\u51FA\u5E76\u6E32\u67D3\u5FBD\u6807\u3002\u663E\u5F0F\u5B57\u6BB5 recommended \u662F\u53E6\u4E00\u6761\u66F4\u660E\u786E\u7684\u4FE1\u53F7\uFF0C\u4F18\u5148\u4E8E\u6587\u5B57\u3002\n\nconst MARKER = 'recommended|\u63A8\u8350';\n// \u534A\u89D2/\u5168\u89D2\u5706\u62EC\u53F7\u4E0E\u65B9\u62EC\u53F7/\u65B9\u5934\u62EC\u53F7\nconst BRACKETED_MARKER = `[\uFF08(\u3010\\\\[]\\\\s*(?:${MARKER})\\\\s*[\uFF09)\u3011\\\\]]`;\n// \u65E0\u62EC\u53F7\u5199\u6CD5\u5FC5\u987B\u7531\u5206\u9694\u7B26\u5F15\u51FA\uFF0C\u5426\u5219\u300C\u67E5\u770B\u63A8\u8350\u300D\u8FD9\u79CD\u6B63\u5E38\u6587\u5B57\u4F1A\u88AB\u8BEF\u5224\nconst SEPARATOR = '\uFF1B;\uFF0C,\u3001:\uFF1A\\\\-\u2014';\nconst TRAILING_PUNCTUATION = '\u3002.\uFF01!\uFF1F?\uFF1B;\uFF0C,\u3001~\uFF5E\\\\s';\n\nconst BRACKETED_SUFFIX = new RegExp(`[\\\\s]*[${SEPARATOR}]?\\\\s*${BRACKETED_MARKER}[${TRAILING_PUNCTUATION}]*$`, 'i');\nconst BARE_SUFFIX = new RegExp(`[\\\\s]*[${SEPARATOR}]\\\\s*(?:${MARKER})[${TRAILING_PUNCTUATION}]*$`, 'i');\n\n/** \u4F9B\u6D4B\u8BD5\u6838\u5BF9\u5BA2\u6237\u7AEF\u89C4\u5219\u7684\u63A8\u8350\u6807\u8BB0\u540E\u7F00\uFF1B\u5BA2\u6237\u7AEF\u53EA\u8BA4 label \u672B\u5C3E\u7684\u8FD9\u4E24\u79CD\u62EC\u53F7\u5199\u6CD5\u3002 */\nexport const RECOMMENDED_LABEL_SUFFIX = '\uFF08\u63A8\u8350\uFF09';\n\n/**\n * \u53BB\u6389\u6587\u672C\u672B\u5C3E\u7684\u63A8\u8350\u6807\u8BB0\u3002\n * @param {string} text - label \u6216 description \u539F\u6587\u3002\n * @returns {{ text: string, found: boolean }} \u53BB\u6389\u6807\u8BB0\u540E\u7684\u6587\u672C\uFF0C\u4EE5\u53CA\u662F\u5426\u627E\u5230\u6807\u8BB0\u3002\n */\nexport function stripRecommendationMarker(text) {\n if (typeof text !== 'string') return { text, found: false };\n const match = BRACKETED_SUFFIX.exec(text) ?? BARE_SUFFIX.exec(text);\n if (match === null) return { text, found: false };\n return { text: text.slice(0, match.index).replace(/\\s+$/, ''), found: true };\n}\n\n/**\n * \u628A\u4E00\u4E2A option \u5F52\u4E00\u5316\u6210\u5BA2\u6237\u7AEF\u80FD\u6E32\u67D3\u7684\u5F62\u5F0F\u3002\n * @param {{ label: string, description?: string, recommended?: boolean }} option - \u6A21\u578B\u7ED9\u7684\u9009\u9879\u3002\n * @returns {{ originalLabel: string, label: string, description?: string, recommended: boolean }}\n * \u4EA4\u7ED9\u754C\u9762\u65F6\u7528 label/description\uFF1B\u56DE\u4F20\u7B54\u6848\u65F6\u7528 originalLabel \u8FD8\u539F\u6A21\u578B\u539F\u672C\u5199\u7684 label\u3002\n */\nexport function normalizeOption(option) {\n const label = stripRecommendationMarker(option.label);\n const description = option.description === undefined ? undefined : stripRecommendationMarker(option.description);\n const recommended = option.recommended === true || label.found || (description !== undefined && description.found);\n const cleanLabel = label.text;\n return {\n originalLabel: option.label,\n label: recommended ? `${cleanLabel}${RECOMMENDED_LABEL_SUFFIX}` : cleanLabel,\n description: description === undefined ? undefined : description.text,\n recommended,\n };\n}\n"],
4
+ "sourcesContent": ["import { defineTool } from \"@deepseek-ai/dsh-tools\";\nimport \"@deepseek-ai/dsh-user-questions\";\nimport { RESERVED_ID_PREFIX, ROUND_END_QUESTION, isBlank, mergeNumberIntoHeader } from \"./contract.js\";\nimport { normalizeOption } from \"./recommendation.js\";\n\n/**\n * @lynn123411/dsh-ask-user-grilling \u2014 a presentation variant of the native\n * `ask_user_question` (`@deepseek-ai/dsh-tool-ask-user`). Same capability seam\n * (ctx.userQuestions), the same tool description and the same descriptions for\n * the shared parameters verbatim; only the rendered form differs.\n *\n * ask_user_grilling:\n * - forces multi-select on every question \u2014 the schema offers no opt-out\n * - merges the optional `number` into the header as \"<number> \u00B7 <header>\",\n * so a form page carries the same Q-number the round announced in prose;\n * a header that already opens with that number is sent as it is\n * - passes the optional `detail` through to the seam: the client renders it as\n * markdown under the question, while the question itself is a plain heading\n * with no markdown and no line breaks, so a multi-paragraph body belongs in\n * `detail`\n * - normalizes the recommendation marker into the one form the client renders,\n * a trailing \"\uFF08\u63A8\u8350\uFF09\" on the label: an explicit `recommended` flag, or a\n * loose marker at the end of the label or the description, is moved there \u2014\n * the client reads only the label and accepts only the bracketed suffix\n * - appends a round-end supplement question; per-question supplement goes\n * through the built-in custom input (\"Type your answer\" / \"\u8F93\u5165\u4F60\u7684\u7B54\u6848\"),\n * so no extra per-question option is added (it would duplicate that field)\n * - rejects what the form cannot carry: a question id under the reserved\n * `__grill_` prefix, a duplicate question id, a blank question text, a blank\n * option label, or two options of one question that end up with the same\n * label (the client keys selection by label, so a collision cannot be\n * restored or even clicked apart)\n *\n * Two rows mount this module. The preset tool row registers the tool (the\n * default). The profile bundle row, inserted by this package's\n * `cordis.patch.yml`, exists only so the Web client serves `lib/client.js` \u2014\n * the browser bundle is served for an enabled Loader entry, and a preset row is\n * a directly plugged subtree rather than a Loader entry, so the package must be\n * in `dsh.profile.bundles` for its card to reach the page. That row passes\n * `config.carrier: true` and registers nothing; without it the tool would also\n * become a root-layer tool, visible to agents on every other preset.\n */\nconst name = \"tool-ask-user-grilling\";\nconst inject = [\"tools\", \"userQuestions\"];\n\n/** \u8F7D\u4F53\u884C\u8BA4\u8FD9\u4E00\u4E2A\u952E\uFF0C\u8BA4\u5230\u5C31\u6574\u884C\u4EC0\u4E48\u90FD\u4E0D\u6CE8\u518C\uFF08\u6D4F\u89C8\u5668\u534A\u8FB9\u7684 servable entry\uFF0C\u89C1\u6587\u4EF6\u5934\uFF09\u3002 */\nconst CONFIG_KEY = \"carrier\";\n\n/**\n * \u8BFB\u8FD9\u4E00\u884C\u7684 config\u3002\u672A\u77E5\u952E\u4E0E\u9519\u7C7B\u578B\u5F53\u573A\u629B\uFF1A\u62FC\u9519\u7684\u8F7D\u4F53\u884C\u4F1A\u9759\u9ED8\u591A\u6CE8\u518C\u4E00\u4E2A\u5168\u5C40\u5DE5\u5177\uFF0C\n * \u90A3\u6BD4\u542F\u52A8\u5931\u8D25\u96BE\u67E5\u5F97\u591A\u3002\n * @param {unknown} config - loader \u4EA4\u7ED9\u63D2\u4EF6\u884C\u7684 config\u3002\n * @returns {{ carrier: boolean }} \u5F52\u4E00\u5316\u540E\u7684\u914D\u7F6E\u3002\n */\nfunction readConfig(config) {\n if (config === undefined || config === null) return { carrier: false };\n if (typeof config !== \"object\" || Array.isArray(config)) {\n throw new TypeError(`${name}: config must be an object with an optional boolean \"${CONFIG_KEY}\"`);\n }\n const unknown = Object.keys(config).filter((key) => key !== CONFIG_KEY);\n if (unknown.length > 0) {\n throw new TypeError(`${name}: unknown config key(s) ${unknown.map((key) => JSON.stringify(key)).join(\", \")}; the only accepted key is \"${CONFIG_KEY}\"`);\n }\n if (config[CONFIG_KEY] !== undefined && typeof config[CONFIG_KEY] !== \"boolean\") {\n throw new TypeError(`${name}: config.${CONFIG_KEY} must be a boolean`);\n }\n return { carrier: config[CONFIG_KEY] === true };\n}\n\nfunction apply(ctx, config) {\n if (readConfig(config).carrier) return;\n ctx.tools.register(defineTool({\n name: \"ask_user_grilling\",\n description: \"Ask the user a concise question when you need confirmation, a choice, or missing information before proceeding.\",\n parameters: {\n questions: {\n type: \"array\",\n required: true,\n description: \"Questions to ask the user before continuing.\",\n items: {\n type: \"object\",\n additionalProperties: true,\n properties: {\n id: {\n type: \"string\",\n required: true,\n description: \"Stable id for this question; echoed in the answer.\",\n },\n question: {\n type: \"string\",\n required: true,\n description: \"The specific question to ask the user.\",\n },\n header: {\n type: \"string\",\n description: \"Optional short heading for the question, such as \\\"Confirm\\\" or \\\"Choose Mode\\\".\",\n },\n number: {\n type: \"string\",\n description: \"Optional question number, e.g. \\\"Q2\\\". Rendered before the header as \\\"Q2 \u00B7 <header>\\\"; use the same Q-number you announced in the message text.\",\n },\n detail: {\n type: \"string\",\n description: \"Optional supporting body for this question. Rendered as markdown under the question, so put multi-paragraph context here and keep question to the one line that asks.\",\n },\n options: {\n type: \"array\",\n description: \"Optional choices to show the user. If you recommend one, put it first and append \\\"(Recommended)\\\" to that label.\",\n items: {\n type: \"object\",\n additionalProperties: true,\n properties: {\n label: {\n type: \"string\",\n required: true,\n description: \"Short user-facing option label.\",\n },\n description: {\n type: \"string\",\n description: \"One sentence explaining the tradeoff or impact.\",\n },\n recommended: {\n type: \"boolean\",\n description: \"Set true on the option you recommend (alternative to the \\\"(Recommended)\\\" label suffix).\",\n },\n },\n },\n },\n },\n },\n },\n },\n output: {\n schema: {\n type: \"object\",\n additionalProperties: false,\n properties: {\n rejected: {\n type: \"boolean\",\n description: \"True when input validation failed and the round was not asked.\",\n },\n violations: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"Validation violations when rejected.\",\n },\n error: {\n type: \"string\",\n description: \"Human-readable error when rejected.\",\n },\n answers: {\n type: \"array\",\n required: true,\n description: \"One entry per question, in the order asked.\",\n items: {\n type: \"object\",\n additionalProperties: false,\n properties: {\n id: {\n type: \"string\",\n required: true,\n description: \"The question id you supplied.\",\n },\n selected: {\n type: \"array\",\n required: true,\n items: { type: \"string\" },\n description: \"Labels of the options the user picked (may be empty if skipped).\",\n },\n custom: {\n type: \"string\",\n description: \"User-typed free text for this question, if any.\",\n },\n },\n },\n },\n },\n },\n render: (_args, value) => [{ type: \"text\", text: JSON.stringify(value) }],\n },\n async execute(args, exec) {\n // 1. input validation: only what the form cannot represent at all. Stem /\n // option separation stays guidance, NOT enforced: substring matching\n // would reject legitimate stems (e.g. a stem that naturally mentions an\n // option name), so no stem check may refuse a round \u2014 a bad stem is\n // preferable to a false rejection.\n const violations = [];\n const seenIds = new Set();\n args.questions.forEach((question, questionIndex) => {\n const where = `Question ${questionIndex + 1} (id ${JSON.stringify(question.id)})`;\n if (typeof question.id === \"string\" && question.id.startsWith(RESERVED_ID_PREFIX)) {\n violations.push(`${where} uses the reserved prefix ${RESERVED_ID_PREFIX} (owned by the round-end supplement question)`);\n }\n if (typeof question.id === \"string\") {\n if (seenIds.has(question.id)) violations.push(`${where} repeats an id already used in this round; ids must be unique because the answer is keyed by id`);\n seenIds.add(question.id);\n }\n if (isBlank(question.question)) {\n violations.push(`${where} has an empty question text; write the question itself in question and its body in detail`);\n }\n const seenLabels = new Set();\n (question.options ?? []).forEach((option, optionIndex) => {\n const label = normalizeOption(option).label;\n if (isBlank(label)) {\n violations.push(`${where}, option ${optionIndex + 1} has an empty label; every option needs a label the user can read and pick`);\n return;\n }\n if (seenLabels.has(label)) {\n violations.push(`${where} has two options that render with the same label ${JSON.stringify(label)}; the form identifies a choice by its label, so make them differ`);\n return;\n }\n seenLabels.add(label);\n });\n });\n if (violations.length > 0) {\n return {\n rejected: true,\n violations,\n error: `${violations.length} violation(s) in this round: ids must be unique and must not use the reserved ${RESERVED_ID_PREFIX} prefix, question text must not be blank, and the options of one question must not share a label. Fix them and call this tool again.`,\n answers: [],\n };\n }\n\n // 2. transform: force multi-select; merge the optional number into the\n // header; hand detail to the field the client renders as markdown; move\n // the recommendation marker to the label suffix the client renders;\n // per-question supplement is via the built-in custom input (\"Type your\n // answer\"/\"\u8F93\u5165\u4F60\u7684\u7B54\u6848\") \u2014 no extra option is added to avoid\n // duplication with that field\n const labelRestore = new Map();\n const questions = args.questions.map((question) => {\n const header = mergeNumberIntoHeader(question.number, question.header);\n const restore = new Map();\n const options = (question.options ?? []).map((option) => {\n const normalized = normalizeOption(option);\n if (normalized.label !== normalized.originalLabel) {\n restore.set(normalized.label, normalized.originalLabel);\n }\n return {\n label: normalized.label,\n ...(normalized.description !== undefined ? { description: normalized.description } : {}),\n };\n });\n labelRestore.set(question.id, restore);\n return {\n id: question.id,\n question: question.question,\n ...(header !== \"\" ? { header } : {}),\n ...(isBlank(question.detail) ? {} : { detail: question.detail }),\n options,\n multiSelect: true,\n };\n });\n\n // 3. round-end supplement question \u2014 single \"\u65E0\u9700\u8865\u5145\" option; supplement is via custom input, so no \"I have something to add\" option (duplicates that field)\n questions.push({\n ...ROUND_END_QUESTION,\n options: ROUND_END_QUESTION.options.map((option) => ({ ...option })),\n multiSelect: true,\n });\n\n // 4. ask through the userQuestions seam (UI renders from the service)\n const answer = await ctx.userQuestions.ask({\n questions,\n ...(exec.agent !== undefined ? { agent: exec.agent } : {}),\n signal: exec.signal,\n });\n return {\n answers: answer.answers.map((entry) => {\n const restore = labelRestore.get(entry.id);\n return {\n id: entry.id,\n selected: entry.selected.map((label) => restore?.get(label) ?? label),\n ...(entry.custom !== undefined ? { custom: entry.custom } : {}),\n };\n }),\n };\n },\n }));\n}\n\nexport { apply, inject, name };\n", "// \u5BBF\u4E3B\u534A\u8FB9\u4E0E\u754C\u9762\u534A\u8FB9\u5171\u7528\u7684\u7EAF\u5951\u7EA6\uFF1A\u9898\u76EE\u5B57\u6BB5\u7684\u62FC\u6CD5\uFF0C\u52A0\u8F6E\u672B\u8865\u5145\u9898\u8FD9\u4E00\u9053\u7531\u4EE3\u7801\u8FFD\u52A0\u7684\u9898\u3002\n//\n// \u4E24\u5904\u5FC5\u987B\u4E00\u81F4\uFF0C\u6240\u4EE5\u53EA\u6709\u8FD9\u4E00\u4EFD\uFF1A\u8868\u5355\u9875\u6807\u9898\u4E0E transcript \u5361\u7247\u6807\u9898\u90FD\u6309\n// mergeNumberIntoHeader \u62FC\uFF1B\u754C\u9762\u6309 id \u8BA4\u51FA\u8F6E\u672B\u8865\u5145\u9898\uFF0C\u4E5F\u6309 ROUND_END_QUESTION \u62FF\u5B83\u7684\u9898\u5E72\u3002\n// \u5404\u5199\u4E00\u4EFD\u5FC5\u7136\u6F02\u3002\n\n/** \u8F6E\u672B\u8865\u5145\u9898\u7684 id \u524D\u7F00\uFF0C\u540C\u65F6\u662F\u6A21\u578B\u4E0D\u5F97\u5360\u7528\u7684\u4FDD\u7559\u524D\u7F00\u3002 */\nexport const RESERVED_ID_PREFIX = '__grill_';\n\n/**\n * \u6BCF\u6B21\u8C03\u7528\u7531\u4EE3\u7801\u8FFD\u52A0\u5728\u672B\u5C3E\u7684\u8865\u5145\u9898\u3002\u754C\u9762\u534A\u8FB9\u6309 id \u8BA4\u51FA\u5B83\uFF0C\u5BBF\u4E3B\u534A\u8FB9\u628A\u5B83\u9001\u8FDB seam\u3002\n * \u9009\u9879\u6570\u7EC4\u7684\u6D45\u62F7\u8D1D\u7531\u5BBF\u4E3B\u5728\u6295\u9012\u524D\u505A\uFF08seam \u4FA7\u4E0D\u518D\u6539\u5B83\uFF0C\u4F46\u522B\u628A\u8FD9\u4EFD\u5E38\u91CF\u4EA4\u51FA\u53BB\uFF09\u3002\n */\nexport const ROUND_END_QUESTION = Object.freeze({\n id: `${RESERVED_ID_PREFIX}round_supplement__`,\n question: '\u8FD9\u8F6E\u8FD8\u6709\u4EC0\u4E48\u8981\u8865\u5145\u6216\u8C03\u6574\u7684\u5417\uFF1F',\n header: '\u8F6E\u672B\u8865\u5145',\n options: Object.freeze([Object.freeze({ label: '\u65E0\u9700\u8865\u5145' })]),\n});\n\n/**\n * \u53BB\u6389\u9996\u5C3E\u7A7A\u767D\u540E\u662F\u5426\u4E3A\u7A7A\u3002\u7A7A\u4E32\u4E0E\u7EAF\u7A7A\u767D\u90FD\u4E0D\u503C\u5F97\u9001\u8FDB\u8868\u5355\u3002\n * @param {unknown} value - \u5F85\u5224\u5B9A\u7684\u503C\u3002\n * @returns {boolean} \u975E\u5B57\u7B26\u4E32\u6216\u53BB\u7A7A\u767D\u540E\u4E3A\u7A7A\u65F6\u4E3A true\u3002\n */\nexport function isBlank(value) {\n return typeof value !== 'string' || value.trim() === '';\n}\n\n/**\n * \u628A\u9898\u53F7\u5E76\u8FDB\u6807\u9898\uFF1A\u4E24\u8005\u90FD\u7ED9\u5199\u4F5C `<number> \u00B7 <header>`\uFF0C\u53EA\u7ED9\u4E00\u4E2A\u5C31\u662F\u90A3\u4E00\u4E2A\uFF1B\n * \u6807\u9898\u5DF2\u7ECF\u4EE5\u8BE5\u9898\u53F7\u5F00\u5934\u65F6\u539F\u6837\u9001\u51FA\u53BB\uFF08\u6A21\u578B\u5E38\u81EA\u5DF1\u5199\u6210 \"Q2 \u00B7 Deadline\"\uFF09\u3002\n * @param {string} [number] - \u9898\u53F7\u3002\n * @param {string} [header] - \u6807\u9898\u3002\n * @returns {string} \u4EA4\u7ED9\u754C\u9762\u7684\u6807\u9898\uFF1B\u4E24\u8005\u90FD\u7F3A\u65F6\u4E3A\u7A7A\u4E32\uFF08\u8C03\u7528\u65B9\u636E\u6B64\u7701\u7565\u8BE5\u5B57\u6BB5\uFF09\u3002\n */\nexport function mergeNumberIntoHeader(number, header) {\n const num = isBlank(number) ? undefined : number;\n const head = isBlank(header) ? undefined : header;\n if (num === undefined) return head ?? '';\n if (head === undefined) return num;\n return head.startsWith(num) ? head : `${num} \u00B7 ${head}`;\n}\n", "// \u63A8\u8350\u6807\u8BB0\u7684\u5F52\u4E00\u5316\u3002\n//\n// \u5BA2\u6237\u7AEF\uFF08@deepseek-ai/dsh-client-ui-user-questions \u7684 parseRecommendedLabel\uFF09\n// \u53EA\u6709\u4E00\u4E2A\u5224\u5B9A\u4F9D\u636E\uFF1Aoption.label \u5FC5\u987B\u4EE5\u534A\u89D2\u6216\u5168\u89D2\u7684\u62EC\u53F7\u63A8\u8350\u5B57\u6837\u6536\u5C3E\uFF1Boption.description\n// \u5B8C\u5168\u4E0D\u53C2\u4E0E\u3002\u6A21\u578B\u7ECF\u5E38\u628A\u63A8\u8350\u5199\u6210 description \u672B\u5C3E\u7684\u300C\uFF1B\u63A8\u8350\u300D\uFF0C\u6216\u8005\u5199\u6210 label \u91CC\u4E0D\u5E26\n// \u62EC\u53F7\u7684\u5F62\u5F0F\uFF0C\u4E8E\u662F\u5FBD\u6807\u4E0D\u6E32\u67D3\u3001\u6807\u8BB0\u539F\u6837\u663E\u793A\u6210\u6587\u5B57\u3002\n//\n// \u8FD9\u91CC\u5728\u9898\u76EE\u4EA4\u7ED9 ctx.userQuestions.ask \u4E4B\u524D\u628A\u6807\u8BB0\u7EDF\u4E00\u642C\u5230 label \u672B\u5C3E\u7684\u300C\uFF08\u63A8\u8350\uFF09\u300D\uFF0C\n// \u5BA2\u6237\u7AEF\u5C31\u80FD\u8BA4\u51FA\u5E76\u6E32\u67D3\u5FBD\u6807\u3002\u663E\u5F0F\u5B57\u6BB5 recommended \u662F\u53E6\u4E00\u6761\u66F4\u660E\u786E\u7684\u4FE1\u53F7\uFF0C\u4F18\u5148\u4E8E\u6587\u5B57\u3002\n\nconst MARKER = 'recommended|\u63A8\u8350';\n// \u534A\u89D2/\u5168\u89D2\u5706\u62EC\u53F7\u4E0E\u65B9\u62EC\u53F7/\u65B9\u5934\u62EC\u53F7\nconst BRACKETED_MARKER = `[\uFF08(\u3010\\\\[]\\\\s*(?:${MARKER})\\\\s*[\uFF09)\u3011\\\\]]`;\n// \u65E0\u62EC\u53F7\u5199\u6CD5\u5FC5\u987B\u7531\u5206\u9694\u7B26\u5F15\u51FA\uFF0C\u5426\u5219\u300C\u67E5\u770B\u63A8\u8350\u300D\u8FD9\u79CD\u6B63\u5E38\u6587\u5B57\u4F1A\u88AB\u8BEF\u5224\nconst SEPARATOR = '\uFF1B;\uFF0C,\u3001:\uFF1A\\\\-\u2014';\nconst TRAILING_PUNCTUATION = '\u3002.\uFF01!\uFF1F?\uFF1B;\uFF0C,\u3001~\uFF5E\\\\s';\n\nconst BRACKETED_SUFFIX = new RegExp(`[\\\\s]*[${SEPARATOR}]?\\\\s*${BRACKETED_MARKER}[${TRAILING_PUNCTUATION}]*$`, 'i');\nconst BARE_SUFFIX = new RegExp(`[\\\\s]*[${SEPARATOR}]\\\\s*(?:${MARKER})[${TRAILING_PUNCTUATION}]*$`, 'i');\n\n/** \u4F9B\u6D4B\u8BD5\u6838\u5BF9\u5BA2\u6237\u7AEF\u89C4\u5219\u7684\u63A8\u8350\u6807\u8BB0\u540E\u7F00\uFF1B\u5BA2\u6237\u7AEF\u53EA\u8BA4 label \u672B\u5C3E\u7684\u8FD9\u4E24\u79CD\u62EC\u53F7\u5199\u6CD5\u3002 */\nexport const RECOMMENDED_LABEL_SUFFIX = '\uFF08\u63A8\u8350\uFF09';\n\n/**\n * \u53BB\u6389\u6587\u672C\u672B\u5C3E\u7684\u63A8\u8350\u6807\u8BB0\u3002\n * @param {string} text - label \u6216 description \u539F\u6587\u3002\n * @returns {{ text: string, found: boolean }} \u53BB\u6389\u6807\u8BB0\u540E\u7684\u6587\u672C\uFF0C\u4EE5\u53CA\u662F\u5426\u627E\u5230\u6807\u8BB0\u3002\n */\nexport function stripRecommendationMarker(text) {\n if (typeof text !== 'string') return { text, found: false };\n const match = BRACKETED_SUFFIX.exec(text) ?? BARE_SUFFIX.exec(text);\n if (match === null) return { text, found: false };\n return { text: text.slice(0, match.index).replace(/\\s+$/, ''), found: true };\n}\n\n/**\n * \u628A\u4E00\u4E2A option \u5F52\u4E00\u5316\u6210\u5BA2\u6237\u7AEF\u80FD\u6E32\u67D3\u7684\u5F62\u5F0F\u3002\n * @param {{ label: string, description?: string, recommended?: boolean }} option - \u6A21\u578B\u7ED9\u7684\u9009\u9879\u3002\n * @returns {{ originalLabel: string, label: string, description?: string, recommended: boolean }}\n * \u4EA4\u7ED9\u754C\u9762\u65F6\u7528 label/description\uFF1B\u56DE\u4F20\u7B54\u6848\u65F6\u7528 originalLabel \u8FD8\u539F\u6A21\u578B\u539F\u672C\u5199\u7684 label\u3002\n */\nexport function normalizeOption(option) {\n const label = stripRecommendationMarker(option.label);\n const description = option.description === undefined ? undefined : stripRecommendationMarker(option.description);\n const recommended = option.recommended === true || label.found || (description !== undefined && description.found);\n const cleanLabel = label.text;\n return {\n originalLabel: option.label,\n label: recommended ? `${cleanLabel}${RECOMMENDED_LABEL_SUFFIX}` : cleanLabel,\n description: description === undefined ? undefined : description.text,\n recommended,\n };\n}\n"],
5
5
  "mappings": "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",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lynn123411/dsh-ask-user-grilling",
3
- "version": "0.6.1",
3
+ "version": "0.6.2",
4
4
  "description": "Form-presentation variant of the native ask_user_question: same tool description and shared-parameter descriptions verbatim, forced multi-select, an optional question number merged into the header, an optional markdown detail body, a recommendation marker normalized into the one label suffix the client renders, plus an auto-appended round-end supplement question. Its own browser half renders the transcript card for ask_user_grilling (question list, detail markdown, round-end supplement, rejected-round violations).",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
@@ -35,17 +35,24 @@
35
35
  "check": "pnpm build && pnpm test && pnpm assert:lib-untracked"
36
36
  },
37
37
  "peerDependencies": {
38
- "@deepseek-ai/cordis": "^4.0.2",
39
- "@deepseek-ai/dsh-tools": "0.1.6-alpha.2",
40
- "@deepseek-ai/dsh-user-questions": "0.1.6-alpha.2"
38
+ "@deepseek-ai/cordis": "^4.0.4",
39
+ "@deepseek-ai/dsh-tools": "0.1.7-rc.2",
40
+ "@deepseek-ai/dsh-user-questions": "0.1.7-rc.2"
41
41
  },
42
42
  "devDependencies": {
43
+ "@deepseek-ai/cordis": "4.0.4",
44
+ "@deepseek-ai/dsh-client-ui-primitives": "0.1.7-rc.2",
45
+ "@deepseek-ai/dsh-client-ui-user-questions": "0.1.7-rc.2",
46
+ "@deepseek-ai/dsh-system-prompt": "0.1.7-rc.2",
47
+ "@deepseek-ai/dsh-tool-ask-user": "0.1.7-rc.2",
48
+ "@deepseek-ai/dsh-tools": "0.1.7-rc.2",
49
+ "@deepseek-ai/dsh-user-questions": "0.1.7-rc.2",
43
50
  "esbuild": "^0.25.0",
44
51
  "react": "^18.3.1",
45
52
  "react-dom": "^18.3.1"
46
53
  },
47
54
  "engines": {
48
- "dsh": "0.1.6-alpha.2",
55
+ "dsh": "0.1.7-rc.2",
49
56
  "node": "^22.19 || >=24"
50
57
  },
51
58
  "publishConfig": {