@morlay/ui-conversation-message-actions 0.0.9 → 0.0.11
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/lib/client.js +55 -55
- package/lib/client.js.map +1 -1
- package/lib/index.d.mts +5 -2
- package/lib/index.d.mts.map +1 -1
- package/lib/index.mjs +19 -9
- package/lib/index.mjs.map +1 -1
- package/lib/invariant.d.mts.map +1 -1
- package/package.json +19 -18
package/lib/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","names":["createSnapshotStore","useRef","useCallback","useState","useRef","css","a11yCss","DisclosureRow","IconThinkOutline14","memo","useMemo","MarkdownText","Fragment","JsonBlock","css","memo","useMemo","memo","useState","css","IconApiOutline14","IconChevronDownOutline14","IconChevronRightOutline14","MarkdownText","StateDot","IconApiOutline14","useState","css","a11yCss","DisclosureRow","memo","useMemo","css","css","JsonBlock","unreachable","useState","DisclosureRow","css","IconBrowseOutline16","useState","useId","useState","useRef","useCallback","writeClipboard","css","Tooltip","IconCheckOutline16","IconCopyOutline16","IconEditOutline16","IconRefreshOutline16","IconBranchOutline16","useState","useRef","Modal","css","Button","useMemo","useState","css","StateDot","MessageText","JsonBlock","memo","Modal","Button","memo","css","useState","useCallback","Button","IconRefreshOutline16"],"sources":["../src/shared.ts","../src/client/controller.ts","../src/client/chat-node/use-throttled-visual-update.ts","../src/client/chat-node/ReasoningRow.tsx","../src/client/chat-node/AssistantMarkdown.tsx","../src/client/chat-node/AssistantNodeView.tsx","../src/client/chat-node/CompactionItem.tsx","../src/client/chat-node/GenericCommandCard.tsx","../src/client/chat-node/CompactionCommandCard.tsx","../src/client/chat-node/CommandNodeView.tsx","../src/client/chat-node/ContextBody.tsx","../src/client/chat-node/ContextInjectionRow.tsx","../src/client/chat-node/message-chrome.ts","../src/client/chat-node/use-calendar-day.ts","../src/client/chat-node/MessageIconActions.tsx","../src/client/chat-node/MessageEditDialog.tsx","../src/client/chat-node/MessageItem.tsx","../src/client/chat-node/turn-assistant.ts","../src/client/chat-node/TurnTailNodeView.tsx","../src/client/chat-node/register.ts","../src/client/cleanse-session-action.tsx","../src/client/index.ts"],"sourcesContent":["/**\n * Host 与 client 共享的类型与常量:HTTP 路由、操作判别联合、Timeline 响应。\n *\n * @module @morlay/ui-conversation-message-actions/shared\n */\n\nimport type { SessionId } from \"@deepseek-ai/dsh-session\";\nimport type { BranchTimeline, CascadePolicy } from \"@morlay/session-branch\";\nimport type { VersionOperation } from \"@morlay/session-branch\";\n\n/** 同源 HTTP 端点(host 注册、client fetch)。 */\nexport const SESSION_EDITOR_PATH = \"/session-editor\";\n\nexport type { VersionOperation } from \"@morlay/session-branch\";\n\n/** 编辑一个已落定文本块并从其轮次边界分支。 */\nexport interface EditOperation {\n action: \"edit\";\n sessionId: SessionId;\n eventSeq: number;\n blockIndex: number;\n text: string;\n cascade: CascadePolicy;\n}\n\n/** 重生成最后一条已落定助手回复。 */\nexport interface RerollOperation {\n action: \"reroll\";\n sessionId: SessionId;\n}\n\n/** 重试任意历史回合。 */\nexport interface RetryOperation {\n action: \"retry\";\n sessionId: SessionId;\n turn: number;\n cascade: CascadePolicy;\n}\n\n/** 截断式回退:原会话回退到闭合边界。 */\nexport interface RewindOperation {\n action: \"rewind\";\n sessionId: SessionId;\n toBoundary: number;\n}\n\n/** 派生式分支:从闭合边界派生新会话。 */\nexport interface ForkOperation {\n action: \"fork\";\n sessionId: SessionId;\n atSeq?: number;\n childSessionId?: SessionId;\n}\n\n/** 清洗一个会话的 surface/provenance 坐标为稠密空间(修复历史加载失败)。 */\nexport interface CleanseOperation {\n action: \"cleanse\";\n sessionId: SessionId;\n}\n\n/** HTTP 接受的判别联合。 */\nexport type SessionEditorOperation =\n | EditOperation\n | RerollOperation\n | RetryOperation\n | RewindOperation\n | ForkOperation\n | CleanseOperation;\n\n/** 操作响应(分支式返回新版本 id;rewind 返回原 id)。 */\nexport interface SessionEditorOperationResult {\n sessionId: SessionId;\n queuedTurns: number;\n /** 操作后会话是否仍有 live owner(客户端据此决定是否重载页面)。 */\n live?: boolean;\n /** cleanse 操作实际重写的事件数。 */\n changed?: number;\n}\n\n/** 可编辑文本块(编辑面枚举)。 */\nexport interface EditableMessageBlock {\n key: string;\n turn: number;\n eventSeq: number;\n blockIndex: number;\n kind: \"user\" | \"assistant.reasoning\" | \"assistant.response\";\n text: string;\n time: number;\n}\n\n/** 可重试回合(重试面枚举)。 */\nexport interface RetryableTurn {\n turn: number;\n userEventSeq: number;\n preview: string;\n time: number;\n}\n\n/** 版本摘要(Timeline 节点投影,值级)。 */\nexport interface VersionSummary {\n sessionId: string;\n parentSessionId?: string;\n effectId?: string;\n inverseSessionId?: string;\n createdAt: number;\n depth: number;\n current: boolean;\n onCurrentEffectPath: boolean;\n operation?: VersionOperation;\n cascade?: CascadePolicy;\n targetTurn?: number;\n blockKind?: EditableMessageBlock[\"kind\"];\n before?: string;\n after?: string;\n}\n\n/** GET /session-editor 的完整投影(Timeline + 编辑/重试面)。 */\nexport interface SessionEditorTimeline {\n sessionId: string;\n messages: EditableMessageBlock[];\n retryableTurns: RetryableTurn[];\n versions: VersionSummary[];\n /** 原子逆链(从当前版本向外,应用顺序)。 */\n undoStack: string[];\n /** 可直接重施加的子版本。 */\n redoSessionIds: string[];\n}\n\n/** 把 {@link BranchTimeline} 投影成 client 用的 {@link SessionEditorTimeline}。 */\nexport function toTimelinePayload(\n sessionId: SessionId,\n timeline: BranchTimeline,\n messages: EditableMessageBlock[],\n retryableTurns: RetryableTurn[],\n): SessionEditorTimeline {\n const currentPath = new Set<string>();\n for (const node of timeline.nodes) currentPath.add(String(node.sessionId));\n const versions: VersionSummary[] = timeline.nodes.map((node) => ({\n sessionId: String(node.sessionId),\n ...(node.parentSessionId === undefined\n ? {}\n : { parentSessionId: String(node.parentSessionId) }),\n ...(node.effect === undefined\n ? {}\n : {\n effectId: node.effect.id,\n inverseSessionId: String(node.inverseSessionId),\n operation: node.effect.operation,\n cascade: node.effect.cascade,\n targetTurn: node.effect.targetTurn,\n ...(node.effect.blockKind === undefined ? {} : { blockKind: node.effect.blockKind }),\n ...(node.effect.before === undefined ? {} : { before: node.effect.before }),\n ...(node.effect.after === undefined ? {} : { after: node.effect.after }),\n }),\n createdAt: node.createdAt,\n depth: depthOf(timeline, node.sessionId),\n current: String(node.sessionId) === String(sessionId),\n onCurrentEffectPath: currentPath.has(String(node.sessionId)),\n }));\n const versionsById = new Map(versions.map((version) => [version.sessionId, version]));\n const undoStack: string[] = [];\n let cursor = versionsById.get(String(sessionId));\n while (cursor?.inverseSessionId !== undefined) {\n if (undoStack.includes(cursor.inverseSessionId)) break;\n undoStack.push(cursor.inverseSessionId);\n cursor = versionsById.get(cursor.inverseSessionId);\n }\n const redoSessionIds = versions\n .filter((version) => version.inverseSessionId === String(sessionId))\n .map((version) => version.sessionId);\n return {\n sessionId: String(sessionId),\n messages,\n retryableTurns,\n versions,\n undoStack,\n redoSessionIds,\n };\n}\n\n/** 计算节点到根的深度。 */\nfunction depthOf(\n timeline: BranchTimeline,\n sessionId: import(\"@deepseek-ai/dsh-session\").SessionId,\n): number {\n const byId = new Map(timeline.nodes.map((node) => [String(node.sessionId), node]));\n let depth = 0;\n let cursor = byId.get(String(sessionId));\n const seen = new Set<string>();\n while (cursor?.parentSessionId !== undefined && !seen.has(String(cursor.sessionId))) {\n seen.add(String(cursor.sessionId));\n depth += 1;\n cursor = byId.get(String(cursor.parentSessionId));\n }\n return depth;\n}\n","/**\n * Browser controller for one session's Timeline projection and branch mutations.\n * 精简版:HTTP 拉取 timeline + 执行操作 + 会话导航(openWhenListed)。\n */\n\nimport type {\n ClientContext,\n ConversationSnapshot,\n ISessions,\n ObservableSnapshot,\n SessionFace,\n SessionId,\n SnapshotStore,\n} from \"@deepseek-ai/dsh-client-runtime/client\";\nimport { createSnapshotStore } from \"@deepseek-ai/dsh-client-runtime/client\";\nimport {\n SESSION_EDITOR_PATH,\n type EditableMessageBlock,\n type SessionEditorOperation,\n type SessionEditorOperationResult,\n type SessionEditorTimeline,\n type VersionOperation,\n} from \"../shared.ts\";\n\nexport interface SessionEditorState {\n status: \"idle\" | \"loading\" | \"ready\" | \"error\";\n error: string | null;\n pending: VersionOperation | \"cleanse\" | null;\n timeline: SessionEditorTimeline | null;\n /** 会话历史加载失败(openState === \"error\")——据此显示「清洗会话」入口。 */\n sessionOpenError: boolean;\n}\n\n/** 业务 face;渲染层绑定到保留的 source compartment。 */\nexport interface SessionEditorFace {\n hooks: { sessionEditor: ObservableSnapshot<SessionEditorState> };\n acquire(): () => void;\n load(): void;\n edit(\n message: EditableMessageBlock,\n text: string,\n cascade: \"truncate\" | \"preserve\",\n ): Promise<boolean>;\n retry(turn: number, cascade: \"truncate\" | \"preserve\"): Promise<boolean>;\n reroll(): Promise<boolean>;\n rewind(toBoundary: number): Promise<boolean>;\n /** 清洗当前会话的 provenance 坐标为稠密空间(修复历史加载失败)。 */\n cleanse(): Promise<boolean>;\n openVersion(sessionId: string): Promise<void>;\n}\n\nfunction messageOf(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nfunction conversationRevision(snapshot: ConversationSnapshot): string {\n const turnEnds = [...snapshot.turnEnds.entries()]\n .map(([turn, seq]) => `${String(turn)}:${String(seq)}`)\n .join(\",\");\n return [snapshot.openState, snapshot.removed, snapshot.hasMore, turnEnds].join(\"|\");\n}\n\n/** 一个会话共享一个稳定 controller(header + timeline 两个入口复用)。 */\nexport class SessionEditorController {\n readonly store: SnapshotStore<SessionEditorState> = createSnapshotStore<SessionEditorState>({\n status: \"idle\",\n error: null,\n pending: null,\n timeline: null,\n sessionOpenError: false,\n });\n\n readonly face: SessionEditorFace;\n private readonly ctx: ClientContext;\n private readonly sessions: ISessions;\n private sessionSource: SessionFace | undefined;\n private sessionSourceDispose: (() => void) | undefined;\n private sessionRevision: string | undefined;\n private disposed = false;\n private users = 0;\n private readonly navigationWaits = new Set<() => void>();\n\n constructor(\n ctx: ClientContext,\n private readonly sessionId: SessionId,\n ) {\n this.ctx = ctx;\n this.sessions = ctx.get(\"sessions\") as unknown as ISessions;\n this.face = {\n hooks: { sessionEditor: this.store },\n acquire: () => {\n this.users += 1;\n if (this.users === 1 && this.disposed) this.revive();\n return () => this.release();\n },\n load: () => {\n void this.load();\n },\n edit: (message, text, cascade) =>\n this.mutate({\n action: \"edit\",\n sessionId: this.sessionId,\n eventSeq: message.eventSeq,\n blockIndex: message.blockIndex,\n text,\n cascade,\n }),\n retry: (turn, cascade) =>\n this.mutate({ action: \"retry\", sessionId: this.sessionId, turn, cascade }),\n reroll: () => this.mutate({ action: \"reroll\", sessionId: this.sessionId }),\n rewind: (toBoundary) =>\n this.mutate({ action: \"rewind\", sessionId: this.sessionId, toBoundary }),\n cleanse: () => this.mutate({ action: \"cleanse\", sessionId: this.sessionId }),\n openVersion: (sessionId) => this.openWhenListed(sessionId as SessionId),\n };\n this.observe();\n }\n\n private observe(): void {\n this.sessionSource = undefined;\n this.sessionSourceDispose?.();\n this.bindSessionSource();\n this.sessions.list.subscribe(() => this.invalidate());\n }\n\n private bindSessionSource(): void {\n const source = this.sessions.binding(this.sessionId)?.session;\n if (source === this.sessionSource) return;\n this.sessionSourceDispose?.();\n this.sessionSource = source;\n this.sessionRevision =\n source === undefined ? undefined : conversationRevision(source.getSnapshot());\n // 历史加载失败标记:会话 snapshot 的 openState === \"error\" 时显示清洗入口。\n this.store.update((state) => {\n state.sessionOpenError = source?.getSnapshot().openState === \"error\";\n });\n this.sessionSourceDispose = source?.subscribe(() => {\n this.store.update((state) => {\n state.sessionOpenError = source.getSnapshot().openState === \"error\";\n });\n this.invalidate();\n });\n }\n\n private invalidate(): void {\n if (this.disposed || this.store.getSnapshot().status === \"idle\") return;\n // 会话状态变化 → 刷新投影(debounce 由调用方按需)。\n void this.load();\n }\n\n private release(): void {\n this.users -= 1;\n if (this.users <= 0) this.dispose();\n }\n\n private dispose(): void {\n if (this.disposed) return;\n this.disposed = true;\n this.sessionSourceDispose?.();\n this.sessionSourceDispose = undefined;\n this.sessionSource = undefined;\n this.sessionRevision = undefined;\n }\n\n private revive(): void {\n this.disposed = false;\n this.observe();\n void this.load();\n }\n\n async load(): Promise<void> {\n if (this.disposed) return;\n this.store.update((state) => {\n state.status = \"loading\";\n state.error = null;\n });\n try {\n const response = await fetch(\n `${SESSION_EDITOR_PATH}?sessionId=${encodeURIComponent(this.sessionId)}`,\n {\n method: \"GET\",\n headers: { accept: \"application/json\" },\n cache: \"no-store\",\n },\n );\n const value = (await response.json()) as unknown;\n if (this.disposed) return;\n if (response.ok) {\n this.store.update((state) => {\n state.status = \"ready\";\n state.error = null;\n state.timeline = value as SessionEditorTimeline;\n });\n } else {\n const error = (value as { error?: unknown })[\"error\"];\n this.store.update((state) => {\n state.status = \"error\";\n state.error =\n typeof error === \"string\" ? error : `请求失败:HTTP ${String(response.status)}`;\n });\n }\n } catch (error) {\n if (this.disposed) return;\n this.store.update((state) => {\n state.status = \"error\";\n state.error = messageOf(error);\n });\n }\n }\n\n private async mutate(operation: SessionEditorOperation): Promise<boolean> {\n // 只拦截并发操作;不要求 status === \"ready\"——编辑/重试的数据(eventSeq/\n // blockIndex/turn)来自客户端 conversation 节点,与 timeline 加载无关,\n // status 停留在 idle(无 HeaderActions 触发 load)时也必须能发起请求。\n const current = this.store.getSnapshot();\n if (current.pending !== null) return false;\n this.store.update((state) => {\n state.pending = operation.action;\n state.error = null;\n });\n try {\n const response = await fetch(SESSION_EDITOR_PATH, {\n method: \"POST\",\n headers: { accept: \"application/json\", \"content-type\": \"application/json\" },\n body: JSON.stringify(operation),\n });\n const value = (await response.json()) as unknown;\n if (this.disposed) return true;\n if (!response.ok) {\n const error = (value as { error?: unknown })[\"error\"];\n throw new Error(\n typeof error === \"string\" ? error : `请求失败:HTTP ${String(response.status)}`,\n );\n }\n this.store.update((state) => {\n state.pending = null;\n });\n const result = value as SessionEditorOperationResult;\n // edit / retry / reroll 就地编辑(不改变 session id),仅 fork 产生新 id\n // 时才需要等列表发布并打开新版本。\n if (String(result.sessionId) !== String(this.sessionId)) {\n await this.openWhenListed(result.sessionId as SessionId);\n return true;\n }\n // 就地编辑:rewind 会**删除**事件,客户端 conversation 事件流(append-only\n // 发布)无法表达删除——seq 回退只做增量,被剪掉的旧节点会残留。\n // 优先\"会话级刷新\"(resync:重置窗口并重新拉取历史,不整页重载);\n // resync 不可用时回退整页重载。\n const face = this.sessions.binding(this.sessionId)?.session;\n const resync = (face as unknown as { resync?: () => Promise<void> }).resync;\n if (resync !== undefined) {\n try {\n await resync.call(face);\n void this.load();\n return true;\n } catch {\n // fall through to full reload\n }\n }\n location.reload();\n return true;\n } catch (error) {\n if (this.disposed) return false;\n this.store.update((state) => {\n state.pending = null;\n state.error = messageOf(error);\n });\n return false;\n }\n }\n\n /** 会话列表发布是导航的反应式依赖:等新版本出现在列表后再打开。 */\n private openWhenListed(sessionId: SessionId): Promise<void> {\n if (this.sessions.list.getSnapshot().byId[sessionId] !== undefined) {\n this.sessions.open(sessionId);\n return Promise.resolve();\n }\n return new Promise((resolve) => {\n let settled = false;\n let dispose = (): void => {};\n const finish = (open: boolean): void => {\n if (settled) return;\n settled = true;\n dispose();\n this.navigationWaits.delete(cancel);\n if (open) this.sessions.open(sessionId);\n resolve();\n };\n const cancel = (): void => {\n finish(false);\n };\n this.navigationWaits.add(cancel);\n dispose = this.sessions.list.subscribe(() => {\n if (this.sessions.list.getSnapshot().byId[sessionId] === undefined) return;\n finish(true);\n });\n if (this.sessions.list.getSnapshot().byId[sessionId] !== undefined) finish(true);\n });\n }\n}\n","/** Frame-throttled scheduling for non-essential visual alignment. */\nimport { useCallback, useLayoutEffect, useRef } from \"react\";\n\nconst DEFAULT_INTERVAL_FRAMES = 3;\n\n/**\n * Return a stable scheduler that coalesces visual updates over a frame interval.\n * @param update - DOM alignment to run after the throttle interval.\n * @param intervalFrames - frames to wait before applying the latest alignment.\n * @returns a stable function that schedules the latest update.\n */\nexport function useThrottledVisualUpdate(\n update: () => void,\n intervalFrames = DEFAULT_INTERVAL_FRAMES,\n): () => void {\n const updateRef = useRef(update);\n updateRef.current = update;\n const pendingFrameRef = useRef<number | null>(null);\n\n useLayoutEffect(\n () => () => {\n if (pendingFrameRef.current === null) return;\n cancelAnimationFrame(pendingFrameRef.current);\n pendingFrameRef.current = null;\n },\n [],\n );\n\n return useCallback(() => {\n if (pendingFrameRef.current !== null) return;\n let remainingFrames = intervalFrames;\n const advance = (): void => {\n remainingFrames -= 1;\n if (remainingFrames > 0) {\n pendingFrameRef.current = requestAnimationFrame(advance);\n return;\n }\n pendingFrameRef.current = null;\n updateRef.current();\n };\n pendingFrameRef.current = requestAnimationFrame(advance);\n }, [intervalFrames]);\n}\n","/** Assistant reasoning disclosure, independent of Tool-call presentation. */\nimport { useEffect, useRef, useState } from \"react\";\nimport { DisclosureRow, IconThinkOutline14 } from \"@deepseek-ai/dsh-client-ui-primitives\";\nimport type { ChatViewSlotProps } from \"@deepseek-ai/dsh-client-ui-conversation/client\";\nimport { useThrottledVisualUpdate } from \"./use-throttled-visual-update.ts\";\nimport a11yCss from \"./accessibility.module.css\";\nimport css from \"./ReasoningRow.module.css\";\n\nfunction firstLine(text: string): string {\n const newline = text.indexOf(\"\\n\");\n return newline === -1 ? text : text.slice(0, newline);\n}\n\nfunction latestLine(text: string): string {\n const visible = text.trimEnd();\n const newline = visible.lastIndexOf(\"\\n\");\n return newline === -1 ? visible : visible.slice(newline + 1);\n}\n\n/**\n * Render one assistant reasoning block as the Think disclosure row.\n * @param props.text - complete or streaming reasoning text.\n * @param props.running - whether this block is the streaming tail.\n * @param props.t - conversation locale seat for the running status.\n * @returns the reasoning disclosure.\n */\nexport function ReasoningRow({\n text,\n running,\n t,\n}: {\n text: string;\n running: boolean;\n t: ChatViewSlotProps[\"t\"];\n}) {\n const [expanded, setExpanded] = useState(false);\n const summaryRef = useRef<HTMLSpanElement>(null);\n const summary = running ? latestLine(text) : firstLine(text);\n const scheduleSummaryScroll = useThrottledVisualUpdate(() => {\n const element = summaryRef.current;\n if (element === null) return;\n element.scrollLeft = running ? element.scrollWidth - element.clientWidth : 0;\n });\n useEffect(() => {\n scheduleSummaryScroll();\n }, [running, scheduleSummaryScroll, summary]);\n\n return (\n <div className={css.root} data-variant=\"think\" data-state={running ? \"running\" : \"ok\"}>\n {running && <span className={a11yCss.visuallyHidden}>{t(\"row.running\")}</span>}\n <DisclosureRow\n rowClassName={css.row}\n leadingClassName={css.leading}\n titleClassName={css.title}\n chevronClassName={css.chevron}\n icon={<IconThinkOutline14 size={14} />}\n title=\"Think\"\n open={expanded}\n expandable\n expandOnRowClick\n onToggle={() => {\n setExpanded((value) => !value);\n }}\n collapsedContent={\n <>\n <span className={css.separator} aria-hidden />\n <span ref={summaryRef} className={css.summary} data-follow-end={running || undefined}>\n {summary}\n </span>\n </>\n }\n >\n <div className={css.thinkBody}>{text}</div>\n </DisclosureRow>\n </div>\n );\n}\n","// AssistantMarkdown: renders assistant blocks in order — markdown text body,\n// reasoning as the figma Think summary row (expand = indented gray text),\n// other-block JSON fallback. Tool-call heads are NOT rendered here: the chat\n// view groups them into tool rows through its keyed toolview slot (figma\n// step-summary flow). Shared by finalized nodes and the streaming partial;\n// the turn-level loading dots live in the chat view's tail, not here.\n// Finalized content (text) nodes append IconActions once their turn ends\n// (`time` is omitted for mid-turn narration and while the turn still runs);\n// their branch action is enabled only when the node is also the completed\n// turn's transcript tail. Think / tool-head-only nodes stay chrome-free.\n\nimport { Fragment, memo, useMemo } from \"react\";\nimport type { ReactNode } from \"react\";\nimport type { AssistantBlock } from \"@deepseek-ai/dsh-client-runtime/client\";\nimport { JsonBlock, MarkdownText } from \"@deepseek-ai/dsh-client-ui-primitives\";\nimport type { MarkdownFileMentions } from \"@deepseek-ai/dsh-client-ui-primitives\";\nimport type {\n ChatViewSlotProps,\n RenderMessageImages,\n} from \"@deepseek-ai/dsh-client-ui-conversation/client\";\nimport { ReasoningRow } from \"./ReasoningRow.tsx\";\nimport css from \"./AssistantMarkdown.module.css\";\n\nexport interface AssistantMarkdownProps {\n blocks: readonly AssistantBlock[];\n streaming: boolean;\n /** Frozen partial of an aborted turn: rendered with a stopped marker. */\n interrupted?: boolean | undefined;\n /** Render a consecutive image group through the attachment slot. */\n renderMessageImages: RenderMessageImages;\n /** Resolved prose file mentions for this Assistant's closing turn. */\n mentions?: MarkdownFileMentions | undefined;\n /** The owning view's locale seat, passed down as a plain prop. */\n t: ChatViewSlotProps[\"t\"];\n}\n\n/** Reasoning block as the Think variant summary row (figma 39:28304). */\nexport const AssistantMarkdown = memo(function AssistantMarkdown({\n blocks,\n streaming,\n interrupted,\n renderMessageImages,\n mentions,\n t,\n}: AssistantMarkdownProps) {\n // Stable per locale revision (t identity changes on switch): a fresh object\n // per render would rebuild MarkdownText's component table every chunk.\n const codeLabels = useMemo(\n () => ({ copyLabel: t(\"copy\" as never), copiedLabel: t(\"copied\" as never) }),\n [t],\n );\n const last = blocks.length - 1;\n // Tool-call heads render as tool rows in the chat view's grouping pass, so\n // a node that is only those heads (or empty) would paint an empty root\n // between tool groups — skip the shell unless something visible remains.\n const hasVisible =\n streaming || interrupted === true || blocks.some((block) => block.kind !== \"tool-call\");\n if (!hasVisible) return null;\n const rendered: ReactNode[] = [];\n for (let i = 0; i < blocks.length; i++) {\n const block = blocks[i];\n if (block === undefined) continue;\n switch (block.kind) {\n case \"text\":\n rendered.push(\n <MarkdownText\n key={i}\n text={block.text}\n streaming={streaming}\n codeLabels={codeLabels}\n fileMentions={mentions}\n />,\n );\n break;\n case \"reasoning\":\n rendered.push(\n <ReasoningRow key={i} text={block.text} running={streaming && i === last} t={t} />,\n );\n break;\n case \"image\": {\n // Consecutive image blocks share one gallery so several images tile\n // into rows instead of each opening a one-image group of its own.\n // Keyed by the group's FIRST block index: a streaming append that\n // extends the group then only grows `images` instead of remounting\n // the gallery under a shifted key.\n const start = i;\n const group = [block];\n while (i + 1 < blocks.length) {\n const next = blocks[i + 1];\n if (next === undefined || next.kind !== \"image\") break;\n group.push(next);\n i += 1;\n }\n rendered.push(\n <Fragment key={start}>\n {renderMessageImages({\n images: group.map(({ attachment }) => ({ attachment })),\n align: \"start\",\n })}\n </Fragment>,\n );\n break;\n }\n // Grouped into tool rows by ChatView; hasVisible above skips an empty shell.\n case \"tool-call\":\n break;\n default:\n rendered.push(\n <JsonBlock\n key={i}\n label={t(\"message.unknownBlock\")}\n payload={block.block}\n truncatedLabel={(total) => t(\"json.truncated\", { total })}\n />,\n );\n }\n }\n return (\n <div className={css.root} data-streaming={streaming || undefined}>\n <div className={css.body}>\n {rendered}\n {interrupted && <span className={css.stopped}>{t(\"message.stopped\")}</span>}\n </div>\n </div>\n );\n});\n","import { memo, useMemo } from \"react\";\nimport type {\n ChatNodeViewProps,\n TurnTailOwnerProps,\n} from \"@deepseek-ai/dsh-client-ui-conversation/client\";\nimport { AssistantMarkdown } from \"./AssistantMarkdown.tsx\";\n\n/** Streaming, settled, and interrupted Assistant states share one keyed renderer instance. */\nexport const AssistantNodeView = memo(function AssistantNodeView({\n node,\n useTurnData,\n openFile,\n renderMessageImages,\n fileMentions,\n t,\n}: ChatNodeViewProps<\"assistant-step\">) {\n const data = node.data;\n const turn =\n node.location.kind === \"turn\" || node.location.kind === \"step\" ? node.location.turn : undefined;\n const tail = useTurnData(\"turn-tail\");\n const owner = useMemo<TurnTailOwnerProps | undefined>(() => {\n if (turn?.status !== \"closed\" || data.finalNode === undefined) return undefined;\n if (tail?.closing?.finalNode.seq !== data.finalNode.seq) return undefined;\n return { turn, seq: data.finalNode.seq, openFile };\n }, [data.finalNode, openFile, tail, turn]);\n const mentions = useMemo(\n () => (owner === undefined ? undefined : fileMentions(owner)),\n [fileMentions, owner],\n );\n return (\n <AssistantMarkdown\n blocks={data.blocks}\n streaming={data.status === \"running\"}\n interrupted={data.status === \"interrupted\"}\n renderMessageImages={renderMessageImages}\n mentions={mentions}\n t={t}\n />\n );\n});\n","// CompactionItem: the one row a landed compaction contributes to the flow.\n// The conversation it shadowed on the model surface stays above it, so this\n// marker reports where the model stopped seeing that history — it never\n// replaces it. The framed checkpoint payload is written for the model and is\n// not rendered; the disclosure shows the summary from the checkpoint's own\n// cited `compaction/summary` event, and a window cut that left that event outside makes the row\n// non-expandable rather than empty.\n\nimport { memo, useState } from \"react\";\nimport type { CompactionSummaryNode } from \"@deepseek-ai/dsh-client-runtime/client\";\nimport {\n IconApiOutline14,\n IconChevronDownOutline14,\n IconChevronRightOutline14,\n MarkdownText,\n} from \"@deepseek-ai/dsh-client-ui-primitives\";\nimport type { ChatViewSlotProps } from \"@deepseek-ai/dsh-client-ui-conversation/client\";\nimport css from \"./MessageItem.module.css\";\n\ninterface CompactionItemProps {\n node: CompactionSummaryNode;\n /** Optional command title for a manual compaction folded into this marker. */\n title?: string;\n /** Command settlement text used when structured compaction counts are unavailable. */\n fallbackSummary?: string | null;\n /** The owning view's locale seat. */\n t: ChatViewSlotProps[\"t\"];\n}\n\n/**\n * The collapsed-by-default compaction marker.\n * @param props - the marker node off the snapshot cache.\n * @returns the marker row, with the summary disclosure when one is available.\n */\nexport const CompactionItem = memo(function CompactionItem({\n node,\n title,\n fallbackSummary,\n t,\n}: CompactionItemProps) {\n const [expanded, setExpanded] = useState(false);\n const expandable = node.summary !== null;\n const open = expandable && expanded;\n const summary =\n node.shadowedItemCount !== null && node.shadowedTokenCount !== null\n ? t(\"message.compaction.completed\", {\n items: node.shadowedItemCount,\n tokens: node.shadowedTokenCount,\n })\n : (fallbackSummary ??\n (expandable ? t(\"message.compaction.expand\") : t(\"message.compaction.unavailable\")));\n return (\n <div className={css.compactionRow}>\n <button\n type=\"button\"\n className={css.compactionButton}\n disabled={!expandable}\n aria-expanded={expandable ? open : undefined}\n onClick={() => {\n setExpanded((value) => !value);\n }}\n >\n <span className={css.compactionLeading} aria-hidden>\n <span className={css.compactionContextIcon} data-compaction-icon=\"context\">\n <IconApiOutline14 />\n </span>\n <span\n className={css.compactionDisclosureIcon}\n data-compaction-disclosure={open ? \"expanded\" : \"collapsed\"}\n >\n {open ? <IconChevronDownOutline14 /> : <IconChevronRightOutline14 />}\n </span>\n </span>\n <span className={css.compactionTitle}>{title ?? t(\"message.compaction\")}</span>\n <span className={css.compactionSep} aria-hidden />\n <span className={css.compactionSummary}>{summary}</span>\n </button>\n {open && node.summary !== null && (\n <div className={css.compactionBody}>\n <MarkdownText text={node.summary} />\n </div>\n )}\n </div>\n );\n});\n","// GenericCommandCard: the default command row — a stripped-down\n// GenericToolCard rendering the command name and its settlement text.\n// Supplied by the chat view as the keyed commandview slot's render-site\n// fallback (an unregistered command name lands here); registrants may compose\n// it as a base, feeding the same owner payload through.\n\nimport { useState, type ReactNode } from \"react\";\nimport type {\n ChatViewSlotProps,\n CommandRowOwnerProps,\n} from \"@deepseek-ai/dsh-client-ui-conversation/client\";\nimport { DisclosureRow, IconApiOutline14, StateDot } from \"@deepseek-ai/dsh-client-ui-primitives\";\nimport a11yCss from \"./accessibility.module.css\";\nimport css from \"./GenericCommandCard.module.css\";\n\ntype CommandRowState = \"running\" | \"ok\" | \"error\";\n\n/** Node state → row state semantic (running while unsettled; outcome kind after). */\nfunction stateOf(outcome: CommandRowOwnerProps[\"node\"][\"outcome\"]): CommandRowState {\n if (outcome === null) return \"running\";\n return outcome.kind === \"error\" ? \"error\" : \"ok\";\n}\n\nfunction leadingFor(state: CommandRowState): ReactNode {\n return state === \"error\" ? <StateDot state=\"error\" /> : <IconApiOutline14 size={14} />;\n}\n\n/** Card props: the owner payload plus the render site's locale seat (plain prop). */\nexport interface GenericCommandCardProps extends CommandRowOwnerProps {\n t: ChatViewSlotProps[\"t\"];\n /** Command-specific running copy; absent uses the generic command label. */\n runningSummary?: string | undefined;\n}\n\nexport function GenericCommandCard({ node, t, runningSummary }: GenericCommandCardProps) {\n const [expanded, setExpanded] = useState(false);\n const text = node.outcome?.text;\n const summary =\n node.outcome === null\n ? (runningSummary ?? t(\"command.running\"))\n : (text ?? (node.outcome.kind === \"error\" ? t(\"command.failed\") : t(\"command.done\")));\n // Title is the bare command name: the row already reads `name · outcome`,\n // and the dispatched line's own `/` and arguments only restate what the\n // settlement text says (`permission · preset workspace-write`). A\n // cross-window node whose run page fell out of the window has no name.\n const title = node.name ?? t(\"command.title\");\n const state = stateOf(node.outcome);\n const body = text !== undefined && text.includes(\"\\n\") ? text : null;\n const open = expanded && body !== null;\n return (\n <div className={css.root} data-variant=\"others\" data-state={state}>\n {state === \"running\" && <span className={a11yCss.visuallyHidden}>{t(\"row.running\")}</span>}\n {state === \"error\" && <span className={a11yCss.visuallyHidden}>{t(\"row.failed\")}</span>}\n <DisclosureRow\n rowClassName={css.row}\n leadingClassName={css.leading}\n titleClassName={css.title}\n chevronClassName={css.chevron}\n icon={leadingFor(state)}\n title={title}\n open={open}\n expandable={body !== null}\n expandOnRowClick\n keepContentWhenOpen\n onToggle={() => {\n setExpanded((value) => !value);\n }}\n collapsedContent={\n <>\n <span className={css.separator} aria-hidden />\n <span className={css.summary} data-error={state === \"error\" || undefined}>\n {summary}\n </span>\n </>\n }\n >\n <pre className={css.body} data-error={state === \"error\" || undefined}>\n {body}\n </pre>\n </DisclosureRow>\n </div>\n );\n}\n","// CompactionCommandCard: the `/compact` command's running row and its\n// successful checkpoint disclosure. Outcomes without a checkpoint keep the\n// generic command card so no-history, cancellation, and failures retain their\n// complete handler-authored text.\n\nimport type {\n ChatViewSlotProps,\n CommandRowOwnerProps,\n} from \"@deepseek-ai/dsh-client-ui-conversation/client\";\nimport { CompactionItem } from \"./CompactionItem.tsx\";\nimport { GenericCommandCard } from \"./GenericCommandCard.tsx\";\n\ninterface CompactionCommandCardProps extends CommandRowOwnerProps {\n t: ChatViewSlotProps[\"t\"];\n}\n\n/** Render one manual compaction lifecycle without duplicating its checkpoint marker. */\nexport function CompactionCommandCard({ node, compaction, t }: CompactionCommandCardProps) {\n if (compaction !== undefined) {\n return (\n <CompactionItem\n node={compaction}\n title=\"compact\"\n fallbackSummary={node.outcome?.text ?? null}\n t={t}\n />\n );\n }\n if (node.outcome !== null) return <GenericCommandCard node={node} t={t} />;\n return <GenericCommandCard node={node} t={t} runningSummary={t(\"message.compaction.running\")} />;\n}\n","import { memo, useMemo } from \"react\";\nimport type {\n ChatNodeViewProps,\n CommandRowOwnerProps,\n} from \"@deepseek-ai/dsh-client-ui-conversation/client\";\nimport { CompactionCommandCard } from \"./CompactionCommandCard.tsx\";\nimport { GenericCommandCard } from \"./GenericCommandCard.tsx\";\nimport css from \"./ChatView.module.css\";\n\ntype CommandNodeViewProps = ChatNodeViewProps<\"command\">;\n\n/**\n * Ordinary command lifecycle renderer. 注意:shadow 注册(priority -1)无法\n * 声明 `conversation.chat.commandview` children(已被上游声明,重复声明会抛\n * 「already declared」),因此这里不消费 `renderSlot` 子 slot,直接渲染通用\n * command 卡片。\n */\nexport const CommandNodeView = memo(function CommandNodeView({ node, t }: CommandNodeViewProps) {\n const command = node.data;\n const owner = useMemo<CommandRowOwnerProps>(() => ({ node: command }), [command]);\n return (\n <div className={css.callRow}>\n <GenericCommandCard {...owner} t={t} />\n </div>\n );\n});\n\n/** One integrated `/compact` command and compaction transaction renderer. */\nexport const ManualCompactionNodeView = memo(function ManualCompactionNodeView({\n node,\n t,\n}: ChatNodeViewProps<\"manual-compaction\">) {\n const data = node.data;\n return (\n <div className={css.callRow}>\n <CompactionCommandCard\n node={data.command}\n {...(data.compaction === null ? {} : { compaction: data.compaction })}\n t={t}\n />\n </div>\n );\n});\n","// Expanded bodies for the context disclosure, one per durable context form.\n// The producer declares the form; this module only chooses a presentation for\n// it. Every form falls back to OpaqueBody, which is the documented default for\n// an absent, unknown, or malformed form — a resumed or foreign log must render\n// even when this UI version has never seen its producer.\n\nimport type { ReactNode } from \"react\";\nimport type { ContextMessageNode, KnownContextForm } from \"@deepseek-ai/dsh-client-runtime/client\";\nimport { JsonBlock } from \"@deepseek-ai/dsh-client-ui-primitives\";\nimport type { ChatViewSlotProps } from \"@deepseek-ai/dsh-client-ui-conversation/client\";\nimport css from \"./ContextBody.module.css\";\n\n/** Model-facing text stays bounded at the disclosure, not at the producer. */\nconst MAX_CHARS = 20_000;\n\n/** Rows a list body materializes before summarizing the remainder. */\nconst MAX_ENTRIES = 200;\n\ntype Translate = ChatViewSlotProps[\"t\"];\n\n/** One durable source narrowed to the readable-record shape; null for anything else. */\nfunction asRecord(value: unknown): Record<string, unknown> | null {\n return typeof value === \"object\" && value !== null && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : null;\n}\n\n/** One run of the model-facing content: adjacent text, or one unknown block. */\ntype ContentRun = { text: string } | { block: unknown };\n\n/**\n * The content blocks as runs, IN THE ORDER the model received them.\n *\n * Adjacent text blocks join with no separator, matching how provider adapters\n * flatten them — inserting a line break would show the reader a line the model\n * never saw. An unknown block breaks the run and keeps its own fallback rather\n * than being hoisted past the text around it or vanishing; the block union is\n * merge-extensible, so a foreign log may interleave shapes this build does not\n * know.\n */\nfunction contentRuns(content: ContextMessageNode[\"content\"]): ContentRun[] {\n const runs: ContentRun[] = [];\n for (const block of content) {\n if (block.type !== \"text\") {\n runs.push({ block });\n continue;\n }\n const last = runs[runs.length - 1];\n if (last !== undefined && \"text\" in last) last.text += block.text;\n else runs.push({ text: block.text });\n }\n return runs;\n}\n\n/** Only the blocks this UI version does not know, for bodies that replace the text. */\nfunction unknownBlocks(content: ContextMessageNode[\"content\"]): unknown[] {\n return contentRuns(content).flatMap((run) => (\"block\" in run ? [run.block] : []));\n}\n\n/** The model-facing text, truncated to the display bound. */\nfunction boundedText(text: string, t: Translate): string {\n return text.length > MAX_CHARS\n ? `${text.slice(0, MAX_CHARS)}\\n${t(\"json.truncated\", { total: text.length })}`\n : text;\n}\n\n/**\n * One source field rendered as a value row; nested shapes stay compact JSON.\n * Bounded on its own, because source fields are as unbounded as the text: an unknown\n * producer may record an arbitrarily large string or array.\n */\nfunction fieldValue(value: unknown, t: Translate): string {\n const text =\n typeof value === \"string\"\n ? value\n : typeof value === \"number\" || typeof value === \"boolean\"\n ? String(value)\n : JSON.stringify(value);\n return boundedText(text, t);\n}\n\n/**\n * Source fields as a key/value list. `kind` is always omitted because the\n * row header already names the producer. `form` is omitted only when a\n * dedicated body rendered for it — then the presentation the reader is looking\n * at IS that value. On the opaque fallback the declaration is kept, because\n * that is the one place a form this version cannot present would otherwise\n * disappear from the UI entirely.\n */\nfunction SourceFields({\n source,\n formRendered,\n t,\n}: {\n source: unknown;\n formRendered: boolean;\n t: Translate;\n}): ReactNode {\n const record = asRecord(source);\n if (record === null) return null;\n const hidden = formRendered ? [\"kind\", \"form\"] : [\"kind\"];\n const rows = Object.entries(record).filter(([key]) => !hidden.includes(key));\n if (rows.length === 0) return null;\n return (\n <dl className={css.fields} data-context-fields>\n {rows.map(([key, value]) => (\n <div key={key} className={css.field}>\n <dt className={css.fieldKey}>{key}</dt>\n <dd className={css.fieldValue}>{fieldValue(value, t)}</dd>\n </div>\n ))}\n </dl>\n );\n}\n\n/**\n * Content blocks this UI version does not know, kept visible rather than\n * dropped: the block union is merge-extensible, so a newer or foreign log may\n * carry a shape this build has no presentation for.\n * @param props - The unrecognized blocks and the locale seat.\n * @returns One generic JSON block per unknown entry.\n */\nfunction UnknownBlocks({ blocks, t }: { blocks: readonly unknown[]; t: Translate }): ReactNode {\n return (\n <>\n {blocks.map((block, index) => (\n <JsonBlock\n key={index}\n label={t(\"message.unknownBlock\")}\n payload={block}\n truncatedLabel={(total) => t(\"json.truncated\", { total })}\n />\n ))}\n </>\n );\n}\n\n/**\n * The model-facing content of one context, shared by every form that shows it:\n * the text with its real line breaks, then any block this UI version does not\n * know, which keeps its own fallback rather than vanishing.\n * @param props - Durable content and the locale seat.\n * @returns The content blocks as the model received them.\n */\nfunction ModelFacingContent({\n content,\n t,\n}: {\n content: ContextMessageNode[\"content\"];\n t: Translate;\n}): ReactNode {\n return (\n <>\n {contentRuns(content).map((run, index) =>\n \"text\" in run ? (\n run.text !== \"\" && (\n <pre key={index} className={css.text} data-context-text>\n {boundedText(run.text, t)}\n </pre>\n )\n ) : (\n <JsonBlock\n key={index}\n label={t(\"message.unknownBlock\")}\n payload={run.block}\n truncatedLabel={(total) => t(\"json.truncated\", { total })}\n />\n ),\n )}\n </>\n );\n}\n\n/**\n * Default presentation: the model-facing text as text, with its real line\n * breaks, and the remaining source fields beneath it. This is what every form\n * this UI version does not recognize renders as.\n * @param props - Durable content, its source, and the locale seat.\n * @returns The opaque context body.\n */\nexport function OpaqueBody({\n content,\n source,\n t,\n}: {\n content: ContextMessageNode[\"content\"];\n source: unknown;\n t: Translate;\n}): ReactNode {\n return (\n <>\n <ModelFacingContent content={content} t={t} />\n <SourceFields source={source} formRendered={false} t={t} />\n </>\n );\n}\n\n/** One reconciled instruction file, as the durable source records it. */\ninterface InstructionChange {\n action: \"set\" | \"replace\" | \"remove\";\n path: string;\n digest?: string;\n}\n\n/**\n * Instruction changes read off the source, or null when the record is not a\n * usable instruction list.\n *\n * The read is all-or-nothing: silently dropping one unreadable entry would show\n * a confident, incomplete file list for a log this version cannot fully read.\n * Paths are deduplicated in first-seen order, matching how the header label is\n * derived from the same array.\n */\nfunction instructionChanges(source: unknown): InstructionChange[] | null {\n const record = asRecord(source);\n const list = record === null ? undefined : record[\"changes\"];\n if (!Array.isArray(list)) return null;\n const changes: InstructionChange[] = [];\n const seen = new Set<string>();\n for (const entry of list as readonly unknown[]) {\n const change = asRecord(entry);\n if (change === null) return null;\n const path = change[\"path\"];\n if (typeof path !== \"string\" || path === \"\") return null;\n const action = change[\"action\"];\n // The action decides which word the row shows, so an unrecognized one is\n // not a readable change — it would be presented as loaded or updated.\n if (action !== \"set\" && action !== \"replace\" && action !== \"remove\") return null;\n const digest = change[\"digest\"];\n if (seen.has(path)) continue;\n seen.add(path);\n changes.push({ action, path, ...(typeof digest === \"string\" ? { digest } : {}) });\n }\n return changes.length === 0 ? null : changes;\n}\n\n/**\n * Locale key for one reconciled file. The baseline loads a file; a later delta\n * distinguishes a newly reconciled path from a rewritten one, which `set` and\n * `replace` already separate at the producer.\n * @param action - the durable change action.\n * @param baseline - whether this context is the startup/resume baseline.\n * @returns the key naming what happened to that file.\n */\nfunction instructionAction(\n action: InstructionChange[\"action\"],\n baseline: boolean,\n):\n | \"message.context.instructions.removed\"\n | \"message.context.instructions.loaded\"\n | \"message.context.instructions.added\"\n | \"message.context.instructions.updated\" {\n if (action === \"remove\") return \"message.context.instructions.removed\";\n if (baseline) return \"message.context.instructions.loaded\";\n return action === \"set\"\n ? \"message.context.instructions.added\"\n : \"message.context.instructions.updated\";\n}\n\n/**\n * `instructions` form: the files this context reconciled, then their text.\n *\n * The text keeps its `<system-reminder>` framing verbatim — the framing is part\n * of what the model read, so hiding it would misreport the request.\n * @param props - Durable content, its source, and the locale seat.\n * @returns The instructions context body, or the opaque body when the change\n * list is unreadable.\n */\nexport function InstructionsBody({\n content,\n source,\n t,\n}: {\n content: ContextMessageNode[\"content\"];\n source: unknown;\n t: Translate;\n}): ReactNode {\n const changes = instructionChanges(source);\n if (changes === null) return <OpaqueBody content={content} source={source} t={t} />;\n const baseline = asRecord(source)?.[\"baseline\"] === true;\n return (\n <>\n <ul className={css.files} data-context-files>\n {changes.map((change) => (\n <li key={change.path} className={css.file} title={change.digest}>\n <span className={css.filePath}>{change.path}</span>\n <span className={css.fileAction}>{t(instructionAction(change.action, baseline))}</span>\n </li>\n ))}\n </ul>\n <ModelFacingContent content={content} t={t} />\n </>\n );\n}\n\n/** One catalog entry, as the durable source records it. */\ninterface CatalogEntry {\n name: string;\n description: string;\n}\n\n/**\n * Catalog entries read off the source, or null when the record is not a usable\n * catalog. All-or-nothing for the same reason as the instruction list: this body\n * replaces the model-facing text, so a partial list would hide the only complete\n * account of what the model read.\n */\nfunction catalogEntries(source: unknown): CatalogEntry[] | null {\n const record = asRecord(source);\n const list = record === null ? undefined : record[\"entries\"];\n if (!Array.isArray(list)) return null;\n const entries: CatalogEntry[] = [];\n for (const item of list as readonly unknown[]) {\n const entry = asRecord(item);\n if (entry === null) return null;\n const name = entry[\"name\"];\n const description = entry[\"description\"];\n if (typeof name !== \"string\" || name === \"\" || typeof description !== \"string\") return null;\n entries.push({ name, description });\n }\n // An empty list is a real catalog: a replacement with no entries retires\n // every earlier name. Only an unreadable shape falls back.\n return entries;\n}\n\n/**\n * `catalog` form: the published entries as a list, read from the source rather\n * than re-parsed out of the model-facing prose.\n *\n * A catalog whose source carries no usable entries falls through to the opaque\n * body, so an older or hand-edited log still shows its text.\n * @param props - Durable content, its source, and the locale seat.\n * @returns The catalog context body, or the opaque body when the entry list is\n * unreadable.\n */\nexport function CatalogBody({\n content,\n source,\n t,\n}: {\n content: ContextMessageNode[\"content\"];\n source: unknown;\n t: Translate;\n}): ReactNode {\n const entries = catalogEntries(source);\n if (entries === null) return <OpaqueBody content={content} source={source} t={t} />;\n const update = asRecord(source)?.[\"update\"] === true;\n // Entry count is unbounded (a provider may publish any number of skills), and\n // the scrollport bounds height, not node count — so the list bounds itself.\n const shown = entries.slice(0, MAX_ENTRIES);\n const rest = unknownBlocks(content);\n return (\n <>\n {update && (\n <p className={css.catalogNotice} data-context-catalog-update>\n {t(\"message.context.catalog.replaced\")}\n </p>\n )}\n <ul className={css.entries} data-context-entries>\n {shown.map((entry, index) => (\n // Index key: a hand-edited or foreign log may repeat a name, and a\n // duplicate React key would drop a row the model did see.\n <li key={index} className={css.entry}>\n <code className={css.entryName}>{entry.name}</code>\n <span className={css.entryDescription}>{entry.description}</span>\n </li>\n ))}\n </ul>\n {shown.length < entries.length && (\n <p className={css.catalogNotice} data-context-entries-truncated>\n {t(\"message.context.catalog.more\", { count: entries.length - shown.length })}\n </p>\n )}\n {/* The block union is merge-extensible: a catalog message carrying an\n unknown block still shows it rather than dropping model-visible content. */}\n <UnknownBlocks blocks={rest} t={t} />\n </>\n );\n}\n\n/** One named contribution to a runtime snapshot, as the durable source records it. */\ninterface SnapshotSection {\n name: string;\n text: string;\n}\n\n/** Snapshot sections read off the source, or null when the record is unusable. */\nfunction snapshotSections(source: unknown): SnapshotSection[] | null {\n const record = asRecord(source);\n const list = record === null ? undefined : record[\"sections\"];\n if (!Array.isArray(list)) return null;\n const sections: SnapshotSection[] = [];\n for (const item of list as readonly unknown[]) {\n const section = asRecord(item);\n if (section === null) return null;\n const name = section[\"name\"];\n const text = section[\"text\"];\n if (typeof name !== \"string\" || name === \"\" || typeof text !== \"string\") return null;\n sections.push({ name, text });\n }\n return sections.length === 0 ? null : sections;\n}\n\n/**\n * `snapshot` form: the named contributions this snapshot assembled, in order.\n *\n * The sections are the same bytes the model read, split at the boundaries the\n * producer assembled them on, so a reader sees which subsystem contributed\n * which state instead of one undifferentiated wall.\n *\n * One sentence of the model-facing text is NOT in any section: the producer's\n * framing line declaring that this snapshot supersedes earlier ones. Unlike the\n * `<system-reminder>` wrapper an instruction context carries — which wraps\n * content and cannot be separated from it — that line states the form's own\n * semantics, so the body states them as a caption instead of reprinting the\n * joined prose beside the sections it was split from.\n * @param props - Durable content, its source, and the locale seat.\n * @returns The snapshot context body, or the opaque body when unreadable.\n */\nexport function SnapshotBody({\n content,\n source,\n t,\n}: {\n content: ContextMessageNode[\"content\"];\n source: unknown;\n t: Translate;\n}): ReactNode {\n const sections = snapshotSections(source);\n /* v8 ignore next -- contextBody reads the sections before choosing this body. */\n if (sections === null) return <OpaqueBody content={content} source={source} t={t} />;\n return (\n <>\n <p className={css.catalogNotice} data-context-snapshot-supersedes>\n {t(\"message.context.snapshot.supersedes\")}\n </p>\n <dl className={css.sections} data-context-sections>\n {sections.map((section, index) => (\n <div key={index} className={css.section}>\n <dt className={css.sectionName}>{section.name}</dt>\n <dd className={css.sectionText}>{boundedText(section.text, t)}</dd>\n </div>\n ))}\n </dl>\n </>\n );\n}\n\n/**\n * `notice` form: what just happened, with the model-facing text beneath it.\n *\n * The one-line account also rides the collapsed row ({@link contextBody}), so a\n * notice is usually readable without expanding at all.\n * @param props - Durable content, its source, and the locale seat.\n * @returns The notice context body.\n */\nexport function NoticeBody({\n content,\n t,\n}: {\n content: ContextMessageNode[\"content\"];\n source: unknown;\n t: Translate;\n}): ReactNode {\n return <ModelFacingContent content={content} t={t} />;\n}\n\n/**\n * `relay` form: which agent sent this, then what it said.\n *\n * The sender is an opaque session id; it is shown as a field rather than a\n * label, because this client cannot resolve it to a title.\n * @param props - Durable content, its source, and the locale seat.\n * @returns The relay context body.\n */\nexport function RelayBody({\n content,\n source,\n t,\n}: {\n content: ContextMessageNode[\"content\"];\n source: unknown;\n t: Translate;\n}): ReactNode {\n const sender = relaySender(source);\n /* v8 ignore next -- contextBody resolves the sender before choosing this body. */\n if (sender === null) return <OpaqueBody content={content} source={source} t={t} />;\n return (\n <>\n <p className={css.relaySender} data-context-relay-sender>\n {t(\"message.context.relay.from\", { session: sender })}\n </p>\n <ModelFacingContent content={content} t={t} />\n </>\n );\n}\n\n/** The sending agent's session id, or null when the record does not name one. */\nfunction relaySender(source: unknown): string | null {\n const sender = asRecord(source)?.[\"senderSessionId\"];\n return typeof sender === \"string\" && sender !== \"\" ? sender : null;\n}\n\n/** One recalled session, as the durable source records it. */\ninterface RecalledSession {\n label: string;\n retained: number;\n omitted: number;\n truncated: boolean;\n}\n\n/** Recalled sessions read off the source, or null when the record is unusable. */\nfunction recalledSessions(source: unknown): RecalledSession[] | null {\n const record = asRecord(source);\n const list = record === null ? undefined : record[\"references\"];\n if (!Array.isArray(list)) return null;\n const sessions: RecalledSession[] = [];\n for (const item of list as readonly unknown[]) {\n const reference = asRecord(item);\n if (reference === null) return null;\n const label = reference[\"label\"];\n const retained = reference[\"retainedMessages\"];\n const omitted = reference[\"omittedMessages\"];\n const truncated = reference[\"truncated\"];\n // Completeness is the fact this card exists to report, so a reference that\n // cannot state it is not a readable recall — showing the label alone would\n // present a confident card over unknown loss.\n if (\n typeof label !== \"string\" ||\n label === \"\" ||\n typeof retained !== \"number\" ||\n typeof omitted !== \"number\" ||\n typeof truncated !== \"boolean\"\n )\n return null;\n sessions.push({ label, retained, omitted, truncated });\n }\n return sessions.length === 0 ? null : sessions;\n}\n\n/**\n * `recall` form: which sessions this material came from and how much of each\n * survived the read, then the material itself.\n *\n * Completeness is the fact a reader needs first: recalled context is bounded on\n * the way in, so a card that hid the omitted count would overstate what the\n * model received.\n * @param props - Durable content, its source, and the locale seat.\n * @returns The recall context body, or the opaque body when unreadable.\n */\nexport function RecallBody({\n content,\n source,\n t,\n}: {\n content: ContextMessageNode[\"content\"];\n source: unknown;\n t: Translate;\n}): ReactNode {\n const sessions = recalledSessions(source);\n if (sessions === null) return <OpaqueBody content={content} source={source} t={t} />;\n return (\n <>\n <ul className={css.recalls} data-context-recalls>\n {sessions.map((session, index) => (\n <li key={index} className={css.recall}>\n <span className={css.recallLabel}>{session.label}</span>\n <span className={css.recallCounts}>\n {t(\"message.context.recall.counts\", {\n retained: session.retained,\n omitted: session.omitted,\n })}\n </span>\n {session.truncated && (\n <span className={css.recallCounts}>{t(\"message.context.recall.truncated\")}</span>\n )}\n </li>\n ))}\n </ul>\n <ModelFacingContent content={content} t={t} />\n </>\n );\n}\n\n/** The one-line account a `notice` puts on its collapsed row, when it records one. */\nfunction noticeSummary(source: unknown): string | null {\n const summary = asRecord(source)?.[\"summary\"];\n return typeof summary === \"string\" && summary !== \"\" ? summary : null;\n}\n\n/**\n * Choose the body for one context node.\n *\n * Returns the form the body actually rendered as, which is not always the\n * declared one: a declared form whose fields are unreadable falls back to\n * opaque, and the caller labels the row with what it really shows.\n * `summary` is the collapsed row's one-line account, which only a `notice`\n * records: its whole point is being readable without expanding.\n * @param form - the producer-declared form projected onto the node.\n * @param props - durable content, its source, and the locale seat.\n * @returns the rendered form (null for opaque), its collapsed summary, and its body.\n */\nexport function contextBody(\n form: ContextMessageNode[\"form\"],\n props: { content: ContextMessageNode[\"content\"]; source: unknown; t: Translate },\n): { rendered: KnownContextForm | null; summary: string | null; body: ReactNode } {\n const opaque = { rendered: null, summary: null, body: <OpaqueBody {...props} /> };\n switch (form) {\n case \"instructions\":\n return instructionChanges(props.source) === null\n ? opaque\n : { rendered: \"instructions\", summary: null, body: <InstructionsBody {...props} /> };\n case \"catalog\":\n return catalogEntries(props.source) === null\n ? opaque\n : { rendered: \"catalog\", summary: null, body: <CatalogBody {...props} /> };\n case \"snapshot\":\n return snapshotSections(props.source) === null\n ? opaque\n : { rendered: \"snapshot\", summary: null, body: <SnapshotBody {...props} /> };\n case \"notice\": {\n const summary = noticeSummary(props.source);\n return summary === null\n ? opaque\n : { rendered: \"notice\", summary, body: <NoticeBody {...props} /> };\n }\n case \"relay\":\n return relaySender(props.source) === null\n ? opaque\n : { rendered: \"relay\", summary: null, body: <RelayBody {...props} /> };\n case \"recall\":\n return recalledSessions(props.source) === null\n ? opaque\n : { rendered: \"recall\", summary: null, body: <RecallBody {...props} /> };\n case null:\n return opaque;\n /* v8 ignore next 4 -- closed-union backstop; the compiler rejects a new\n KnownContextForm here rather than letting it degrade to opaque silently. */\n default: {\n const unreachable: never = form;\n throw new Error(`unreachable context form: ${String(unreachable)}`);\n }\n }\n}\n","import { useState } from \"react\";\nimport type { ContextMessageNode } from \"@deepseek-ai/dsh-client-runtime/client\";\nimport type { ChatViewSlotProps } from \"@deepseek-ai/dsh-client-ui-conversation/client\";\nimport { DisclosureRow, IconBrowseOutline16 } from \"@deepseek-ai/dsh-client-ui-primitives\";\nimport { contextBody } from \"./ContextBody.tsx\";\nimport css from \"./ContextInjectionRow.module.css\";\n\n/** Props for the logged non-user message presentation. */\nexport interface ContextInjectionRowProps {\n content: ContextMessageNode[\"content\"];\n source: ContextMessageNode[\"source\"];\n /** Role and producer name projected from the durable source. */\n provenance: ContextMessageNode[\"provenance\"];\n /** Producer-declared information form; null renders the opaque body. */\n form: ContextMessageNode[\"form\"];\n /** The owning view's locale seat, passed down as a plain prop. */\n t: ChatViewSlotProps[\"t\"];\n}\n\n/**\n * Render logged context with the Tool calls disclosure chrome from Figma.\n *\n * The header names the role the context plays and, beside it, the producer the\n * durable source identifies, so a reader can tell an injected skill catalog\n * from a workspace instruction file or a recalled session without expanding.\n * The expanded body follows the producer-declared form; an absent or unknown\n * form renders the opaque body.\n * @param props - Durable content, its projected producer role/name and form, and the locale seat.\n * @returns A collapsed context row with a bounded, form-specific body.\n */\nexport function ContextInjectionRow({\n content,\n source,\n provenance,\n form,\n t,\n}: ContextInjectionRowProps) {\n const [open, setOpen] = useState(false);\n // Resolved rather than declared: a form whose fields are unreadable renders\n // the opaque body, and the marker must say what the row actually shows.\n const { rendered, summary, body } = contextBody(form, { content, source, t });\n\n return (\n <DisclosureRow\n className={css.root}\n icon={<IconBrowseOutline16 size={14} />}\n chevronClassName={css.chevron}\n title={t(provenance.role === \"recall\" ? \"message.contextRecall\" : \"message.contextInjection\")}\n collapsedContent={\n provenance.label === null ? undefined : (\n /* ToolRow's separator shape: an aria-hidden dot, so the accessible name\n stays the two readable parts and the two disclosure rows expose one\n name shape. A source that names no producer drops the dot with it. */\n <>\n <span className={css.sep} aria-hidden />\n <span className={css.source} data-context-source>\n {provenance.label}\n </span>\n {summary !== null && (\n <>\n <span className={css.sep} aria-hidden />\n <span className={css.summary} data-context-summary>\n {summary}\n </span>\n </>\n )}\n </>\n )\n }\n keepContentWhenOpen\n open={open}\n expandable\n expandOnRowClick\n onToggle={() => {\n setOpen((value) => !value);\n }}\n >\n <div\n className={css.body}\n data-context-injection-body\n data-context-form={rendered ?? undefined}\n >\n {body}\n </div>\n </DisclosureRow>\n );\n}\n","// Shared time-label helpers for user/assistant IconActions rows.\n\nimport type { Translate } from \"@deepseek-ai/dsh-client-ui-slots\";\n\n/** The date-template share of the conversation dictionary the clock consumes. */\nexport type ClockTranslate = Translate<\"clock.md\" | \"clock.ymd\">;\n\n/** The elapsed-duration share of the conversation dictionary. */\nexport type RunDurationTranslate = Translate<\"duration.seconds\" | \"duration.minutes\">;\nfunction pad2(n: number): string {\n return String(n).padStart(2, \"0\");\n}\n\n/**\n * Local calendar-day epoch (ms at local midnight) for an instant.\n * @param ms - Unix epoch ms.\n * @returns Midnight of that local calendar day.\n */\nexport function startOfLocalDay(ms: number): number {\n const d = new Date(ms);\n d.setHours(0, 0, 0, 0);\n return d.getTime();\n}\n\n/**\n * Delay until the next local midnight after `ms` (at least 1ms).\n * @param ms - Unix epoch ms.\n * @returns Milliseconds until the following local midnight.\n */\nexport function msUntilNextLocalMidnight(ms: number): number {\n const next = new Date(ms);\n next.setHours(24, 0, 0, 0);\n return Math.max(next.getTime() - ms, 1);\n}\n\n/**\n * Localized elapsed-time label shared by running and settled turn chrome.\n * @param ms - Elapsed duration in milliseconds (negatives clamp to zero).\n * @param t - Translate seat supplying the duration templates.\n * @returns Display string in whole seconds.\n */\nexport function formatRunDuration(ms: number, t: RunDurationTranslate): string {\n const total = Math.max(0, Math.floor(ms / 1000));\n const minutes = Math.floor(total / 60);\n const seconds = total % 60;\n return minutes > 0\n ? t(\"duration.minutes\", { minutes, seconds: String(seconds).padStart(2, \"0\") })\n : t(\"duration.seconds\", { seconds });\n}\n\n/**\n * Sub-turn latency figure: one decimal under ten seconds, whole seconds\n * beyond. Unit-less so the locale template owns the second suffix.\n * @param ms - Latency in milliseconds (negatives clamp to zero).\n * @returns Display number in seconds without unit.\n */\nexport function formatLatencySeconds(ms: number): string {\n const s = Math.max(0, ms) / 1000;\n return s < 10 ? String(Math.round(s * 10) / 10) : String(Math.round(s));\n}\n\n/**\n * Decode-throughput figure: whole tokens from ten up, one decimal below.\n * @param tps - Tokens per second.\n * @returns Display number without unit.\n */\nexport function formatTokensPerSecond(tps: number): string {\n const clamped = Math.max(0, tps);\n return clamped >= 10 ? String(Math.round(clamped)) : String(Math.round(clamped * 10) / 10);\n}\n\n/**\n * Compact local timestamp for message IconActions. Same calendar day →\n * `HH:mm`; earlier this year → the `clock.md` date template + clock; other\n * years → the `clock.ymd` template + clock. Pure: the date templates arrive\n * through the caller's locale seat.\n * @param time - Unix epoch ms from the source session event.\n * @param t - translate seat supplying the `clock.md` / `clock.ymd` templates.\n * @param now - Reference instant for the day/year cut (defaults to wall clock).\n * @returns Date-aware clock string (24-hour, zero-padded time).\n */\nexport function formatMessageClock(\n time: number,\n t: ClockTranslate,\n now: number = Date.now(),\n): string {\n const d = new Date(time);\n const n = new Date(now);\n const clock = `${pad2(d.getHours())}:${pad2(d.getMinutes())}`;\n if (\n d.getFullYear() === n.getFullYear() &&\n d.getMonth() === n.getMonth() &&\n d.getDate() === n.getDate()\n ) {\n return clock;\n }\n const params = { y: d.getFullYear(), m: d.getMonth() + 1, d: d.getDate() };\n const md = d.getFullYear() === n.getFullYear() ? t(\"clock.md\", params) : t(\"clock.ymd\", params);\n return `${md} ${clock}`;\n}\n","// Component-local calendar-day tick: memoized message rows keep stable props\n// across midnight, so the IconActions clock needs a local day seat that\n// re-fires at the next local midnight without reaching for framework hooks.\n\nimport { useEffect, useState } from \"react\";\nimport { msUntilNextLocalMidnight, startOfLocalDay } from \"./message-chrome.ts\";\n\n/**\n * Local calendar-day epoch that advances at each local midnight.\n * @returns Midnight ms for the current local day; updates after the boundary.\n */\nexport function useCalendarDay(): number {\n const [day, setDay] = useState(() => startOfLocalDay(Date.now()));\n useEffect(() => {\n let timer: ReturnType<typeof setTimeout>;\n const arm = (): void => {\n const now = Date.now();\n setDay(startOfLocalDay(now));\n timer = setTimeout(arm, msUntilNextLocalMidnight(now));\n };\n timer = setTimeout(arm, msUntilNextLocalMidnight(Date.now()));\n return () => {\n clearTimeout(timer);\n };\n }, []);\n return day;\n}\n","// Shared IconActions chrome for user and assistant messages: copy\n// live, optional branch wiring, and an optional date-aware clock.\n\nimport { useCallback, useEffect, useId, useRef, useState, type ReactNode } from \"react\";\nimport {\n IconBranchOutline16,\n IconCheckOutline16,\n IconCopyOutline16,\n IconEditOutline16,\n IconRefreshOutline16,\n Tooltip,\n writeClipboard,\n} from \"@deepseek-ai/dsh-client-ui-primitives\";\nimport type { ChatViewSlotProps } from \"@deepseek-ai/dsh-client-ui-conversation/client\";\nimport {\n formatLatencySeconds,\n formatMessageClock,\n formatRunDuration,\n formatTokensPerSecond,\n} from \"./message-chrome.ts\";\nimport { useCalendarDay } from \"./use-calendar-day.ts\";\nimport css from \"./MessageIconActions.module.css\";\n\nexport interface MessageIconActionsProps {\n /** Plain text the copy action writes. */\n text: string;\n /** Unix epoch ms for the clock label; omitted for transient messages. */\n time?: number | undefined;\n /** Turn wall time in ms, appended to the clock as `· Ran for 15s`; omitted when the turn's start is unknown. */\n runMs?: number | undefined;\n /** Turn first-step TTFT in ms, appended as `· TTFT 1.2s`; omitted when unrecorded. */\n ttftMs?: number | undefined;\n /** Turn decode throughput, appended as `· 34 tok/s`; omitted when unrecorded. */\n tokensPerSecond?: number | undefined;\n /** Clock before icons (user) or after (assistant). */\n clock: \"start\" | \"end\";\n /** Fork the session at this message; omission hides the branch action. */\n onBranch?: (() => void) | undefined;\n /** The message is not a completed transcript tail, so branch stays visible but unavailable. */\n branchUnavailable?: boolean | undefined;\n /** Parent layout class composed onto the actions row. */\n className?: string | undefined;\n /**\n * Slot-rendered actions owned by independent plugins, placed between the\n * built-in copy and branch controls.\n */\n extraActions?: ReactNode;\n /** Edit this message block in place (session-editor). */\n onEdit?: (() => void) | undefined;\n /** Retry this turn in place (session-editor). */\n onRetry?: (() => void) | undefined;\n /** The owning view's locale seat, passed down as a plain prop. */\n t: ChatViewSlotProps[\"t\"];\n}\n\n/**\n * Copy / branch (/ clock) IconActions row shared by user and assistant chrome.\n * @param props - Copy text, event time, clock side, branch callback, className.\n * @returns The actions row element.\n */\nexport function MessageIconActions({\n text,\n time,\n runMs,\n ttftMs,\n tokensPerSecond,\n clock,\n onBranch,\n branchUnavailable = false,\n className,\n extraActions,\n onEdit,\n onRetry,\n t,\n}: MessageIconActionsProps) {\n const day = useCalendarDay();\n const reasonId = useId();\n // Same success chrome as CodeBlock: a short check swap after the write,\n // gated so re-clicks during the window neither re-copy nor stack timers.\n const [copied, setCopied] = useState(false);\n const copyPending = useRef(false);\n const copyTimer = useRef<number | null>(null);\n const copyEpoch = useRef(0);\n useEffect(\n () => () => {\n copyEpoch.current += 1;\n copyPending.current = false;\n if (copyTimer.current !== null) clearTimeout(copyTimer.current);\n },\n [],\n );\n const onCopy = useCallback(() => {\n if (copied || copyPending.current) return;\n const epoch = copyEpoch.current;\n copyPending.current = true;\n void writeClipboard(text).then((ok) => {\n if (epoch !== copyEpoch.current) return;\n copyPending.current = false;\n if (!ok) return;\n setCopied(true);\n copyTimer.current = window.setTimeout(() => {\n copyTimer.current = null;\n setCopied(false);\n }, 1000);\n });\n }, [copied, text]);\n // The dot is decorative and stays hidden, but its margins separate the\n // readings only on screen: without the flanking spaces a reader hears one\n // run-on string (\"Ran for 13sTTFT 0.2s12 tok/s\") instead of three facts.\n const clockEl =\n time === undefined ? null : (\n <span className={clock === \"start\" ? css.timeStart : css.timeEnd}>\n {formatMessageClock(time, t, day)}\n {runMs !== undefined && (\n <>\n {\" \"}\n <span className={css.runTimeDot} aria-hidden>\n ·\n </span>{\" \"}\n {t(\"message.ranFor\", { duration: formatRunDuration(runMs, t) })}\n </>\n )}\n {ttftMs !== undefined && (\n <>\n {\" \"}\n <span className={css.runTimeDot} aria-hidden>\n ·\n </span>{\" \"}\n {t(\"message.ttft\", { seconds: formatLatencySeconds(ttftMs) })}\n </>\n )}\n {tokensPerSecond !== undefined && (\n <>\n {\" \"}\n <span className={css.runTimeDot} aria-hidden>\n ·\n </span>{\" \"}\n {t(\"message.tokensPerSecond\", { tps: formatTokensPerSecond(tokensPerSecond) })}\n </>\n )}\n </span>\n );\n return (\n <div className={className === undefined ? css.actions : `${css.actions} ${className}`}>\n {clock === \"start\" ? clockEl : null}\n <Tooltip label={copied ? t(\"copied\" as never) : t(\"copy\" as never)} side=\"bottom\">\n <button\n type=\"button\"\n className={css.action}\n aria-label={copied ? t(\"copied\" as never) : t(\"copy\" as never)}\n onClick={onCopy}\n >\n {copied ? <IconCheckOutline16 /> : <IconCopyOutline16 />}\n </button>\n </Tooltip>\n {extraActions}\n {onEdit !== undefined && (\n <Tooltip label=\"编辑\" side=\"bottom\">\n <button type=\"button\" className={css.action} aria-label=\"编辑\" onClick={onEdit}>\n <IconEditOutline16 />\n </button>\n </Tooltip>\n )}\n {onRetry !== undefined && (\n <Tooltip label=\"重试此回合\" side=\"bottom\">\n <button type=\"button\" className={css.action} aria-label=\"重试此回合\" onClick={onRetry}>\n <IconRefreshOutline16 />\n </button>\n </Tooltip>\n )}\n {onBranch !== undefined && (\n <Tooltip\n label={branchUnavailable ? t(\"message.branchUnavailable\") : t(\"message.branch\")}\n side=\"bottom\"\n >\n {/* Native disabled buttons do not deliver the hover/focus events Tooltip needs. */}\n <button\n type=\"button\"\n className={css.action}\n aria-label={t(\"message.branch\")}\n aria-disabled={branchUnavailable || undefined}\n aria-describedby={branchUnavailable ? reasonId : undefined}\n data-unavailable={branchUnavailable || undefined}\n onClick={branchUnavailable ? undefined : onBranch}\n >\n <IconBranchOutline16 />\n </button>\n </Tooltip>\n )}\n {onBranch !== undefined && branchUnavailable && (\n <span id={reasonId} className={css.visuallyHidden}>\n {t(\"message.branchUnavailable\")}\n </span>\n )}\n {clock === \"end\" ? clockEl : null}\n </div>\n );\n}\n","/**\n * 消息编辑弹窗:与 dsh settings 同风格的 Modal(@deepseek-ai/dsh-client-ui-primitives)。\n * 输入框复用 composer-card 的视觉(InputBar 同款 border/radius/surface/阴影\n * token)与自动增长交互。保存成功后关闭;失败保持打开。\n */\n\nimport { useRef, useState } from \"react\";\nimport { Button, Modal } from \"@deepseek-ai/dsh-client-ui-primitives\";\nimport type { EditableMessageBlock } from \"../../shared.ts\";\nimport css from \"./MessageEditDialog.module.css\";\n\nconst BLOCK_TITLE: Record<EditableMessageBlock[\"kind\"], string> = {\n user: \"编辑用户消息\",\n \"assistant.reasoning\": \"编辑助手思考\",\n \"assistant.response\": \"编辑助手回复\",\n};\n\n/** 编辑弹窗:调用 onSave 保存;返回 true 关闭,false 保持打开。 */\nexport function MessageEditDialog({\n block,\n onSave,\n onClose,\n}: {\n block: EditableMessageBlock;\n onSave: (text: string) => Promise<boolean>;\n onClose: () => void;\n}) {\n const [text, setText] = useState(block.text);\n const [saving, setSaving] = useState(false);\n const inputRef = useRef<HTMLTextAreaElement | null>(null);\n\n /** composer-card 式自动增长:高度随内容(scrollHeight)自适应。 */\n const autosize = (): void => {\n const el = inputRef.current;\n if (el === null) return;\n el.style.height = \"auto\";\n el.style.height = `${el.scrollHeight}px`;\n };\n\n const save = (): void => {\n if (saving) return;\n setSaving(true);\n void onSave(text).then((applied) => {\n if (applied) onClose();\n else setSaving(false);\n });\n };\n\n return (\n <Modal\n open\n onClose={onClose}\n title={BLOCK_TITLE[block.kind]}\n closeLabel=\"关闭\"\n footer={\n <div className={css.actions}>\n <Button variant=\"outline\" onClick={onClose} disabled={saving}>\n 取消\n </Button>\n <Button variant=\"primary\" onClick={save} disabled={saving}>\n {saving ? \"保存中…\" : \"保存\"}\n </Button>\n </div>\n }\n >\n <textarea\n ref={inputRef}\n className={css.input}\n value={text}\n onChange={(event) => {\n setText(event.target.value);\n autosize();\n }}\n autoFocus\n rows={4}\n />\n </Modal>\n );\n}\n","// MessageItem: simple chat nodes — user and consumed-steering bubbles\n// (right-aligned, with clock + copy IconActions; branch lives only under\n// assistant answers), pending steering (copy only), context injection,\n// compaction marker, retry disclosure, and unknown-surface JSON rows.\n\nimport { memo, useEffect, useMemo, useState } from \"react\";\nimport type { ReactNode } from \"react\";\nimport type { InjectFace } from \"@deepseek-ai/dsh-client-ui-slots\";\nimport { Button, Modal } from \"@deepseek-ai/dsh-client-ui-primitives\";\nimport type {\n ModelRetryNode,\n TurnErrorNode,\n UserMessageNode,\n} from \"@deepseek-ai/dsh-client-runtime/client\";\nimport { JsonBlock, MessageText, StateDot } from \"@deepseek-ai/dsh-client-ui-primitives\";\nimport type {\n ChatNodeViewProps,\n ChatViewSlotProps,\n RenderMessageImages,\n} from \"@deepseek-ai/dsh-client-ui-conversation/client\";\nimport { CompactionItem } from \"./CompactionItem.tsx\";\nimport { ContextInjectionRow } from \"./ContextInjectionRow.tsx\";\nimport { MessageIconActions } from \"./MessageIconActions.tsx\";\nimport { MessageEditDialog } from \"./MessageEditDialog.tsx\";\nimport css from \"./MessageItem.module.css\";\nimport type { EditableMessageBlock } from \"../../shared.ts\";\nimport type { SessionEditorFace } from \"../controller.ts\";\n\ntype UserImage = Extract<UserMessageNode[\"content\"][number], { type: \"image\" }>;\n\nfunction contentParts(content: readonly unknown[]): {\n text: string;\n images: { attachment: UserImage[\"attachment\"] }[];\n rest: unknown[];\n} {\n const texts: string[] = [];\n const images: { attachment: UserImage[\"attachment\"] }[] = [];\n const rest: unknown[] = [];\n for (const block of content) {\n const b = block as { type?: string; text?: string; attachment?: unknown };\n if (b.type === \"text\" && typeof b.text === \"string\") texts.push(b.text);\n else if (b.type === \"image\" && b.attachment !== undefined) {\n images.push({ attachment: (b as UserImage).attachment });\n } else rest.push(block);\n }\n return { text: texts.join(\"\"), images, rest };\n}\n\nfunction retrySeconds(milliseconds: number): number {\n return Math.max(1, Math.ceil(milliseconds / 1_000));\n}\n\ninterface RetryCountdown {\n deadline: number;\n seconds: number;\n}\n\nfunction ModelRetryItem({\n node,\n active,\n t,\n}: {\n node: ModelRetryNode;\n active: boolean;\n t: ChatViewSlotProps[\"t\"];\n}) {\n // Anchor the host-scheduled delay to this browser's first render of the\n // retry node. Host event time and Date.now() may belong to different clocks.\n const deadline = useMemo(() => Date.now() + node.delayMs, [node.delayMs, node.seq]);\n const scheduledSeconds = retrySeconds(node.delayMs);\n const maximum = node.mode === \"normal\" ? node.maxRetries : \"∞\";\n const [countdown, setCountdown] = useState<RetryCountdown>(() => ({\n deadline,\n seconds: retrySeconds(deadline - Date.now()),\n }));\n const remainingSeconds =\n countdown.deadline === deadline ? countdown.seconds : retrySeconds(deadline - Date.now());\n\n useEffect(() => {\n if (!active) return;\n const updateCountdown = (): number => {\n const next = retrySeconds(deadline - Date.now());\n setCountdown((current) =>\n current.deadline === deadline && current.seconds === next\n ? current\n : { deadline, seconds: next },\n );\n return next;\n };\n if (updateCountdown() === 1) return;\n const timer = window.setInterval(() => {\n if (updateCountdown() === 1) window.clearInterval(timer);\n }, 250);\n return () => {\n window.clearInterval(timer);\n };\n }, [active, deadline]);\n\n const label = active\n ? t(\"message.retry.active\")\n : node.retryState === \"cancelled\"\n ? t(\"message.retry.cancelled\")\n : node.retryState === \"started\"\n ? t(\"message.retry.started\")\n : t(\"message.retry.scheduled\");\n const seconds = active ? remainingSeconds : scheduledSeconds;\n\n return (\n <details className={css.retryRow} data-active={active || undefined}>\n <summary className={css.retrySummary}>\n <span className={css.retryText} role=\"status\">\n {t(\"message.retry.status\", { label, retry: node.retry, maximum, seconds })}\n </span>\n </summary>\n <div className={css.retryDetails}>\n <div>\n <span className={css.retryDetailLabel}>{t(\"message.retry.delay\")}</span>\n {Math.round(node.delayMs)}ms\n </div>\n <div>\n <span className={css.retryDetailLabel}>{t(\"message.retry.failure\")}</span>\n {node.failure.message}\n </div>\n </div>\n </details>\n );\n}\n\n/** Persistent, turn-positioned feedback for a terminal failure. */\nfunction TurnErrorItem({ node, t }: { node: TurnErrorNode; t: ChatViewSlotProps[\"t\"] }) {\n return (\n <div className={css.turnErrorRow} role=\"status\">\n <StateDot state=\"error\" className={css.turnErrorDot} />\n <div className={css.turnErrorCopy}>\n <span className={css.turnErrorTitle}>{t(\"message.turnError\")}</span>\n <span className={css.turnErrorMessage}>{node.message}</span>\n </div>\n {node.code !== undefined && <code className={css.turnErrorCode}>{node.code}</code>}\n </div>\n );\n}\n\n/** Persistent, turn-positioned notice for a turn ended at the output-token cap. */\nfunction TurnMaxTokensItem({ t }: { t: ChatViewSlotProps[\"t\"] }) {\n return (\n <div className={css.turnErrorRow} role=\"status\">\n <StateDot state=\"warning\" className={css.turnErrorDot} />\n <div className={css.turnErrorCopy}>\n <span className={css.maxTokensTitle}>{t(\"message.maxTokens\")}</span>\n <span className={css.turnErrorMessage}>{t(\"message.maxTokens.hint\")}</span>\n </div>\n </div>\n );\n}\n\n/**\n * Display projection of reference forms in a user bubble (free geometry — no\n * textarea alignment constraint here); everything else stays plain text. The\n * logged model text remains the single truth; this is presentation only.\n * Plain-text `/name` / `@name` word-boundary tokens decorate (the sent text\n * IS the reference — the bubble uses the same plainest token\n * scan as the composer, minus the lexicon: sent tokens were validated at\n * compose time, so shape alone decorates).\n */\nfunction projectUserText(text: string): ReactNode {\n const re = /(^|\\s)([/@][\\w-]+)(?=\\s|$)/g;\n const parts: ReactNode[] = [];\n let cursor = 0;\n let m: RegExpExecArray | null;\n while ((m = re.exec(text)) !== null) {\n const tokenStart = m.index + (m[1]?.length ?? 0);\n const label = m[2] ?? \"\";\n if (tokenStart > cursor)\n parts.push(<MessageText key={cursor} text={text.slice(cursor, tokenStart)} />);\n parts.push(\n <span\n key={tokenStart}\n className={css.refChip}\n data-ref-chip={label.startsWith(\"@\") ? \"subagent\" : \"skill\"}\n >\n {label}\n </span>,\n );\n cursor = tokenStart + label.length;\n }\n if (parts.length === 0) return <MessageText text={text} />;\n if (cursor < text.length) parts.push(<MessageText key={cursor} text={text.slice(cursor)} />);\n return <>{parts}</>;\n}\n\n/** Right-aligned bubble shared by user and steering rows. */\nfunction UserStyleBubble({\n content,\n renderMessageImages,\n actions,\n pending = false,\n t,\n}: {\n content: readonly unknown[];\n renderMessageImages: RenderMessageImages;\n /** Optional IconActions (or similar) below the bubble; receives the joined text. */\n actions?: (text: string) => ReactNode;\n /** Whether this is the Host-authoritative pre-admission steering projection. */\n pending?: boolean;\n t: ChatViewSlotProps[\"t\"];\n}): ReactNode {\n const { text, images, rest } = contentParts(content);\n const truncated = (total: number): string => t(\"json.truncated\", { total });\n const showBubble = text !== \"\" || rest.length > 0;\n return (\n <div className={css.userRow} data-pending-steering={pending || undefined} data-time-hover-root>\n <div className={css.userStack}>\n {renderMessageImages({ images, align: \"end\" })}\n {showBubble && (\n <div className={css.bubble}>\n {projectUserText(text)}\n {rest.map((block, i) => (\n <JsonBlock\n key={i}\n label={t(\"message.extraBlock\")}\n payload={block}\n truncatedLabel={truncated}\n />\n ))}\n </div>\n )}\n </div>\n {actions?.(text)}\n </div>\n );\n}\n\n/**\n * Render one Host-authoritative pending steering item with the same visual\n * language as its eventual durable transcript node.\n * @param props - Pending message content and conversation translator.\n * @returns the pending steering bubble.\n */\nexport function PendingSteeringBubble({\n content,\n renderMessageImages,\n t,\n}: {\n content: readonly unknown[];\n renderMessageImages: RenderMessageImages;\n t: ChatViewSlotProps[\"t\"];\n}): ReactNode {\n return (\n <UserStyleBubble\n content={content}\n renderMessageImages={renderMessageImages}\n pending\n t={t}\n actions={(text) => (\n <MessageIconActions text={text} clock=\"start\" className={css.actions} t={t} />\n )}\n />\n );\n}\n\n/** User and admitted-steering keyed Chat renderer. */\nexport const UserMessageNodeView = memo(function UserMessageNodeView({\n node,\n renderMessageImages,\n t,\n edit,\n retry,\n}: ChatNodeViewProps<\"user\" | \"steering\"> & InjectFace<SessionEditorFace>) {\n const data = node.data;\n const [editing, setEditing] = useState<EditableMessageBlock | null>(null);\n const [confirmingRetry, setConfirmingRetry] = useState(false);\n const turnLocation =\n node.location.kind === \"turn\" || node.location.kind === \"step\" ? node.location.turn : undefined;\n const turn = turnLocation?.turn;\n // 重试只对已闭合轮次开放(未闭合/无闭合边界的轮次服务端无法重放)。\n const retryable = turnLocation?.status === \"closed\";\n // 编辑目标:第一个文本块(与 Timeline 编辑面的 blockIndex 对齐)。\n const textBlockIndex = data.content.findIndex(\n (block) => (block as { type?: string }).type === \"text\",\n );\n const textBlock =\n textBlockIndex === -1 ? undefined : (data.content[textBlockIndex] as { text?: string });\n const onEdit =\n textBlock === undefined || turn === undefined\n ? undefined\n : () => {\n setEditing({\n key: `${node.anchorSeq}:${String(textBlockIndex)}`,\n turn,\n eventSeq: node.anchorSeq,\n blockIndex: textBlockIndex,\n kind: \"user\",\n text: textBlock.text ?? \"\",\n time: data.time,\n });\n };\n // 重试先弹确认(就地编辑会抛弃该回合及其后的内容)。\n const onRetry =\n retryable && turn !== undefined\n ? () => {\n setConfirmingRetry(true);\n }\n : undefined;\n return (\n <>\n {editing !== null && (\n <MessageEditDialog\n block={editing}\n onSave={(text) => edit(editing, text, \"truncate\")}\n onClose={() => setEditing(null)}\n />\n )}\n {confirmingRetry && turn !== undefined && (\n <Modal\n open\n onClose={() => setConfirmingRetry(false)}\n title=\"重试回合\"\n closeLabel=\"关闭\"\n description={`将重新生成第 ${turn} 轮的回复,并抛弃该回合之后的内容。`}\n footer={\n <div className={css.confirmActions}>\n <Button variant=\"outline\" onClick={() => setConfirmingRetry(false)}>\n 取消\n </Button>\n <Button\n variant=\"primary\"\n onClick={() => {\n setConfirmingRetry(false);\n void retry(turn, \"truncate\");\n }}\n >\n 确认重试\n </Button>\n </div>\n }\n />\n )}\n <UserStyleBubble\n content={data.content}\n renderMessageImages={renderMessageImages}\n t={t}\n actions={(text) => (\n <MessageIconActions\n text={text}\n time={data.time}\n clock=\"start\"\n className={css.actions}\n t={t}\n onEdit={onEdit}\n onRetry={onRetry}\n />\n )}\n />\n </>\n );\n});\n\n/** Injected-context keyed Chat renderer. */\nexport const ContextMessageNodeView = memo(function ContextMessageNodeView({\n node,\n t,\n}: ChatNodeViewProps<\"context\">) {\n const data = node.data;\n return (\n <ContextInjectionRow\n content={data.content}\n source={data.source}\n provenance={data.provenance}\n form={data.form}\n t={t}\n />\n );\n});\n\n/** Automatic compaction keyed Chat renderer. */\nexport const CompactionNodeView = memo(function CompactionNodeView({\n node,\n t,\n}: ChatNodeViewProps<\"compaction\">) {\n return <CompactionItem node={node.data} t={t} />;\n});\n\n/** Correlated retry-chain keyed Chat renderer. */\nexport const RetryNodeView = memo(function RetryNodeView({\n node,\n t,\n}: ChatNodeViewProps<\"model-retry\">) {\n const data = node.data;\n return (\n <ModelRetryItem node={data.current} active={data.current.retryState === \"scheduled\"} t={t} />\n );\n});\n\n/** Terminal turn-error keyed Chat renderer. */\nexport const TurnErrorNodeView = memo(function TurnErrorNodeView({\n node,\n t,\n}: ChatNodeViewProps<\"turn-error\">) {\n return <TurnErrorItem node={node.data} t={t} />;\n});\n\n/** Max-tokens turn-end notice keyed Chat renderer. */\nexport const TurnMaxTokensNodeView = memo(function TurnMaxTokensNodeView({\n t,\n}: ChatNodeViewProps<\"turn-max-tokens\">) {\n return <TurnMaxTokensItem t={t} />;\n});\n\n/** Explicit unknown-surface keyed Chat renderer. */\nexport const UnknownNodeView = memo(function UnknownNodeView({\n node,\n t,\n}: ChatNodeViewProps<\"unknown\">) {\n const data = node.data;\n return (\n <div className={css.contextRow}>\n <JsonBlock\n label={t(\"message.unknownSurface\", { type: data.type })}\n payload={data.data}\n truncatedLabel={(total) => t(\"json.truncated\", { total })}\n />\n </div>\n );\n});\n","import type { AssistantBlock } from \"@deepseek-ai/dsh-client-runtime/client\";\n\n/**\n * Collect visible prose from one Assistant lifecycle.\n * @param blocks - Assistant content blocks.\n * @returns concatenated text blocks.\n */\nexport function assistantText(blocks: readonly AssistantBlock[]): string {\n return blocks.flatMap((block) => (block.kind === \"text\" ? [block.text] : [])).join(\"\");\n}\n","import { memo } from \"react\";\nimport type { InjectFace } from \"@deepseek-ai/dsh-client-ui-slots\";\nimport type { ChatNodeViewProps } from \"@deepseek-ai/dsh-client-ui-conversation/client\";\nimport { MessageIconActions } from \"./MessageIconActions.tsx\";\nimport { assistantText } from \"./turn-assistant.ts\";\nimport css from \"./TurnTailNodeView.module.css\";\nimport type { SessionEditorFace } from \"../controller.ts\";\n\ntype TurnTailNodeViewProps = ChatNodeViewProps<\"turn-tail\"> & InjectFace<SessionEditorFace>;\n\n/**\n * Turn-local actions over the Location index, independent of Assistant\n * placement.\n *\n * 注意:本 renderer 是 `conversation.chat.node` 的 shadow 注册(priority -1),\n * 而 `renderSlotChain` / `renderSlot` 只在注册声明了对应 children 时由 slot\n * 链传入——turnTail / assistant-actions 的 children 已被上游(ui-conversation)\n * 声明,shadow 注册再声明会抛「already declared」,因此这里不消费子 slot。\n *\n * 编辑 / 重试按钮只挂在 **user 消息**(UserMessageNodeView)上,助手尾部不\n * 提供(避免对未闭合/无 user 输入的轮次误触)。\n */\nexport const TurnTailNodeView = memo(function TurnTailNodeView({\n node,\n forkAt,\n t,\n useSession,\n}: TurnTailNodeViewProps) {\n const data = node.data;\n const hasLaterChatNode = useSession(\n (snapshot) => snapshot.chat.locations.getTurn(data.turn).at(-1) !== node.key,\n );\n const turn =\n node.location.kind === \"turn\" || node.location.kind === \"step\" ? node.location.turn : undefined;\n if (turn === undefined) return null;\n const closing = data.closing;\n const tail = null;\n if (closing === null) return tail === null ? null : <div className={css.root}>{tail}</div>;\n const runMs =\n turn.start === undefined || turn.end === undefined\n ? undefined\n : Math.max(0, turn.end.time - turn.start.time);\n return (\n <div className={css.root} data-turn-tail={data.turn} data-time-hover-root>\n <MessageIconActions\n text={assistantText(closing.blocks)}\n time={closing.time}\n runMs={runMs}\n ttftMs={data.ttftMs}\n tokensPerSecond={data.tokensPerSecond}\n clock=\"end\"\n onBranch={() => {\n forkAt(closing.finalNode.seq);\n }}\n branchUnavailable={data.branchUnavailable || hasLaterChatNode}\n className={css.actions}\n t={t}\n />\n </div>\n );\n});\n","/**\n * Register this package's chat-node renderers behind the keyed\n * `conversation.chat.node` seat. Every key is re-registered at `priority: -1`\n * so the lowest priority wins and the upstream renderers are shadowed without\n * touching `@deepseek-ai/*`. The per-session editor face is injected so the\n * copied renderers can drive edit / retry directly.\n */\n\nimport type { Context } from \"@deepseek-ai/cordis\";\nimport type { SessionId } from \"@deepseek-ai/dsh-client-runtime/client\";\nimport \"@deepseek-ai/dsh-client-ui-conversation/client\";\nimport { AssistantNodeView } from \"./AssistantNodeView.tsx\";\nimport { CommandNodeView, ManualCompactionNodeView } from \"./CommandNodeView.tsx\";\nimport {\n CompactionNodeView,\n ContextMessageNodeView,\n RetryNodeView,\n TurnErrorNodeView,\n TurnMaxTokensNodeView,\n UnknownNodeView,\n UserMessageNodeView,\n} from \"./MessageItem.tsx\";\nimport { TurnTailNodeView } from \"./TurnTailNodeView.tsx\";\nimport type { SessionEditorController } from \"../controller.ts\";\n\n/** `conversation` 字典命名空间(与上游一致)。 */\nconst NS = \"conversation\";\n\n/** 注册全部 chat-node key;priority -1 替换上游渲染。 */\nexport function registerChatNodeRenderers(\n ctx: Context,\n controllerFor: (sessionId: SessionId) => SessionEditorController,\n): void {\n const inject = (sessionId: SessionId) => controllerFor(sessionId).face;\n\n ctx.slots.register(\n { name: \"conversation.chat.node\", key: \"user\", locale: NS, priority: -1, inject },\n UserMessageNodeView,\n );\n ctx.slots.register(\n { name: \"conversation.chat.node\", key: \"steering\", locale: NS, priority: -1, inject },\n UserMessageNodeView,\n );\n ctx.slots.register(\n { name: \"conversation.chat.node\", key: \"context\", locale: NS, priority: -1, inject },\n ContextMessageNodeView,\n );\n ctx.slots.register(\n { name: \"conversation.chat.node\", key: \"assistant-step\", locale: NS, priority: -1, inject },\n AssistantNodeView,\n );\n ctx.slots.register(\n // command / turn-tail 的 children 由上游声明(commandview / turnTail /\n // assistant-actions);shadow 注册不重复声明,仅替换渲染器。\n { name: \"conversation.chat.node\", key: \"command\", locale: NS, priority: -1, inject } as never,\n CommandNodeView as never,\n );\n ctx.slots.register(\n { name: \"conversation.chat.node\", key: \"manual-compaction\", locale: NS, priority: -1, inject },\n ManualCompactionNodeView,\n );\n ctx.slots.register(\n { name: \"conversation.chat.node\", key: \"compaction\", locale: NS, priority: -1, inject },\n CompactionNodeView,\n );\n ctx.slots.register(\n { name: \"conversation.chat.node\", key: \"model-retry\", locale: NS, priority: -1, inject },\n RetryNodeView,\n );\n ctx.slots.register(\n { name: \"conversation.chat.node\", key: \"turn-error\", locale: NS, priority: -1, inject },\n TurnErrorNodeView,\n );\n ctx.slots.register(\n { name: \"conversation.chat.node\", key: \"turn-max-tokens\", locale: NS, priority: -1, inject },\n TurnMaxTokensNodeView,\n );\n ctx.slots.register(\n // 见 command:turnTail / assistant-actions 的 children 由上游声明。\n { name: \"conversation.chat.node\", key: \"turn-tail\", locale: NS, priority: -1, inject } as never,\n TurnTailNodeView as never,\n );\n ctx.slots.register(\n { name: \"conversation.chat.node\", key: \"unknown\", locale: NS, priority: -1, inject },\n UnknownNodeView,\n );\n}\n","/**\n * 会话头部「清洗会话」入口。\n *\n * 仅当会话历史加载失败(会话 snapshot 的 `openState === \"error\"`)时渲染:\n * 点击调用服务端 cleanse,把该会话的 sourceEventSeqs / surfaceOp /\n * shadowedRange 坐标一次性重写为稠密空间,成功后客户端 resync 重新加载\n * 历史。注入面来自 `SessionEditorFace`(hooks → `useSessionEditor`,\n * 方法 → `cleanse`)。\n */\n\nimport { useCallback, useState } from \"react\";\nimport { Button, IconRefreshOutline16 } from \"@deepseek-ai/dsh-client-ui-primitives\";\nimport type { SessionEditorState } from \"./controller.ts\";\n\nexport interface CleanseSessionActionProps {\n /** inject hooks:订阅 sessionEditor 状态。 */\n useSessionEditor: <S>(sel: (s: SessionEditorState) => S) => S;\n /** inject face:发起清洗。 */\n cleanse: () => Promise<boolean>;\n}\n\n/**\n * 历史加载失败时显示「清洗会话」按钮。\n * @param props - 注入的 selector 钩子与清洗方法。\n * @returns 按钮元素;会话未处于错误状态时返回 null。\n */\nexport function CleanseSessionAction({\n useSessionEditor,\n cleanse,\n}: CleanseSessionActionProps): JSX.Element | null {\n const openError = useSessionEditor((s) => s.sessionOpenError);\n const cleansing = useSessionEditor((s) => s.pending === \"cleanse\");\n const [busy, setBusy] = useState(false);\n const onClick = useCallback(() => {\n setBusy(true);\n void cleanse().finally(() => setBusy(false));\n }, [cleanse]);\n if (!openError) return null;\n const working = busy || cleansing;\n return (\n <Button\n variant=\"outline\"\n size=\"sm\"\n icon={<IconRefreshOutline16 />}\n onClick={onClick}\n disabled={working}\n title=\"清洗会话:把 provenance 坐标重写为稠密空间,修复历史加载失败\"\n >\n {working ? \"清洗中…\" : \"清洗会话\"}\n </Button>\n );\n}\n","/**\n * Session Editor browser half: the chat-node renderers that replace the\n * upstream `conversation.chat.node` registrations (priority shadow) so the\n * edit / retry entry points render directly in the message actions row.\n */\n\nimport type { ClientContext, SessionId } from \"@deepseek-ai/dsh-client-runtime/client\";\nimport type {} from \"@deepseek-ai/dsh-client-ui-conversation/client\";\nimport { SessionEditorController } from \"./controller.ts\";\nimport { registerChatNodeRenderers } from \"./chat-node/register.ts\";\nimport { CleanseSessionAction } from \"./cleanse-session-action.tsx\";\n\nexport const inject = [\"slots\", \"conversation\", \"connection\", \"sessions\"];\n\n/** 注册 UI 贡献 + chat-node renderer,共享同一 per-session controller。 */\nexport function apply(ctx: ClientContext): void {\n const controllers = new Map<SessionId, SessionEditorController>();\n const controllerFor = (sessionId: SessionId): SessionEditorController => {\n let controller = controllers.get(sessionId);\n if (controller === undefined) {\n controller = new SessionEditorController(ctx, sessionId);\n controllers.set(sessionId, controller);\n }\n return controller;\n };\n\n ctx.on(\"connection/reset\", () => {\n for (const controller of controllers.values()) void controller.load();\n });\n\n // 替换整个 conversation.chat.node:priority -1 最低渲染,shadow 上游注册。\n registerChatNodeRenderers(ctx, controllerFor);\n\n // 会话头部「清洗会话」入口:仅历史加载失败(openState === \"error\")时\n // 显示。header.actions 是 list 槽(注册需 id),上游未注册组件——这里是\n // 纯新增,无 shadow 冲突;priority -1 与其它注入面一致。\n ctx.slots.register(\n {\n name: \"conversation.session.header.actions\",\n id: \"session-editor.cleanse\",\n priority: -1,\n inject: (sessionId: SessionId) => controllerFor(sessionId).face,\n } as never,\n CleanseSessionAction as never,\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"client.js","names":["createSnapshotStore","useRef","useCallback","useState","useRef","css","a11yCss","DisclosureRow","IconThinkOutline14","memo","useMemo","MarkdownText","Fragment","JsonBlock","css","memo","useMemo","memo","useState","css","IconApiOutline14","IconChevronDownOutline14","IconChevronRightOutline14","MarkdownText","StateDot","IconApiOutline14","useState","css","a11yCss","DisclosureRow","memo","useMemo","css","css","JsonBlock","unreachable","useState","DisclosureRow","css","IconBrowseOutline16","useState","useId","useState","useRef","useCallback","writeClipboard","css","Tooltip","IconCheckOutline16","IconCopyOutline16","IconEditOutline16","IconRefreshOutline16","IconBranchOutline16","useState","useRef","Modal","css","Button","useMemo","useState","css","StateDot","MessageText","JsonBlock","memo","Modal","Button","memo","css","useState","useCallback","Button","IconRefreshOutline16"],"sources":["../src/shared.ts","../src/client/controller.ts","../src/client/chat-node/use-throttled-visual-update.ts","../src/client/chat-node/ReasoningRow.tsx","../src/client/chat-node/AssistantMarkdown.tsx","../src/client/chat-node/AssistantNodeView.tsx","../src/client/chat-node/CompactionItem.tsx","../src/client/chat-node/GenericCommandCard.tsx","../src/client/chat-node/CompactionCommandCard.tsx","../src/client/chat-node/CommandNodeView.tsx","../src/client/chat-node/ContextBody.tsx","../src/client/chat-node/ContextInjectionRow.tsx","../src/client/chat-node/message-chrome.ts","../src/client/chat-node/use-calendar-day.ts","../src/client/chat-node/MessageIconActions.tsx","../src/client/chat-node/MessageEditDialog.tsx","../src/client/chat-node/MessageItem.tsx","../src/client/chat-node/turn-assistant.ts","../src/client/chat-node/TurnTailNodeView.tsx","../src/client/chat-node/register.ts","../src/client/cleanse-session-action.tsx","../src/client/index.ts"],"sourcesContent":["/**\n * Host 与 client 共享的类型与常量:HTTP 路由、操作判别联合、Timeline 响应。\n *\n * @module @morlay/ui-conversation-message-actions/shared\n */\n\nimport type { SessionId } from \"@deepseek-ai/dsh-session\";\nimport type { BranchTimeline, CascadePolicy } from \"@morlay/session-branch\";\nimport type { VersionOperation } from \"@morlay/session-branch\";\n\n/** 同源 HTTP 端点(host 注册、client fetch)。 */\nexport const SESSION_EDITOR_PATH = \"/session-editor\";\n\nexport type { VersionOperation } from \"@morlay/session-branch\";\n\n/** 编辑一个已落定文本块并从其轮次边界分支。 */\nexport interface EditOperation {\n action: \"edit\";\n sessionId: SessionId;\n eventSeq: number;\n blockIndex: number;\n text: string;\n cascade: CascadePolicy;\n}\n\n/** 重生成最后一条已落定助手回复。 */\nexport interface RerollOperation {\n action: \"reroll\";\n sessionId: SessionId;\n}\n\n/** 重试任意历史回合。 */\nexport interface RetryOperation {\n action: \"retry\";\n sessionId: SessionId;\n turn: number;\n cascade: CascadePolicy;\n}\n\n/** 截断式回退:原会话回退到闭合边界。 */\nexport interface RewindOperation {\n action: \"rewind\";\n sessionId: SessionId;\n toBoundary: number;\n}\n\n/** 派生式分支:从闭合边界派生新会话。 */\nexport interface ForkOperation {\n action: \"fork\";\n sessionId: SessionId;\n atSeq?: number;\n childSessionId?: SessionId;\n}\n\n/** 清洗一个会话的 surface/provenance 坐标为稠密空间(修复历史加载失败)。 */\nexport interface CleanseOperation {\n action: \"cleanse\";\n sessionId: SessionId;\n}\n\n/** HTTP 接受的判别联合。 */\nexport type SessionEditorOperation =\n | EditOperation\n | RerollOperation\n | RetryOperation\n | RewindOperation\n | ForkOperation\n | CleanseOperation;\n\n/** 操作响应(分支式返回新版本 id;rewind 返回原 id)。 */\nexport interface SessionEditorOperationResult {\n sessionId: SessionId;\n queuedTurns: number;\n /** 操作后会话是否仍有 live owner(客户端据此决定是否重载页面)。 */\n live?: boolean;\n /** cleanse 操作实际重写的事件数。 */\n changed?: number;\n}\n\n/** 可编辑文本块(编辑面枚举)。 */\nexport interface EditableMessageBlock {\n key: string;\n turn: number;\n eventSeq: number;\n blockIndex: number;\n kind: \"user\" | \"assistant.reasoning\" | \"assistant.response\";\n text: string;\n time: number;\n}\n\n/** 可重试回合(重试面枚举)。 */\nexport interface RetryableTurn {\n turn: number;\n userEventSeq: number;\n preview: string;\n time: number;\n}\n\n/** 版本摘要(Timeline 节点投影,值级)。 */\nexport interface VersionSummary {\n sessionId: string;\n parentSessionId?: string;\n effectId?: string;\n inverseSessionId?: string;\n createdAt: number;\n depth: number;\n current: boolean;\n onCurrentEffectPath: boolean;\n operation?: VersionOperation;\n cascade?: CascadePolicy;\n targetTurn?: number;\n blockKind?: EditableMessageBlock[\"kind\"];\n before?: string;\n after?: string;\n}\n\n/** GET /session-editor 的完整投影(Timeline + 编辑/重试面)。 */\nexport interface SessionEditorTimeline {\n sessionId: string;\n messages: EditableMessageBlock[];\n retryableTurns: RetryableTurn[];\n versions: VersionSummary[];\n /** 原子逆链(从当前版本向外,应用顺序)。 */\n undoStack: string[];\n /** 可直接重施加的子版本。 */\n redoSessionIds: string[];\n}\n\n/** 把 {@link BranchTimeline} 投影成 client 用的 {@link SessionEditorTimeline}。 */\nexport function toTimelinePayload(\n sessionId: SessionId,\n timeline: BranchTimeline,\n messages: EditableMessageBlock[],\n retryableTurns: RetryableTurn[],\n): SessionEditorTimeline {\n const currentPath = new Set<string>();\n for (const node of timeline.nodes) currentPath.add(String(node.sessionId));\n const versions: VersionSummary[] = timeline.nodes.map((node) => ({\n sessionId: String(node.sessionId),\n ...(node.parentSessionId === undefined\n ? {}\n : { parentSessionId: String(node.parentSessionId) }),\n ...(node.effect === undefined\n ? {}\n : {\n effectId: node.effect.id,\n inverseSessionId: String(node.inverseSessionId),\n operation: node.effect.operation,\n cascade: node.effect.cascade,\n targetTurn: node.effect.targetTurn,\n ...(node.effect.blockKind === undefined ? {} : { blockKind: node.effect.blockKind }),\n ...(node.effect.before === undefined ? {} : { before: node.effect.before }),\n ...(node.effect.after === undefined ? {} : { after: node.effect.after }),\n }),\n createdAt: node.createdAt,\n depth: depthOf(timeline, node.sessionId),\n current: String(node.sessionId) === String(sessionId),\n onCurrentEffectPath: currentPath.has(String(node.sessionId)),\n }));\n const versionsById = new Map(versions.map((version) => [version.sessionId, version]));\n const undoStack: string[] = [];\n let cursor = versionsById.get(String(sessionId));\n while (cursor?.inverseSessionId !== undefined) {\n if (undoStack.includes(cursor.inverseSessionId)) break;\n undoStack.push(cursor.inverseSessionId);\n cursor = versionsById.get(cursor.inverseSessionId);\n }\n const redoSessionIds = versions\n .filter((version) => version.inverseSessionId === String(sessionId))\n .map((version) => version.sessionId);\n return {\n sessionId: String(sessionId),\n messages,\n retryableTurns,\n versions,\n undoStack,\n redoSessionIds,\n };\n}\n\n/** 计算节点到根的深度。 */\nfunction depthOf(\n timeline: BranchTimeline,\n sessionId: import(\"@deepseek-ai/dsh-session\").SessionId,\n): number {\n const byId = new Map(timeline.nodes.map((node) => [String(node.sessionId), node]));\n let depth = 0;\n let cursor = byId.get(String(sessionId));\n const seen = new Set<string>();\n while (cursor?.parentSessionId !== undefined && !seen.has(String(cursor.sessionId))) {\n seen.add(String(cursor.sessionId));\n depth += 1;\n cursor = byId.get(String(cursor.parentSessionId));\n }\n return depth;\n}\n","/**\n * Browser controller for one session's Timeline projection and branch mutations.\n * 精简版:HTTP 拉取 timeline + 执行操作 + 会话导航(openWhenListed)。\n */\n\nimport type {\n ClientContext,\n ConversationSnapshot,\n ISessions,\n ObservableSnapshot,\n SessionFace,\n SessionId,\n SnapshotStore,\n} from \"@deepseek-ai/dsh-client-runtime/client\";\nimport { createSnapshotStore } from \"@deepseek-ai/dsh-client-runtime/client\";\nimport {\n SESSION_EDITOR_PATH,\n type EditableMessageBlock,\n type SessionEditorOperation,\n type SessionEditorOperationResult,\n type SessionEditorTimeline,\n type VersionOperation,\n} from \"../shared.ts\";\n\nexport interface SessionEditorState {\n status: \"idle\" | \"loading\" | \"ready\" | \"error\";\n error: string | null;\n pending: VersionOperation | \"cleanse\" | null;\n timeline: SessionEditorTimeline | null;\n /** 会话历史加载失败(openState === \"error\")——据此显示「清洗会话」入口。 */\n sessionOpenError: boolean;\n}\n\n/** 业务 face;渲染层绑定到保留的 source compartment。 */\nexport interface SessionEditorFace {\n hooks: { sessionEditor: ObservableSnapshot<SessionEditorState> };\n acquire(): () => void;\n load(): void;\n edit(\n message: EditableMessageBlock,\n text: string,\n cascade: \"truncate\" | \"preserve\",\n ): Promise<boolean>;\n retry(turn: number, cascade: \"truncate\" | \"preserve\"): Promise<boolean>;\n reroll(): Promise<boolean>;\n rewind(toBoundary: number): Promise<boolean>;\n /** 清洗当前会话的 provenance 坐标为稠密空间(修复历史加载失败)。 */\n cleanse(): Promise<boolean>;\n openVersion(sessionId: string): Promise<void>;\n}\n\nfunction messageOf(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nfunction conversationRevision(snapshot: ConversationSnapshot): string {\n const turnEnds = [...snapshot.turnEnds.entries()]\n .map(([turn, seq]) => `${String(turn)}:${String(seq)}`)\n .join(\",\");\n return [snapshot.openState, snapshot.removed, snapshot.hasMore, turnEnds].join(\"|\");\n}\n\n/** 一个会话共享一个稳定 controller(header + timeline 两个入口复用)。 */\nexport class SessionEditorController {\n readonly store: SnapshotStore<SessionEditorState> = createSnapshotStore<SessionEditorState>({\n status: \"idle\",\n error: null,\n pending: null,\n timeline: null,\n sessionOpenError: false,\n });\n\n readonly face: SessionEditorFace;\n private readonly ctx: ClientContext;\n private readonly sessions: ISessions;\n private sessionSource: SessionFace | undefined;\n private sessionSourceDispose: (() => void) | undefined;\n private sessionRevision: string | undefined;\n private disposed = false;\n private users = 0;\n private readonly navigationWaits = new Set<() => void>();\n\n constructor(\n ctx: ClientContext,\n private readonly sessionId: SessionId,\n ) {\n this.ctx = ctx;\n this.sessions = ctx.get(\"sessions\") as unknown as ISessions;\n this.face = {\n hooks: { sessionEditor: this.store },\n acquire: () => {\n this.users += 1;\n if (this.users === 1 && this.disposed) this.revive();\n return () => this.release();\n },\n load: () => {\n void this.load();\n },\n edit: (message, text, cascade) =>\n this.mutate({\n action: \"edit\",\n sessionId: this.sessionId,\n eventSeq: message.eventSeq,\n blockIndex: message.blockIndex,\n text,\n cascade,\n }),\n retry: (turn, cascade) =>\n this.mutate({ action: \"retry\", sessionId: this.sessionId, turn, cascade }),\n reroll: () => this.mutate({ action: \"reroll\", sessionId: this.sessionId }),\n rewind: (toBoundary) =>\n this.mutate({ action: \"rewind\", sessionId: this.sessionId, toBoundary }),\n cleanse: () => this.mutate({ action: \"cleanse\", sessionId: this.sessionId }),\n openVersion: (sessionId) => this.openWhenListed(sessionId as SessionId),\n };\n this.observe();\n }\n\n private observe(): void {\n this.sessionSource = undefined;\n this.sessionSourceDispose?.();\n this.bindSessionSource();\n this.sessions.list.subscribe(() => this.invalidate());\n }\n\n private bindSessionSource(): void {\n const source = this.sessions.binding(this.sessionId)?.session;\n if (source === this.sessionSource) return;\n this.sessionSourceDispose?.();\n this.sessionSource = source;\n this.sessionRevision =\n source === undefined ? undefined : conversationRevision(source.getSnapshot());\n // 历史加载失败标记:会话 snapshot 的 openState === \"error\" 时显示清洗入口。\n this.store.update((state) => {\n state.sessionOpenError = source?.getSnapshot().openState === \"error\";\n });\n this.sessionSourceDispose = source?.subscribe(() => {\n this.store.update((state) => {\n state.sessionOpenError = source.getSnapshot().openState === \"error\";\n });\n this.invalidate();\n });\n }\n\n private invalidate(): void {\n if (this.disposed || this.store.getSnapshot().status === \"idle\") return;\n // 会话状态变化 → 刷新投影(debounce 由调用方按需)。\n void this.load();\n }\n\n private release(): void {\n this.users -= 1;\n if (this.users <= 0) this.dispose();\n }\n\n private dispose(): void {\n if (this.disposed) return;\n this.disposed = true;\n this.sessionSourceDispose?.();\n this.sessionSourceDispose = undefined;\n this.sessionSource = undefined;\n this.sessionRevision = undefined;\n }\n\n private revive(): void {\n this.disposed = false;\n this.observe();\n void this.load();\n }\n\n async load(): Promise<void> {\n if (this.disposed) return;\n this.store.update((state) => {\n state.status = \"loading\";\n state.error = null;\n });\n try {\n const response = await fetch(\n `${SESSION_EDITOR_PATH}?sessionId=${encodeURIComponent(this.sessionId)}`,\n {\n method: \"GET\",\n headers: { accept: \"application/json\" },\n cache: \"no-store\",\n },\n );\n const value = (await response.json()) as unknown;\n if (this.disposed) return;\n if (response.ok) {\n this.store.update((state) => {\n state.status = \"ready\";\n state.error = null;\n state.timeline = value as SessionEditorTimeline;\n });\n } else {\n const error = (value as { error?: unknown })[\"error\"];\n this.store.update((state) => {\n state.status = \"error\";\n state.error =\n typeof error === \"string\" ? error : `请求失败:HTTP ${String(response.status)}`;\n });\n }\n } catch (error) {\n if (this.disposed) return;\n this.store.update((state) => {\n state.status = \"error\";\n state.error = messageOf(error);\n });\n }\n }\n\n private async mutate(operation: SessionEditorOperation): Promise<boolean> {\n // 只拦截并发操作;不要求 status === \"ready\"——编辑/重试的数据(eventSeq/\n // blockIndex/turn)来自客户端 conversation 节点,与 timeline 加载无关,\n // status 停留在 idle(无 HeaderActions 触发 load)时也必须能发起请求。\n const current = this.store.getSnapshot();\n if (current.pending !== null) return false;\n this.store.update((state) => {\n state.pending = operation.action;\n state.error = null;\n });\n try {\n const response = await fetch(SESSION_EDITOR_PATH, {\n method: \"POST\",\n headers: { accept: \"application/json\", \"content-type\": \"application/json\" },\n body: JSON.stringify(operation),\n });\n const value = (await response.json()) as unknown;\n if (this.disposed) return true;\n if (!response.ok) {\n const error = (value as { error?: unknown })[\"error\"];\n throw new Error(\n typeof error === \"string\" ? error : `请求失败:HTTP ${String(response.status)}`,\n );\n }\n this.store.update((state) => {\n state.pending = null;\n });\n const result = value as SessionEditorOperationResult;\n // edit / retry / reroll 就地编辑(不改变 session id),仅 fork 产生新 id\n // 时才需要等列表发布并打开新版本。\n if (String(result.sessionId) !== String(this.sessionId)) {\n await this.openWhenListed(result.sessionId as SessionId);\n return true;\n }\n // 就地编辑:rewind 会**删除**事件,客户端 conversation 事件流(append-only\n // 发布)无法表达删除——seq 回退只做增量,被剪掉的旧节点会残留。\n // 优先\"会话级刷新\"(resync:重置窗口并重新拉取历史,不整页重载);\n // resync 不可用时回退整页重载。\n const face = this.sessions.binding(this.sessionId)?.session;\n const resync = (face as unknown as { resync?: () => Promise<void> }).resync;\n if (resync !== undefined) {\n try {\n await resync.call(face);\n void this.load();\n return true;\n } catch {\n // fall through to full reload\n }\n }\n location.reload();\n return true;\n } catch (error) {\n if (this.disposed) return false;\n this.store.update((state) => {\n state.pending = null;\n state.error = messageOf(error);\n });\n return false;\n }\n }\n\n /** 会话列表发布是导航的反应式依赖:等新版本出现在列表后再打开。 */\n private openWhenListed(sessionId: SessionId): Promise<void> {\n if (this.sessions.list.getSnapshot().byId[sessionId] !== undefined) {\n this.sessions.open(sessionId);\n return Promise.resolve();\n }\n return new Promise((resolve) => {\n let settled = false;\n let dispose = (): void => {};\n const finish = (open: boolean): void => {\n if (settled) return;\n settled = true;\n dispose();\n this.navigationWaits.delete(cancel);\n if (open) this.sessions.open(sessionId);\n resolve();\n };\n const cancel = (): void => {\n finish(false);\n };\n this.navigationWaits.add(cancel);\n dispose = this.sessions.list.subscribe(() => {\n if (this.sessions.list.getSnapshot().byId[sessionId] === undefined) return;\n finish(true);\n });\n if (this.sessions.list.getSnapshot().byId[sessionId] !== undefined) finish(true);\n });\n }\n}\n","/** Frame-throttled scheduling for non-essential visual alignment. */\nimport { useCallback, useLayoutEffect, useRef } from \"react\";\n\nconst DEFAULT_INTERVAL_FRAMES = 3;\n\n/**\n * Return a stable scheduler that coalesces visual updates over a frame interval.\n * @param update - DOM alignment to run after the throttle interval.\n * @param intervalFrames - frames to wait before applying the latest alignment.\n * @returns a stable function that schedules the latest update.\n */\nexport function useThrottledVisualUpdate(\n update: () => void,\n intervalFrames = DEFAULT_INTERVAL_FRAMES,\n): () => void {\n const updateRef = useRef(update);\n updateRef.current = update;\n const pendingFrameRef = useRef<number | null>(null);\n\n useLayoutEffect(\n () => () => {\n if (pendingFrameRef.current === null) return;\n cancelAnimationFrame(pendingFrameRef.current);\n pendingFrameRef.current = null;\n },\n [],\n );\n\n return useCallback(() => {\n if (pendingFrameRef.current !== null) return;\n let remainingFrames = intervalFrames;\n const advance = (): void => {\n remainingFrames -= 1;\n if (remainingFrames > 0) {\n pendingFrameRef.current = requestAnimationFrame(advance);\n return;\n }\n pendingFrameRef.current = null;\n updateRef.current();\n };\n pendingFrameRef.current = requestAnimationFrame(advance);\n }, [intervalFrames]);\n}\n","/** Assistant reasoning disclosure, independent of Tool-call presentation. */\nimport { useEffect, useRef, useState } from \"react\";\nimport { DisclosureRow, IconThinkOutline14 } from \"@deepseek-ai/dsh-client-ui-primitives\";\nimport type { ChatViewSlotProps } from \"@deepseek-ai/dsh-client-ui-conversation/client\";\nimport { useThrottledVisualUpdate } from \"./use-throttled-visual-update.ts\";\nimport a11yCss from \"./accessibility.module.css\";\nimport css from \"./ReasoningRow.module.css\";\n\nfunction firstLine(text: string): string {\n const newline = text.indexOf(\"\\n\");\n return newline === -1 ? text : text.slice(0, newline);\n}\n\nfunction latestLine(text: string): string {\n const visible = text.trimEnd();\n const newline = visible.lastIndexOf(\"\\n\");\n return newline === -1 ? visible : visible.slice(newline + 1);\n}\n\n/**\n * Render one assistant reasoning block as the Think disclosure row.\n * @param props.text - complete or streaming reasoning text.\n * @param props.running - whether this block is the streaming tail.\n * @param props.t - conversation locale seat for the running status.\n * @returns the reasoning disclosure.\n */\nexport function ReasoningRow({\n text,\n running,\n t,\n}: {\n text: string;\n running: boolean;\n t: ChatViewSlotProps[\"t\"];\n}) {\n const [expanded, setExpanded] = useState(false);\n const summaryRef = useRef<HTMLSpanElement>(null);\n const summary = running ? latestLine(text) : firstLine(text);\n const scheduleSummaryScroll = useThrottledVisualUpdate(() => {\n const element = summaryRef.current;\n if (element === null) return;\n element.scrollLeft = running ? element.scrollWidth - element.clientWidth : 0;\n });\n useEffect(() => {\n scheduleSummaryScroll();\n }, [running, scheduleSummaryScroll, summary]);\n\n return (\n <div className={css.root} data-variant=\"think\" data-state={running ? \"running\" : \"ok\"}>\n {running && <span className={a11yCss.visuallyHidden}>{t(\"row.running\")}</span>}\n <DisclosureRow\n rowClassName={css.row}\n leadingClassName={css.leading}\n titleClassName={css.title}\n chevronClassName={css.chevron}\n icon={<IconThinkOutline14 size={14} />}\n title=\"Think\"\n open={expanded}\n expandable\n expandOnRowClick\n onToggle={() => {\n setExpanded((value) => !value);\n }}\n collapsedContent={\n <>\n <span className={css.separator} aria-hidden />\n <span ref={summaryRef} className={css.summary} data-follow-end={running || undefined}>\n {summary}\n </span>\n </>\n }\n >\n <div className={css.thinkBody}>{text}</div>\n </DisclosureRow>\n </div>\n );\n}\n","// AssistantMarkdown: renders assistant blocks in order — markdown text body,\n// reasoning as the figma Think summary row (expand = indented gray text),\n// other-block JSON fallback. Tool-call heads are NOT rendered here: the chat\n// view groups them into tool rows through its keyed toolview slot (figma\n// step-summary flow). Shared by finalized nodes and the streaming partial;\n// the turn-level loading dots live in the chat view's tail, not here.\n// Finalized content (text) nodes append IconActions once their turn ends\n// (`time` is omitted for mid-turn narration and while the turn still runs);\n// their branch action is enabled only when the node is also the completed\n// turn's transcript tail. Think / tool-head-only nodes stay chrome-free.\n\nimport { Fragment, memo, useMemo } from \"react\";\nimport type { ReactNode } from \"react\";\nimport type { AssistantBlock } from \"@deepseek-ai/dsh-client-runtime/client\";\nimport { JsonBlock, MarkdownText } from \"@deepseek-ai/dsh-client-ui-primitives\";\nimport type { MarkdownFileMentions } from \"@deepseek-ai/dsh-client-ui-primitives\";\nimport type {\n ChatViewSlotProps,\n RenderMessageImages,\n} from \"@deepseek-ai/dsh-client-ui-conversation/client\";\nimport { ReasoningRow } from \"./ReasoningRow.tsx\";\nimport css from \"./AssistantMarkdown.module.css\";\n\nexport interface AssistantMarkdownProps {\n blocks: readonly AssistantBlock[];\n streaming: boolean;\n /** Frozen partial of an aborted turn: rendered with a stopped marker. */\n interrupted?: boolean | undefined;\n /** Render a consecutive image group through the attachment slot. */\n renderMessageImages: RenderMessageImages;\n /** Resolved prose file mentions for this Assistant's closing turn. */\n mentions?: MarkdownFileMentions | undefined;\n /** The owning view's locale seat, passed down as a plain prop. */\n t: ChatViewSlotProps[\"t\"];\n}\n\n/** Reasoning block as the Think variant summary row (figma 39:28304). */\nexport const AssistantMarkdown = memo(function AssistantMarkdown({\n blocks,\n streaming,\n interrupted,\n renderMessageImages,\n mentions,\n t,\n}: AssistantMarkdownProps) {\n // Stable per locale revision (t identity changes on switch): a fresh object\n // per render would rebuild MarkdownText's component table every chunk.\n const codeLabels = useMemo(\n () => ({ copyLabel: t(\"copy\" as never), copiedLabel: t(\"copied\" as never) }),\n [t],\n );\n const last = blocks.length - 1;\n // Tool-call heads render as tool rows in the chat view's grouping pass, so\n // a node that is only those heads (or empty) would paint an empty root\n // between tool groups — skip the shell unless something visible remains.\n const hasVisible =\n streaming || interrupted === true || blocks.some((block) => block.kind !== \"tool-call\");\n if (!hasVisible) return null;\n const rendered: ReactNode[] = [];\n for (let i = 0; i < blocks.length; i++) {\n const block = blocks[i];\n if (block === undefined) continue;\n switch (block.kind) {\n case \"text\":\n rendered.push(\n <MarkdownText\n key={i}\n text={block.text}\n streaming={streaming}\n codeLabels={codeLabels}\n fileMentions={mentions}\n />,\n );\n break;\n case \"reasoning\":\n rendered.push(\n <ReasoningRow key={i} text={block.text} running={streaming && i === last} t={t} />,\n );\n break;\n case \"image\": {\n // Consecutive image blocks share one gallery so several images tile\n // into rows instead of each opening a one-image group of its own.\n // Keyed by the group's FIRST block index: a streaming append that\n // extends the group then only grows `images` instead of remounting\n // the gallery under a shifted key.\n const start = i;\n const group = [block];\n while (i + 1 < blocks.length) {\n const next = blocks[i + 1];\n if (next === undefined || next.kind !== \"image\") break;\n group.push(next);\n i += 1;\n }\n rendered.push(\n <Fragment key={start}>\n {renderMessageImages({\n images: group.map(({ attachment }) => ({ attachment })),\n align: \"start\",\n })}\n </Fragment>,\n );\n break;\n }\n // Grouped into tool rows by ChatView; hasVisible above skips an empty shell.\n case \"tool-call\":\n break;\n default:\n rendered.push(\n <JsonBlock\n key={i}\n label={t(\"message.unknownBlock\")}\n payload={block.block}\n truncatedLabel={(total) => t(\"json.truncated\", { total })}\n />,\n );\n }\n }\n return (\n <div className={css.root} data-streaming={streaming || undefined}>\n <div className={css.body}>\n {rendered}\n {interrupted && <span className={css.stopped}>{t(\"message.stopped\")}</span>}\n </div>\n </div>\n );\n});\n","import { memo, useMemo } from \"react\";\nimport type {\n ChatNodeViewProps,\n TurnTailOwnerProps,\n} from \"@deepseek-ai/dsh-client-ui-conversation/client\";\nimport { AssistantMarkdown } from \"./AssistantMarkdown.tsx\";\n\n/** Streaming, settled, and interrupted Assistant states share one keyed renderer instance. */\nexport const AssistantNodeView = memo(function AssistantNodeView({\n node,\n useTurnData,\n openFile,\n renderMessageImages,\n fileMentions,\n t,\n}: ChatNodeViewProps<\"assistant-step\">) {\n const data = node.data;\n const turn =\n node.location.kind === \"turn\" || node.location.kind === \"step\" ? node.location.turn : undefined;\n const tail = useTurnData(\"turn-tail\");\n const owner = useMemo<TurnTailOwnerProps | undefined>(() => {\n if (turn?.status !== \"closed\" || data.finalNode === undefined) return undefined;\n if (tail?.closing?.finalNode.seq !== data.finalNode.seq) return undefined;\n return { turn, seq: data.finalNode.seq, openFile };\n }, [data.finalNode, openFile, tail, turn]);\n const mentions = useMemo(\n () => (owner === undefined ? undefined : fileMentions(owner)),\n [fileMentions, owner],\n );\n return (\n <AssistantMarkdown\n blocks={data.blocks}\n streaming={data.status === \"running\"}\n interrupted={data.status === \"interrupted\"}\n renderMessageImages={renderMessageImages}\n mentions={mentions}\n t={t}\n />\n );\n});\n","// CompactionItem: the one row a landed compaction contributes to the flow.\n// The conversation it shadowed on the model surface stays above it, so this\n// marker reports where the model stopped seeing that history — it never\n// replaces it. The framed checkpoint payload is written for the model and is\n// not rendered; the disclosure shows the summary from the checkpoint's own\n// cited `compaction/summary` event, and a window cut that left that event outside makes the row\n// non-expandable rather than empty.\n\nimport { memo, useState } from \"react\";\nimport type { CompactionSummaryNode } from \"@deepseek-ai/dsh-client-runtime/client\";\nimport {\n IconApiOutline14,\n IconChevronDownOutline14,\n IconChevronRightOutline14,\n MarkdownText,\n} from \"@deepseek-ai/dsh-client-ui-primitives\";\nimport type { ChatViewSlotProps } from \"@deepseek-ai/dsh-client-ui-conversation/client\";\nimport css from \"./MessageItem.module.css\";\n\ninterface CompactionItemProps {\n node: CompactionSummaryNode;\n /** Optional command title for a manual compaction folded into this marker. */\n title?: string;\n /** Command settlement text used when structured compaction counts are unavailable. */\n fallbackSummary?: string | null;\n /** The owning view's locale seat. */\n t: ChatViewSlotProps[\"t\"];\n}\n\n/**\n * The collapsed-by-default compaction marker.\n * @param props - the marker node off the snapshot cache.\n * @returns the marker row, with the summary disclosure when one is available.\n */\nexport const CompactionItem = memo(function CompactionItem({\n node,\n title,\n fallbackSummary,\n t,\n}: CompactionItemProps) {\n const [expanded, setExpanded] = useState(false);\n const expandable = node.summary !== null;\n const open = expandable && expanded;\n const summary =\n node.shadowedItemCount !== null && node.shadowedTokenCount !== null\n ? t(\"message.compaction.completed\", {\n items: node.shadowedItemCount,\n tokens: node.shadowedTokenCount,\n })\n : (fallbackSummary ??\n (expandable ? t(\"message.compaction.expand\") : t(\"message.compaction.unavailable\")));\n return (\n <div className={css.compactionRow}>\n <button\n type=\"button\"\n className={css.compactionButton}\n disabled={!expandable}\n aria-expanded={expandable ? open : undefined}\n onClick={() => {\n setExpanded((value) => !value);\n }}\n >\n <span className={css.compactionLeading} aria-hidden>\n <span className={css.compactionContextIcon} data-compaction-icon=\"context\">\n <IconApiOutline14 />\n </span>\n <span\n className={css.compactionDisclosureIcon}\n data-compaction-disclosure={open ? \"expanded\" : \"collapsed\"}\n >\n {open ? <IconChevronDownOutline14 /> : <IconChevronRightOutline14 />}\n </span>\n </span>\n <span className={css.compactionTitle}>{title ?? t(\"message.compaction\")}</span>\n <span className={css.compactionSep} aria-hidden />\n <span className={css.compactionSummary}>{summary}</span>\n </button>\n {open && node.summary !== null && (\n <div className={css.compactionBody}>\n <MarkdownText text={node.summary} />\n </div>\n )}\n </div>\n );\n});\n","// GenericCommandCard: the default command row — a stripped-down\n// GenericToolCard rendering the command name and its settlement text.\n// Supplied by the chat view as the keyed commandview slot's render-site\n// fallback (an unregistered command name lands here); registrants may compose\n// it as a base, feeding the same owner payload through.\n\nimport { useState, type ReactNode } from \"react\";\nimport type {\n ChatViewSlotProps,\n CommandRowOwnerProps,\n} from \"@deepseek-ai/dsh-client-ui-conversation/client\";\nimport { DisclosureRow, IconApiOutline14, StateDot } from \"@deepseek-ai/dsh-client-ui-primitives\";\nimport a11yCss from \"./accessibility.module.css\";\nimport css from \"./GenericCommandCard.module.css\";\n\ntype CommandRowState = \"running\" | \"ok\" | \"error\";\n\n/** Node state → row state semantic (running while unsettled; outcome kind after). */\nfunction stateOf(outcome: CommandRowOwnerProps[\"node\"][\"outcome\"]): CommandRowState {\n if (outcome === null) return \"running\";\n return outcome.kind === \"error\" ? \"error\" : \"ok\";\n}\n\nfunction leadingFor(state: CommandRowState): ReactNode {\n return state === \"error\" ? <StateDot state=\"error\" /> : <IconApiOutline14 size={14} />;\n}\n\n/** Card props: the owner payload plus the render site's locale seat (plain prop). */\nexport interface GenericCommandCardProps extends CommandRowOwnerProps {\n t: ChatViewSlotProps[\"t\"];\n /** Command-specific running copy; absent uses the generic command label. */\n runningSummary?: string | undefined;\n}\n\nexport function GenericCommandCard({ node, t, runningSummary }: GenericCommandCardProps) {\n const [expanded, setExpanded] = useState(false);\n const text = node.outcome?.text;\n const summary =\n node.outcome === null\n ? (runningSummary ?? t(\"command.running\"))\n : (text ?? (node.outcome.kind === \"error\" ? t(\"command.failed\") : t(\"command.done\")));\n // Title is the bare command name: the row already reads `name · outcome`,\n // and the dispatched line's own `/` and arguments only restate what the\n // settlement text says (`permission · preset workspace-write`). A\n // cross-window node whose run page fell out of the window has no name.\n const title = node.name ?? t(\"command.title\");\n const state = stateOf(node.outcome);\n const body = text !== undefined && text.includes(\"\\n\") ? text : null;\n const open = expanded && body !== null;\n return (\n <div className={css.root} data-variant=\"others\" data-state={state}>\n {state === \"running\" && <span className={a11yCss.visuallyHidden}>{t(\"row.running\")}</span>}\n {state === \"error\" && <span className={a11yCss.visuallyHidden}>{t(\"row.failed\")}</span>}\n <DisclosureRow\n rowClassName={css.row}\n leadingClassName={css.leading}\n titleClassName={css.title}\n chevronClassName={css.chevron}\n icon={leadingFor(state)}\n title={title}\n open={open}\n expandable={body !== null}\n expandOnRowClick\n keepContentWhenOpen\n onToggle={() => {\n setExpanded((value) => !value);\n }}\n collapsedContent={\n <>\n <span className={css.separator} aria-hidden />\n <span className={css.summary} data-error={state === \"error\" || undefined}>\n {summary}\n </span>\n </>\n }\n >\n <pre className={css.body} data-error={state === \"error\" || undefined}>\n {body}\n </pre>\n </DisclosureRow>\n </div>\n );\n}\n","// CompactionCommandCard: the `/compact` command's running row and its\n// successful checkpoint disclosure. Outcomes without a checkpoint keep the\n// generic command card so no-history, cancellation, and failures retain their\n// complete handler-authored text.\n\nimport type {\n ChatViewSlotProps,\n CommandRowOwnerProps,\n} from \"@deepseek-ai/dsh-client-ui-conversation/client\";\nimport { CompactionItem } from \"./CompactionItem.tsx\";\nimport { GenericCommandCard } from \"./GenericCommandCard.tsx\";\n\ninterface CompactionCommandCardProps extends CommandRowOwnerProps {\n t: ChatViewSlotProps[\"t\"];\n}\n\n/** Render one manual compaction lifecycle without duplicating its checkpoint marker. */\nexport function CompactionCommandCard({ node, compaction, t }: CompactionCommandCardProps) {\n if (compaction !== undefined) {\n return (\n <CompactionItem\n node={compaction}\n title=\"compact\"\n fallbackSummary={node.outcome?.text ?? null}\n t={t}\n />\n );\n }\n if (node.outcome !== null) return <GenericCommandCard node={node} t={t} />;\n return <GenericCommandCard node={node} t={t} runningSummary={t(\"message.compaction.running\")} />;\n}\n","import { memo, useMemo } from \"react\";\nimport type {\n ChatNodeViewProps,\n CommandRowOwnerProps,\n} from \"@deepseek-ai/dsh-client-ui-conversation/client\";\nimport { CompactionCommandCard } from \"./CompactionCommandCard.tsx\";\nimport { GenericCommandCard } from \"./GenericCommandCard.tsx\";\nimport css from \"./ChatView.module.css\";\n\ntype CommandNodeViewProps = ChatNodeViewProps<\"command\">;\n\n/**\n * Ordinary command lifecycle renderer. 注意:shadow 注册(priority -1)无法\n * 声明 `conversation.chat.commandview` children(已被上游声明,重复声明会抛\n * 「already declared」),因此这里不消费 `renderSlot` 子 slot,直接渲染通用\n * command 卡片。\n */\nexport const CommandNodeView = memo(function CommandNodeView({ node, t }: CommandNodeViewProps) {\n const command = node.data;\n const owner = useMemo<CommandRowOwnerProps>(() => ({ node: command }), [command]);\n return (\n <div className={css.callRow}>\n <GenericCommandCard {...owner} t={t} />\n </div>\n );\n});\n\n/** One integrated `/compact` command and compaction transaction renderer. */\nexport const ManualCompactionNodeView = memo(function ManualCompactionNodeView({\n node,\n t,\n}: ChatNodeViewProps<\"manual-compaction\">) {\n const data = node.data;\n return (\n <div className={css.callRow}>\n <CompactionCommandCard\n node={data.command}\n {...(data.compaction === null ? {} : { compaction: data.compaction })}\n t={t}\n />\n </div>\n );\n});\n","// Expanded bodies for the context disclosure, one per durable context form.\n// The producer declares the form; this module only chooses a presentation for\n// it. Every form falls back to OpaqueBody, which is the documented default for\n// an absent, unknown, or malformed form — a resumed or foreign log must render\n// even when this UI version has never seen its producer.\n\nimport type { ReactNode } from \"react\";\nimport type { ContextMessageNode, KnownContextForm } from \"@deepseek-ai/dsh-client-runtime/client\";\nimport { JsonBlock } from \"@deepseek-ai/dsh-client-ui-primitives\";\nimport type { ChatViewSlotProps } from \"@deepseek-ai/dsh-client-ui-conversation/client\";\nimport css from \"./ContextBody.module.css\";\n\n/** Model-facing text stays bounded at the disclosure, not at the producer. */\nconst MAX_CHARS = 20_000;\n\n/** Rows a list body materializes before summarizing the remainder. */\nconst MAX_ENTRIES = 200;\n\ntype Translate = ChatViewSlotProps[\"t\"];\n\n/** One durable source narrowed to the readable-record shape; null for anything else. */\nfunction asRecord(value: unknown): Record<string, unknown> | null {\n return typeof value === \"object\" && value !== null && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : null;\n}\n\n/** One run of the model-facing content: adjacent text, or one unknown block. */\ntype ContentRun = { text: string } | { block: unknown };\n\n/**\n * The content blocks as runs, IN THE ORDER the model received them.\n *\n * Adjacent text blocks join with no separator, matching how provider adapters\n * flatten them — inserting a line break would show the reader a line the model\n * never saw. An unknown block breaks the run and keeps its own fallback rather\n * than being hoisted past the text around it or vanishing; the block union is\n * merge-extensible, so a foreign log may interleave shapes this build does not\n * know.\n */\nfunction contentRuns(content: ContextMessageNode[\"content\"]): ContentRun[] {\n const runs: ContentRun[] = [];\n for (const block of content) {\n if (block.type !== \"text\") {\n runs.push({ block });\n continue;\n }\n const last = runs[runs.length - 1];\n if (last !== undefined && \"text\" in last) last.text += block.text;\n else runs.push({ text: block.text });\n }\n return runs;\n}\n\n/** Only the blocks this UI version does not know, for bodies that replace the text. */\nfunction unknownBlocks(content: ContextMessageNode[\"content\"]): unknown[] {\n return contentRuns(content).flatMap((run) => (\"block\" in run ? [run.block] : []));\n}\n\n/** The model-facing text, truncated to the display bound. */\nfunction boundedText(text: string, t: Translate): string {\n return text.length > MAX_CHARS\n ? `${text.slice(0, MAX_CHARS)}\\n${t(\"json.truncated\", { total: text.length })}`\n : text;\n}\n\n/**\n * One source field rendered as a value row; nested shapes stay compact JSON.\n * Bounded on its own, because source fields are as unbounded as the text: an unknown\n * producer may record an arbitrarily large string or array.\n */\nfunction fieldValue(value: unknown, t: Translate): string {\n const text =\n typeof value === \"string\"\n ? value\n : typeof value === \"number\" || typeof value === \"boolean\"\n ? String(value)\n : JSON.stringify(value);\n return boundedText(text, t);\n}\n\n/**\n * Source fields as a key/value list. `kind` is always omitted because the\n * row header already names the producer. `form` is omitted only when a\n * dedicated body rendered for it — then the presentation the reader is looking\n * at IS that value. On the opaque fallback the declaration is kept, because\n * that is the one place a form this version cannot present would otherwise\n * disappear from the UI entirely.\n */\nfunction SourceFields({\n source,\n formRendered,\n t,\n}: {\n source: unknown;\n formRendered: boolean;\n t: Translate;\n}): ReactNode {\n const record = asRecord(source);\n if (record === null) return null;\n const hidden = formRendered ? [\"kind\", \"form\"] : [\"kind\"];\n const rows = Object.entries(record).filter(([key]) => !hidden.includes(key));\n if (rows.length === 0) return null;\n return (\n <dl className={css.fields} data-context-fields>\n {rows.map(([key, value]) => (\n <div key={key} className={css.field}>\n <dt className={css.fieldKey}>{key}</dt>\n <dd className={css.fieldValue}>{fieldValue(value, t)}</dd>\n </div>\n ))}\n </dl>\n );\n}\n\n/**\n * Content blocks this UI version does not know, kept visible rather than\n * dropped: the block union is merge-extensible, so a newer or foreign log may\n * carry a shape this build has no presentation for.\n * @param props - The unrecognized blocks and the locale seat.\n * @returns One generic JSON block per unknown entry.\n */\nfunction UnknownBlocks({ blocks, t }: { blocks: readonly unknown[]; t: Translate }): ReactNode {\n return (\n <>\n {blocks.map((block, index) => (\n <JsonBlock\n key={index}\n label={t(\"message.unknownBlock\")}\n payload={block}\n truncatedLabel={(total) => t(\"json.truncated\", { total })}\n />\n ))}\n </>\n );\n}\n\n/**\n * The model-facing content of one context, shared by every form that shows it:\n * the text with its real line breaks, then any block this UI version does not\n * know, which keeps its own fallback rather than vanishing.\n * @param props - Durable content and the locale seat.\n * @returns The content blocks as the model received them.\n */\nfunction ModelFacingContent({\n content,\n t,\n}: {\n content: ContextMessageNode[\"content\"];\n t: Translate;\n}): ReactNode {\n return (\n <>\n {contentRuns(content).map((run, index) =>\n \"text\" in run ? (\n run.text !== \"\" && (\n <pre key={index} className={css.text} data-context-text>\n {boundedText(run.text, t)}\n </pre>\n )\n ) : (\n <JsonBlock\n key={index}\n label={t(\"message.unknownBlock\")}\n payload={run.block}\n truncatedLabel={(total) => t(\"json.truncated\", { total })}\n />\n ),\n )}\n </>\n );\n}\n\n/**\n * Default presentation: the model-facing text as text, with its real line\n * breaks, and the remaining source fields beneath it. This is what every form\n * this UI version does not recognize renders as.\n * @param props - Durable content, its source, and the locale seat.\n * @returns The opaque context body.\n */\nexport function OpaqueBody({\n content,\n source,\n t,\n}: {\n content: ContextMessageNode[\"content\"];\n source: unknown;\n t: Translate;\n}): ReactNode {\n return (\n <>\n <ModelFacingContent content={content} t={t} />\n <SourceFields source={source} formRendered={false} t={t} />\n </>\n );\n}\n\n/** One reconciled instruction file, as the durable source records it. */\ninterface InstructionChange {\n action: \"set\" | \"replace\" | \"remove\";\n path: string;\n digest?: string;\n}\n\n/**\n * Instruction changes read off the source, or null when the record is not a\n * usable instruction list.\n *\n * The read is all-or-nothing: silently dropping one unreadable entry would show\n * a confident, incomplete file list for a log this version cannot fully read.\n * Paths are deduplicated in first-seen order, matching how the header label is\n * derived from the same array.\n */\nfunction instructionChanges(source: unknown): InstructionChange[] | null {\n const record = asRecord(source);\n const list = record === null ? undefined : record[\"changes\"];\n if (!Array.isArray(list)) return null;\n const changes: InstructionChange[] = [];\n const seen = new Set<string>();\n for (const entry of list as readonly unknown[]) {\n const change = asRecord(entry);\n if (change === null) return null;\n const path = change[\"path\"];\n if (typeof path !== \"string\" || path === \"\") return null;\n const action = change[\"action\"];\n // The action decides which word the row shows, so an unrecognized one is\n // not a readable change — it would be presented as loaded or updated.\n if (action !== \"set\" && action !== \"replace\" && action !== \"remove\") return null;\n const digest = change[\"digest\"];\n if (seen.has(path)) continue;\n seen.add(path);\n changes.push({ action, path, ...(typeof digest === \"string\" ? { digest } : {}) });\n }\n return changes.length === 0 ? null : changes;\n}\n\n/**\n * Locale key for one reconciled file. The baseline loads a file; a later delta\n * distinguishes a newly reconciled path from a rewritten one, which `set` and\n * `replace` already separate at the producer.\n * @param action - the durable change action.\n * @param baseline - whether this context is the startup/resume baseline.\n * @returns the key naming what happened to that file.\n */\nfunction instructionAction(\n action: InstructionChange[\"action\"],\n baseline: boolean,\n):\n | \"message.context.instructions.removed\"\n | \"message.context.instructions.loaded\"\n | \"message.context.instructions.added\"\n | \"message.context.instructions.updated\" {\n if (action === \"remove\") return \"message.context.instructions.removed\";\n if (baseline) return \"message.context.instructions.loaded\";\n return action === \"set\"\n ? \"message.context.instructions.added\"\n : \"message.context.instructions.updated\";\n}\n\n/**\n * `instructions` form: the files this context reconciled, then their text.\n *\n * The text keeps its `<system-reminder>` framing verbatim — the framing is part\n * of what the model read, so hiding it would misreport the request.\n * @param props - Durable content, its source, and the locale seat.\n * @returns The instructions context body, or the opaque body when the change\n * list is unreadable.\n */\nexport function InstructionsBody({\n content,\n source,\n t,\n}: {\n content: ContextMessageNode[\"content\"];\n source: unknown;\n t: Translate;\n}): ReactNode {\n const changes = instructionChanges(source);\n if (changes === null) return <OpaqueBody content={content} source={source} t={t} />;\n const baseline = asRecord(source)?.[\"baseline\"] === true;\n return (\n <>\n <ul className={css.files} data-context-files>\n {changes.map((change) => (\n <li key={change.path} className={css.file} title={change.digest}>\n <span className={css.filePath}>{change.path}</span>\n <span className={css.fileAction}>{t(instructionAction(change.action, baseline))}</span>\n </li>\n ))}\n </ul>\n <ModelFacingContent content={content} t={t} />\n </>\n );\n}\n\n/** One catalog entry, as the durable source records it. */\ninterface CatalogEntry {\n name: string;\n description: string;\n}\n\n/**\n * Catalog entries read off the source, or null when the record is not a usable\n * catalog. All-or-nothing for the same reason as the instruction list: this body\n * replaces the model-facing text, so a partial list would hide the only complete\n * account of what the model read.\n */\nfunction catalogEntries(source: unknown): CatalogEntry[] | null {\n const record = asRecord(source);\n const list = record === null ? undefined : record[\"entries\"];\n if (!Array.isArray(list)) return null;\n const entries: CatalogEntry[] = [];\n for (const item of list as readonly unknown[]) {\n const entry = asRecord(item);\n if (entry === null) return null;\n const name = entry[\"name\"];\n const description = entry[\"description\"];\n if (typeof name !== \"string\" || name === \"\" || typeof description !== \"string\") return null;\n entries.push({ name, description });\n }\n // An empty list is a real catalog: a replacement with no entries retires\n // every earlier name. Only an unreadable shape falls back.\n return entries;\n}\n\n/**\n * `catalog` form: the published entries as a list, read from the source rather\n * than re-parsed out of the model-facing prose.\n *\n * A catalog whose source carries no usable entries falls through to the opaque\n * body, so an older or hand-edited log still shows its text.\n * @param props - Durable content, its source, and the locale seat.\n * @returns The catalog context body, or the opaque body when the entry list is\n * unreadable.\n */\nexport function CatalogBody({\n content,\n source,\n t,\n}: {\n content: ContextMessageNode[\"content\"];\n source: unknown;\n t: Translate;\n}): ReactNode {\n const entries = catalogEntries(source);\n if (entries === null) return <OpaqueBody content={content} source={source} t={t} />;\n const update = asRecord(source)?.[\"update\"] === true;\n // Entry count is unbounded (a provider may publish any number of skills), and\n // the scrollport bounds height, not node count — so the list bounds itself.\n const shown = entries.slice(0, MAX_ENTRIES);\n const rest = unknownBlocks(content);\n return (\n <>\n {update && (\n <p className={css.catalogNotice} data-context-catalog-update>\n {t(\"message.context.catalog.replaced\")}\n </p>\n )}\n <ul className={css.entries} data-context-entries>\n {shown.map((entry, index) => (\n // Index key: a hand-edited or foreign log may repeat a name, and a\n // duplicate React key would drop a row the model did see.\n <li key={index} className={css.entry}>\n <code className={css.entryName}>{entry.name}</code>\n <span className={css.entryDescription}>{entry.description}</span>\n </li>\n ))}\n </ul>\n {shown.length < entries.length && (\n <p className={css.catalogNotice} data-context-entries-truncated>\n {t(\"message.context.catalog.more\", { count: entries.length - shown.length })}\n </p>\n )}\n {/* The block union is merge-extensible: a catalog message carrying an\n unknown block still shows it rather than dropping model-visible content. */}\n <UnknownBlocks blocks={rest} t={t} />\n </>\n );\n}\n\n/** One named contribution to a runtime snapshot, as the durable source records it. */\ninterface SnapshotSection {\n name: string;\n text: string;\n}\n\n/** Snapshot sections read off the source, or null when the record is unusable. */\nfunction snapshotSections(source: unknown): SnapshotSection[] | null {\n const record = asRecord(source);\n const list = record === null ? undefined : record[\"sections\"];\n if (!Array.isArray(list)) return null;\n const sections: SnapshotSection[] = [];\n for (const item of list as readonly unknown[]) {\n const section = asRecord(item);\n if (section === null) return null;\n const name = section[\"name\"];\n const text = section[\"text\"];\n if (typeof name !== \"string\" || name === \"\" || typeof text !== \"string\") return null;\n sections.push({ name, text });\n }\n return sections.length === 0 ? null : sections;\n}\n\n/**\n * `snapshot` form: the named contributions this snapshot assembled, in order.\n *\n * The sections are the same bytes the model read, split at the boundaries the\n * producer assembled them on, so a reader sees which subsystem contributed\n * which state instead of one undifferentiated wall.\n *\n * One sentence of the model-facing text is NOT in any section: the producer's\n * framing line declaring that this snapshot supersedes earlier ones. Unlike the\n * `<system-reminder>` wrapper an instruction context carries — which wraps\n * content and cannot be separated from it — that line states the form's own\n * semantics, so the body states them as a caption instead of reprinting the\n * joined prose beside the sections it was split from.\n * @param props - Durable content, its source, and the locale seat.\n * @returns The snapshot context body, or the opaque body when unreadable.\n */\nexport function SnapshotBody({\n content,\n source,\n t,\n}: {\n content: ContextMessageNode[\"content\"];\n source: unknown;\n t: Translate;\n}): ReactNode {\n const sections = snapshotSections(source);\n /* v8 ignore next -- contextBody reads the sections before choosing this body. */\n if (sections === null) return <OpaqueBody content={content} source={source} t={t} />;\n return (\n <>\n <p className={css.catalogNotice} data-context-snapshot-supersedes>\n {t(\"message.context.snapshot.supersedes\")}\n </p>\n <dl className={css.sections} data-context-sections>\n {sections.map((section, index) => (\n <div key={index} className={css.section}>\n <dt className={css.sectionName}>{section.name}</dt>\n <dd className={css.sectionText}>{boundedText(section.text, t)}</dd>\n </div>\n ))}\n </dl>\n </>\n );\n}\n\n/**\n * `notice` form: what just happened, with the model-facing text beneath it.\n *\n * The one-line account also rides the collapsed row ({@link contextBody}), so a\n * notice is usually readable without expanding at all.\n * @param props - Durable content, its source, and the locale seat.\n * @returns The notice context body.\n */\nexport function NoticeBody({\n content,\n t,\n}: {\n content: ContextMessageNode[\"content\"];\n source: unknown;\n t: Translate;\n}): ReactNode {\n return <ModelFacingContent content={content} t={t} />;\n}\n\n/**\n * `relay` form: which agent sent this, then what it said.\n *\n * The sender is an opaque session id; it is shown as a field rather than a\n * label, because this client cannot resolve it to a title.\n * @param props - Durable content, its source, and the locale seat.\n * @returns The relay context body.\n */\nexport function RelayBody({\n content,\n source,\n t,\n}: {\n content: ContextMessageNode[\"content\"];\n source: unknown;\n t: Translate;\n}): ReactNode {\n const sender = relaySender(source);\n /* v8 ignore next -- contextBody resolves the sender before choosing this body. */\n if (sender === null) return <OpaqueBody content={content} source={source} t={t} />;\n return (\n <>\n <p className={css.relaySender} data-context-relay-sender>\n {t(\"message.context.relay.from\", { session: sender })}\n </p>\n <ModelFacingContent content={content} t={t} />\n </>\n );\n}\n\n/** The sending agent's session id, or null when the record does not name one. */\nfunction relaySender(source: unknown): string | null {\n const sender = asRecord(source)?.[\"senderSessionId\"];\n return typeof sender === \"string\" && sender !== \"\" ? sender : null;\n}\n\n/** One recalled session, as the durable source records it. */\ninterface RecalledSession {\n label: string;\n retained: number;\n omitted: number;\n truncated: boolean;\n}\n\n/** Recalled sessions read off the source, or null when the record is unusable. */\nfunction recalledSessions(source: unknown): RecalledSession[] | null {\n const record = asRecord(source);\n const list = record === null ? undefined : record[\"references\"];\n if (!Array.isArray(list)) return null;\n const sessions: RecalledSession[] = [];\n for (const item of list as readonly unknown[]) {\n const reference = asRecord(item);\n if (reference === null) return null;\n const label = reference[\"label\"];\n const retained = reference[\"retainedMessages\"];\n const omitted = reference[\"omittedMessages\"];\n const truncated = reference[\"truncated\"];\n // Completeness is the fact this card exists to report, so a reference that\n // cannot state it is not a readable recall — showing the label alone would\n // present a confident card over unknown loss.\n if (\n typeof label !== \"string\" ||\n label === \"\" ||\n typeof retained !== \"number\" ||\n typeof omitted !== \"number\" ||\n typeof truncated !== \"boolean\"\n )\n return null;\n sessions.push({ label, retained, omitted, truncated });\n }\n return sessions.length === 0 ? null : sessions;\n}\n\n/**\n * `recall` form: which sessions this material came from and how much of each\n * survived the read, then the material itself.\n *\n * Completeness is the fact a reader needs first: recalled context is bounded on\n * the way in, so a card that hid the omitted count would overstate what the\n * model received.\n * @param props - Durable content, its source, and the locale seat.\n * @returns The recall context body, or the opaque body when unreadable.\n */\nexport function RecallBody({\n content,\n source,\n t,\n}: {\n content: ContextMessageNode[\"content\"];\n source: unknown;\n t: Translate;\n}): ReactNode {\n const sessions = recalledSessions(source);\n if (sessions === null) return <OpaqueBody content={content} source={source} t={t} />;\n return (\n <>\n <ul className={css.recalls} data-context-recalls>\n {sessions.map((session, index) => (\n <li key={index} className={css.recall}>\n <span className={css.recallLabel}>{session.label}</span>\n <span className={css.recallCounts}>\n {t(\"message.context.recall.counts\", {\n retained: session.retained,\n omitted: session.omitted,\n })}\n </span>\n {session.truncated && (\n <span className={css.recallCounts}>{t(\"message.context.recall.truncated\")}</span>\n )}\n </li>\n ))}\n </ul>\n <ModelFacingContent content={content} t={t} />\n </>\n );\n}\n\n/** The one-line account a `notice` puts on its collapsed row, when it records one. */\nfunction noticeSummary(source: unknown): string | null {\n const summary = asRecord(source)?.[\"summary\"];\n return typeof summary === \"string\" && summary !== \"\" ? summary : null;\n}\n\n/**\n * Choose the body for one context node.\n *\n * Returns the form the body actually rendered as, which is not always the\n * declared one: a declared form whose fields are unreadable falls back to\n * opaque, and the caller labels the row with what it really shows.\n * `summary` is the collapsed row's one-line account, which only a `notice`\n * records: its whole point is being readable without expanding.\n * @param form - the producer-declared form projected onto the node.\n * @param props - durable content, its source, and the locale seat.\n * @returns the rendered form (null for opaque), its collapsed summary, and its body.\n */\nexport function contextBody(\n form: ContextMessageNode[\"form\"],\n props: { content: ContextMessageNode[\"content\"]; source: unknown; t: Translate },\n): { rendered: KnownContextForm | null; summary: string | null; body: ReactNode } {\n const opaque = { rendered: null, summary: null, body: <OpaqueBody {...props} /> };\n switch (form) {\n case \"instructions\":\n return instructionChanges(props.source) === null\n ? opaque\n : { rendered: \"instructions\", summary: null, body: <InstructionsBody {...props} /> };\n case \"catalog\":\n return catalogEntries(props.source) === null\n ? opaque\n : { rendered: \"catalog\", summary: null, body: <CatalogBody {...props} /> };\n case \"snapshot\":\n return snapshotSections(props.source) === null\n ? opaque\n : { rendered: \"snapshot\", summary: null, body: <SnapshotBody {...props} /> };\n case \"notice\": {\n const summary = noticeSummary(props.source);\n return summary === null\n ? opaque\n : { rendered: \"notice\", summary, body: <NoticeBody {...props} /> };\n }\n case \"relay\":\n return relaySender(props.source) === null\n ? opaque\n : { rendered: \"relay\", summary: null, body: <RelayBody {...props} /> };\n case \"recall\":\n return recalledSessions(props.source) === null\n ? opaque\n : { rendered: \"recall\", summary: null, body: <RecallBody {...props} /> };\n case null:\n return opaque;\n /* v8 ignore next 4 -- closed-union backstop; the compiler rejects a new\n KnownContextForm here rather than letting it degrade to opaque silently. */\n default: {\n const unreachable: never = form;\n throw new Error(`unreachable context form: ${String(unreachable)}`);\n }\n }\n}\n","import { useState } from \"react\";\nimport type { ContextMessageNode } from \"@deepseek-ai/dsh-client-runtime/client\";\nimport type { ChatViewSlotProps } from \"@deepseek-ai/dsh-client-ui-conversation/client\";\nimport { DisclosureRow, IconBrowseOutline16 } from \"@deepseek-ai/dsh-client-ui-primitives\";\nimport { contextBody } from \"./ContextBody.tsx\";\nimport css from \"./ContextInjectionRow.module.css\";\n\n/** Props for the logged non-user message presentation. */\nexport interface ContextInjectionRowProps {\n content: ContextMessageNode[\"content\"];\n source: ContextMessageNode[\"source\"];\n /** Role and producer name projected from the durable source. */\n provenance: ContextMessageNode[\"provenance\"];\n /** Producer-declared information form; null renders the opaque body. */\n form: ContextMessageNode[\"form\"];\n /** The owning view's locale seat, passed down as a plain prop. */\n t: ChatViewSlotProps[\"t\"];\n}\n\n/**\n * Render logged context with the Tool calls disclosure chrome from Figma.\n *\n * The header names the role the context plays and, beside it, the producer the\n * durable source identifies, so a reader can tell an injected skill catalog\n * from a workspace instruction file or a recalled session without expanding.\n * The expanded body follows the producer-declared form; an absent or unknown\n * form renders the opaque body.\n * @param props - Durable content, its projected producer role/name and form, and the locale seat.\n * @returns A collapsed context row with a bounded, form-specific body.\n */\nexport function ContextInjectionRow({\n content,\n source,\n provenance,\n form,\n t,\n}: ContextInjectionRowProps) {\n const [open, setOpen] = useState(false);\n // Resolved rather than declared: a form whose fields are unreadable renders\n // the opaque body, and the marker must say what the row actually shows.\n const { rendered, summary, body } = contextBody(form, { content, source, t });\n\n return (\n <DisclosureRow\n className={css.root}\n icon={<IconBrowseOutline16 size={14} />}\n chevronClassName={css.chevron}\n title={t(provenance.role === \"recall\" ? \"message.contextRecall\" : \"message.contextInjection\")}\n collapsedContent={\n provenance.label === null ? undefined : (\n /* ToolRow's separator shape: an aria-hidden dot, so the accessible name\n stays the two readable parts and the two disclosure rows expose one\n name shape. A source that names no producer drops the dot with it. */\n <>\n <span className={css.sep} aria-hidden />\n <span className={css.source} data-context-source>\n {provenance.label}\n </span>\n {summary !== null && (\n <>\n <span className={css.sep} aria-hidden />\n <span className={css.summary} data-context-summary>\n {summary}\n </span>\n </>\n )}\n </>\n )\n }\n keepContentWhenOpen\n open={open}\n expandable\n expandOnRowClick\n onToggle={() => {\n setOpen((value) => !value);\n }}\n >\n <div\n className={css.body}\n data-context-injection-body\n data-context-form={rendered ?? undefined}\n >\n {body}\n </div>\n </DisclosureRow>\n );\n}\n","// Shared time-label helpers for user/assistant IconActions rows.\n\nimport type { Translate } from \"@deepseek-ai/dsh-client-ui-slots\";\n\n/** The date-template share of the conversation dictionary the clock consumes. */\nexport type ClockTranslate = Translate<\"clock.md\" | \"clock.ymd\">;\n\n/** The elapsed-duration share of the conversation dictionary. */\nexport type RunDurationTranslate = Translate<\"duration.seconds\" | \"duration.minutes\">;\nfunction pad2(n: number): string {\n return String(n).padStart(2, \"0\");\n}\n\n/**\n * Local calendar-day epoch (ms at local midnight) for an instant.\n * @param ms - Unix epoch ms.\n * @returns Midnight of that local calendar day.\n */\nexport function startOfLocalDay(ms: number): number {\n const d = new Date(ms);\n d.setHours(0, 0, 0, 0);\n return d.getTime();\n}\n\n/**\n * Delay until the next local midnight after `ms` (at least 1ms).\n * @param ms - Unix epoch ms.\n * @returns Milliseconds until the following local midnight.\n */\nexport function msUntilNextLocalMidnight(ms: number): number {\n const next = new Date(ms);\n next.setHours(24, 0, 0, 0);\n return Math.max(next.getTime() - ms, 1);\n}\n\n/**\n * Localized elapsed-time label shared by running and settled turn chrome.\n * @param ms - Elapsed duration in milliseconds (negatives clamp to zero).\n * @param t - Translate seat supplying the duration templates.\n * @returns Display string in whole seconds.\n */\nexport function formatRunDuration(ms: number, t: RunDurationTranslate): string {\n const total = Math.max(0, Math.floor(ms / 1000));\n const minutes = Math.floor(total / 60);\n const seconds = total % 60;\n return minutes > 0\n ? t(\"duration.minutes\", { minutes, seconds: String(seconds).padStart(2, \"0\") })\n : t(\"duration.seconds\", { seconds });\n}\n\n/**\n * Sub-turn latency figure: one decimal under ten seconds, whole seconds\n * beyond. Unit-less so the locale template owns the second suffix.\n * @param ms - Latency in milliseconds (negatives clamp to zero).\n * @returns Display number in seconds without unit.\n */\nexport function formatLatencySeconds(ms: number): string {\n const s = Math.max(0, ms) / 1000;\n return s < 10 ? String(Math.round(s * 10) / 10) : String(Math.round(s));\n}\n\n/**\n * Decode-throughput figure: whole tokens from ten up, one decimal below.\n * @param tps - Tokens per second.\n * @returns Display number without unit.\n */\nexport function formatTokensPerSecond(tps: number): string {\n const clamped = Math.max(0, tps);\n return clamped >= 10 ? String(Math.round(clamped)) : String(Math.round(clamped * 10) / 10);\n}\n\n/**\n * Compact local timestamp for message IconActions. Same calendar day →\n * `HH:mm`; earlier this year → the `clock.md` date template + clock; other\n * years → the `clock.ymd` template + clock. Pure: the date templates arrive\n * through the caller's locale seat.\n * @param time - Unix epoch ms from the source session event.\n * @param t - translate seat supplying the `clock.md` / `clock.ymd` templates.\n * @param now - Reference instant for the day/year cut (defaults to wall clock).\n * @returns Date-aware clock string (24-hour, zero-padded time).\n */\nexport function formatMessageClock(\n time: number,\n t: ClockTranslate,\n now: number = Date.now(),\n): string {\n const d = new Date(time);\n const n = new Date(now);\n const clock = `${pad2(d.getHours())}:${pad2(d.getMinutes())}`;\n if (\n d.getFullYear() === n.getFullYear() &&\n d.getMonth() === n.getMonth() &&\n d.getDate() === n.getDate()\n ) {\n return clock;\n }\n const params = { y: d.getFullYear(), m: d.getMonth() + 1, d: d.getDate() };\n const md = d.getFullYear() === n.getFullYear() ? t(\"clock.md\", params) : t(\"clock.ymd\", params);\n return `${md} ${clock}`;\n}\n","// Component-local calendar-day tick: memoized message rows keep stable props\n// across midnight, so the IconActions clock needs a local day seat that\n// re-fires at the next local midnight without reaching for framework hooks.\n\nimport { useEffect, useState } from \"react\";\nimport { msUntilNextLocalMidnight, startOfLocalDay } from \"./message-chrome.ts\";\n\n/**\n * Local calendar-day epoch that advances at each local midnight.\n * @returns Midnight ms for the current local day; updates after the boundary.\n */\nexport function useCalendarDay(): number {\n const [day, setDay] = useState(() => startOfLocalDay(Date.now()));\n useEffect(() => {\n let timer: ReturnType<typeof setTimeout>;\n const arm = (): void => {\n const now = Date.now();\n setDay(startOfLocalDay(now));\n timer = setTimeout(arm, msUntilNextLocalMidnight(now));\n };\n timer = setTimeout(arm, msUntilNextLocalMidnight(Date.now()));\n return () => {\n clearTimeout(timer);\n };\n }, []);\n return day;\n}\n","// Shared IconActions chrome for user and assistant messages: copy\n// live, optional branch wiring, and an optional date-aware clock.\n\nimport { useCallback, useEffect, useId, useRef, useState, type ReactNode } from \"react\";\nimport {\n IconBranchOutline16,\n IconCheckOutline16,\n IconCopyOutline16,\n IconEditOutline16,\n IconRefreshOutline16,\n Tooltip,\n writeClipboard,\n} from \"@deepseek-ai/dsh-client-ui-primitives\";\nimport type { ChatViewSlotProps } from \"@deepseek-ai/dsh-client-ui-conversation/client\";\nimport {\n formatLatencySeconds,\n formatMessageClock,\n formatRunDuration,\n formatTokensPerSecond,\n} from \"./message-chrome.ts\";\nimport { useCalendarDay } from \"./use-calendar-day.ts\";\nimport css from \"./MessageIconActions.module.css\";\n\nexport interface MessageIconActionsProps {\n /** Plain text the copy action writes. */\n text: string;\n /** Unix epoch ms for the clock label; omitted for transient messages. */\n time?: number | undefined;\n /** Turn wall time in ms, appended to the clock as `· Ran for 15s`; omitted when the turn's start is unknown. */\n runMs?: number | undefined;\n /** Turn first-step TTFT in ms, appended as `· TTFT 1.2s`; omitted when unrecorded. */\n ttftMs?: number | undefined;\n /** Turn decode throughput, appended as `· 34 tok/s`; omitted when unrecorded. */\n tokensPerSecond?: number | undefined;\n /** Clock before icons (user) or after (assistant). */\n clock: \"start\" | \"end\";\n /** Fork the session at this message; omission hides the branch action. */\n onBranch?: (() => void) | undefined;\n /** The message is not a completed transcript tail, so branch stays visible but unavailable. */\n branchUnavailable?: boolean | undefined;\n /** Parent layout class composed onto the actions row. */\n className?: string | undefined;\n /**\n * Slot-rendered actions owned by independent plugins, placed between the\n * built-in copy and branch controls.\n */\n extraActions?: ReactNode;\n /** Edit this message block in place (session-editor). */\n onEdit?: (() => void) | undefined;\n /** Retry this turn in place (session-editor). */\n onRetry?: (() => void) | undefined;\n /** The owning view's locale seat, passed down as a plain prop. */\n t: ChatViewSlotProps[\"t\"];\n}\n\n/**\n * Copy / branch (/ clock) IconActions row shared by user and assistant chrome.\n * @param props - Copy text, event time, clock side, branch callback, className.\n * @returns The actions row element.\n */\nexport function MessageIconActions({\n text,\n time,\n runMs,\n ttftMs,\n tokensPerSecond,\n clock,\n onBranch,\n branchUnavailable = false,\n className,\n extraActions,\n onEdit,\n onRetry,\n t,\n}: MessageIconActionsProps) {\n const day = useCalendarDay();\n const reasonId = useId();\n // Same success chrome as CodeBlock: a short check swap after the write,\n // gated so re-clicks during the window neither re-copy nor stack timers.\n const [copied, setCopied] = useState(false);\n const copyPending = useRef(false);\n const copyTimer = useRef<number | null>(null);\n const copyEpoch = useRef(0);\n useEffect(\n () => () => {\n copyEpoch.current += 1;\n copyPending.current = false;\n if (copyTimer.current !== null) clearTimeout(copyTimer.current);\n },\n [],\n );\n const onCopy = useCallback(() => {\n if (copied || copyPending.current) return;\n const epoch = copyEpoch.current;\n copyPending.current = true;\n void writeClipboard(text).then((ok) => {\n if (epoch !== copyEpoch.current) return;\n copyPending.current = false;\n if (!ok) return;\n setCopied(true);\n copyTimer.current = window.setTimeout(() => {\n copyTimer.current = null;\n setCopied(false);\n }, 1000);\n });\n }, [copied, text]);\n // The dot is decorative and stays hidden, but its margins separate the\n // readings only on screen: without the flanking spaces a reader hears one\n // run-on string (\"Ran for 13sTTFT 0.2s12 tok/s\") instead of three facts.\n const clockEl =\n time === undefined ? null : (\n <span className={clock === \"start\" ? css.timeStart : css.timeEnd}>\n {formatMessageClock(time, t, day)}\n {runMs !== undefined && (\n <>\n {\" \"}\n <span className={css.runTimeDot} aria-hidden>\n ·\n </span>{\" \"}\n {t(\"message.ranFor\", { duration: formatRunDuration(runMs, t) })}\n </>\n )}\n {ttftMs !== undefined && (\n <>\n {\" \"}\n <span className={css.runTimeDot} aria-hidden>\n ·\n </span>{\" \"}\n {t(\"message.ttft\", { seconds: formatLatencySeconds(ttftMs) })}\n </>\n )}\n {tokensPerSecond !== undefined && (\n <>\n {\" \"}\n <span className={css.runTimeDot} aria-hidden>\n ·\n </span>{\" \"}\n {t(\"message.tokensPerSecond\", { tps: formatTokensPerSecond(tokensPerSecond) })}\n </>\n )}\n </span>\n );\n return (\n <div className={className === undefined ? css.actions : `${css.actions} ${className}`}>\n {clock === \"start\" ? clockEl : null}\n <Tooltip label={copied ? t(\"copied\" as never) : t(\"copy\" as never)} side=\"bottom\">\n <button\n type=\"button\"\n className={css.action}\n aria-label={copied ? t(\"copied\" as never) : t(\"copy\" as never)}\n onClick={onCopy}\n >\n {copied ? <IconCheckOutline16 /> : <IconCopyOutline16 />}\n </button>\n </Tooltip>\n {extraActions}\n {onEdit !== undefined && (\n <Tooltip label=\"编辑\" side=\"bottom\">\n <button type=\"button\" className={css.action} aria-label=\"编辑\" onClick={onEdit}>\n <IconEditOutline16 />\n </button>\n </Tooltip>\n )}\n {onRetry !== undefined && (\n <Tooltip label=\"重试此回合\" side=\"bottom\">\n <button type=\"button\" className={css.action} aria-label=\"重试此回合\" onClick={onRetry}>\n <IconRefreshOutline16 />\n </button>\n </Tooltip>\n )}\n {onBranch !== undefined && (\n <Tooltip\n label={branchUnavailable ? t(\"message.branchUnavailable\") : t(\"message.branch\")}\n side=\"bottom\"\n >\n {/* Native disabled buttons do not deliver the hover/focus events Tooltip needs. */}\n <button\n type=\"button\"\n className={css.action}\n aria-label={t(\"message.branch\")}\n aria-disabled={branchUnavailable || undefined}\n aria-describedby={branchUnavailable ? reasonId : undefined}\n data-unavailable={branchUnavailable || undefined}\n onClick={branchUnavailable ? undefined : onBranch}\n >\n <IconBranchOutline16 />\n </button>\n </Tooltip>\n )}\n {onBranch !== undefined && branchUnavailable && (\n <span id={reasonId} className={css.visuallyHidden}>\n {t(\"message.branchUnavailable\")}\n </span>\n )}\n {clock === \"end\" ? clockEl : null}\n </div>\n );\n}\n","/**\n * 消息编辑弹窗:与 dsh settings 同风格的 Modal(@deepseek-ai/dsh-client-ui-primitives)。\n * 输入框复用 composer-card 的视觉(InputBar 同款 border/radius/surface/阴影\n * token)与自动增长交互。保存成功后关闭;失败保持打开。\n */\n\nimport { useRef, useState } from \"react\";\nimport { Button, Modal } from \"@deepseek-ai/dsh-client-ui-primitives\";\nimport type { EditableMessageBlock } from \"../../shared.ts\";\nimport css from \"./MessageEditDialog.module.css\";\n\nconst BLOCK_TITLE: Record<EditableMessageBlock[\"kind\"], string> = {\n user: \"编辑用户消息\",\n \"assistant.reasoning\": \"编辑助手思考\",\n \"assistant.response\": \"编辑助手回复\",\n};\n\n/** 编辑弹窗:调用 onSave 保存;返回 true 关闭,false 保持打开。 */\nexport function MessageEditDialog({\n block,\n onSave,\n onClose,\n}: {\n block: EditableMessageBlock;\n onSave: (text: string) => Promise<boolean>;\n onClose: () => void;\n}) {\n const [text, setText] = useState(block.text);\n const [saving, setSaving] = useState(false);\n const inputRef = useRef<HTMLTextAreaElement | null>(null);\n\n /** composer-card 式自动增长:高度随内容(scrollHeight)自适应。 */\n const autosize = (): void => {\n const el = inputRef.current;\n if (el === null) return;\n el.style.height = \"auto\";\n el.style.height = `${el.scrollHeight}px`;\n };\n\n const save = (): void => {\n if (saving) return;\n setSaving(true);\n void onSave(text).then((applied) => {\n if (applied) onClose();\n else setSaving(false);\n });\n };\n\n return (\n <Modal\n open\n onClose={onClose}\n title={BLOCK_TITLE[block.kind]}\n closeLabel=\"关闭\"\n footer={\n <div className={css.actions}>\n <Button variant=\"outline\" onClick={onClose} disabled={saving}>\n 取消\n </Button>\n <Button variant=\"primary\" onClick={save} disabled={saving}>\n {saving ? \"保存中…\" : \"保存\"}\n </Button>\n </div>\n }\n >\n <textarea\n ref={inputRef}\n className={css.input}\n value={text}\n onChange={(event) => {\n setText(event.target.value);\n autosize();\n }}\n autoFocus\n rows={4}\n />\n </Modal>\n );\n}\n","// MessageItem: simple chat nodes — user and consumed-steering bubbles\n// (right-aligned, with clock + copy IconActions; branch lives only under\n// assistant answers), pending steering (copy only), context injection,\n// compaction marker, retry disclosure, and unknown-surface JSON rows.\n\nimport { memo, useEffect, useMemo, useState } from \"react\";\nimport type { ReactNode } from \"react\";\nimport type { InjectFace } from \"@deepseek-ai/dsh-client-ui-slots\";\nimport { Button, Modal } from \"@deepseek-ai/dsh-client-ui-primitives\";\nimport type {\n ModelRetryNode,\n TurnErrorNode,\n UserMessageNode,\n} from \"@deepseek-ai/dsh-client-runtime/client\";\nimport { JsonBlock, MessageText, StateDot } from \"@deepseek-ai/dsh-client-ui-primitives\";\nimport type {\n ChatNodeViewProps,\n ChatViewSlotProps,\n RenderMessageImages,\n} from \"@deepseek-ai/dsh-client-ui-conversation/client\";\nimport { CompactionItem } from \"./CompactionItem.tsx\";\nimport { ContextInjectionRow } from \"./ContextInjectionRow.tsx\";\nimport { MessageIconActions } from \"./MessageIconActions.tsx\";\nimport { MessageEditDialog } from \"./MessageEditDialog.tsx\";\nimport css from \"./MessageItem.module.css\";\nimport type { EditableMessageBlock } from \"../../shared.ts\";\nimport type { SessionEditorFace } from \"../controller.ts\";\n\ntype UserImage = Extract<UserMessageNode[\"content\"][number], { type: \"image\" }>;\n\nfunction contentParts(content: readonly unknown[]): {\n text: string;\n images: { attachment: UserImage[\"attachment\"] }[];\n rest: unknown[];\n} {\n const texts: string[] = [];\n const images: { attachment: UserImage[\"attachment\"] }[] = [];\n const rest: unknown[] = [];\n for (const block of content) {\n const b = block as { type?: string; text?: string; attachment?: unknown };\n if (b.type === \"text\" && typeof b.text === \"string\") texts.push(b.text);\n else if (b.type === \"image\" && b.attachment !== undefined) {\n images.push({ attachment: (b as UserImage).attachment });\n } else rest.push(block);\n }\n return { text: texts.join(\"\"), images, rest };\n}\n\nfunction retrySeconds(milliseconds: number): number {\n return Math.max(1, Math.ceil(milliseconds / 1_000));\n}\n\ninterface RetryCountdown {\n deadline: number;\n seconds: number;\n}\n\nfunction ModelRetryItem({\n node,\n active,\n t,\n}: {\n node: ModelRetryNode;\n active: boolean;\n t: ChatViewSlotProps[\"t\"];\n}) {\n // Anchor the host-scheduled delay to this browser's first render of the\n // retry node. Host event time and Date.now() may belong to different clocks.\n const deadline = useMemo(() => Date.now() + node.delayMs, [node.delayMs, node.seq]);\n const scheduledSeconds = retrySeconds(node.delayMs);\n const maximum = node.mode === \"normal\" ? node.maxRetries : \"∞\";\n const [countdown, setCountdown] = useState<RetryCountdown>(() => ({\n deadline,\n seconds: retrySeconds(deadline - Date.now()),\n }));\n const remainingSeconds =\n countdown.deadline === deadline ? countdown.seconds : retrySeconds(deadline - Date.now());\n\n useEffect(() => {\n if (!active) return;\n const updateCountdown = (): number => {\n const next = retrySeconds(deadline - Date.now());\n setCountdown((current) =>\n current.deadline === deadline && current.seconds === next\n ? current\n : { deadline, seconds: next },\n );\n return next;\n };\n if (updateCountdown() === 1) return;\n const timer = window.setInterval(() => {\n if (updateCountdown() === 1) window.clearInterval(timer);\n }, 250);\n return () => {\n window.clearInterval(timer);\n };\n }, [active, deadline]);\n\n const label = active\n ? t(\"message.retry.active\")\n : node.retryState === \"cancelled\"\n ? t(\"message.retry.cancelled\")\n : node.retryState === \"started\"\n ? t(\"message.retry.started\")\n : t(\"message.retry.scheduled\");\n const seconds = active ? remainingSeconds : scheduledSeconds;\n\n return (\n <details className={css.retryRow} data-active={active || undefined}>\n <summary className={css.retrySummary}>\n <span className={css.retryText} role=\"status\">\n {t(\"message.retry.status\", { label, retry: node.retry, maximum, seconds })}\n </span>\n </summary>\n <div className={css.retryDetails}>\n <div>\n <span className={css.retryDetailLabel}>{t(\"message.retry.delay\")}</span>\n {Math.round(node.delayMs)}ms\n </div>\n <div>\n <span className={css.retryDetailLabel}>{t(\"message.retry.failure\")}</span>\n {node.failure.message}\n </div>\n </div>\n </details>\n );\n}\n\n/** Persistent, turn-positioned feedback for a terminal failure. */\nfunction TurnErrorItem({ node, t }: { node: TurnErrorNode; t: ChatViewSlotProps[\"t\"] }) {\n return (\n <div className={css.turnErrorRow} role=\"status\">\n <StateDot state=\"error\" className={css.turnErrorDot} />\n <div className={css.turnErrorCopy}>\n <span className={css.turnErrorTitle}>{t(\"message.turnError\")}</span>\n <span className={css.turnErrorMessage}>{node.message}</span>\n </div>\n {node.code !== undefined && <code className={css.turnErrorCode}>{node.code}</code>}\n </div>\n );\n}\n\n/** Persistent, turn-positioned notice for a turn ended at the output-token cap. */\nfunction TurnMaxTokensItem({ t }: { t: ChatViewSlotProps[\"t\"] }) {\n return (\n <div className={css.turnErrorRow} role=\"status\">\n <StateDot state=\"warning\" className={css.turnErrorDot} />\n <div className={css.turnErrorCopy}>\n <span className={css.maxTokensTitle}>{t(\"message.maxTokens\")}</span>\n <span className={css.turnErrorMessage}>{t(\"message.maxTokens.hint\")}</span>\n </div>\n </div>\n );\n}\n\n/**\n * Display projection of reference forms in a user bubble (free geometry — no\n * textarea alignment constraint here); everything else stays plain text. The\n * logged model text remains the single truth; this is presentation only.\n * Plain-text `/name` / `@name` word-boundary tokens decorate (the sent text\n * IS the reference — the bubble uses the same plainest token\n * scan as the composer, minus the lexicon: sent tokens were validated at\n * compose time, so shape alone decorates).\n */\nfunction projectUserText(text: string): ReactNode {\n const re = /(^|\\s)([/@][\\w-]+)(?=\\s|$)/g;\n const parts: ReactNode[] = [];\n let cursor = 0;\n let m: RegExpExecArray | null;\n while ((m = re.exec(text)) !== null) {\n const tokenStart = m.index + (m[1]?.length ?? 0);\n const label = m[2] ?? \"\";\n if (tokenStart > cursor)\n parts.push(<MessageText key={cursor} text={text.slice(cursor, tokenStart)} />);\n parts.push(\n <span\n key={tokenStart}\n className={css.refChip}\n data-ref-chip={label.startsWith(\"@\") ? \"subagent\" : \"skill\"}\n >\n {label}\n </span>,\n );\n cursor = tokenStart + label.length;\n }\n if (parts.length === 0) return <MessageText text={text} />;\n if (cursor < text.length) parts.push(<MessageText key={cursor} text={text.slice(cursor)} />);\n return <>{parts}</>;\n}\n\n/** Right-aligned bubble shared by user and steering rows. */\nfunction UserStyleBubble({\n content,\n renderMessageImages,\n actions,\n pending = false,\n t,\n}: {\n content: readonly unknown[];\n renderMessageImages: RenderMessageImages;\n /** Optional IconActions (or similar) below the bubble; receives the joined text. */\n actions?: (text: string) => ReactNode;\n /** Whether this is the Host-authoritative pre-admission steering projection. */\n pending?: boolean;\n t: ChatViewSlotProps[\"t\"];\n}): ReactNode {\n const { text, images, rest } = contentParts(content);\n const truncated = (total: number): string => t(\"json.truncated\", { total });\n const showBubble = text !== \"\" || rest.length > 0;\n return (\n <div className={css.userRow} data-pending-steering={pending || undefined} data-time-hover-root>\n <div className={css.userStack}>\n {renderMessageImages({ images, align: \"end\" })}\n {showBubble && (\n <div className={css.bubble}>\n {projectUserText(text)}\n {rest.map((block, i) => (\n <JsonBlock\n key={i}\n label={t(\"message.extraBlock\")}\n payload={block}\n truncatedLabel={truncated}\n />\n ))}\n </div>\n )}\n </div>\n {actions?.(text)}\n </div>\n );\n}\n\n/**\n * Render one Host-authoritative pending steering item with the same visual\n * language as its eventual durable transcript node.\n * @param props - Pending message content and conversation translator.\n * @returns the pending steering bubble.\n */\nexport function PendingSteeringBubble({\n content,\n renderMessageImages,\n t,\n}: {\n content: readonly unknown[];\n renderMessageImages: RenderMessageImages;\n t: ChatViewSlotProps[\"t\"];\n}): ReactNode {\n return (\n <UserStyleBubble\n content={content}\n renderMessageImages={renderMessageImages}\n pending\n t={t}\n actions={(text) => (\n <MessageIconActions text={text} clock=\"start\" className={css.actions} t={t} />\n )}\n />\n );\n}\n\n/** User and admitted-steering keyed Chat renderer. */\nexport const UserMessageNodeView = memo(function UserMessageNodeView({\n node,\n renderMessageImages,\n t,\n edit,\n retry,\n}: ChatNodeViewProps<\"user\" | \"steering\"> & InjectFace<SessionEditorFace>) {\n const data = node.data;\n const [editing, setEditing] = useState<EditableMessageBlock | null>(null);\n const [confirmingRetry, setConfirmingRetry] = useState(false);\n const turnLocation =\n node.location.kind === \"turn\" || node.location.kind === \"step\" ? node.location.turn : undefined;\n const turn = turnLocation?.turn;\n // 重试只对已闭合轮次开放(未闭合/无闭合边界的轮次服务端无法重放)。\n const retryable = turnLocation?.status === \"closed\";\n // 编辑目标:第一个文本块(与 Timeline 编辑面的 blockIndex 对齐)。\n const textBlockIndex = data.content.findIndex(\n (block) => (block as { type?: string }).type === \"text\",\n );\n const textBlock =\n textBlockIndex === -1 ? undefined : (data.content[textBlockIndex] as { text?: string });\n const onEdit =\n textBlock === undefined || turn === undefined\n ? undefined\n : () => {\n setEditing({\n key: `${node.anchorSeq}:${String(textBlockIndex)}`,\n turn,\n eventSeq: node.anchorSeq,\n blockIndex: textBlockIndex,\n kind: \"user\",\n text: textBlock.text ?? \"\",\n time: data.time,\n });\n };\n // 重试先弹确认(就地编辑会抛弃该回合及其后的内容)。\n const onRetry =\n retryable && turn !== undefined\n ? () => {\n setConfirmingRetry(true);\n }\n : undefined;\n return (\n <>\n {editing !== null && (\n <MessageEditDialog\n block={editing}\n onSave={(text) => edit(editing, text, \"truncate\")}\n onClose={() => setEditing(null)}\n />\n )}\n {confirmingRetry && turn !== undefined && (\n <Modal\n open\n onClose={() => setConfirmingRetry(false)}\n title=\"重试回合\"\n closeLabel=\"关闭\"\n description={`将重新生成第 ${turn} 轮的回复,并抛弃该回合之后的内容。`}\n footer={\n <div className={css.confirmActions}>\n <Button variant=\"outline\" onClick={() => setConfirmingRetry(false)}>\n 取消\n </Button>\n <Button\n variant=\"primary\"\n onClick={() => {\n setConfirmingRetry(false);\n void retry(turn, \"truncate\");\n }}\n >\n 确认重试\n </Button>\n </div>\n }\n />\n )}\n <UserStyleBubble\n content={data.content}\n renderMessageImages={renderMessageImages}\n t={t}\n actions={(text) => (\n <MessageIconActions\n text={text}\n time={data.time}\n clock=\"start\"\n className={css.actions}\n t={t}\n onEdit={onEdit}\n onRetry={onRetry}\n />\n )}\n />\n </>\n );\n});\n\n/** Injected-context keyed Chat renderer. */\nexport const ContextMessageNodeView = memo(function ContextMessageNodeView({\n node,\n t,\n}: ChatNodeViewProps<\"context\">) {\n const data = node.data;\n return (\n <ContextInjectionRow\n content={data.content}\n source={data.source}\n provenance={data.provenance}\n form={data.form}\n t={t}\n />\n );\n});\n\n/** Automatic compaction keyed Chat renderer. */\nexport const CompactionNodeView = memo(function CompactionNodeView({\n node,\n t,\n}: ChatNodeViewProps<\"compaction\">) {\n return <CompactionItem node={node.data} t={t} />;\n});\n\n/** Correlated retry-chain keyed Chat renderer. */\nexport const RetryNodeView = memo(function RetryNodeView({\n node,\n t,\n}: ChatNodeViewProps<\"model-retry\">) {\n const data = node.data;\n return (\n <ModelRetryItem node={data.current} active={data.current.retryState === \"scheduled\"} t={t} />\n );\n});\n\n/** Terminal turn-error keyed Chat renderer. */\nexport const TurnErrorNodeView = memo(function TurnErrorNodeView({\n node,\n t,\n}: ChatNodeViewProps<\"turn-error\">) {\n return <TurnErrorItem node={node.data} t={t} />;\n});\n\n/** Max-tokens turn-end notice keyed Chat renderer. */\nexport const TurnMaxTokensNodeView = memo(function TurnMaxTokensNodeView({\n t,\n}: ChatNodeViewProps<\"turn-max-tokens\">) {\n return <TurnMaxTokensItem t={t} />;\n});\n\n/** Explicit unknown-surface keyed Chat renderer. */\nexport const UnknownNodeView = memo(function UnknownNodeView({\n node,\n t,\n}: ChatNodeViewProps<\"unknown\">) {\n const data = node.data;\n return (\n <div className={css.contextRow}>\n <JsonBlock\n label={t(\"message.unknownSurface\", { type: data.type })}\n payload={data.data}\n truncatedLabel={(total) => t(\"json.truncated\", { total })}\n />\n </div>\n );\n});\n","import type { AssistantBlock } from \"@deepseek-ai/dsh-client-runtime/client\";\n\n/**\n * Collect visible prose from one Assistant lifecycle.\n * @param blocks - Assistant content blocks.\n * @returns concatenated text blocks.\n */\nexport function assistantText(blocks: readonly AssistantBlock[]): string {\n return blocks.flatMap((block) => (block.kind === \"text\" ? [block.text] : [])).join(\"\");\n}\n","import { memo } from \"react\";\nimport type { InjectFace } from \"@deepseek-ai/dsh-client-ui-slots\";\nimport type { ChatNodeViewProps } from \"@deepseek-ai/dsh-client-ui-conversation/client\";\nimport { MessageIconActions } from \"./MessageIconActions.tsx\";\nimport { assistantText } from \"./turn-assistant.ts\";\nimport css from \"./TurnTailNodeView.module.css\";\nimport type { SessionEditorFace } from \"../controller.ts\";\n\ntype TurnTailNodeViewProps = ChatNodeViewProps<\"turn-tail\"> & InjectFace<SessionEditorFace>;\n\n/**\n * Turn-local actions over the Location index, independent of Assistant\n * placement.\n *\n * 注意:本 renderer 是 `conversation.chat.node` 的 shadow 注册(priority -1),\n * 而 `renderSlotChain` / `renderSlot` 只在注册声明了对应 children 时由 slot\n * 链传入——turnTail / assistant-actions 的 children 已被上游(ui-conversation)\n * 声明,shadow 注册再声明会抛「already declared」,因此这里不消费子 slot。\n *\n * 编辑 / 重试按钮只挂在 **user 消息**(UserMessageNodeView)上,助手尾部不\n * 提供(避免对未闭合/无 user 输入的轮次误触)。\n */\nexport const TurnTailNodeView = memo(function TurnTailNodeView({\n node,\n forkAt,\n t,\n useSession,\n}: TurnTailNodeViewProps) {\n const data = node.data;\n const hasLaterChatNode = useSession(\n (snapshot) => snapshot.chat.locations.getTurn(data.turn).at(-1) !== node.key,\n );\n const turn =\n node.location.kind === \"turn\" || node.location.kind === \"step\" ? node.location.turn : undefined;\n if (turn === undefined) return null;\n const closing = data.closing;\n const tail = null;\n if (closing === null) return tail === null ? null : <div className={css.root}>{tail}</div>;\n const runMs =\n turn.start === undefined || turn.end === undefined\n ? undefined\n : Math.max(0, turn.end.time - turn.start.time);\n return (\n <div className={css.root} data-turn-tail={data.turn} data-time-hover-root>\n <MessageIconActions\n text={assistantText(closing.blocks)}\n time={closing.time}\n runMs={runMs}\n ttftMs={data.ttftMs}\n tokensPerSecond={data.tokensPerSecond}\n clock=\"end\"\n onBranch={() => {\n forkAt(closing.finalNode.seq);\n }}\n branchUnavailable={data.branchUnavailable || hasLaterChatNode}\n className={css.actions}\n t={t}\n />\n </div>\n );\n});\n","/**\n * Register this package's chat-node renderers behind the keyed\n * `conversation.chat.node` seat. Every key is re-registered at `priority: -1`\n * so the lowest priority wins and the upstream renderers are shadowed without\n * touching `@deepseek-ai/*`. The per-session editor face is injected so the\n * copied renderers can drive edit / retry directly.\n */\n\nimport type { Context } from \"@deepseek-ai/cordis\";\nimport type { SessionId } from \"@deepseek-ai/dsh-client-runtime/client\";\nimport \"@deepseek-ai/dsh-client-ui-conversation/client\";\nimport { AssistantNodeView } from \"./AssistantNodeView.tsx\";\nimport { CommandNodeView, ManualCompactionNodeView } from \"./CommandNodeView.tsx\";\nimport {\n CompactionNodeView,\n ContextMessageNodeView,\n RetryNodeView,\n TurnErrorNodeView,\n TurnMaxTokensNodeView,\n UnknownNodeView,\n UserMessageNodeView,\n} from \"./MessageItem.tsx\";\nimport { TurnTailNodeView } from \"./TurnTailNodeView.tsx\";\nimport type { SessionEditorController } from \"../controller.ts\";\n\n/** `conversation` 字典命名空间(与上游一致)。 */\nconst NS = \"conversation\";\n\n/** 注册全部 chat-node key;priority -1 替换上游渲染。 */\nexport function registerChatNodeRenderers(\n ctx: Context,\n controllerFor: (sessionId: SessionId) => SessionEditorController,\n): void {\n const inject = (sessionId: SessionId) => controllerFor(sessionId).face;\n\n ctx.slots.register(\n { name: \"conversation.chat.node\", key: \"user\", locale: NS, priority: -1, inject },\n UserMessageNodeView,\n );\n ctx.slots.register(\n { name: \"conversation.chat.node\", key: \"steering\", locale: NS, priority: -1, inject },\n UserMessageNodeView,\n );\n ctx.slots.register(\n { name: \"conversation.chat.node\", key: \"context\", locale: NS, priority: -1, inject },\n ContextMessageNodeView,\n );\n ctx.slots.register(\n { name: \"conversation.chat.node\", key: \"assistant-step\", locale: NS, priority: -1, inject },\n AssistantNodeView,\n );\n ctx.slots.register(\n // command / turn-tail 的 children 由上游声明(commandview / turnTail /\n // assistant-actions);shadow 注册不重复声明,仅替换渲染器。\n { name: \"conversation.chat.node\", key: \"command\", locale: NS, priority: -1, inject } as never,\n CommandNodeView as never,\n );\n ctx.slots.register(\n { name: \"conversation.chat.node\", key: \"manual-compaction\", locale: NS, priority: -1, inject },\n ManualCompactionNodeView,\n );\n ctx.slots.register(\n { name: \"conversation.chat.node\", key: \"compaction\", locale: NS, priority: -1, inject },\n CompactionNodeView,\n );\n ctx.slots.register(\n { name: \"conversation.chat.node\", key: \"model-retry\", locale: NS, priority: -1, inject },\n RetryNodeView,\n );\n ctx.slots.register(\n { name: \"conversation.chat.node\", key: \"turn-error\", locale: NS, priority: -1, inject },\n TurnErrorNodeView,\n );\n ctx.slots.register(\n { name: \"conversation.chat.node\", key: \"turn-max-tokens\", locale: NS, priority: -1, inject },\n TurnMaxTokensNodeView,\n );\n ctx.slots.register(\n // 见 command:turnTail / assistant-actions 的 children 由上游声明。\n { name: \"conversation.chat.node\", key: \"turn-tail\", locale: NS, priority: -1, inject } as never,\n TurnTailNodeView as never,\n );\n ctx.slots.register(\n { name: \"conversation.chat.node\", key: \"unknown\", locale: NS, priority: -1, inject },\n UnknownNodeView,\n );\n}\n","/**\n * 会话头部「清洗会话」入口。\n *\n * 仅当会话历史加载失败(会话 snapshot 的 `openState === \"error\"`)时渲染:\n * 点击调用服务端 cleanse,把该会话的 sourceEventSeqs / surfaceOp /\n * shadowedRange 坐标一次性重写为稠密空间,成功后客户端 resync 重新加载\n * 历史。注入面来自 `SessionEditorFace`(hooks → `useSessionEditor`,\n * 方法 → `cleanse`)。\n */\n\nimport { useCallback, useState, type ReactElement } from \"react\";\nimport { Button, IconRefreshOutline16 } from \"@deepseek-ai/dsh-client-ui-primitives\";\nimport type { SessionEditorState } from \"./controller.ts\";\n\nexport interface CleanseSessionActionProps {\n /** inject hooks:订阅 sessionEditor 状态。 */\n useSessionEditor: <S>(sel: (s: SessionEditorState) => S) => S;\n /** inject face:发起清洗。 */\n cleanse: () => Promise<boolean>;\n}\n\n/**\n * 历史加载失败时显示「清洗会话」按钮。\n * @param props - 注入的 selector 钩子与清洗方法。\n * @returns 按钮元素;会话未处于错误状态时返回 null。\n */\nexport function CleanseSessionAction({\n useSessionEditor,\n cleanse,\n}: CleanseSessionActionProps): ReactElement | null {\n const openError = useSessionEditor((s) => s.sessionOpenError);\n const cleansing = useSessionEditor((s) => s.pending === \"cleanse\");\n const [busy, setBusy] = useState(false);\n const onClick = useCallback(() => {\n setBusy(true);\n void cleanse().finally(() => setBusy(false));\n }, [cleanse]);\n if (!openError) return null;\n const working = busy || cleansing;\n return (\n <Button\n variant=\"outline\"\n size=\"sm\"\n icon={<IconRefreshOutline16 />}\n onClick={onClick}\n disabled={working}\n title=\"清洗会话:把 provenance 坐标重写为稠密空间,修复历史加载失败\"\n >\n {working ? \"清洗中…\" : \"清洗会话\"}\n </Button>\n );\n}\n","/**\n * Session Editor browser half: the chat-node renderers that replace the\n * upstream `conversation.chat.node` registrations (priority shadow) so the\n * edit / retry entry points render directly in the message actions row.\n */\n\nimport type { ClientContext, SessionId } from \"@deepseek-ai/dsh-client-runtime/client\";\nimport type {} from \"@deepseek-ai/dsh-client-ui-conversation/client\";\nimport { SessionEditorController } from \"./controller.ts\";\nimport { registerChatNodeRenderers } from \"./chat-node/register.ts\";\nimport { CleanseSessionAction } from \"./cleanse-session-action.tsx\";\n\nexport const inject = [\"slots\", \"conversation\", \"connection\", \"sessions\"];\n\n/** 注册 UI 贡献 + chat-node renderer,共享同一 per-session controller。 */\nexport function apply(ctx: ClientContext): void {\n const controllers = new Map<SessionId, SessionEditorController>();\n const controllerFor = (sessionId: SessionId): SessionEditorController => {\n let controller = controllers.get(sessionId);\n if (controller === undefined) {\n controller = new SessionEditorController(ctx, sessionId);\n controllers.set(sessionId, controller);\n }\n return controller;\n };\n\n ctx.on(\"connection/reset\", () => {\n for (const controller of controllers.values()) void controller.load();\n });\n\n // 替换整个 conversation.chat.node:priority -1 最低渲染,shadow 上游注册。\n registerChatNodeRenderers(ctx, controllerFor);\n\n // 会话头部「清洗会话」入口:仅历史加载失败(openState === \"error\")时\n // 显示。header.actions 是 list 槽(注册需 id),上游未注册组件——这里是\n // 纯新增,无 shadow 冲突;priority -1 与其它注入面一致。\n ctx.slots.register(\n {\n name: \"conversation.session.header.actions\",\n id: \"session-editor.cleanse\",\n priority: -1,\n inject: (sessionId: SessionId) => controllerFor(sessionId).face,\n } as never,\n CleanseSessionAction as never,\n );\n}\n"],"mappings":"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"}
|