/** * thinkView.tsx — assistant-step 渲染器(整合自 dsh-think-zh-expand,MIT)。 * * 来源:baosfeng/my-dsh-plugins → plugins/dsh-think-zh-expand/lib/parts/ * assistant.part.js(上游 v0.4.7)。转写差异: * 1. TSX + tsdown 工程(上游为 React.createElement 手写拼接 parts); * 2. 类名前缀 dsh-ws-(与上游 dsh-think-zh-expand- 互不干扰); * 3. 行为默认「思考中展开、思考完自动收起」(上游为始终默认展开); * 4. 思考块外观与官方 ReasoningRow 一致:头部用官方 primitives 的 * DisclosureRow + 思考图标(0.1.5 为 IconThinkOutline14;0.1.7 改名为 * IconThinkOutlineRegular / IconThinkOutlineMedium,按新名优先回退解析), * 正文纯文本;样式逐条对齐官方 * ReasoningRow.module.css(折叠高度、扫描动画、字号变量、summary 跟随)。 * 官方类名是 CSS 模块 hash、无法跨包复用,故用同名自有类 + 相同声明复刻; * 5. 正式回复 text 块走官方 primitives 的 MarkdownText(官方 DOM 结构 + * labels 文案),本插件不自带 Markdown 渲染、不接管围栏渲染——围栏交给 * genui / dsh-mermaid-render 等专门插件;组件缺失时降级纯文本。 * * 渲染契约:替换官方 conversation.chat.node 的 assistant-step 渲染器,只为 * 思考块提供展开/收起交互;image 块相邻分组复用宿主 renderMessageImages; * tool-call 块由独立节点渲染(返回 null)。 */ import { type ReactNode } from 'react'; export declare const THINK_STYLES = "\n.dsh-ws-assistant{display:flex;flex-direction:column;color:var(--dsw-alias-label-primary);font-size:var(--dsh-content-font-size,14px);line-height:calc(24px + var(--dsh-content-font-delta,0px))}\n.dsh-ws-assistant-body{display:flex;flex-direction:column;gap:16px}\n.dsh-ws-assistant-body .md-table-wide{--dsh-table-spare:max(0px,calc((100cqw - var(--dsh-chat-content-width)) / 2));--dsh-table-lead:calc(var(--dsh-table-spare) + min(var(--dsh-chat-content-width),100cqw) - 100%);box-sizing:border-box;width:calc(100% + var(--dsh-table-lead) + var(--dsh-table-spare));max-width:none;margin-left:calc(-1 * var(--dsh-table-lead));padding-left:var(--dsh-table-lead)}\n.dsh-ws-think{display:flex;flex-direction:column}\n.dsh-ws-think:not([data-expanded]){contain:size layout;height:calc(24px + var(--dsh-content-font-delta,0px))}\n.dsh-ws-think-row{position:relative;overflow:hidden}\n.dsh-ws-think[data-state=running] .dsh-ws-think-row:after{content:\"\";inset-block:0;background:linear-gradient(90deg,transparent 0%,color-mix(in srgb,var(--dsw-alias-bg-base) 60%,transparent) 55%,transparent 100%);pointer-events:none;width:300px;animation:2.6s ease-out infinite dsh-ws-think-sweep;position:absolute;left:0}\n@keyframes dsh-ws-think-sweep{0%{left:-300px}90%,to{left:100%}}\n@media (prefers-reduced-motion:reduce){.dsh-ws-think[data-state=running] .dsh-ws-think-row:after{animation:none}}\n.dsh-ws-think-leading{flex-shrink:0}\n.dsh-ws-think-chevron{color:var(--dsw-alias-label-secondary)}\n.dsh-ws-think-title{font-weight:400}\n.dsh-ws-think-separator{background:var(--dsw-alias-label-caption);border-radius:1px;flex:none;width:2px;height:2px;margin:0 8px}\n.dsh-ws-think-summary{min-width:0;color:var(--dsw-alias-label-tertiary);font-size:var(--dsh-content-font-size-secondary,13px);line-height:calc(20px + var(--dsh-content-font-delta-secondary,0px));white-space:nowrap;flex:auto;overflow:hidden}\n.dsh-ws-think-summary-text{text-overflow:ellipsis;display:block;overflow:hidden}\n.dsh-ws-think-summary[data-follow-end]{justify-content:flex-end;display:flex}\n.dsh-ws-think-summary[data-follow-end] .dsh-ws-think-summary-text{text-align:start;text-overflow:clip;flex:none;width:max-content;min-width:100%;overflow:visible}\n.dsh-ws-think-body{padding:4px 0 4px calc(22px + var(--dsh-content-font-delta,0px));color:var(--dsw-alias-label-tertiary);font-size:var(--dsh-content-font-size-secondary,13px);line-height:calc(20px + var(--dsh-content-font-delta-secondary,0px));white-space:pre-wrap;word-break:break-word}\n.dsh-ws-plain{white-space:pre-wrap;word-break:break-word}\n.dsh-ws-unknown{margin:0;white-space:pre-wrap;word-break:break-word;font-family:var(--dsw-font-markdown-code-block,monospace);font-size:var(--dsh-content-font-size-secondary,13px)}\n.dsh-ws-visually-hidden{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n.dsh-ws-stopped{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-tertiary);border-radius:6px;align-self:flex-start;padding:0 6px;font-size:11px;line-height:18px}\n"; export declare function stripControlTags(text: string): string; export interface ThinkBlockProps { text: string; running: boolean; /** true=思考完自动收起(默认);false=上游语义(默认展开、可手动收起)。 */ collapseAfterRun?: boolean; } /** 首行 / 末行摘要(与官方 ReasoningRow 的 firstLine / latestLine 同义)。 */ export declare function firstLine(text: string): string; export declare function latestLine(text: string): string; export declare function ThinkBlock({ text, running, collapseAfterRun }: ThinkBlockProps): import("react").JSX.Element; interface RenderMessageImagesProps { images: { attachment?: unknown; }[]; align: string; } /** 宿主的分组标签(0.1.7 起):同一 assistant-step 会分别以这两个值各渲染一次。 */ export type GroupPart = 'reasoning' | 'response'; /** assistant-step 节点渲染器(替换官方单行折叠版)。 */ export interface AssistantStepViewProps { node?: { data?: { status?: string; blocks?: unknown[]; }; } | null; renderMessageImages?: (props: RenderMessageImagesProps) => ReactNode; /** true=思考完自动收起(默认);false=始终展开(上游语义)。 */ collapseAfterRun?: boolean; /** * 宿主分组标签:'reasoning'=过程折叠组内的那次渲染,'response'=正文条目的 * 那次渲染;0.1.5 及更早的宿主不传(此时按旧行为渲染全部块)。 */ groupPart?: GroupPart; } export declare function AssistantStepView({ node, renderMessageImages, collapseAfterRun, groupPart, }: AssistantStepViewProps): import("react").JSX.Element | null; export {};