@sh1robana/dsh-plugin-message-edit 0.3.2 → 0.3.3
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/CHANGELOG.md +10 -0
- package/NOTICE.md +2 -2
- package/README.md +6 -5
- package/build-info.json +6 -6
- package/client.js +75 -75
- package/client.js.map +1 -1
- package/docs//345/217/221/345/270/203/346/214/207/345/215/227.md +10 -10
- package/index.mjs +3 -3
- package/package.json +145 -141
package/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","names":["styles","styles","styles","styles","styles","styles","styles"],"sources":["shared.ts","transport.ts","saved-user-messages.ts","build-info.ts","attachmentTools.ts","composerTools.ts","controller.ts","confirmCancelEdit.ts","AttachmentEditor.tsx","fileReferences.ts","RichMessageInput.ts","MessageComposer.ts","InlineMessageEdit.tsx","MessageEditHeader.tsx","MessageEditTimelineView.tsx","UserMessageProjection.tsx","index.ts"],"sourcesContent":["import type { ContentBlock } from '@deepseek-ai/dsh-llm'\r\n\r\n/** Same-origin endpoint owned by the Message Edit host plugin. */\r\nexport const MESSAGE_EDIT_PATH = '/api/message-edit'\r\n\r\n/** Timeline sits between Trajectory (10) and Prompt Studio (20). */\r\nexport const MESSAGE_EDIT_VIEW_ORDER = 15\r\n\r\n/** Downstream-history policy after a historical turn changes. */\r\nexport type CascadePolicy = 'truncate' | 'preserve'\r\n\r\n/** User-visible operation represented by one child version. */\r\nexport type VersionOperation = 'edit' | 'reroll' | 'retry'\r\n\r\n/** Editable model-surface block classification. */\r\nexport type EditableBlockKind = 'user' | 'assistant.reasoning' | 'assistant.response'\r\n\r\n/** 附件沿用宿主的持久内容块,保留显示名称、尺寸和卸载状态。 */\r\nexport type MessageEditAttachmentBlock = Extract<ContentBlock, { type: 'image' | 'file' }>\r\n\r\n/** 已有附件通过当前消息中的内容块位置保留,客户端不提交持久引用。 */\r\nexport interface EditableMessageAttachment {\r\n blockIndex: number\r\n content: MessageEditAttachmentBlock\r\n}\r\n\r\n/** 新附件复用官方草稿序列化格式;文件凭据只能在来源 Agent 内解析。 */\r\nexport type MessageEditAttachmentInput = {\r\n type: 'retained'\r\n blockIndex: number\r\n} | {\r\n type: 'image'\r\n mediaType: 'image/png' | 'image/jpeg' | 'image/webp' | 'image/gif'\r\n data: string\r\n name?: string\r\n} | {\r\n type: 'file'\r\n receiptId: string\r\n}\r\n\r\n/** 编辑器中的会话配置草稿,只有确认保存后才应用到目标会话。 */\r\nexport interface MessageEditSettings {\r\n provider?: string\r\n model?: string\r\n reasoningEffort?: string\r\n permissionPreset?: string\r\n}\r\n\r\n/** 供编辑器复用正常输入框的模型、推理和权限选项。 */\r\nexport interface MessageEditComposerOptions {\r\n current: MessageEditSettings\r\n models: readonly {\r\n provider: string\r\n providerLabel?: string\r\n model: string\r\n label: string\r\n reasoningEfforts: readonly string[]\r\n reasoningEffortLabels?: Readonly<Record<string, string>>\r\n }[]\r\n permissions: readonly { id: string; label: string; description?: string }[]\r\n}\r\n\r\n/** 官方工作区文件候选的编辑器展示格式。 */\r\nexport interface MessageEditReference {\r\n path: string\r\n label: string\r\n kind: 'file' | 'folder'\r\n}\r\n\r\n/** Current durable event schema for structurally paired version effects. */\r\nexport const MESSAGE_EDIT_VERSION_SCHEMA = 2\r\n\r\n/** Forward half of one atomic version effect. */\r\nexport interface MessageEditEffect {\r\n id: string\r\n operation: VersionOperation\r\n cascade: CascadePolicy\r\n targetTurn: number\r\n targetEventSeq: number\r\n targetBlockIndex?: number\r\n blockKind?: EditableBlockKind\r\n before?: string\r\n after?: string\r\n /** 用户消息编辑是否重新请求模型;旧版本未记录时沿用原有行为。 */\r\n regenerate?: boolean\r\n}\r\n\r\n/** Inverse half generated together with a version effect. */\r\nexport interface MessageEditInverse {\r\n kind: 'restore-version'\r\n sessionId: string\r\n}\r\n\r\n/** Durable effect/inverse pair appended to each branch created by this plugin. */\r\nexport interface MessageEditVersionEvent {\r\n schemaVersion: typeof MESSAGE_EDIT_VERSION_SCHEMA\r\n effect: MessageEditEffect\r\n inverse: MessageEditInverse\r\n}\r\n\r\n/** Read compatibility for branches written before structural pairing. */\r\nexport interface LegacyMessageEditVersionEvent {\r\n sourceSessionId: string\r\n operation: VersionOperation\r\n cascade: CascadePolicy\r\n targetTurn: number\r\n targetEventSeq: number\r\n targetBlockIndex?: number\r\n blockKind?: EditableBlockKind\r\n before?: string\r\n after?: string\r\n}\r\n\r\n/** Every durable event shape accepted by the lineage reader. */\r\nexport type StoredMessageEditVersionEvent = MessageEditVersionEvent | LegacyMessageEditVersionEvent\r\n\r\n/** One text-bearing block that the Timeline editor can replace. */\r\nexport interface EditableMessageBlock {\r\n key: string\r\n turn: number\r\n eventSeq: number\r\n blockIndex: number\r\n kind: EditableBlockKind\r\n text: string\r\n time: number\r\n /** 用户消息的最新完整内容,供官方气泡同时投影正文和附件。 */\r\n content?: readonly ContentBlock[]\r\n attachments?: readonly EditableMessageAttachment[]\r\n}\r\n\r\n/** One completed message-triggered turn eligible for Retry. */\r\nexport interface RetryableTurn {\r\n turn: number\r\n userEventSeq: number\r\n preview: string\r\n time: number\r\n}\r\n\r\n/** One session version in the complete known lineage tree. */\r\nexport interface VersionSummary {\r\n sessionId: string\r\n parentSessionId?: string\r\n effectId?: string\r\n inverseSessionId?: string\r\n createdAt: number\r\n depth: number\r\n current: boolean\r\n onCurrentEffectPath: boolean\r\n /** 其他版本无法读取时保留节点并说明原因,禁止切换到该版本。 */\r\n unavailableReason?: string\r\n operation?: VersionOperation\r\n cascade?: CascadePolicy\r\n targetTurn?: number\r\n blockKind?: EditableBlockKind\r\n before?: string\r\n after?: string\r\n}\r\n\r\n/** Complete value-level projection consumed by both Timeline and header controls. */\r\nexport interface MessageEditTimeline {\r\n sessionId: string\r\n messages: EditableMessageBlock[]\r\n retryableTurns: RetryableTurn[]\r\n versions: VersionSummary[]\r\n /** Atomic inverses from the current version outward, in application order. */\r\n undoStack: string[]\r\n /** Direct child effects that can be re-applied from the current version. */\r\n redoSessionIds: string[]\r\n /** 实际加载的宿主构建,供客户端识别前后端版本不一致。 */\r\n build?: MessageEditBuildInfo\r\n}\r\n\r\n/** 构建身份不包含会话内容或本机路径。 */\r\nexport interface MessageEditBuildInfo {\r\n version: string\r\n buildId: string\r\n targetDshVersion: string\r\n}\r\n\r\n/** 原地保存的只读修订链;active 为 false 时禁止拿旧节点直接执行操作。 */\r\nexport interface MessageEditRevision {\r\n originalEventSeq: number\r\n replacementEventSeq: number\r\n revisionEventSeqs: number[]\r\n active: boolean\r\n}\r\n\r\n/** Edit one text/reasoning block and regenerate from its turn boundary. */\r\nexport interface EditOperation {\r\n action: 'edit'\r\n sessionId: string\r\n eventSeq: number\r\n blockIndex: number\r\n text: string\r\n cascade: CascadePolicy\r\n /** 用户消息默认重新生成,false 表示保留已有对话且只保存文本。 */\r\n regenerate?: boolean\r\n /** 未提供时保留当前附件,空数组移除全部;仅用户消息接受此字段。 */\r\n attachments?: readonly MessageEditAttachmentInput[]\r\n settings?: MessageEditSettings\r\n}\r\n\r\n/** 在当前会话保存用户文本,不创建分支、不排入模型输入。 */\r\nexport interface SaveOperation {\r\n action: 'save'\r\n sessionId: string\r\n eventSeq: number\r\n blockIndex: number\r\n text: string\r\n /** 未提供时保留当前附件,空数组移除全部。 */\r\n attachments?: readonly MessageEditAttachmentInput[]\r\n settings?: MessageEditSettings\r\n}\r\n\r\n/** Regenerate the latest completed assistant reply. */\r\nexport interface RerollOperation {\r\n action: 'reroll'\r\n sessionId: string\r\n}\r\n\r\n/** Regenerate any selected historical turn. */\r\nexport interface RetryOperation {\r\n action: 'retry'\r\n sessionId: string\r\n turn: number\r\n cascade: CascadePolicy\r\n}\r\n\r\n/** Mutation accepted by the host route. */\r\nexport type MessageEditOperation = SaveOperation | EditOperation | RerollOperation | RetryOperation\r\n\r\n/** 当前会话保存或新版本创建完成后的宿主确认。 */\r\nexport interface MessageEditOperationResult {\r\n sessionId: string\r\n queuedTurns: number\r\n /** 仅保存时为 true,且 sessionId 必须仍为来源会话。 */\r\n saved?: boolean\r\n /** 内容及设置没有变化,未写事件、未创建分支,也未请求模型。 */\r\n unchanged?: boolean\r\n}\r\n","import type { ClientTransportHooks } from '@deepseek-ai/dsh-client-connection/client'\n\n/** 使用页面提供的宿主传输,兼容桌面端的自定义协议和普通 Web 页面。 */\nexport function hostFetch(input: string, init: RequestInit): Promise<Response> {\n const globals = globalThis as typeof globalThis & { __DSH_TRANSPORT__?: ClientTransportHooks }\n const path = input.replace(/^\\//, '')\n const transport = globals.__DSH_TRANSPORT__\n return transport?.fetch !== undefined\n ? transport.fetch(path, init)\n : globalThis.fetch(path, init)\n}\n","import type { SessionEvent } from '@deepseek-ai/dsh-session'\nimport type { UserMessage } from '@deepseek-ai/dsh-llm'\n\n/** 使用已知用户消息替换事件记录编辑,原日志与消息身份保持不变。 */\nexport interface SavedUserMessageSource {\n messageEdit?: { originalEventSeq: number }\n}\n\nexport function savedUserMessageSeq(event: SessionEvent): number | undefined {\n if (event.type !== 'user/message' || typeof event.surfaceOp !== 'object' || event.surfaceOp.op !== 'replace') return undefined\n const metadata = (event.data.source as UserMessage['source'] & SavedUserMessageSource).messageEdit\n const original = metadata?.originalEventSeq\n return Number.isSafeInteger(original) && (original as number) >= 0 ? original : undefined\n}\n\n/** 为聊天和历史操作还原用户可见文本;官方替换事件本身不增加聊天行。 */\nexport function savedUserMessages(events: readonly SessionEvent[]): Map<number, SessionEvent<'user/message'>> {\n const result = new Map<number, SessionEvent<'user/message'>>()\n for (const event of events) {\n const originalSeq = savedUserMessageSeq(event)\n if (originalSeq === undefined || event.type !== 'user/message') continue\n const original = events[originalSeq]\n if (original?.type !== 'user/message' || original.surfaceOp !== 'append' || original.data.id !== event.data.id) continue\n result.set(originalSeq, event)\n }\n return result\n}\n\nexport function visibleUserEvents(events: readonly SessionEvent[]): readonly SessionEvent[] {\n const saved = savedUserMessages(events)\n if (saved.size === 0) return events\n return events.map(event => {\n const replacement = saved.get(event.seq)\n return replacement === undefined ? event : { ...event, data: replacement.data } as SessionEvent\n })\n}\n","/** 由构建脚本生成;前后端共享同一份构建身份。 */\nexport const MESSAGE_EDIT_BUILD_INFO = Object.freeze({\n \"version\": \"0.3.2\",\n \"buildId\": \"dd2956d22ba2bccbd0c2\",\n \"targetDshVersion\": \"0.2.1-rc.2\"\n})\n","import type { Context } from '@deepseek-ai/cordis'\nimport type { ImageAttachmentRef } from '@deepseek-ai/dsh-attachment'\nimport type {\n ComposerAttachment,\n ConversationController,\n DraftAttachmentId,\n DraftFileUploads,\n SubmitAttachment,\n} from '@deepseek-ai/dsh-client-ui-conversation/client'\nimport type { SessionId } from '@deepseek-ai/dsh-session/types'\n\n/** 附件草稿独立于主输入框,沿用官方上传、序列化与资源释放流程。 */\nexport interface MessageAttachmentTools {\n create(files: readonly File[]): readonly ComposerAttachment[]\n serialize(ids: readonly DraftAttachmentId[]): Promise<readonly SubmitAttachment[]>\n release(id: DraftAttachmentId): void\n retry(id: DraftAttachmentId): void\n uploads(): DraftFileUploads\n subscribe(listener: () => void): () => void\n imageUrl(attachment: ImageAttachmentRef): Promise<string>\n}\n\nexport function attachmentTools(ctx: Context, sessionId: SessionId): MessageAttachmentTools {\n const conversation = (): ConversationController => {\n const service = ctx.get('conversation') as ConversationController | undefined\n if (service === undefined) throw new Error('DSH 附件服务尚未就绪,请重启后重试。')\n return service\n }\n return {\n create: files => conversation().createDrafts(sessionId, files),\n serialize: async ids => (await conversation().serializeDraftAttachments(ids)).attachments,\n release: id => { conversation().releaseDraftAttachment(id) },\n retry: id => { conversation().retryFileUpload(sessionId, id) },\n uploads: () => conversation().fileUploads.getSnapshot(),\n subscribe: listener => conversation().fileUploads.subscribe(listener),\n imageUrl: attachment => ctx.uiConversation.imageUrl(sessionId, attachment),\n }\n}\n","import type { Context } from '@deepseek-ai/cordis'\nimport type { ISessions } from '@deepseek-ai/dsh-api-session-controller/client'\nimport type { SessionId } from '@deepseek-ai/dsh-session/types'\nimport { MESSAGE_EDIT_PATH, type MessageEditComposerOptions, type MessageEditSettings } from '../shared.ts'\nimport { hostFetch } from './transport.ts'\n\nexport interface ComposerModelOption {\n provider: string\n model: string\n label: string\n reasoningEfforts: readonly string[]\n}\n\nexport type ComposerSettings = MessageEditSettings\nexport type ComposerOptions = MessageEditComposerOptions\n\nexport type ComposerReference = {\n path: string\n label: string\n kind: 'file' | 'folder'\n} | { sessionId: string; mention: string; label: string; kind: 'session' }\n\nexport interface ComposerCommand {\n name: string\n label?: string\n description?: string\n hint?: string\n section?: string\n}\n\ninterface CommandUiService {\n candidates(scope: { sessionId: SessionId }, request: { query: string; position: 'leading'; signal: AbortSignal }): Promise<readonly ComposerCommand[]>\n execute(scope: { sessionId: SessionId }, line: string): Promise<{ kind: 'success' } | { kind: 'error'; text: string }>\n}\n\n/** 编辑器使用同一宿主服务,但不写入主输入框的 SessionInput。 */\nexport interface MessageComposerTools {\n options(): Promise<ComposerOptions>\n references(query: string, signal: AbortSignal): Promise<readonly ComposerReference[]>\n openPath(path: string): Promise<void>\n openSession(sessionId: string): void\n openAttachment(eventSeq: number, blockIndex: number): Promise<void>\n openUpload(receiptId: string): Promise<void>\n command(line: string): Promise<void>\n commands(query: string, signal: AbortSignal): Promise<readonly ComposerCommand[]>\n}\n\nasync function readResponse(response: Response): Promise<unknown> {\n const value = await response.json() as { error?: string }\n if (!response.ok) throw new Error(value.error ?? `请求失败:HTTP ${String(response.status)}`)\n return value\n}\n\nexport function composerTools(ctx: Context, sessionId: SessionId): MessageComposerTools {\n const get = async (query: Record<string, string>, signal?: AbortSignal): Promise<unknown> => {\n const params = new URLSearchParams({ sessionId, ...query })\n return readResponse(await hostFetch(`${MESSAGE_EDIT_PATH}?${params}`, {\n method: 'GET', cache: 'no-store', ...signal === undefined ? {} : { signal },\n }))\n }\n const post = async (operation: Record<string, unknown>): Promise<void> => {\n await readResponse(await hostFetch(MESSAGE_EDIT_PATH, {\n method: 'POST', headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ sessionId, ...operation }),\n }))\n }\n return {\n options: async () => await get({ view: 'options' }) as ComposerOptions,\n references: async (query, signal) => {\n const remote = ctx.get('remote') as unknown as { sessionReferenceResolver?: {\n candidates(sessionId: SessionId, query: string, signal: AbortSignal): Promise<{ ok: true; value: readonly { sessionId: string; mention: string; label: string }[] } | { ok: false; error: { message: string } }>\n } } | undefined\n const [files, sessions] = await Promise.all([\n get({ view: 'references', query }, signal) as Promise<readonly ComposerReference[]>,\n remote?.sessionReferenceResolver?.candidates(sessionId, query, signal),\n ])\n return [...files, ...sessions?.ok ? sessions.value.map(item => ({ ...item, kind: 'session' as const })) : []]\n },\n openPath: path => post({ action: 'open-reference', path }),\n openSession: id => { ctx.uiWorkspace.openSession(id as SessionId) },\n openAttachment: (eventSeq, blockIndex) => post({ action: 'open-attachment', eventSeq, blockIndex }),\n openUpload: receiptId => post({ action: 'open-upload', receiptId }),\n commands: async (query, signal) => {\n const commands = ctx.get('commandUi') as unknown as CommandUiService | undefined\n return commands === undefined ? [] : commands.candidates({ sessionId }, { query, position: 'leading', signal })\n },\n command: async line => {\n const commands = ctx.get('commandUi') as unknown as CommandUiService | undefined\n if (commands !== undefined) {\n const result = await commands.execute({ sessionId }, line)\n if (result.kind === 'error') throw new Error(result.text)\n return\n }\n const sessions = ctx.get('sessions') as unknown as ISessions\n const session = sessions.binding(sessionId)?.session\n if (session === undefined) throw new Error('当前会话尚未就绪,请稍后重试。')\n const result = await session.command(line)\n if (!result.ok) throw new Error(result.error.message)\n if (!result.value.matched) throw new Error('当前 DSH 未提供此指令。')\n },\n }\n}\n","/** Browser controller for one session's Timeline projection and branch mutations. */\r\nimport type { Context } from '@deepseek-ai/cordis'\r\nimport type {\r\n ISessions,\r\n SessionEventSource,\r\n SessionEventWindow,\r\n SessionListState,\r\n} from '@deepseek-ai/dsh-api-session-controller/client'\r\nimport type { SessionId } from '@deepseek-ai/dsh-session/types'\r\nimport { createSnapshotStore, type ObservableSnapshot, type SnapshotStore } from '@deepseek-ai/dsh-client-store'\r\nimport type {} from '@deepseek-ai/dsh-client-ui-workspace/client'\r\nimport { hostFetch } from './transport.ts'\r\nimport { savedUserMessageSeq } from '../saved-user-messages.ts'\r\nimport { MESSAGE_EDIT_BUILD_INFO } from '../build-info.ts'\r\nimport { attachmentTools, type MessageAttachmentTools } from './attachmentTools.ts'\r\nimport { composerTools, type ComposerSettings, type MessageComposerTools } from './composerTools.ts'\r\nimport {\r\n MESSAGE_EDIT_PATH,\r\n type CascadePolicy,\r\n type EditableBlockKind,\r\n type EditableMessageBlock,\r\n type MessageEditAttachmentInput,\r\n type MessageEditOperation,\r\n type MessageEditOperationResult,\r\n type MessageEditTimeline,\r\n type RetryableTurn,\r\n type VersionOperation,\r\n type VersionSummary,\r\n} from '../shared.ts'\r\n\r\n/** Reactive controller state shared by the Timeline and header entries. */\r\nexport interface MessageEditState {\r\n status: 'idle' | 'loading' | 'ready' | 'error'\r\n error: string | null\r\n pending: VersionOperation | null\r\n timeline: MessageEditTimeline | null\r\n}\r\n\r\n/** 合并回合完成时的后台刷新,不延迟首次加载。 */\r\nconst REFRESH_DELAY_MS = 300\r\n\r\n/** Plain business face; the renderer binds the reserved source compartment. */\r\nexport interface MessageEditFace {\r\n hooks: { messageEdit: ObservableSnapshot<MessageEditState> }\r\n acquire(): () => void\r\n load(): void\r\n edit(message: EditableMessageBlock, text: string, cascade: CascadePolicy, regenerate?: boolean, attachments?: readonly MessageEditAttachmentInput[], settings?: ComposerSettings): Promise<boolean>\r\n attachmentTools: MessageAttachmentTools\r\n composerTools: MessageComposerTools\r\n retry(turn: number, cascade: CascadePolicy): Promise<boolean>\r\n reroll(): Promise<boolean>\r\n openVersion(sessionId: string): Promise<void>\r\n}\r\n\r\nfunction messageOf(error: unknown): string {\r\n return error instanceof Error ? error.message : String(error)\r\n}\r\n\r\nfunction objectValue(value: unknown, label: string): Record<string, unknown> {\r\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\r\n throw new TypeError(`${label} 不是对象`)\r\n }\r\n return value as Record<string, unknown>\r\n}\r\n\r\nfunction stringValue(value: unknown, label: string): string {\r\n if (typeof value !== 'string') throw new TypeError(`${label} 不是字符串`)\r\n return value\r\n}\r\n\r\nfunction numberValue(value: unknown, label: string): number {\r\n if (typeof value !== 'number' || !Number.isFinite(value)) throw new TypeError(`${label} 不是数字`)\r\n return value\r\n}\r\n\r\nfunction booleanValue(value: unknown, label: string): boolean {\r\n if (typeof value !== 'boolean') throw new TypeError(`${label} 不是布尔值`)\r\n return value\r\n}\r\n\r\nfunction blockKind(value: unknown): EditableBlockKind {\r\n if (value !== 'user' && value !== 'assistant.reasoning' && value !== 'assistant.response') {\r\n throw new TypeError('消息块类型无效')\r\n }\r\n return value\r\n}\r\n\r\nfunction decodeMessage(value: unknown, index: number): EditableMessageBlock {\r\n const row = objectValue(value, `messages[${String(index)}]`)\r\n return {\r\n key: stringValue(row['key'], '消息 key'),\r\n turn: numberValue(row['turn'], '消息 turn'),\r\n eventSeq: numberValue(row['eventSeq'], '消息 eventSeq'),\r\n blockIndex: numberValue(row['blockIndex'], '消息 blockIndex'),\r\n kind: blockKind(row['kind']),\r\n text: stringValue(row['text'], '消息 text'),\r\n time: numberValue(row['time'], '消息 time'),\r\n ...row['content'] === undefined ? {} : { content: arrayValue(row['content'], '消息 content') as EditableMessageBlock['content'] & {} },\r\n ...row['attachments'] === undefined ? {} : { attachments: arrayValue(row['attachments'], '消息 attachments') as EditableMessageBlock['attachments'] & {} },\r\n }\r\n}\r\n\r\nfunction decodeRetryable(value: unknown, index: number): RetryableTurn {\r\n const row = objectValue(value, `retryableTurns[${String(index)}]`)\r\n return {\r\n turn: numberValue(row['turn'], '回合 turn'),\r\n userEventSeq: numberValue(row['userEventSeq'], '回合 userEventSeq'),\r\n preview: stringValue(row['preview'], '回合 preview'),\r\n time: numberValue(row['time'], '回合 time'),\r\n }\r\n}\r\n\r\nfunction optionalOperation(value: unknown): VersionOperation | undefined {\r\n if (value === undefined) return undefined\r\n if (value === 'edit' || value === 'reroll' || value === 'retry') return value\r\n throw new TypeError('版本 operation 无效')\r\n}\r\n\r\nfunction decodeVersion(value: unknown, index: number): VersionSummary {\r\n const row = objectValue(value, `versions[${String(index)}]`)\r\n const operation = optionalOperation(row['operation'])\r\n const cascade = row['cascade']\r\n if (cascade !== undefined && cascade !== 'truncate' && cascade !== 'preserve') {\r\n throw new TypeError('版本 cascade 无效')\r\n }\r\n const kind = row['blockKind'] === undefined ? undefined : blockKind(row['blockKind'])\r\n return {\r\n sessionId: stringValue(row['sessionId'], '版本 sessionId'),\r\n ...row['parentSessionId'] === undefined\r\n ? {}\r\n : { parentSessionId: stringValue(row['parentSessionId'], '版本 parentSessionId') },\r\n ...row['effectId'] === undefined\r\n ? {}\r\n : { effectId: stringValue(row['effectId'], '版本 effectId') },\r\n ...row['inverseSessionId'] === undefined\r\n ? {}\r\n : { inverseSessionId: stringValue(row['inverseSessionId'], '版本 inverseSessionId') },\r\n createdAt: numberValue(row['createdAt'], '版本 createdAt'),\r\n depth: numberValue(row['depth'], '版本 depth'),\r\n current: booleanValue(row['current'], '版本 current'),\r\n onCurrentEffectPath: booleanValue(row['onCurrentEffectPath'], '版本 onCurrentEffectPath'),\r\n ...operation === undefined ? {} : { operation },\r\n ...cascade === undefined ? {} : { cascade },\r\n ...row['targetTurn'] === undefined ? {} : { targetTurn: numberValue(row['targetTurn'], '版本 targetTurn') },\r\n ...kind === undefined ? {} : { blockKind: kind },\r\n ...row['before'] === undefined ? {} : { before: stringValue(row['before'], '版本 before') },\r\n ...row['after'] === undefined ? {} : { after: stringValue(row['after'], '版本 after') },\r\n ...row['unavailableReason'] === undefined ? {} : { unavailableReason: stringValue(row['unavailableReason'], '版本 unavailableReason') },\r\n }\r\n}\r\n\r\nfunction arrayValue(value: unknown, label: string): unknown[] {\r\n if (!Array.isArray(value)) throw new TypeError(`${label} 不是数组`)\r\n return value\r\n}\r\n\r\nfunction stringArray(value: unknown, label: string): string[] {\r\n return arrayValue(value, label).map((item, index) => stringValue(item, `${label}[${String(index)}]`))\r\n}\r\n\r\nfunction decodeTimeline(value: unknown): MessageEditTimeline {\r\n const data = objectValue(value, 'Timeline 响应')\r\n return {\r\n sessionId: stringValue(data['sessionId'], 'Timeline sessionId'),\r\n messages: arrayValue(data['messages'], 'Timeline messages').map(decodeMessage),\r\n retryableTurns: arrayValue(data['retryableTurns'], 'Timeline retryableTurns').map(decodeRetryable),\r\n versions: arrayValue(data['versions'], 'Timeline versions').map(decodeVersion),\r\n undoStack: stringArray(data['undoStack'], 'Timeline undoStack'),\r\n redoSessionIds: stringArray(data['redoSessionIds'], 'Timeline redoSessionIds'),\r\n }\r\n}\r\n\r\nfunction decodeOperationResult(value: unknown): MessageEditOperationResult {\r\n const data = objectValue(value, '操作响应')\r\n return {\r\n sessionId: stringValue(data['sessionId'], '操作 sessionId'),\r\n queuedTurns: numberValue(data['queuedTurns'], '操作 queuedTurns'),\r\n ...data['saved'] === undefined ? {} : { saved: booleanValue(data['saved'], '操作 saved') },\r\n ...data['unchanged'] === undefined ? {} : { unchanged: booleanValue(data['unchanged'], '操作 unchanged') },\r\n }\r\n}\r\n\r\nasync function responseValue(response: Response): Promise<unknown> {\r\n const value = await response.json() as unknown\r\n if (response.ok) return value\r\n const error = objectValue(value, '错误响应')['error']\r\n throw new Error(typeof error === 'string' ? error : `请求失败:HTTP ${String(response.status)}`)\r\n}\r\n\r\nfunction conversationRevision(snapshot: SessionEventWindow): string {\r\n const changes = snapshot.entries.flatMap(entry => {\r\n if (entry.type !== 'event') return []\r\n if (entry.event.type === 'turn/end') return [`turn:${String(entry.event.data.turn)}:${String(entry.event.seq)}`]\r\n if (savedUserMessageSeq(entry.event) !== undefined) return [`save:${String(entry.event.seq)}`]\r\n return []\r\n })\r\n return [snapshot.hasMore, changes.join(',')].join('|')\r\n}\r\n\r\nfunction lineageRevision(snapshot: SessionListState, sessionId: SessionId): string {\r\n let root = sessionId\r\n const ancestorIds = new Set<SessionId>()\r\n while (!ancestorIds.has(root)) {\r\n ancestorIds.add(root)\r\n const parent = snapshot.byId[root]?.parentId\r\n if (parent === undefined || snapshot.byId[parent] === undefined) break\r\n root = parent\r\n }\r\n\r\n const connected: string[] = []\r\n for (const rawId of Object.keys(snapshot.byId).sort()) {\r\n const id = rawId as SessionId\r\n const seen = new Set<SessionId>()\r\n let cursor: SessionId | undefined = id\r\n while (cursor !== undefined && !seen.has(cursor)) {\r\n if (cursor === root) {\r\n connected.push(`${id}>${snapshot.byId[id]?.parentId ?? ''}`)\r\n break\r\n }\r\n seen.add(cursor)\r\n cursor = snapshot.byId[cursor]?.parentId\r\n }\r\n }\r\n return connected.join('|')\r\n}\r\n\r\n/** One stable controller is shared by all entries mounted for the same session. */\r\nexport class MessageEditController {\r\n readonly store: SnapshotStore<MessageEditState> = createSnapshotStore<MessageEditState>({\r\n status: 'idle',\r\n error: null,\r\n pending: null,\r\n timeline: null,\r\n })\r\n\r\n readonly face: MessageEditFace\r\n private generation = 0\r\n private readonly ctx: Context\r\n private readonly sessions: ISessions\r\n private sessionSource: SessionEventSource | undefined\r\n private sessionSourceDispose: (() => void) | undefined\r\n private sessionRevision: string | undefined\r\n private listRevision = ''\r\n private refreshScheduled = false\r\n private refreshTimer: ReturnType<typeof setTimeout> | undefined\r\n private observing = false\r\n private disposeObservation: (() => Promise<void>) | undefined = undefined\r\n private inflight: Promise<void> | null = null\r\n private rerunAfter = false\r\n private abort: AbortController | null = null\r\n private disposed = false\r\n private users = 0\r\n\r\n constructor(\r\n ctx: Context,\r\n private readonly sessionId: SessionId,\r\n ) {\r\n this.ctx = ctx\r\n this.sessions = ctx.get('sessions') as unknown as ISessions\r\n this.face = {\r\n hooks: { messageEdit: this.store },\r\n acquire: () => {\r\n this.users += 1\r\n if (this.users === 1 && this.disposed) this.revive()\r\n return () => this.release()\r\n },\r\n load: () => {\r\n const status = this.store.getSnapshot().status\r\n if (status === 'idle' || status === 'error') void this.load()\r\n },\r\n attachmentTools: attachmentTools(ctx, this.sessionId),\r\n composerTools: composerTools(ctx, this.sessionId),\r\n edit: (message, text, cascade, regenerate = true, attachments, settings) => this.mutate(message.kind === 'user' && !regenerate ? {\r\n action: 'save',\r\n sessionId: this.sessionId,\r\n eventSeq: message.eventSeq,\r\n blockIndex: message.blockIndex,\r\n text,\r\n ...attachments === undefined ? {} : { attachments },\r\n ...settings === undefined ? {} : { settings },\r\n } : {\r\n action: 'edit',\r\n sessionId: this.sessionId,\r\n eventSeq: message.eventSeq,\r\n blockIndex: message.blockIndex,\r\n text,\r\n cascade,\r\n regenerate,\r\n ...attachments === undefined ? {} : { attachments },\r\n ...settings === undefined ? {} : { settings },\r\n }),\r\n retry: (turn, cascade) => this.mutate({\r\n action: 'retry',\r\n sessionId: this.sessionId,\r\n turn,\r\n cascade,\r\n }),\r\n reroll: () => this.mutate({ action: 'reroll', sessionId: this.sessionId }),\r\n openVersion: sessionId => this.openWhenListed(sessionId as SessionId),\r\n }\r\n this.observe()\r\n }\r\n\r\n private observe(): void {\r\n this.disposeObservation = this.ctx.effect(\r\n () => this.observeDependencies(),\r\n `message-edit: observe ${this.sessionId}`,\r\n )\r\n }\r\n\r\n private release(): void {\r\n this.users -= 1\r\n if (this.users <= 0) this.dispose()\r\n }\r\n\r\n /** Tear subscriptions down once no mounted entry uses this controller. */\r\n private dispose(): void {\r\n if (this.disposed) return\r\n this.disposed = true\r\n this.generation += 1\r\n if (this.refreshTimer !== undefined) {\r\n clearTimeout(this.refreshTimer)\r\n this.refreshTimer = undefined\r\n this.refreshScheduled = false\r\n }\r\n this.abort?.abort()\r\n this.abort = null\r\n void this.disposeObservation?.()\r\n this.disposeObservation = undefined\r\n }\r\n\r\n /** Re-observe after a transient zero; the retained store keeps old data\r\n * until the immediate refetch below commits. */\r\n private revive(): void {\r\n this.disposed = false\r\n this.observe()\r\n this.refresh()\r\n }\r\n\r\n /** Bind to replaceable value sources instead of retaining a Session object. */\r\n private observeDependencies(): () => void {\r\n this.observing = true\r\n this.listRevision = lineageRevision(this.sessions.list.getSnapshot(), this.sessionId)\r\n this.bindSessionSource()\r\n const disposeList = this.sessions.list.subscribe(() => {\r\n const rebound = this.bindSessionSource()\r\n const nextRevision = lineageRevision(this.sessions.list.getSnapshot(), this.sessionId)\r\n if (nextRevision === this.listRevision && !rebound) return\r\n this.listRevision = nextRevision\r\n this.invalidate()\r\n })\r\n return () => {\r\n this.observing = false\r\n this.generation += 1\r\n disposeList()\r\n this.sessionSourceDispose?.()\r\n this.sessionSourceDispose = undefined\r\n this.sessionSource = undefined\r\n this.sessionRevision = undefined\r\n }\r\n }\r\n\r\n private bindSessionSource(): boolean {\r\n const source = this.sessions.binding(this.sessionId)?.eventSource\r\n if (source === this.sessionSource) return false\r\n this.sessionSourceDispose?.()\r\n this.sessionSource = source\r\n this.sessionRevision = source === undefined ? undefined : conversationRevision(source.getSnapshot())\r\n this.sessionSourceDispose = source?.subscribe(() => {\r\n if (this.sessionSource !== source) return\r\n const revision = conversationRevision(source.getSnapshot())\r\n if (revision === this.sessionRevision) return\r\n this.sessionRevision = revision\r\n this.invalidate()\r\n })\r\n return true\r\n }\r\n\r\n private invalidate(): void {\r\n if (!this.observing || this.store.getSnapshot().status === 'idle' || this.refreshScheduled) return\r\n this.refreshScheduled = true\r\n this.refreshTimer = setTimeout(() => {\r\n this.refreshTimer = undefined\r\n this.refreshScheduled = false\r\n if (this.observing && this.store.getSnapshot().status !== 'idle') this.refresh()\r\n }, REFRESH_DELAY_MS)\r\n }\r\n\r\n /** Invalidation-driven refetch: one in-flight request absorbs the demand\r\n * and commits a single rerun once it settles. */\r\n private refresh(): void {\r\n if (this.disposed) return\r\n if (this.inflight !== null) {\r\n this.rerunAfter = true\r\n return\r\n }\r\n void this.load()\r\n }\r\n\r\n /** Refetch the full value-level projection; concurrent callers share one\r\n * request, and an invalidation during flight schedules exactly one rerun. */\r\n async load(): Promise<void> {\r\n if (this.disposed) return\r\n if (this.inflight !== null) return this.inflight\r\n const generation = ++this.generation\r\n this.abort?.abort()\r\n const abort = new AbortController()\r\n this.abort = abort\r\n this.store.update((state) => {\r\n // 已确认的消息在后台刷新时保持可操作,首次加载及错误恢复仍等待验证。\r\n if (state.status !== 'ready') state.status = 'loading'\r\n state.error = null\r\n })\r\n const run = this.performLoad(generation, abort)\r\n this.inflight = run\r\n try {\r\n await run\r\n } finally {\r\n if (this.inflight === run) this.inflight = null\r\n if (this.rerunAfter && !this.disposed) {\r\n this.rerunAfter = false\r\n void this.load()\r\n }\r\n }\r\n }\r\n\r\n private async performLoad(generation: number, abort: AbortController): Promise<void> {\r\n try {\r\n const response = await hostFetch(`${MESSAGE_EDIT_PATH}?sessionId=${encodeURIComponent(this.sessionId)}`, {\r\n method: 'GET',\r\n headers: { accept: 'application/json' },\r\n cache: 'no-store',\r\n signal: abort.signal,\r\n })\r\n const value = await responseValue(response)\r\n const build = objectValue(value, 'Timeline 响应')['build']\r\n if (build !== undefined) {\r\n const identity = objectValue(build, '宿主构建')\r\n if (identity['version'] !== MESSAGE_EDIT_BUILD_INFO.version || identity['buildId'] !== MESSAGE_EDIT_BUILD_INFO.buildId) {\r\n throw new Error('消息编辑插件的前后端版本不一致,请彻底退出 DSH 后重新启动;浏览器页面请刷新。')\r\n }\r\n }\r\n const timeline = decodeTimeline(value)\r\n if (generation !== this.generation) return\r\n this.store.update((state) => {\r\n state.status = 'ready'\r\n state.error = null\r\n state.timeline = timeline\r\n })\r\n } catch (error) {\r\n if (generation !== this.generation) return\r\n this.store.update((state) => {\r\n state.status = 'error'\r\n state.error = messageOf(error)\r\n })\r\n }\r\n }\r\n\r\n /** Refresh only controllers whose projection has already been requested. */\r\n refreshIfLoaded(): void {\r\n if (this.disposed || this.store.getSnapshot().status === 'idle') return\r\n this.refresh()\r\n }\r\n\r\n private async mutate(operation: MessageEditOperation): Promise<boolean> {\r\n const current = this.store.getSnapshot()\r\n if (current.pending !== null || current.status !== 'ready') return false\r\n this.store.update((state) => {\r\n state.pending = operation.action === 'save' ? 'edit' : operation.action\r\n state.error = null\r\n })\r\n try {\r\n const response = await hostFetch(MESSAGE_EDIT_PATH, {\r\n method: 'POST',\r\n headers: {\r\n accept: 'application/json',\r\n 'content-type': 'application/json',\r\n },\r\n body: JSON.stringify(operation),\r\n })\r\n const result = decodeOperationResult(await responseValue(response))\r\n if (result.unchanged === true && (result.sessionId !== this.sessionId || result.queuedTurns !== 0)) {\r\n throw new Error('宿主未确认无修改保存,请更新插件并重启 DSH。')\r\n }\r\n if (operation.action === 'save'\r\n && (result.sessionId !== this.sessionId || result.queuedTurns !== 0 || result.saved !== true)) {\r\n throw new Error('宿主未确认在当前会话保存,请更新插件并彻底重启 DSH。')\r\n }\r\n if (!this.disposed && result.unchanged !== true) {\r\n if (operation.action === 'save') {\r\n // 保存期间保留忙碌状态,并确保刷新不被保存前的在途请求吸收。\r\n if (this.inflight !== null) {\r\n this.rerunAfter = true\r\n await this.load()\r\n }\r\n await this.load()\r\n } else await this.openWhenListed(result.sessionId as SessionId)\r\n }\r\n this.store.update((state) => { state.pending = null })\r\n return true\r\n } catch (error) {\r\n this.store.update((state) => {\r\n state.pending = null\r\n if (!this.disposed) state.error = messageOf(error)\r\n })\r\n return false\r\n }\r\n }\r\n\r\n /** 通过新版工作区导航持有会话引用,并同步切换主视图。 */\r\n private async openWhenListed(sessionId: SessionId): Promise<void> {\r\n if (this.disposed) return\r\n await this.sessions.refresh()\r\n if (!this.disposed) this.ctx.uiWorkspace.openSession(sessionId)\r\n }\r\n}\r\n","import styles from './InlineMessageEdit.module.css'\n\n/** 确认取消时保留原编辑器,只有选择“是”才提交关闭操作。 */\nexport function confirmCancelEdit(onConfirm: () => void, onReject: () => void): () => void {\n const overlay = document.createElement('div')\n overlay.className = `${styles['overlay'] ?? ''} ${styles['confirmationOverlay'] ?? ''}`\n const panel = document.createElement('div')\n panel.className = styles['confirmPanel'] ?? ''\n panel.setAttribute('role', 'alertdialog')\n panel.setAttribute('aria-modal', 'true')\n panel.setAttribute('aria-label', '是否确认取消编辑')\n const title = document.createElement('div')\n title.className = styles['title'] ?? ''\n title.textContent = '是否确认取消编辑'\n const footer = document.createElement('div')\n footer.className = styles['footer'] ?? ''\n const yes = document.createElement('button')\n yes.type = 'button'\n yes.textContent = '是'\n const no = document.createElement('button')\n no.type = 'button'\n no.textContent = '否'\n footer.append(yes, no)\n panel.append(title, footer)\n overlay.appendChild(panel)\n document.body.appendChild(overlay)\n let mounted = true\n const dispose = (): void => {\n if (!mounted) return\n mounted = false\n yes.removeEventListener('click', confirm)\n no.removeEventListener('click', reject)\n overlay.removeEventListener('keydown', onKeyDown)\n overlay.remove()\n }\n const confirm = (): void => {\n if (!mounted) return\n dispose()\n onConfirm()\n }\n const reject = (): void => {\n if (!mounted) return\n dispose()\n onReject()\n }\n const onKeyDown = (event: KeyboardEvent): void => {\n if (event.key === 'Escape') {\n event.preventDefault()\n reject()\n } else if (event.key === 'Tab') {\n event.preventDefault()\n if (document.activeElement === no) yes.focus()\n else no.focus()\n }\n }\n yes.addEventListener('click', confirm)\n no.addEventListener('click', reject)\n overlay.addEventListener('keydown', onKeyDown)\n no.focus()\n return dispose\n}\n","import { useEffect, useRef, type ReactNode } from 'react'\nimport type { ComposerAttachment } from '@deepseek-ai/dsh-client-ui-conversation/client'\nimport type { EditableMessageAttachment, MessageEditAttachmentInput } from '../shared.ts'\nimport type { MessageAttachmentTools } from './attachmentTools.ts'\nimport styles from './InlineMessageEdit.module.css'\n\ntype AttachmentItem = { existing: EditableMessageAttachment } | { draft: ComposerAttachment }\n\nexport interface AttachmentEditorHandle {\n addFiles(files: readonly File[]): void\n pickFiles(): void\n serialize(): Promise<readonly MessageEditAttachmentInput[]>\n setDisabled(disabled: boolean): void\n dispose(): void\n}\n\nexport interface AttachmentEditorOptions {\n onFiles?(files: readonly File[]): void\n hideAdd?: boolean\n openExisting?(blockIndex: number): Promise<void>\n openDraft?(draft: ComposerAttachment): Promise<void>\n}\n\nfunction sizeLabel(bytes: number): string {\n if (bytes < 1024) return `${String(bytes)} B`\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`\n}\n\n/** 两种编辑入口共享附件草稿,关闭编辑器时仅释放新增附件。 */\nexport function mountAttachmentEditor(\n container: HTMLElement,\n initial: readonly EditableMessageAttachment[],\n tools: MessageAttachmentTools,\n onBusy: (busy: boolean) => void,\n actions?: HTMLElement,\n options: AttachmentEditorOptions = {},\n): AttachmentEditorHandle {\n const items: AttachmentItem[] = initial.map(existing => ({ existing }))\n const list = document.createElement('div')\n list.className = styles['attachmentList'] ?? ''\n list.setAttribute('aria-label', '消息附件')\n const add = document.createElement('button')\n add.type = 'button'\n add.className = `${styles['attachmentAdd'] ?? ''} ${styles['attachmentAddCircle'] ?? ''}`\n add.textContent = '+'\n add.setAttribute('aria-label', '添加附件')\n add.title = '添加图片或文件;替换附件时,先移除原附件再添加新文件。'\n const picker = document.createElement('input')\n picker.type = 'file'\n picker.multiple = true\n picker.hidden = true\n picker.setAttribute('aria-label', '选择消息附件')\n const notice = document.createElement('div')\n notice.className = styles['attachmentNotice'] ?? ''\n notice.setAttribute('role', 'alert')\n if (actions === undefined) container.append(list, ...options.hideAdd ? [] : [add], picker, notice)\n else {\n container.append(list, notice)\n actions.prepend(...options.hideAdd ? [] : [add], picker)\n }\n let disposed = false\n let disabled = false\n let unsubscribe: (() => void) | undefined\n const imageUrls = new Map<number, Promise<string>>()\n let previewItem: AttachmentItem | undefined\n let previewRevision = 0\n let dismissPreview: (() => void) | undefined\n\n const closePreview = (): void => {\n previewRevision += 1\n previewItem = undefined\n dismissPreview?.()\n dismissPreview = undefined\n }\n const imageUrl = (existing: EditableMessageAttachment): Promise<string> => {\n if (existing.content.type !== 'image') throw new Error('此附件不是图片。')\n let url = imageUrls.get(existing.blockIndex)\n if (url === undefined) {\n url = tools.imageUrl(existing.content.attachment)\n imageUrls.set(existing.blockIndex, url)\n void url.catch(() => {\n if (imageUrls.get(existing.blockIndex) === url) imageUrls.delete(existing.blockIndex)\n })\n }\n return url\n }\n const showPreview = (src: string, name: string, item: AttachmentItem): void => {\n closePreview()\n previewItem = item\n const previousFocus = document.activeElement as HTMLElement | null\n const overlay = document.createElement('div')\n overlay.className = styles['attachmentLightbox'] ?? ''\n overlay.setAttribute('role', 'dialog')\n overlay.setAttribute('aria-modal', 'true')\n overlay.setAttribute('aria-label', '图片预览')\n const image = document.createElement('img')\n image.className = styles['attachmentOriginal'] ?? ''\n image.src = src\n image.alt = name\n const close = document.createElement('button')\n close.type = 'button'\n close.className = styles['attachmentPreviewClose'] ?? ''\n close.textContent = '×'\n close.setAttribute('aria-label', '关闭图片预览')\n const outside = (event: MouseEvent): void => { if (event.target === overlay) closePreview() }\n const key = (event: KeyboardEvent): void => {\n if (event.key !== 'Escape' && event.key !== 'Tab') return\n event.preventDefault()\n event.stopPropagation()\n if (event.key === 'Escape') closePreview()\n else close.focus()\n }\n overlay.append(image, close)\n overlay.addEventListener('click', outside)\n close.addEventListener('click', closePreview)\n document.addEventListener('keydown', key, true)\n dismissPreview = () => {\n document.removeEventListener('keydown', key, true)\n overlay.removeEventListener('click', outside)\n close.removeEventListener('click', closePreview)\n overlay.remove()\n if (previousFocus?.isConnected) previousFocus.focus()\n }\n // 挂到 body 避免编辑弹窗的滚动和变换裁切图片原图。\n document.body.append(overlay)\n close.focus()\n }\n const openAttachment = async (item: AttachmentItem, name: string): Promise<void> => {\n if (disabled || disposed || !items.includes(item)) return\n notice.textContent = ''\n const content = 'existing' in item ? item.existing.content : undefined\n const draft = 'draft' in item ? item.draft : undefined\n try {\n if (content?.type === 'image' || draft?.kind === 'image') {\n closePreview()\n const revision = previewRevision\n previewItem = item\n let src: string\n if (draft?.kind === 'image') src = draft.previewUrl\n else if ('existing' in item) src = await imageUrl(item.existing)\n else return\n if (!disabled && !disposed && items.includes(item) && revision === previewRevision) showPreview(src, name, item)\n } else if ('existing' in item) {\n if (options.openExisting === undefined) throw new Error('当前编辑入口尚不支持打开文件。')\n await options.openExisting(item.existing.blockIndex)\n } else {\n if (options.openDraft === undefined) throw new Error('当前编辑入口尚不支持打开文件。')\n await options.openDraft(item.draft)\n }\n } catch (error) {\n if (!disposed) notice.textContent = error instanceof Error ? error.message : String(error)\n }\n }\n\n const refresh = (): void => {\n if (disposed) return\n const uploads = items.some(item => 'draft' in item && item.draft.kind === 'file') ? tools.uploads() : {}\n const pending = items.some(item => 'draft' in item && item.draft.kind === 'file'\n && uploads[item.draft.id]?.status !== 'ready')\n const cards = items.map((item) => {\n const card = document.createElement('div')\n card.className = styles['attachmentCard'] ?? ''\n const content = 'existing' in item ? item.existing.content : undefined\n const draft = 'draft' in item ? item.draft : undefined\n const name = content?.attachment.name ?? draft?.file.name ?? '图片附件'\n const bytes = content?.attachment.bytes ?? draft?.file.size ?? 0\n const isImage = content?.type === 'image' || draft?.kind === 'image'\n const open = document.createElement('button')\n open.type = 'button'\n open.className = styles['attachmentOpen'] ?? ''\n open.setAttribute('data-kind', isImage ? 'image' : 'file')\n open.setAttribute('aria-label', isImage ? `放大图片:${name}` : `打开文件:${name}`)\n open.title = isImage ? '点击放大图片' : '使用默认应用打开文件'\n open.disabled = disabled\n open.addEventListener('click', () => { void openAttachment(item, name) })\n const preview = document.createElement(isImage ? 'img' : 'span')\n preview.className = styles['attachmentPreview'] ?? ''\n if (isImage) {\n const image = preview as HTMLImageElement\n image.alt = name\n if (draft?.kind === 'image') image.src = draft.previewUrl\n if (content?.type === 'image' && 'existing' in item) {\n const url = imageUrl(item.existing)\n void url.then(value => { if (!disposed) image.src = value }).catch(() => {\n if (!disposed) image.alt = `${name}(预览暂不可用)`\n })\n }\n } else {\n preview.textContent = '文件'\n }\n const info = document.createElement('div')\n info.className = styles['attachmentInfo'] ?? ''\n const label = document.createElement('span')\n label.textContent = name\n label.title = name\n const status = document.createElement('span')\n status.className = styles['attachmentStatus'] ?? ''\n const upload = draft?.kind === 'file' ? uploads[draft.id] : undefined\n status.textContent = upload?.status === 'error' ? `上传失败:${upload.message}`\n : draft?.kind === 'file' && upload?.status !== 'ready'\n ? upload?.status === 'uploading' && upload.total\n ? `上传中 ${String(Math.round(upload.loaded / upload.total * 100))}%`\n : '正在上传…'\n : sizeLabel(bytes)\n info.append(label, status)\n const remove = document.createElement('button')\n remove.type = 'button'\n remove.className = styles['attachmentRemove'] ?? ''\n remove.textContent = '×'\n remove.title = `移除 ${name}`\n remove.setAttribute('aria-label', `移除附件:${name}`)\n remove.disabled = disabled\n remove.addEventListener('click', () => {\n if (disabled || disposed) return\n const index = items.indexOf(item)\n if (index < 0) return\n items.splice(index, 1)\n if (previewItem === item) closePreview()\n if ('draft' in item) tools.release(item.draft.id)\n refresh()\n })\n open.append(preview, info)\n card.append(open, remove)\n if (upload?.status === 'error' && draft !== undefined) {\n const retry = document.createElement('button')\n retry.type = 'button'\n retry.textContent = '重试上传'\n retry.disabled = disabled\n retry.addEventListener('click', () => { if (!disabled && !disposed) tools.retry(draft.id) })\n card.append(retry)\n }\n return card\n })\n list.replaceChildren(...cards)\n add.disabled = disabled\n picker.disabled = disabled\n onBusy(pending)\n }\n const addFiles = (files: readonly File[]): void => {\n if (disabled || disposed || files.length === 0) return\n try {\n for (const draft of tools.create(files)) items.push({ draft })\n unsubscribe ??= tools.subscribe(refresh)\n notice.textContent = ''\n refresh()\n } catch (error) {\n notice.textContent = error instanceof Error ? error.message : String(error)\n }\n }\n const openPicker = (): void => { if (!disabled && !disposed) picker.click() }\n const picked = (): void => {\n try {\n if (!disabled && !disposed) {\n const files = Array.from(picker.files ?? [])\n if (files.length > 0) (options.onFiles ?? addFiles)(files)\n }\n } catch (error) {\n notice.textContent = error instanceof Error ? error.message : String(error)\n } finally {\n picker.value = ''\n }\n }\n add.addEventListener('click', openPicker)\n picker.addEventListener('change', picked)\n refresh()\n return {\n addFiles,\n pickFiles: openPicker,\n serialize: async () => {\n const drafts = items.flatMap(item => 'draft' in item ? [item.draft.id] : [])\n const uploaded = drafts.length === 0 ? [] : await tools.serialize(drafts)\n let index = 0\n return items.map(item => {\n if ('existing' in item) return { type: 'retained', blockIndex: item.existing.blockIndex }\n const attachment = uploaded[index++]\n if (attachment === undefined) throw new Error('附件尚未准备完成,请稍后重试。')\n return attachment\n })\n },\n setDisabled: value => { disabled = value; if (value) closePreview(); refresh() },\n dispose: () => {\n if (disposed) return\n disposed = true\n closePreview()\n unsubscribe?.()\n add.removeEventListener('click', openPicker)\n picker.removeEventListener('change', picked)\n for (const item of items) if ('draft' in item) tools.release(item.draft.id)\n add.remove()\n picker.remove()\n container.replaceChildren()\n },\n }\n}\n\n/** Timeline 复用弹窗的附件编辑器,不把主输入框的草稿带入历史消息。 */\nexport function AttachmentEditor({ initial, tools, onMount, onBusy, disabled }: {\n initial: readonly EditableMessageAttachment[]\n tools: MessageAttachmentTools\n onMount(handle: AttachmentEditorHandle | undefined): void\n onBusy(busy: boolean): void\n disabled: boolean\n}): ReactNode {\n const container = useRef<HTMLDivElement>(null)\n const editor = useRef<AttachmentEditorHandle | undefined>(undefined)\n const callbacks = useRef({ onMount, onBusy })\n callbacks.current = { onMount, onBusy }\n useEffect(() => {\n if (container.current === null) return\n const handle = mountAttachmentEditor(container.current, initial, tools, busy => callbacks.current.onBusy(busy))\n editor.current = handle\n callbacks.current.onMount(handle)\n return () => {\n callbacks.current.onMount(undefined)\n handle.dispose()\n editor.current = undefined\n }\n }, [initial, tools])\n useEffect(() => { editor.current?.setDisabled(disabled) }, [disabled])\n return <div ref={container} className={styles['attachmentEditor']} />\n}\n","export interface FileReferenceToken {\n readonly start: number\n readonly end: number\n readonly path: string\n readonly token: string\n readonly label: string\n}\n\nexport interface SessionReferenceToken {\n readonly start: number\n readonly end: number\n readonly sessionId: string\n readonly token: string\n readonly label: string\n}\n\ninterface HostPathBridge {\n pathFor(file: File): string\n}\n\nconst invalidPathCharacters = /[\\u0000-\\u001f\\u007f-\\u009f\"]/u\n\n/** 使用桌面端提供的真实路径;浏览器内创建的文件没有宿主路径。 */\nexport function filePathFor(file: File): string | undefined {\n const bridge = (globalThis as typeof globalThis & { __DSH_HOST_PATHS__?: HostPathBridge }).__DSH_HOST_PATHS__\n try {\n const path = bridge?.pathFor(file)\n return path === undefined || path === '' ? undefined : path\n } catch {\n return undefined\n }\n}\n\n/** 对齐官方 @ 文件语法,空格使用双引号,路径分隔符统一为斜杠。 */\nexport function formatFileReference(path: string): string {\n if (path === '' || invalidPathCharacters.test(path)) throw new Error('文件路径无法表示为 DSH 引用。')\n const normalized = path.replace(/\\\\/gu, '/')\n return /\\s/u.test(normalized) ? `@\"${normalized}\"` : `@${normalized}`\n}\n\nfunction pathFromClipboardLine(line: string): string | undefined {\n let path = line.trim()\n if (path.startsWith('\"') && path.endsWith('\"')) path = path.slice(1, -1)\n if (/^file:/iu.test(path)) {\n try {\n const address = new URL(path)\n if (address.protocol !== 'file:' || address.search !== '' || address.hash !== '') return undefined\n path = decodeURIComponent(address.pathname)\n if (address.hostname !== '' && address.hostname !== 'localhost') path = `//${address.hostname}${path}`\n else if (/^\\/[a-z]:\\//iu.test(path)) path = path.slice(1)\n } catch {\n return undefined\n }\n }\n if (invalidPathCharacters.test(path)) return undefined\n if (/^\\/[^/]*$/u.test(path) && !/^\\/[^\\s]+\\.[a-z0-9]+$/iu.test(path)) return undefined\n if (!/^(?:[a-z]:[\\\\/]|\\\\\\\\[^\\\\/]+[\\\\/]|\\/)/iu.test(path)) return undefined\n return path.replace(/\\\\/gu, '/')\n}\n\n/** 只读取剪贴板的路径文本;实际 File 由 filePathFor 处理,图片不会重复添加。 */\nexport function pastedFilePaths(data: DataTransfer): readonly string[] {\n const result: string[] = []\n const seen = new Set<string>()\n const read = (type: string): string => {\n try { return data.getData(type) } catch { return '' }\n }\n for (const type of ['text/uri-list', 'text/plain']) {\n const lines = read(type).split(/\\r\\n|\\n|\\r/u).filter(line => line.trim() !== '' && (type !== 'text/uri-list' || !line.trimStart().startsWith('#')))\n const paths = lines.map(pathFromClipboardLine)\n // 一段普通说明中夹有路径不应丢掉说明文字,只有整批为路径时才接管粘贴。\n if (paths.some(path => path === undefined)) continue\n for (const path of paths) {\n if (path === undefined || seen.has(path)) continue\n seen.add(path)\n result.push(path)\n }\n }\n return result\n}\n\n/** 提取完整文件引用与文本位置;邮件地址和 @ 会话引用保留为普通文字。 */\nexport function parseFileReferences(text: string): readonly FileReferenceToken[] {\n const result: FileReferenceToken[] = []\n const pattern = /(?:^|\\s)(@(?:\"([^\"\\r\\n]+)\"|([^\\s\"]+)))/gu\n for (const match of text.matchAll(pattern)) {\n const token = match[1]\n const path = match[2] ?? match[3]\n if (token === undefined || path === undefined || invalidPathCharacters.test(path)) continue\n if (path.startsWith('[') || path.startsWith('dsh-session:')) continue\n const start = match.index + match[0].length - token.length\n const normalized = path.replace(/\\\\/gu, '/')\n const folder = normalized.endsWith('/')\n const segments = normalized.replace(/\\/+$/u, '').split('/')\n const name = segments.at(-1) || normalized\n result.push({ start, end: start + token.length, path, token, label: `${name}${folder ? '/' : ''}` })\n }\n return result\n}\n\nfunction sessionReferenceUri(sessionId: string): string {\n const bytes = new TextEncoder().encode(JSON.stringify(sessionId))\n const binary = Array.from(bytes, byte => String.fromCharCode(byte)).join('')\n return `dsh-session:${btoa(binary).replace(/\\+/gu, '-').replace(/\\//gu, '_').replace(/=+$/u, '')}`\n}\n\n/** 保持官方会话引用的 UTF-8 JSON 与 base64url 编码,显示名称独立于会话身份。 */\nexport function formatSessionReference(sessionId: string, label: string = sessionId): string {\n return `@[${label.replace(/[\\\\\\]]/gu, character => `\\\\${character}`)}](${sessionReferenceUri(sessionId)})`\n}\n\n/** 识别 canonical 会话引用;错误 URI 继续保留文字,不生成可导航 chip。 */\nexport function parseSessionReferences(text: string): readonly SessionReferenceToken[] {\n const result: SessionReferenceToken[] = []\n const pattern = /@\\[((?:\\\\.|[^\\\\\\]])*)\\]\\((dsh-session:[^\\s)]*)\\)|(dsh-session:[A-Za-z0-9_-]+)/gu\n for (const match of text.matchAll(pattern)) {\n const uri = match[2] ?? match[3]\n if (uri === undefined) continue\n const payload = uri.slice('dsh-session:'.length)\n if (!/^[A-Za-z0-9_-]+$/u.test(payload)) continue\n try {\n const binary = atob(payload.replace(/-/gu, '+').replace(/_/gu, '/'))\n const bytes = Uint8Array.from(binary, character => character.charCodeAt(0))\n const sessionId: unknown = JSON.parse(new TextDecoder('utf-8', { fatal: true }).decode(bytes))\n if (typeof sessionId !== 'string' || sessionReferenceUri(sessionId) !== uri) continue\n const token = match[0]\n const label = match[1] === undefined ? sessionId : match[1].replace(/\\\\(.)/gu, '$1')\n result.push({ start: match.index, end: match.index + token.length, sessionId, token, label })\n } catch {\n continue\n }\n }\n return result\n}\n","import { parseFileReferences, parseSessionReferences, pastedFilePaths } from './fileReferences.ts'\nimport styles from './InlineMessageEdit.module.css'\n\nexport interface RichMessageInputHandle {\n text(): string\n insert(text: string): void\n replaceTrailing(token: string, text: string): void\n focus(): void\n setDisabled(disabled: boolean): void\n dispose(): void\n}\n\nfunction escapeHtml(text: string): string {\n return text.replace(/[&<>\"']/g, value => ({ '&': '&', '<': '<', '>': '>', '\"': '"', \"'\": ''' })[value]!)\n}\n\n/** 引用以原生 @路径持久化,显示节点只负责高亮和点击。 */\nfunction referenceHtml(text: string): string {\n let result = ''\n let offset = 0\n const sessions = parseSessionReferences(text)\n const files = parseFileReferences(text).filter(file => !sessions.some(session => file.start >= session.start && file.start < session.end))\n for (const reference of [...files, ...sessions].sort((left, right) => left.start - right.start)) {\n result += escapeHtml(text.slice(offset, reference.start)).replace(/\\n/g, '<br>')\n const location = 'path' in reference ? `data-file-path=\"${escapeHtml(reference.path)}\"` : `data-session-id=\"${escapeHtml(reference.sessionId)}\"`\n result += `<span class=\"${styles['fileReference'] ?? ''}\" contenteditable=\"false\" role=\"link\" tabindex=\"0\" ${location} data-file-token=\"${escapeHtml(reference.token)}\" title=\"${escapeHtml('path' in reference ? reference.path : reference.label)}\">${'path' in reference ? '▤' : '@'} ${escapeHtml(reference.label)}</span>`\n offset = reference.end\n }\n return result + escapeHtml(text.slice(offset)).replace(/\\n/g, '<br>')\n}\n\n/** 同时处理浏览器生成的段落和粘贴插入的换行,保留多行正文。 */\nexport function messageInputText(node: Node): string {\n if (node.nodeType === 3) return node.textContent ?? ''\n const element = node as HTMLElement\n if (element.dataset?.['fileToken'] !== undefined) return element.dataset['fileToken']\n if (element.tagName === 'BR') return '\\n'\n const children = Array.from(node.childNodes ?? [])\n let result = ''\n for (const child of children) {\n const block = child.nodeType === 1 && /^(DIV|P)$/.test((child as HTMLElement).tagName)\n if (block && result !== '' && !result.endsWith('\\n')) result += '\\n'\n result += messageInputText(child)\n if (block && child !== children.at(-1) && !result.endsWith('\\n')) result += '\\n'\n }\n return children.length === 0 ? node.textContent ?? '' : result.replace(/\\u00a0/g, ' ')\n}\n\n/** 独立内容框使用浏览器编辑历史,不绑定主会话的单例草稿。 */\nexport function mountRichMessageInput(\n container: HTMLElement,\n initialText: string,\n options: {\n addFiles(files: readonly File[]): void\n addPaths(paths: readonly string[]): void\n openPath(path: string): Promise<void>\n openSession(sessionId: string): void\n onError(error: unknown): void\n onSend(): void\n onSave(): void\n onChange?(text: string): void\n onKeydown?(event: KeyboardEvent): boolean\n },\n): RichMessageInputHandle {\n const input = document.createElement('div')\n input.className = `${styles['input'] ?? ''} ${styles['richInput'] ?? ''}`\n input.contentEditable = 'true'\n input.setAttribute('role', 'textbox')\n input.setAttribute('aria-label', '消息正文')\n input.setAttribute('aria-multiline', 'true')\n input.setAttribute('data-placeholder', '编辑消息,粘贴文件,输入 / 调用指令、@ 引用文件或对话')\n input.innerHTML = referenceHtml(initialText)\n container.append(input)\n let disabled = false\n let disposed = false\n let composing = false\n let edited = false\n let caret: Range | undefined\n const selection = (): Selection | null => document.getSelection()\n const remember = (): void => {\n const current = selection()\n if (current?.rangeCount && input.contains(current.anchorNode)) caret = current.getRangeAt(0).cloneRange()\n }\n const focus = (): void => {\n input.focus()\n const current = selection()\n if (current === null) return\n const range = caret ?? document.createRange()\n if (caret === undefined) { range.selectNodeContents(input); range.collapse(false) }\n current.removeAllRanges()\n current.addRange(range)\n }\n const changed = (): void => {\n if (composing) return\n edited = true\n remember()\n const current = selection()\n const prefix = document.createRange()\n prefix.selectNodeContents(input)\n if (current?.rangeCount && input.contains(current.anchorNode)) {\n const range = current.getRangeAt(0)\n prefix.setEnd(range.endContainer, range.endOffset)\n }\n options.onChange?.(messageInputText(prefix.cloneContents()))\n }\n const insert = (text: string): void => {\n if (disabled || disposed) return\n focus()\n const current = selection()\n if (current?.rangeCount && (parseFileReferences(text)[0]?.start === 0 || parseSessionReferences(text)[0]?.start === 0)) {\n const range = current.getRangeAt(0)\n const prefix = document.createRange()\n prefix.selectNodeContents(input)\n prefix.setEnd(range.startContainer, range.startOffset)\n const before = messageInputText(prefix.cloneContents())\n if (before !== '' && !/\\s$/.test(before)) text = ` ${text}`\n }\n // 所有 HTML 来自转义后的文本与固定引用模板,富文本剪贴板不进入正文。\n document.execCommand('insertHTML', false, referenceHtml(text))\n changed()\n }\n const paste = (event: ClipboardEvent): void => {\n if (disabled || event.clipboardData === null) return\n const files = Array.from(event.clipboardData.files)\n if (!files.length) for (const item of Array.from(event.clipboardData.items)) {\n const file = item.kind === 'file' ? item.getAsFile() : null\n if (file !== null) files.push(file)\n }\n const paths = files.length === 0 ? pastedFilePaths(event.clipboardData) : []\n event.preventDefault()\n if (files.length) options.addFiles(files)\n else if (paths.length) options.addPaths(paths)\n else insert(event.clipboardData.getData('text/plain'))\n }\n const drop = (event: DragEvent): void => {\n if (disabled || event.dataTransfer === null) return\n event.preventDefault()\n const files = Array.from(event.dataTransfer.files)\n if (files.length) options.addFiles(files)\n else {\n const paths = pastedFilePaths(event.dataTransfer)\n if (paths.length) options.addPaths(paths)\n else insert(event.dataTransfer.getData('text/plain'))\n }\n }\n const dragOver = (event: DragEvent): void => { if (!disabled) event.preventDefault() }\n const openReference = (event: MouseEvent | KeyboardEvent): void => {\n const chip = (event.target as HTMLElement).closest<HTMLElement>('[data-file-path], [data-session-id]')\n if (chip === null || !input.contains(chip)) return\n if (event instanceof KeyboardEvent && event.key !== 'Enter' && event.key !== ' ') return\n event.preventDefault()\n const path = chip.dataset['filePath']\n if (path !== undefined) void options.openPath(path).catch(options.onError)\n const sessionId = chip.dataset['sessionId']\n if (sessionId !== undefined) options.openSession(sessionId)\n }\n const keydown = (event: KeyboardEvent): void => {\n if (composing || event.isComposing || event.keyCode === 229 || disabled) return\n if ((event.target as HTMLElement).dataset['fileToken'] !== undefined) { openReference(event); return }\n if (options.onKeydown?.(event)) return\n if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === 's') {\n event.preventDefault(); options.onSave()\n } else if (event.key === 'Enter' && !event.shiftKey && !event.altKey) {\n event.preventDefault(); options.onSend()\n }\n }\n const copy = (event: ClipboardEvent): void => {\n const current = selection()\n if (current?.rangeCount && input.contains(current.anchorNode) && event.clipboardData !== null) {\n event.clipboardData.setData('text/plain', messageInputText(current.getRangeAt(0).cloneContents()))\n event.preventDefault()\n if (event.type === 'cut' && !disabled) document.execCommand('delete')\n }\n }\n const compositionStart = (): void => { composing = true }\n const compositionEnd = (): void => { composing = false; changed() }\n input.addEventListener('compositionstart', compositionStart)\n input.addEventListener('compositionend', compositionEnd)\n input.addEventListener('input', changed)\n input.addEventListener('keyup', remember)\n input.addEventListener('mouseup', remember)\n input.addEventListener('blur', remember)\n input.addEventListener('paste', paste)\n input.addEventListener('drop', drop)\n input.addEventListener('dragover', dragOver)\n input.addEventListener('click', openReference)\n input.addEventListener('keydown', keydown)\n input.addEventListener('copy', copy)\n input.addEventListener('cut', copy)\n return {\n // 未输入时直接使用原始值,避免浏览器的空白归一化制造虚假修改。\n text: () => edited ? messageInputText(input) : initialText, insert, focus,\n replaceTrailing: (token, text) => {\n if (disabled || disposed) return\n focus()\n const current = selection()\n if (current === null) return\n for (let index = 0; index < token.length; index++) current.modify('extend', 'backward', 'character')\n remember()\n insert(text)\n },\n setDisabled: value => { disabled = value; input.contentEditable = String(!value); input.setAttribute('aria-disabled', String(value)) },\n dispose: () => {\n disposed = true\n input.removeEventListener('compositionstart', compositionStart)\n input.removeEventListener('compositionend', compositionEnd)\n input.removeEventListener('input', changed)\n input.removeEventListener('keyup', remember)\n input.removeEventListener('mouseup', remember)\n input.removeEventListener('blur', remember)\n input.removeEventListener('paste', paste)\n input.removeEventListener('drop', drop)\n input.removeEventListener('dragover', dragOver)\n input.removeEventListener('click', openReference)\n input.removeEventListener('keydown', keydown)\n input.removeEventListener('copy', copy)\n input.removeEventListener('cut', copy)\n input.remove()\n },\n }\n}\n","import type { EditableMessageBlock, MessageEditAttachmentInput } from '../shared.ts'\nimport type { MessageAttachmentTools } from './attachmentTools.ts'\nimport type { ComposerOptions, ComposerSettings, MessageComposerTools } from './composerTools.ts'\nimport { mountAttachmentEditor, type AttachmentEditorHandle } from './AttachmentEditor.tsx'\nimport { filePathFor, formatFileReference } from './fileReferences.ts'\nimport { mountRichMessageInput, type RichMessageInputHandle } from './RichMessageInput.ts'\nimport styles from './InlineMessageEdit.module.css'\n\nexport interface MessageComposerHandle {\n text(): string\n settings(regenerate?: boolean): ComposerSettings | undefined\n serialize(): Promise<readonly MessageEditAttachmentInput[]>\n focus(): void\n setDisabled(disabled: boolean): void\n dispose(): void\n}\n\nfunction button(label: string, className?: string): HTMLButtonElement {\n const element = document.createElement('button')\n element.type = 'button'\n element.textContent = label\n if (className !== undefined) element.className = className\n return element\n}\n\n/** 弹窗与 Timeline 共用独立的正文、附件及提交选项。 */\nexport function mountMessageComposer(container: HTMLElement, block: EditableMessageBlock,\n attachmentTools: MessageAttachmentTools, tools: MessageComposerTools,\n events: { onBusy(busy: boolean): void; onSend(): void; onSave(): void },\n): MessageComposerHandle {\n const frame = document.createElement('div')\n frame.className = styles['composer'] ?? ''\n const attachments = document.createElement('div')\n const inputContainer = document.createElement('div')\n const toolbar = document.createElement('div')\n toolbar.className = styles['composerToolbar'] ?? ''\n const plus = button('+', styles['composerPlus'])\n plus.setAttribute('aria-label', '添加文件')\n plus.title = '添加文件'\n const permission = button('权限 ▾', styles['composerControl'])\n permission.setAttribute('aria-label', '修改权限')\n const model = button('模型 ▾', styles['composerModel'])\n model.setAttribute('aria-label', '修改模型和推理等级')\n const status = document.createElement('div')\n status.className = styles['attachmentNotice'] ?? ''\n status.setAttribute('role', 'status')\n const popup = document.createElement('div')\n popup.className = styles['composerMenu'] ?? ''\n popup.hidden = true\n const suggestions = document.createElement('div')\n suggestions.className = styles['referenceSuggestions'] ?? ''\n suggestions.hidden = true\n toolbar.append(plus, permission, model)\n frame.append(attachments, inputContainer, suggestions, popup, toolbar)\n container.append(frame, status)\n let disabled = false\n let disposed = false\n let options: ComposerOptions | undefined\n let draftSettings: ComposerSettings = {}\n let search: AbortController | undefined\n let searchTimer: ReturnType<typeof setTimeout> | undefined\n let highlighted = 0\n let richInput: RichMessageInputHandle\n let attachmentEditor: AttachmentEditorHandle\n const showError = (error: unknown): void => { if (!disposed) status.textContent = error instanceof Error ? error.message : String(error) }\n const addPaths = (paths: readonly string[]): void => {\n richInput.insert(paths.map(path => formatFileReference(path)).join(' ') + ' ')\n }\n const addFiles = (files: readonly File[]): void => {\n if (disabled || disposed) return\n const uploads: File[] = []\n const paths: string[] = []\n for (const file of files) {\n const path = filePathFor(file)\n if (path !== undefined && !/^image\\/(png|jpeg|webp|gif)$/.test(file.type)) paths.push(path)\n else uploads.push(file)\n }\n if (paths.length) addPaths(paths)\n if (uploads.length) attachmentEditor.addFiles(uploads)\n }\n const closeMenu = (): void => {\n popup.hidden = true\n permission.setAttribute('aria-expanded', 'false')\n model.setAttribute('aria-expanded', 'false')\n }\n const beginMenu = (label: string, kind: 'permission' | 'model' | 'modelList' | 'command' = 'command'): void => {\n popup.replaceChildren()\n popup.setAttribute('role', 'menu')\n popup.setAttribute('aria-label', label)\n popup.dataset['kind'] = kind\n popup.hidden = false\n permission.setAttribute('aria-expanded', String(kind === 'permission'))\n model.setAttribute('aria-expanded', String(kind === 'model' || kind === 'modelList'))\n }\n const menuItem = (label: string, description: string, act: () => void, selected?: boolean, target = popup): HTMLButtonElement => {\n const item = button('')\n const text = document.createElement('span')\n text.className = styles['menuItemLabel'] ?? ''\n text.textContent = label\n item.setAttribute('role', selected === undefined ? 'menuitem' : 'menuitemradio')\n if (selected !== undefined) item.setAttribute('aria-checked', String(selected))\n item.title = label\n const hint = document.createElement('span')\n hint.className = styles['menuValue'] ?? ''\n hint.textContent = selected === undefined ? description : selected ? '✓' : ''\n if (selected !== undefined) hint.setAttribute('aria-hidden', 'true')\n item.append(text, hint)\n item.disabled = disabled\n item.addEventListener('click', () => { closeMenu(); act() })\n target.append(item)\n return item\n }\n const permissionLabel = (id: string | undefined): string => {\n const labels: Record<string, string> = {\n 'read-only': '仅可查看', 'workspace-write': '工作区内修改',\n 'danger-full-access': '完全权限', 'auto-review': 'Auto review',\n }\n return id === undefined ? '权限' : labels[id] ?? options?.permissions.find(preset => preset.id === id)?.label ?? (id === 'custom' ? '自定义权限' : id)\n }\n const effortLabel = (effort: string | undefined): string => {\n if (!effort) return '默认'\n const values = { ...options?.current, ...draftSettings }\n const selected = options?.models.find(entry => entry.provider === values.provider && entry.model === values.model)\n return selected?.reasoningEffortLabels?.[effort] ?? ({ off: 'Off', low: 'Low', medium: 'Medium', high: 'High', max: 'Max' } as Record<string, string>)[effort] ?? effort\n }\n const updateControls = (): void => {\n const values = { ...options?.current, ...draftSettings }\n permission.textContent = `${permissionLabel(values.permissionPreset)} ▾`\n const selected = options?.models.find(entry => entry.provider === values.provider && entry.model === values.model)\n model.textContent = `${selected?.label ?? values.model ?? '模型'}${values.reasoningEffort ? ` ${effortLabel(values.reasoningEffort)}` : ''} ▾`\n model.title = model.textContent\n }\n const permissionMenu = (): void => {\n beginMenu('选择权限', 'permission')\n const values = { ...options?.current, ...draftSettings }\n for (const preset of options?.permissions ?? []) {\n const item = menuItem(permissionLabel(preset.id), '', () => { draftSettings.permissionPreset = preset.id; updateControls(); richInput.focus() }, preset.id === values.permissionPreset)\n item.title = preset.description ?? permissionLabel(preset.id)\n }\n if (options === undefined) menuItem('重新加载选项', '', () => { void loadOptions() })\n }\n const modelMenu = (): void => {\n beginMenu('选择模型和推理等级', 'model')\n const values = { ...options?.current, ...draftSettings }\n const selected = options?.models.find(entry => entry.provider === values.provider && entry.model === values.model)\n menuItem('模型', `${selected?.label ?? values.model ?? '选择模型'} ›`, modelList)\n if (selected?.reasoningEfforts.length) {\n menuItem('推理等级', `${effortLabel(values.reasoningEffort)} ›`, () => {\n beginMenu('选择推理等级', 'model')\n menuItem('‹ 推理等级', '', modelMenu)\n for (const effort of ['', ...selected.reasoningEfforts]) menuItem(effortLabel(effort), '', () => {\n draftSettings = { ...draftSettings, provider: selected.provider, model: selected.model, reasoningEffort: effort }\n updateControls(); richInput.focus()\n }, effort === (values.reasoningEffort ?? ''))\n })\n }\n if (options === undefined) menuItem('重新加载选项', '', () => { void loadOptions() })\n }\n const modelList = (): void => {\n beginMenu('选择模型', 'modelList')\n const back = menuItem('‹ 模型', '', modelMenu)\n back.className = styles['menuBack'] ?? ''\n const field = document.createElement('input')\n field.placeholder = '搜索模型…'\n field.setAttribute('aria-label', '搜索模型')\n field.className = styles['modelSearch'] ?? ''\n const list = document.createElement('div')\n list.className = styles['modelList'] ?? ''\n popup.append(field, list)\n const render = (): void => {\n // 搜索框保持挂载,筛选时不丢失焦点和光标。\n list.replaceChildren()\n const values = { ...options?.current, ...draftSettings }\n const query = field.value.trim().toLocaleLowerCase()\n const groups = new Map<string, ComposerOptions['models'][number][]>()\n for (const entry of options?.models ?? []) {\n if (query && !`${entry.label} ${entry.model} ${entry.providerLabel ?? entry.provider}`.toLocaleLowerCase().includes(query)) continue\n const group = groups.get(entry.provider) ?? []\n group.push(entry); groups.set(entry.provider, group)\n }\n for (const entries of groups.values()) {\n const heading = document.createElement('div')\n heading.className = styles['menuHeading'] ?? ''\n heading.textContent = entries[0]?.providerLabel ?? entries[0]?.provider ?? ''\n list.append(heading)\n for (const entry of entries) menuItem(entry.label, '', () => {\n draftSettings = { ...draftSettings, provider: entry.provider, model: entry.model }\n if (!entry.reasoningEfforts.includes(values.reasoningEffort ?? '')) {\n // 不将旧模型不支持的推理等级传给新模型。\n draftSettings.reasoningEffort = ''\n }\n updateControls(); richInput.focus()\n }, entry.provider === values.provider && entry.model === values.model, list)\n }\n if (!groups.size) {\n const empty = document.createElement('div')\n empty.className = styles['menuHeading'] ?? ''\n empty.textContent = '没有找到匹配的模型'\n list.append(empty)\n }\n }\n field.addEventListener('input', render)\n render()\n field.focus()\n }\n const executeCommand = (line: string): void => {\n if (disabled) return\n status.textContent = '正在执行指令…'\n void tools.command(line).then(() => { if (!disposed) status.textContent = '指令已执行。' }).catch(showError)\n }\n const commandForm = (name: string, label: string, placeholder: string): void => {\n beginMenu(label)\n const field = document.createElement('input')\n field.placeholder = placeholder\n field.setAttribute('aria-label', label)\n const run = button(label)\n run.addEventListener('click', () => { closeMenu(); executeCommand(`/${name}${field.value.trim() ? ` ${field.value.trim()}` : ''}`) })\n popup.append(field, run)\n field.focus()\n }\n const planMenu = (): void => {\n beginMenu('计划模式')\n menuItem('进入计划模式', '先规划,再执行', () => executeCommand('/plan'))\n menuItem('退出计划模式', '恢复正常对话', () => executeCommand('/plan off'))\n }\n const chooseCommand = (name: string): void => {\n switch (name) {\n case 'file': attachmentEditor.pickFiles(); break\n case 'goal': commandForm('goal', '设置或查看目标', '输入目标;留空查看当前目标'); break\n case 'plan': planMenu(); break\n case 'feedback': commandForm('feedback', '发送反馈', '输入反馈内容'); break\n case 'permission': permissionMenu(); break\n case 'model': modelMenu(); break\n default: executeCommand(`/${name}`)\n }\n }\n const suggestReferences = (text: string): void => {\n search?.abort()\n if (searchTimer !== undefined) clearTimeout(searchTimer)\n suggestions.hidden = true\n const slash = /^\\/([^\\s]*)$/.exec(text)\n const match = /(?:^|\\s)@([^\\s@]*)$/.exec(text)\n if (slash !== null) {\n const controller = new AbortController()\n search = controller\n void tools.commands(slash[1] ?? '', controller.signal).then(commands => {\n if (disposed || controller.signal.aborted || !commands.length) return\n suggestions.replaceChildren()\n suggestions.setAttribute('role', 'listbox')\n suggestions.setAttribute('aria-label', '指令候选')\n for (const command of commands.slice(0, 12)) {\n const item = button(`${command.label ?? command.name} /${command.name}`)\n item.setAttribute('role', 'option')\n item.addEventListener('mousedown', event => event.preventDefault())\n item.addEventListener('click', () => {\n suggestions.hidden = true\n richInput.replaceTrailing(`/${slash[1] ?? ''}`, '')\n chooseCommand(command.name)\n })\n suggestions.append(item)\n }\n highlighted = 0\n suggestions.hidden = false\n suggestions.children[0]?.setAttribute('aria-selected', 'true')\n }).catch(error => { if (!controller.signal.aborted) showError(error) })\n return\n }\n if (match === null) return\n const query = match[1] ?? ''\n searchTimer = setTimeout(() => {\n const controller = new AbortController()\n search = controller\n void tools.references(query, controller.signal).then(results => {\n if (disposed || controller.signal.aborted || !results.length) return\n suggestions.replaceChildren()\n suggestions.setAttribute('role', 'listbox')\n suggestions.setAttribute('aria-label', '文件引用候选')\n for (const reference of results.slice(0, 12)) {\n const item = button(`${reference.kind === 'folder' ? '▱' : reference.kind === 'session' ? '@' : '▤'} ${reference.label}`)\n item.title = reference.kind === 'session' ? reference.label : reference.path\n item.setAttribute('role', 'option')\n item.addEventListener('mousedown', event => event.preventDefault())\n item.addEventListener('click', () => {\n richInput.replaceTrailing(`@${query}`, `${reference.kind === 'session' ? reference.mention : formatFileReference(reference.path)} `)\n suggestions.hidden = true\n })\n suggestions.append(item)\n }\n suggestions.hidden = false\n highlighted = 0\n suggestions.children[0]?.setAttribute('aria-selected', 'true')\n }).catch(error => { if (!controller.signal.aborted) showError(error) })\n }, 150)\n }\n richInput = mountRichMessageInput(inputContainer, block.text, {\n addFiles, addPaths, openPath: tools.openPath, openSession: tools.openSession, onError: showError,\n onSend: events.onSend, onSave: events.onSave, onChange: suggestReferences,\n onKeydown: event => {\n if (suggestions.hidden) return false\n if (event.key === 'Escape') { suggestions.hidden = true; event.preventDefault(); return true }\n if (event.key === 'ArrowUp' || event.key === 'ArrowDown') {\n const direction = event.key === 'ArrowUp' ? -1 : 1\n highlighted = (highlighted + direction + suggestions.children.length) % suggestions.children.length\n for (const [index, item] of Array.from(suggestions.children).entries()) item.setAttribute('aria-selected', String(index === highlighted))\n event.preventDefault(); return true\n }\n if (event.key === 'Enter' || event.key === 'Tab') {\n (suggestions.children[highlighted] as HTMLButtonElement | undefined)?.click()\n event.preventDefault(); return true\n }\n return false\n },\n })\n attachmentEditor = mountAttachmentEditor(attachments, block.attachments ?? [], attachmentTools, events.onBusy, undefined, {\n hideAdd: true, onFiles: addFiles,\n openExisting: blockIndex => tools.openAttachment(block.eventSeq, blockIndex),\n openDraft: async draft => {\n const path = filePathFor(draft.file)\n if (path !== undefined) return tools.openPath(path)\n const [payload] = await attachmentTools.serialize([draft.id])\n if (payload?.type !== 'file') throw new Error('附件尚未准备完成,请稍后重试。')\n await tools.openUpload(payload.receiptId)\n },\n })\n const loadOptions = async (): Promise<void> => {\n try {\n const result = await tools.options()\n if (!Array.isArray(result.models) || !Array.isArray(result.permissions)) throw new Error('宿主尚未提供编辑选项,请安装新版插件并重启 DSH。')\n if (disposed) return\n options = result\n updateControls()\n } catch (error) { showError(error) }\n }\n const outside = (event: MouseEvent): void => {\n const path = event.composedPath()\n if (!path.includes(popup) && !path.includes(plus) && !path.includes(permission) && !path.includes(model)) closeMenu()\n }\n const togglePermission = (): void => {\n if (!popup.hidden && popup.getAttribute('aria-label') === '选择权限') closeMenu()\n else permissionMenu()\n }\n const toggleModel = (): void => {\n if (!popup.hidden && (popup.dataset['kind'] === 'model' || popup.dataset['kind'] === 'modelList')) closeMenu()\n else modelMenu()\n }\n const dropTarget = container.closest<HTMLElement>('[role=\"dialog\"]') ?? frame\n const fileDrag = (event: DragEvent): void => {\n const transfer = event.dataTransfer\n if (transfer === null || !Array.from(transfer.types).includes('Files')) return\n // 宿主在 document 冒泡接收文件;先于正文接管,避免两个草稿重复收取。\n event.preventDefault()\n event.stopPropagation()\n if (event.type === 'dragenter' || event.type === 'dragover') transfer.dropEffect = disabled ? 'none' : 'copy'\n if (event.type !== 'drop' || disabled || disposed) return\n try { addFiles(Array.from(transfer.files)) } catch (error) { showError(error) }\n }\n const fileDragEvents = ['dragenter', 'dragover', 'dragleave', 'drop'] as const\n for (const name of fileDragEvents) dropTarget.addEventListener(name, fileDrag, true)\n frame.addEventListener('keydown', event => {\n if (event.isComposing || event.keyCode === 229) return\n if (event.key === 'Escape' && !popup.hidden) { closeMenu(); richInput.focus(); event.stopPropagation() }\n })\n plus.addEventListener('click', () => { closeMenu(); attachmentEditor.pickFiles() })\n permission.addEventListener('click', togglePermission)\n model.addEventListener('click', toggleModel)\n document.addEventListener('click', outside)\n void loadOptions()\n return {\n text: richInput.text,\n settings: regenerate => {\n const settings = { ...regenerate ? options?.current : {}, ...draftSettings }\n if (settings.permissionPreset !== undefined && !options?.permissions.some(item => item.id === settings.permissionPreset)) {\n delete settings.permissionPreset\n }\n if (settings.reasoningEffort === '') delete settings.reasoningEffort\n return Object.keys(settings).length ? settings : undefined\n },\n serialize: () => attachmentEditor.serialize(),\n focus: richInput.focus,\n setDisabled: value => {\n disabled = value\n richInput.setDisabled(value)\n attachmentEditor.setDisabled(value)\n plus.disabled = value; permission.disabled = value; model.disabled = value\n if (value) { closeMenu(); suggestions.hidden = true }\n },\n dispose: () => {\n disposed = true\n search?.abort()\n if (searchTimer !== undefined) clearTimeout(searchTimer)\n document.removeEventListener('click', outside)\n for (const name of fileDragEvents) dropTarget.removeEventListener(name, fileDrag, true)\n attachmentEditor.dispose()\n richInput.dispose()\n frame.remove(); status.remove()\n },\n }\n}\n","/**\r\n * Message-row edit affordance: injects retry + edit icon buttons into each\r\n * settled message's icon-actions row (the official MessageIconActions has no\r\n * plugin slot, so injection rides a MutationObserver over action rows).\r\n * Icons are the official outline-16 SVGs inlined to avoid bundling the\r\n * primitives package.\r\n */\r\nimport { useLayoutEffect, useRef } from 'react'\r\nimport type { EditableMessageBlock } from '../shared.ts'\r\nimport type { MessageEditFace } from './controller.ts'\r\nimport { confirmCancelEdit } from './confirmCancelEdit.ts'\r\nimport { mountMessageComposer, type MessageComposerHandle } from './MessageComposer.ts'\r\nimport styles from './InlineMessageEdit.module.css'\r\n\r\nconst BLOCK_TITLE: Record<EditableMessageBlock['kind'], string> = {\r\n user: '编辑用户消息',\r\n 'assistant.reasoning': '编辑助手思考',\r\n 'assistant.response': '编辑助手回复',\r\n}\r\n\r\nconst STYLE = {\r\n overlay: styles['overlay'] ?? '',\r\n panel: styles['panel'] ?? '',\r\n title: styles['title'] ?? '',\r\n input: styles['input'] ?? '',\r\n footer: styles['footer'] ?? '',\r\n iconButton: styles['iconButton'] ?? '',\r\n picker: styles['picker'] ?? '',\r\n pickerItem: styles['pickerItem'] ?? '',\r\n pickerItemActive: styles['pickerItemActive'] ?? '',\r\n}\r\n\r\n/** Official ic_ds_refresh_outline_16 path (dsh-client-ui-primitives). */\r\nconst REFRESH_PATH = 'M7.92136 0.349152C10.3744 0.349234 12.5564 1.5052 13.9557 3.29894L15.1281 2.12759C15.3303 1.92546 15.6767 2.06943 15.6767 2.35538V5.53923C15.6766 5.71626 15.5329 5.85976 15.3559 5.86002H12.171C11.8854 5.8597 11.7426 5.51465 11.9443 5.31249L12.9641 4.29056C11.8237 2.74305 9.98908 1.74106 7.92136 1.74097C4.46436 1.74097 1.66233 4.543 1.66233 8C1.66233 11.457 4.46436 14.259 7.92136 14.259C11.3782 14.2589 14.1804 11.4569 14.1804 8H15.5722C15.5722 12.2251 12.1465 15.6507 7.92136 15.6508C3.69614 15.6508 0.270508 12.2252 0.270508 8C0.270508 3.77478 3.69614 0.349152 7.92136 0.349152Z'\r\n\r\n/** Official ic_ds_edit_outline_16 path (dsh-client-ui-primitives). */\r\nconst EDIT_PATH = 'M9.94076 1.34942C10.7047 0.90231 11.6503 0.902415 12.4143 1.34942C12.7061 1.52015 12.9688 1.79118 13.3104 2.13284C13.6521 2.47448 13.9231 2.73721 14.0939 3.02894C14.5408 3.79294 14.5409 4.73856 14.0939 5.50251C13.9231 5.79415 13.652 6.05704 13.3104 6.39861L6.65932 13.0497C6.28068 13.4284 6.00695 13.7108 5.66543 13.9097C5.32391 14.1085 4.94315 14.2074 4.42705 14.3498L3.24394 14.6761C2.77527 14.8054 2.34538 14.9262 2.00131 14.9684C1.65196 15.0112 1.17964 15.0013 0.810764 14.6325C0.441921 14.2637 0.432107 13.7913 0.47486 13.442C0.517035 13.0979 0.6379 12.668 0.767181 12.1993L1.09352 11.0162C1.23588 10.5001 1.33481 10.1193 1.5336 9.77784C1.7325 9.43632 2.0149 9.1626 2.39355 8.78395L9.04466 2.13284C9.38625 1.79126 9.64911 1.52016 9.94076 1.34942ZM15.5427 14.8398H7.55223L8.96707 13.425H15.5427V14.8398ZM3.39382 9.78422C2.965 10.213 2.84244 10.3436 2.75709 10.49C2.67183 10.6366 2.61862 10.8079 2.45733 11.3925L2.13099 12.5756C2.00183 13.0439 1.92194 13.3419 1.88863 13.5536C2.10041 13.5204 2.39872 13.4416 2.86764 13.3123L4.05075 12.9859C4.63544 12.8246 4.80669 12.7715 4.95323 12.6862C5.09968 12.6008 5.23022 12.4783 5.65905 12.0494L10.721 6.98644L8.45577 4.72121L3.39382 9.78422ZM11.7 2.57079C11.3774 2.38198 10.9777 2.38198 10.6551 2.57079C10.5602 2.62647 10.4487 2.72931 10.0449 3.13311L9.45604 3.72094L11.7213 5.98617L12.3102 5.39833C12.7139 4.99457 12.8168 4.88307 12.8725 4.78818C13.0613 4.46561 13.0612 4.06585 12.8725 3.74326C12.8169 3.64827 12.7146 3.53752 12.3102 3.13311C11.9057 2.72863 11.795 2.6264 11.7 2.57079Z'\r\n\r\nfunction svgIcon(path: string): SVGSVGElement {\r\n const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg')\r\n svg.setAttribute('width', '16')\r\n svg.setAttribute('height', '16')\r\n svg.setAttribute('viewBox', '0 0 16 16')\r\n svg.setAttribute('fill', 'none')\r\n const p = document.createElementNS('http://www.w3.org/2000/svg', 'path')\r\n p.setAttribute('d', path)\r\n p.setAttribute('fill', 'currentColor')\r\n svg.appendChild(p)\r\n return svg\r\n}\r\n\r\nfunction blockTitle(kind: EditableMessageBlock['kind']): string {\r\n return BLOCK_TITLE[kind] ?? '编辑消息'\r\n}\r\n\r\ntype OverlayCleanup = () => void\r\n\r\n/** 编辑器支持用户消息只保存或保存并发送,关闭前确认取消。 */\r\nexport function mountEditor(\r\n block: EditableMessageBlock,\r\n edit: MessageEditFace['edit'],\r\n close: () => void,\r\n attachmentTools: MessageEditFace['attachmentTools'],\r\n composerTools: MessageEditFace['composerTools'],\r\n): OverlayCleanup {\r\n const overlay = document.createElement('div')\r\n overlay.className = STYLE.overlay\r\n const panel = document.createElement('div')\r\n panel.className = STYLE.panel\r\n panel.setAttribute('role', 'dialog')\r\n panel.setAttribute('aria-modal', 'true')\r\n panel.setAttribute('aria-label', blockTitle(block.kind))\r\n const title = document.createElement('div')\r\n title.className = STYLE.title\r\n title.textContent = blockTitle(block.kind)\r\n const input = document.createElement('textarea')\r\n input.className = STYLE.input\r\n input.value = block.text\r\n input.setAttribute('aria-label', '消息正文')\r\n const attachments = document.createElement('div')\r\n attachments.className = styles['attachmentEditor'] ?? ''\r\n const error = document.createElement('div')\r\n error.className = styles['attachmentNotice'] ?? ''\r\n error.setAttribute('role', 'alert')\r\n const footer = document.createElement('div')\r\n footer.className = STYLE.footer\r\n const save = document.createElement('button')\r\n save.type = 'button'\r\n save.textContent = '保存'\r\n const send = block.kind === 'user' ? document.createElement('button') : undefined\r\n if (send !== undefined) {\r\n send.type = 'button'\r\n send.textContent = '保存并发送'\r\n }\r\n const cancel = document.createElement('button')\r\n cancel.type = 'button'\r\n cancel.textContent = '取消'\r\n footer.append(save, ...send === undefined ? [] : [send], cancel)\r\n panel.append(title, ...block.kind === 'user' ? [attachments] : [input], error, footer)\r\n overlay.appendChild(panel)\r\n document.body.appendChild(overlay)\r\n let mounted = true\r\n let saving = false\r\n let uploading = false\r\n let composer: MessageComposerHandle | undefined\r\n let closeConfirmation: OverlayCleanup | undefined\r\n const updateButtons = (): void => {\r\n save.disabled = saving || uploading\r\n if (send !== undefined) send.disabled = saving || uploading\r\n cancel.disabled = saving\r\n input.readOnly = saving\r\n }\r\n const applyEdit = (regenerate: boolean): void => {\r\n if (saving || uploading) return\r\n saving = true\r\n updateButtons()\r\n composer?.setDisabled(true)\r\n error.textContent = ''\r\n void (async () => {\r\n try {\r\n const payload = await composer?.serialize()\r\n if (!mounted) return\r\n const applied = await edit(block, composer?.text() ?? input.value, 'truncate', regenerate, payload, composer?.settings(regenerate))\r\n if (!mounted) return\r\n if (applied) close()\r\n else error.textContent = '保存失败,请检查消息状态后重试。'\r\n } catch (cause) {\r\n if (mounted) error.textContent = cause instanceof Error ? cause.message : String(cause)\r\n } finally {\r\n if (mounted) {\r\n saving = false\r\n composer?.setDisabled(false)\r\n updateButtons()\r\n }\r\n }\r\n })()\r\n }\r\n const saveEdit = (): void => { applyEdit(block.kind !== 'user') }\r\n const saveAndSend = (): void => { applyEdit(true) }\r\n const cancelEdit = (): void => {\r\n if (saving || closeConfirmation !== undefined) return\r\n closeConfirmation = confirmCancelEdit(() => {\r\n closeConfirmation = undefined\r\n close()\r\n }, () => {\r\n closeConfirmation = undefined\r\n if (composer === undefined) input.focus()\r\n else composer.focus()\r\n })\r\n }\r\n const dismiss = (event: MouseEvent): void => { if (event.target === overlay) cancelEdit() }\r\n if (block.kind === 'user') {\r\n composer = mountMessageComposer(attachments, block, attachmentTools, composerTools, {\r\n onBusy: busy => { uploading = busy; updateButtons() },\r\n onSave: saveEdit, onSend: saveAndSend,\r\n })\r\n composer.focus()\r\n } else {\r\n input.focus()\r\n input.setSelectionRange(input.value.length, input.value.length)\r\n }\r\n save.addEventListener('click', saveEdit)\r\n send?.addEventListener('click', saveAndSend)\r\n cancel.addEventListener('click', cancelEdit)\r\n overlay.addEventListener('click', dismiss)\r\n return () => {\r\n mounted = false\r\n composer?.dispose()\r\n closeConfirmation?.()\r\n save.removeEventListener('click', saveEdit)\r\n send?.removeEventListener('click', saveAndSend)\r\n cancel.removeEventListener('click', cancelEdit)\r\n overlay.removeEventListener('click', dismiss)\r\n overlay.remove()\r\n }\r\n}\r\n\r\n/** Mount one block-picker DOM effect and return its exact inverse. */\r\nfunction mountPicker(\r\n blocks: readonly EditableMessageBlock[],\r\n select: (block: EditableMessageBlock) => void,\r\n close: () => void,\r\n): OverlayCleanup {\r\n const overlay = document.createElement('div')\r\n overlay.className = STYLE.overlay\r\n const panel = document.createElement('div')\r\n panel.className = STYLE.panel\r\n const title = document.createElement('div')\r\n title.className = STYLE.title\r\n title.textContent = blocks.some(block => block.kind === 'user') ? '编辑消息' : '编辑助手消息'\r\n const picker = document.createElement('div')\r\n picker.className = STYLE.picker\r\n const itemListeners: Array<{ item: HTMLButtonElement; listener: () => void }> = []\r\n for (const block of blocks) {\r\n const item = document.createElement('button')\r\n item.className = STYLE.pickerItem\r\n item.textContent = `${blockTitle(block.kind)}:${block.text.slice(0, 24)}${block.text.length > 24 ? '…' : ''}`\r\n const listener = (): void => { select(block) }\r\n item.addEventListener('click', listener)\r\n itemListeners.push({ item, listener })\r\n picker.appendChild(item)\r\n }\r\n const cancel = document.createElement('button')\r\n cancel.textContent = '取消'\r\n cancel.className = STYLE.pickerItemActive\r\n const cancelPicker = (): void => { close() }\r\n cancel.addEventListener('click', cancelPicker)\r\n panel.append(title, picker, cancel)\r\n overlay.appendChild(panel)\r\n document.body.appendChild(overlay)\r\n return () => {\r\n for (const { item, listener } of itemListeners) item.removeEventListener('click', listener)\r\n cancel.removeEventListener('click', cancelPicker)\r\n overlay.remove()\r\n }\r\n}\r\n\r\n/** Compose every overlay with a single idempotent active inverse. */\r\nfunction createOverlayHost(edit: MessageEditFace['edit'], attachmentTools: MessageEditFace['attachmentTools'], composerTools: MessageEditFace['composerTools']): {\r\n editBlock(block: EditableMessageBlock): void\r\n chooseBlock(blocks: readonly EditableMessageBlock[]): void\r\n dispose(): void\r\n} {\r\n let active: OverlayCleanup | undefined\r\n const mount = (effect: (close: () => void) => OverlayCleanup): void => {\r\n active?.()\r\n let cleanup: OverlayCleanup = () => {}\r\n let mounted = true\r\n const close = (): void => {\r\n if (!mounted) return\r\n mounted = false\r\n cleanup()\r\n if (active === close) active = undefined\r\n }\r\n active = close\r\n try {\r\n cleanup = effect(close)\r\n } catch (error: unknown) {\r\n active = undefined\r\n mounted = false\r\n throw error\r\n }\r\n }\r\n const editBlock = (block: EditableMessageBlock): void => {\r\n mount(close => mountEditor(block, edit, close, attachmentTools, composerTools))\r\n }\r\n const chooseBlock = (blocks: readonly EditableMessageBlock[]): void => {\r\n mount(close => mountPicker(blocks, (block) => {\r\n close()\r\n editBlock(block)\r\n }, close))\r\n }\r\n return {\r\n editBlock,\r\n chooseBlock,\r\n dispose: () => { active?.() },\r\n }\r\n}\r\n\r\n/** 按消息标识更新操作按钮,数据刷新时保留按钮与正在编辑的弹窗。 */\r\nexport function InlineMessageEdit({\r\n messages,\r\n edit,\r\n retry,\r\n attachmentTools,\r\n composerTools,\r\n disabled = false,\r\n}: {\r\n messages: readonly EditableMessageBlock[]\r\n edit: MessageEditFace['edit']\r\n retry: MessageEditFace['retry']\r\n attachmentTools: MessageEditFace['attachmentTools']\r\n composerTools: MessageEditFace['composerTools']\r\n disabled?: boolean\r\n}): null {\r\n const current = useRef({ messages, disabled })\r\n current.current = { messages, disabled }\r\n const synchronize = useRef<(() => void) | undefined>(undefined)\r\n useLayoutEffect(() => {\r\n const bindings = new Map<HTMLElement, {\r\n eventSeq: number\r\n blocks: readonly EditableMessageBlock[]\r\n editButton: HTMLButtonElement\r\n retryButton: HTMLButtonElement\r\n dispose(): void\r\n }>()\r\n const overlays = createOverlayHost(edit, attachmentTools, composerTools)\r\n let observer: MutationObserver | undefined\r\n let alive = true\r\n let frame: number | undefined\r\n let scheduled = false\r\n\r\n const sync = (): void => {\r\n const actionRows = Array.from(document.querySelectorAll<HTMLElement>('[data-clock=\"start\"], [data-clock=\"end\"]'))\r\n const presentRows = new Set(actionRows)\r\n for (const [row, binding] of bindings) {\r\n if (presentRows.has(row)) continue\r\n binding.dispose()\r\n bindings.delete(row)\r\n }\r\n const blocksByEvent = new Map<number, EditableMessageBlock[]>()\r\n const turns = new Map<number, { user?: number; assistant?: number }>()\r\n for (const message of current.current.messages) {\r\n let blocks = blocksByEvent.get(message.eventSeq)\r\n if (blocks === undefined) { blocks = []; blocksByEvent.set(message.eventSeq, blocks) }\r\n blocks.push(message)\r\n let turn = turns.get(message.turn)\r\n if (turn === undefined) { turn = {}; turns.set(message.turn, turn) }\r\n if (message.kind === 'user') turn.user ??= message.eventSeq\r\n else turn.assistant = message.eventSeq\r\n }\r\n const claimedEvents = new Set<number>()\r\n for (const row of actionRows) {\r\n const marker = row as HTMLElement & {\r\n __messageEditInjected?: boolean\r\n __messageEditEventSeq?: number\r\n }\r\n let binding = bindings.get(row)\r\n if (marker.__messageEditInjected === true && binding === undefined) {\r\n if (marker.__messageEditEventSeq !== undefined) claimedEvents.add(marker.__messageEditEventSeq)\r\n continue\r\n }\r\n // 新版将助手操作栏放在回合尾部,按 DOM 的回合标识匹配,避免重复文本串到其他消息。\r\n const node = row.closest<HTMLElement>('[data-chat-flow-kind]')\r\n const kind = node?.dataset['chatFlowKind']\r\n const turn = Number(node?.dataset['chatTurn'])\r\n const eventSeq = !Number.isSafeInteger(turn) || turn < 1 ? undefined\r\n : kind === 'user' ? turns.get(turn)?.user\r\n : kind === 'turn-tail' ? turns.get(turn)?.assistant : undefined\r\n const blocks = eventSeq === undefined ? undefined : blocksByEvent.get(eventSeq)\r\n if (eventSeq === undefined || blocks === undefined || claimedEvents.has(eventSeq)) {\r\n binding?.dispose()\r\n bindings.delete(row)\r\n continue\r\n }\r\n claimedEvents.add(eventSeq)\r\n if (binding?.eventSeq === eventSeq && row.contains(binding.editButton) && row.contains(binding.retryButton)) {\r\n binding.blocks = blocks\r\n binding.editButton.disabled = current.current.disabled\r\n binding.retryButton.disabled = current.current.disabled\r\n continue\r\n }\r\n binding?.dispose()\r\n bindings.delete(row)\r\n const previousMarker = marker.__messageEditInjected\r\n const previousEventSeq = marker.__messageEditEventSeq\r\n marker.__messageEditInjected = true\r\n marker.__messageEditEventSeq = eventSeq\r\n\r\n const editButton = document.createElement('button')\r\n editButton.type = 'button'\r\n editButton.className = STYLE.iconButton\r\n editButton.setAttribute('aria-label', '编辑消息')\r\n editButton.title = '编辑消息'\r\n editButton.setAttribute('data-message-edit-control', '')\r\n editButton.disabled = current.current.disabled\r\n editButton.appendChild(svgIcon(EDIT_PATH))\r\n const editMessage = (): void => {\r\n if (current.current.disabled || binding === undefined) return\r\n if (binding.blocks.length === 1 && binding.blocks[0] !== undefined) overlays.editBlock(binding.blocks[0])\r\n else overlays.chooseBlock(binding.blocks)\r\n }\r\n editButton.addEventListener('click', editMessage)\r\n\r\n const retryButton = document.createElement('button')\r\n retryButton.type = 'button'\r\n retryButton.className = STYLE.iconButton\r\n retryButton.setAttribute('aria-label', '重试此回合')\r\n retryButton.title = '重试此回合'\r\n retryButton.setAttribute('data-message-edit-control', '')\r\n retryButton.disabled = current.current.disabled\r\n retryButton.appendChild(svgIcon(REFRESH_PATH))\r\n const retryTurn = (): void => {\r\n if (current.current.disabled) return\r\n const targetTurn = binding?.blocks[0]?.turn\r\n if (targetTurn !== undefined) void retry(targetTurn, 'truncate')\r\n }\r\n retryButton.addEventListener('click', retryTurn)\r\n\r\n // 仅跟随操作行的直接按钮,避免进入用量或反馈的子容器而丢失原生间距。\r\n const officialButtons = Array.from(row.querySelectorAll('button'))\r\n .filter(button => button.parentElement === row && button !== editButton && button !== retryButton)\r\n const lastOfficial = officialButtons.at(-1)\r\n if (lastOfficial !== undefined) {\r\n lastOfficial.insertAdjacentElement('afterend', retryButton)\r\n lastOfficial.insertAdjacentElement('afterend', editButton)\r\n } else {\r\n row.appendChild(editButton)\r\n row.appendChild(retryButton)\r\n }\r\n const dispose = (): void => {\r\n editButton.removeEventListener('click', editMessage)\r\n retryButton.removeEventListener('click', retryTurn)\r\n editButton.remove()\r\n retryButton.remove()\r\n if (previousMarker === undefined) delete marker.__messageEditInjected\r\n else marker.__messageEditInjected = previousMarker\r\n if (previousEventSeq === undefined) delete marker.__messageEditEventSeq\r\n else marker.__messageEditEventSeq = previousEventSeq\r\n }\r\n binding = { eventSeq, blocks, editButton, retryButton, dispose }\r\n bindings.set(row, binding)\r\n }\r\n }\r\n\r\n synchronize.current = sync\r\n sync()\r\n observer = new MutationObserver(() => {\r\n if (!alive || scheduled) return\r\n scheduled = true\r\n frame = requestAnimationFrame(() => {\r\n frame = undefined\r\n scheduled = false\r\n if (alive) sync()\r\n })\r\n })\r\n observer.observe(document.body, { childList: true, subtree: true })\r\n\r\n return () => {\r\n alive = false\r\n if (frame !== undefined) cancelAnimationFrame(frame)\r\n observer?.disconnect()\r\n overlays.dispose()\r\n for (const binding of bindings.values()) binding.dispose()\r\n bindings.clear()\r\n if (synchronize.current === sync) synchronize.current = undefined\r\n }\r\n }, [edit, retry, attachmentTools, composerTools])\r\n\r\n // 在浏览器绘制前同步消息与可用状态,不留下看似可点但事件拒绝操作的间隙。\r\n useLayoutEffect(() => { synchronize.current?.() }, [messages, disabled])\r\n\r\n return null\r\n}\r\n","import { useEffect, type ReactNode } from 'react'\r\nimport type { InjectFace, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'\r\nimport type { MessageEditFace } from './controller.ts'\r\nimport { InlineMessageEdit } from './InlineMessageEdit.tsx'\r\nimport styles from './MessageEditHeader.module.css'\r\n\r\ntype MessageEditHeaderProps = PropsRuntime<'conversation.session.header.actions'> & InjectFace<MessageEditFace>\r\n\r\n/** Header contribution shared with the Timeline controller. */\r\nexport function MessageEditHeader({\r\n useMessageEdit,\r\n acquire,\r\n load,\r\n openVersion,\r\n reroll,\r\n edit,\r\n retry,\r\n attachmentTools,\r\n composerTools,\r\n}: MessageEditHeaderProps): ReactNode {\r\n const state = useMessageEdit(value => value)\r\n\r\n useEffect(() => {\r\n const release = acquire()\r\n load()\r\n return release\r\n }, [acquire, load])\r\n\r\n const timeline = state.timeline\r\n const versions = state.timeline?.versions ?? []\r\n const undoSessionId = timeline?.undoStack[0]\r\n const redoSessionId = timeline?.redoSessionIds.at(-1)\r\n const effectDepth = timeline?.undoStack.length ?? 0\r\n const busy = state.pending !== null || state.status !== 'ready'\r\n const loadFailed = state.status === 'error'\r\n\r\n return (\r\n <>\r\n <InlineMessageEdit\r\n messages={timeline?.messages ?? []}\r\n edit={edit}\r\n retry={retry}\r\n attachmentTools={attachmentTools}\r\n composerTools={composerTools}\r\n disabled={busy}\r\n />\r\n <div className={styles['root']}>\r\n <button\r\n type=\"button\"\r\n className={styles['iconButton']}\r\n aria-label=\"撤销当前版本效果\"\r\n title=\"撤销当前效果,保留更早效果\"\r\n disabled={undoSessionId === undefined || busy}\r\n onClick={() => { if (undoSessionId !== undefined) void openVersion(undoSessionId) }}\r\n >\r\n ←\r\n </button>\r\n <span className={styles['counter']} role={loadFailed ? 'alert' : undefined}>\r\n {loadFailed ? '消息加载失败'\r\n : state.status === 'idle' || state.status === 'loading' ? '正在载入…'\r\n : versions.length === 0 ? '效果 —' : `效果 ${String(effectDepth)} 层 · ${String(versions.length)} 版`}\r\n </span>\r\n <button\r\n type=\"button\"\r\n className={styles['iconButton']}\r\n aria-label=\"重施加下一版本效果\"\r\n title={timeline !== null && timeline.redoSessionIds.length > 1\r\n ? `重施加最新效果(另有 ${String(timeline.redoSessionIds.length - 1)} 个分支)`\r\n : '重施加下一效果'}\r\n disabled={redoSessionId === undefined || busy}\r\n onClick={() => { if (redoSessionId !== undefined) void openVersion(redoSessionId) }}\r\n >\r\n →\r\n </button>\r\n {loadFailed\r\n ? <button type=\"button\" className={styles['rerollButton']} aria-label=\"重新载入消息时间线\" onClick={load}>重新载入</button>\r\n : <button\r\n type=\"button\"\r\n className={styles['rerollButton']}\r\n disabled={busy || state.timeline === null}\r\n onClick={() => { void reroll() }}\r\n >\r\n {state.pending === 'reroll' ? '正在重生成…' : '重生成'}\r\n </button>}\r\n </div>\r\n </>\r\n )\r\n}\r\n","/** Timeline tab: durable version tree plus turn/block edit and retry controls. */\r\nimport { useEffect, useMemo, useRef, useState, type CSSProperties, type ReactNode } from 'react'\r\nimport type { ConvViewProps } from '@deepseek-ai/dsh-client-ui-conversation/client'\r\nimport type { InjectFace } from '@deepseek-ai/dsh-client-ui-slots'\r\nimport type {\r\n CascadePolicy,\r\n EditableBlockKind,\r\n EditableMessageBlock,\r\n RetryableTurn,\r\n VersionOperation,\r\n VersionSummary,\r\n} from '../shared.ts'\r\nimport type { MessageEditFace } from './controller.ts'\r\nimport { mountEditor } from './InlineMessageEdit.tsx'\r\nimport styles from './MessageEditTimelineView.module.css'\r\n\r\ntype MessageEditTimelineViewProps = ConvViewProps & InjectFace<MessageEditFace>\r\n\r\ninterface TurnSection {\r\n retry: RetryableTurn\r\n messages: EditableMessageBlock[]\r\n}\r\n\r\ninterface EditingState {\r\n message: EditableMessageBlock\r\n}\r\n\r\nconst BLOCK_LABEL: Record<EditableBlockKind, string> = {\r\n user: '用户消息',\r\n 'assistant.reasoning': '助手思考',\r\n 'assistant.response': '助手回复',\r\n}\r\n\r\nconst OPERATION_LABEL: Record<VersionOperation, string> = {\r\n edit: '编辑',\r\n reroll: '重生成',\r\n retry: '重试',\r\n}\r\n\r\nfunction timeLabel(value: number): string {\r\n return new Date(value).toLocaleString('zh-CN', {\r\n month: '2-digit',\r\n day: '2-digit',\r\n hour: '2-digit',\r\n minute: '2-digit',\r\n second: '2-digit',\r\n })\r\n}\r\n\r\nfunction turnSections(\r\n turns: readonly RetryableTurn[],\r\n messages: readonly EditableMessageBlock[],\r\n): TurnSection[] {\r\n return turns.map(retry => ({\r\n retry,\r\n messages: messages.filter(message => message.turn === retry.turn),\r\n }))\r\n}\r\n\r\nfunction VersionRow({ version, disabled, onOpen }: {\r\n version: VersionSummary\r\n disabled: boolean\r\n onOpen: (sessionId: string) => void\r\n}): ReactNode {\r\n const depthStyle = { '--message-edit-depth': String(version.depth) } as CSSProperties\r\n const operation = version.unavailableReason !== undefined ? '历史版本'\r\n : version.operation === undefined\r\n ? version.parentSessionId === undefined ? '原始版本' : '外部分支'\r\n : OPERATION_LABEL[version.operation]\r\n return (\r\n <li className={styles['versionItem']} style={depthStyle}>\r\n <button\r\n type=\"button\"\r\n className={styles['versionButton']}\r\n data-current={version.current || undefined}\r\n data-unavailable={version.unavailableReason === undefined ? undefined : true}\r\n disabled={version.current || disabled || version.unavailableReason !== undefined}\r\n onClick={() => { if (version.unavailableReason === undefined) onOpen(version.sessionId) }}\r\n >\r\n <span className={styles['versionLine']} aria-hidden />\r\n <span className={styles['versionDot']} aria-hidden />\r\n <span className={styles['versionMain']}>\r\n <span className={styles['versionTitle']}>\r\n {operation}\r\n {version.targetTurn === undefined ? null : ` · 回合 ${String(version.targetTurn)}`}\r\n </span>\r\n <span className={styles['versionMeta']}>\r\n {timeLabel(version.createdAt)} · {version.sessionId.slice(0, 12)}\r\n </span>\r\n {version.unavailableReason === undefined ? null\r\n : <span className={styles['versionUnavailable']}>{version.unavailableReason}</span>}\r\n {version.before === undefined && version.after === undefined\r\n ? null\r\n : (\r\n <span className={styles['versionDiff']}>\r\n <span>原:{version.before || '(空)'}</span>\r\n <span>新:{version.after || '(空)'}</span>\r\n </span>\r\n )}\r\n </span>\r\n {version.unavailableReason !== undefined\r\n ? <span className={styles['unavailableBadge']}>无法读取</span>\r\n : version.current\r\n ? <span className={styles['currentBadge']}>当前</span>\r\n : version.onCurrentEffectPath\r\n ? <span className={styles['pathBadge']}>链上</span>\r\n : null}\r\n </button>\r\n </li>\r\n )\r\n}\r\n\r\nfunction MessageCard({ message, disabled, onBeginEdit }: {\n message: EditableMessageBlock\n disabled: boolean\n onBeginEdit(message: EditableMessageBlock): void\n}): ReactNode {\n return (\n <article className={styles['messageCard']}>\n <div className={styles['messageHeader']}>\n <span className={styles['kindBadge']} data-kind={message.kind}>{BLOCK_LABEL[message.kind]}</span>\n <span className={styles['messageTime']}>{timeLabel(message.time)}</span>\n <button type=\"button\" className={styles['textButton']} disabled={disabled} onClick={() => onBeginEdit(message)}>编辑</button>\n </div>\n {message.attachments?.length ? <p className={styles['messageTime']}>\n 附件:{message.attachments.map(item => item.content.attachment.name ?? '图片附件').join('、')}\n </p> : null}\n <pre className={styles['messageText']}>{message.text || '(空正文)'}</pre>\n </article>\n )\n}\n\n/** Conversation-view entry point. */\r\nexport function MessageEditTimelineView({\r\n useMessageEdit,\r\n acquire,\r\n load,\r\n edit,\r\n retry,\r\n reroll,\r\n openVersion,\r\n attachmentTools,\r\n composerTools,\r\n}: MessageEditTimelineViewProps): ReactNode {\r\n const state = useMessageEdit(value => value)\r\n const [cascade, setCascade] = useState<CascadePolicy>('truncate')\r\n const [editing, setEditing] = useState<EditingState | null>(null)\r\n useEffect(() => {\r\n const release = acquire()\r\n load()\r\n return release\r\n }, [acquire, load])\r\n\r\n const timeline = state.timeline\r\n const sections = useMemo(\r\n () => timeline === null ? [] : turnSections(timeline.retryableTurns, timeline.messages),\r\n [timeline],\r\n )\r\n const busy = state.pending !== null || state.status !== 'ready'\r\n\r\n useEffect(() => {\r\n setEditing((current) => {\r\n if (current === null || timeline === null) return current\r\n return timeline.messages.some(message => message.key === current.message.key) ? current : null\r\n })\r\n }, [timeline])\r\n\r\n const cascadeRef = useRef(cascade)\n cascadeRef.current = cascade\n useEffect(() => {\n if (editing === null) return\n return mountEditor(editing.message, (message, text, _policy, regenerate, attachments, settings) =>\n edit(message, text, cascadeRef.current, regenerate, attachments, settings),\n () => setEditing(null), attachmentTools, composerTools)\n }, [editing, edit, attachmentTools, composerTools])\n\n if (timeline === null && (state.status === 'idle' || state.status === 'loading')) {\r\n return <div className={styles['status']}>正在载入消息时间线…</div>\r\n }\r\n if (timeline === null && state.status === 'error') {\r\n return (\r\n <div className={styles['status']}>\r\n <p className={styles['error']}>{state.error}</p>\r\n <button type=\"button\" className={styles['secondaryButton']} onClick={load}>重新载入</button>\r\n </div>\r\n )\r\n }\r\n if (timeline === null) return null\r\n\r\n return (\r\n <div className={styles['root']}>\r\n <header className={styles['pageHeader']}>\r\n <div>\r\n <h1 className={styles['title']}>消息编辑与重生成</h1>\r\n <p className={styles['intro']}>每次修改都会与其恢复版本成对记录;回合及其完整工具链作为一个整体重新计算。</p>\r\n </div>\r\n <div className={styles['headerActions']}>\r\n <label className={styles['cascadeField']}>\r\n <span>后续策略</span>\r\n <select\r\n className={styles['select']}\r\n value={cascade}\r\n disabled={busy}\r\n onChange={(event) => { setCascade(event.currentTarget.value as CascadePolicy) }}\r\n >\r\n <option value=\"truncate\">截断后续(默认)</option>\r\n <option value=\"preserve\">保留输入并重生成后续</option>\r\n </select>\r\n </label>\r\n <button\r\n type=\"button\"\r\n className={styles['primaryButton']}\r\n disabled={busy}\r\n onClick={() => { void reroll() }}\r\n >\r\n {state.pending === 'reroll' ? '正在重生成…' : '重生成最后回复'}\r\n </button>\r\n </div>\r\n </header>\r\n\r\n {state.error === null ? null : <p className={styles['error']}>{state.error}</p>}\r\n {state.status === 'loading' ? <p className={styles['notice']}>正在刷新时间线…</p> : null}\r\n\r\n <div className={styles['columns']}>\r\n <aside className={styles['versionsPanel']} aria-label=\"版本时间线\">\r\n <div className={styles['sectionHeading']}>\r\n <h2 className={styles['subtitle']}>版本时间线</h2>\r\n <span className={styles['count']}>{String(timeline.versions.length)}</span>\r\n </div>\r\n <div className={styles['effectControls']}>\r\n <span className={styles['effectDepth']}>当前效果链 {String(timeline.undoStack.length)} 层</span>\r\n <div className={styles['effectButtons']}>\r\n <button\r\n type=\"button\"\r\n className={styles['secondaryButton']}\r\n disabled={busy || timeline.undoStack[0] === undefined}\r\n onClick={() => {\r\n const target = timeline.undoStack[0]\r\n if (target !== undefined) void openVersion(target)\r\n }}\r\n >\r\n 撤销当前效果\r\n </button>\r\n <button\r\n type=\"button\"\r\n className={styles['secondaryButton']}\r\n disabled={busy || timeline.redoSessionIds.length === 0}\r\n onClick={() => {\r\n const target = timeline.redoSessionIds.at(-1)\r\n if (target !== undefined) void openVersion(target)\r\n }}\r\n >\r\n {timeline.redoSessionIds.length > 1\r\n ? `重施加最新分支(${String(timeline.redoSessionIds.length)})`\r\n : '重施加下一效果'}\r\n </button>\r\n </div>\r\n </div>\r\n <ol className={styles['versionList']}>\r\n {timeline.versions.map(version => (\r\n <VersionRow\r\n key={version.sessionId}\r\n version={version}\r\n disabled={busy}\r\n onOpen={(sessionId) => { void openVersion(sessionId) }}\r\n />\r\n ))}\r\n </ol>\r\n </aside>\r\n\r\n <main className={styles['turnsPanel']}>\r\n <div className={styles['sectionHeading']}>\r\n <h2 className={styles['subtitle']}>已落定消息</h2>\r\n <span className={styles['count']}>{String(timeline.messages.length)}</span>\r\n </div>\r\n {sections.length === 0\r\n ? <p className={styles['empty']}>当前会话还没有可编辑的已落定回合。</p>\r\n : (\r\n <ol className={styles['turnList']}>\r\n {sections.map(section => (\r\n <li key={section.retry.turn} className={styles['turnSection']}>\r\n <div className={styles['turnHeader']}>\r\n <div>\r\n <h3 className={styles['turnTitle']}>回合 {String(section.retry.turn)}</h3>\r\n <p className={styles['turnPreview']}>{section.retry.preview || '(空用户输入)'}</p>\r\n </div>\r\n <button\r\n type=\"button\"\r\n className={styles['secondaryButton']}\r\n disabled={busy}\r\n onClick={() => { void retry(section.retry.turn, cascade) }}\r\n >\r\n {state.pending === 'retry' ? '正在重试…' : '重试此回合'}\r\n </button>\r\n </div>\r\n <div className={styles['messageList']}>\r\n {section.messages.map(message => (\r\n <MessageCard\r\n key={message.key}\r\n message={message}\r\n disabled={busy}\r\n onBeginEdit={value => { setEditing({ message: value }) }}\r\n />\r\n ))}\r\n </div>\r\n </li>\r\n ))}\r\n </ol>\r\n )}\r\n </main>\r\n </div>\r\n </div>\r\n )\r\n}\r\n","import { createElement, useEffect, type ComponentType, type ReactNode } from 'react'\nimport type { Context } from '@deepseek-ai/cordis'\nimport type { ContentBlock } from '@deepseek-ai/dsh-llm'\nimport type { SessionId } from '@deepseek-ai/dsh-session/types'\nimport type { InjectFace, StoredEntry } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { MessageEditFace } from './controller.ts'\n\nconst CHAT_NODE_SLOT = 'conversation.chat.node'\nconst USER_NODE_KEYS = ['user', 'steering'] as const\n\ninterface UserNode {\n readonly data: {\n readonly seq: number\n readonly content: readonly ContentBlock[]\n }\n}\n\ntype UserNodeProps = Record<string, unknown> & { readonly node: UserNode } & InjectFace<MessageEditFace>\n\ninterface UserSlotOptions {\n name: typeof CHAT_NODE_SLOT\n key: typeof USER_NODE_KEYS[number]\n priority: number\n locale?: string\n inject(sessionId: SessionId): MessageEditFace\n}\n\n/** 通过公开的动态插槽接口接入,避免把整个官方聊天插件打进浏览器包。 */\ninterface ChatNodeSlots {\n entries(name: string): readonly StoredEntry[]\n subscribe(name: string, listener: () => void): () => void\n register(options: UserSlotOptions, component: ComponentType<UserNodeProps>): () => void\n}\n\nfunction equalContentValue(left: unknown, right: unknown): boolean {\n if (left === right) return true\n if (left === null || right === null || typeof left !== 'object' || typeof right !== 'object') return false\n if (Array.isArray(left) !== Array.isArray(right)) return false\n if (Array.isArray(left) && Array.isArray(right)) {\n return left.length === right.length && left.every((value, index) => equalContentValue(value, right[index]))\n }\n const leftRecord = left as Record<string, unknown>\n const rightRecord = right as Record<string, unknown>\n const keys = Object.keys(leftRecord)\n return keys.length === Object.keys(rightRecord).length && keys.every(key =>\n Object.prototype.hasOwnProperty.call(rightRecord, key) && equalContentValue(leftRecord[key], rightRecord[key]))\n}\n\nfunction projectedRenderer(original: StoredEntry): ComponentType<UserNodeProps> {\n const Original = original.component as ComponentType<Record<string, unknown>>\n return function UserMessageProjection(props: UserNodeProps): ReactNode {\n const { acquire, load, node, useMessageEdit } = props\n const messages = useMessageEdit(state => state.timeline?.messages)\n useEffect(() => {\n const release = acquire()\n load()\n return release\n }, [acquire, load])\n\n const savedContent = messages?.find(message => message.kind === 'user'\n && message.eventSeq === node.data.seq && message.content !== undefined)?.content\n let projected = node\n if (savedContent !== undefined) {\n if (!equalContentValue(node.data.content, savedContent)) {\n projected = { ...node, data: { ...node.data, content: savedContent } }\n }\n } else {\n // 兼容未提供完整内容的旧记录,仍按原内容块位置覆盖文本。\n let changed = false\n const content = node.data.content.map((block, blockIndex) => {\n if (block.type !== 'text') return block\n const saved = messages?.find(message => message.kind === 'user'\n && message.eventSeq === node.data.seq && message.blockIndex === blockIndex)\n if (saved === undefined || saved.text === block.text) return block\n changed = true\n return { ...block, text: saved.text }\n })\n if (changed) projected = { ...node, data: { ...node.data, content } }\n }\n return createElement(Original, { ...props, node: projected })\n }\n}\n\n/** 覆写用户消息的显示内容,复用官方气泡、附件和复制操作,不修改宿主的只读事件源。 */\nexport function registerUserMessageProjection(\n ctx: Context,\n faceFor: (sessionId: SessionId) => MessageEditFace,\n): void {\n const slots = ctx.slots as unknown as ChatNodeSlots\n // 旧宿主缺少公开的插槽检查接口时,仍保留 Timeline 的编辑入口。\n if (typeof slots.entries !== 'function' || typeof slots.subscribe !== 'function') return\n ctx.effect(() => {\n const active = new Map<string, { original: StoredEntry; component: ComponentType<UserNodeProps>; dispose(): void }>()\n let disposed = false\n const sync = (): void => {\n if (disposed) return\n for (const key of USER_NODE_KEYS) {\n const current = active.get(key)\n const original = slots.entries(CHAT_NODE_SLOT).find(entry => entry.options.key === key\n && !Array.from(active.values()).some(wrapper => wrapper.component === entry.component))\n if (current?.original === original) continue\n current?.dispose()\n active.delete(key)\n if (original === undefined) continue\n const component = projectedRenderer(original)\n const dispose = slots.register({\n name: CHAT_NODE_SLOT,\n key,\n priority: (original.options.priority ?? 0) - 1,\n ...original.locale === undefined ? {} : { locale: original.locale },\n inject: faceFor,\n }, component)\n active.set(key, { original, component, dispose })\n }\n }\n const unsubscribe = slots.subscribe(CHAT_NODE_SLOT, sync)\n sync()\n return () => {\n disposed = true\n unsubscribe()\n for (const wrapper of active.values()) wrapper.dispose()\n active.clear()\n }\n }, 'message-edit: 用户消息显示投影')\n}\n","/** Message Edit browser half: Timeline view and compact conversation-header controls. */\r\nimport type { Context } from '@deepseek-ai/cordis'\r\nimport type { SessionId } from '@deepseek-ai/dsh-session/types'\r\nimport type {} from '@deepseek-ai/dsh-client-ui-conversation/client'\r\nimport type {} from '@deepseek-ai/dsh-client-ui-renderer/client'\r\nimport { MESSAGE_EDIT_VIEW_ORDER } from '../shared.ts'\r\nimport { MessageEditController } from './controller.ts'\r\nimport { MessageEditHeader } from './MessageEditHeader.tsx'\r\nimport { MessageEditTimelineView } from './MessageEditTimelineView.tsx'\r\nimport { registerUserMessageProjection } from './UserMessageProjection.tsx'\r\nimport { MESSAGE_EDIT_BUILD_INFO } from '../build-info.ts'\r\nimport { MESSAGE_EDIT_PATH } from '../shared.ts'\r\nimport { hostFetch } from './transport.ts'\r\n\r\nexport { MESSAGE_EDIT_BUILD_INFO } from '../build-info.ts'\r\n\r\n/** Explicit value sources and slot declaration-order edges. */\r\nexport const inject = ['slots', 'uiConversation', 'conversation', 'uiWorkspace', 'connection', 'sessions',\r\n 'commandUi', 'remote.commands', 'remote.sessionReferenceResolver']\r\n\r\n/** Register both UI contributions over one per-session controller identity. */\r\nexport function apply(ctx: Context): void {\r\n const globals = globalThis as typeof globalThis & { __DSH_MESSAGE_EDIT__?: unknown }\r\n const diagnostics = Object.freeze({\r\n build: MESSAGE_EDIT_BUILD_INFO,\r\n diagnostics: async () => {\r\n const response = await hostFetch(`${MESSAGE_EDIT_PATH}?view=diagnostics`, {\r\n method: 'GET', headers: { accept: 'application/json' }, cache: 'no-store',\r\n })\r\n if (!response.ok) throw new Error(`无法读取插件诊断:HTTP ${String(response.status)}`)\r\n const host = await response.json() as { build?: { version?: string; buildId?: string } }\r\n return { client: MESSAGE_EDIT_BUILD_INFO, host,\r\n matched: host.build?.version === MESSAGE_EDIT_BUILD_INFO.version && host.build?.buildId === MESSAGE_EDIT_BUILD_INFO.buildId }\r\n },\r\n })\r\n ctx.effect(() => {\r\n const previous = globals.__DSH_MESSAGE_EDIT__\r\n globals.__DSH_MESSAGE_EDIT__ = diagnostics\r\n return () => {\r\n if (globals.__DSH_MESSAGE_EDIT__ === diagnostics) {\r\n if (previous === undefined) delete globals.__DSH_MESSAGE_EDIT__\r\n else globals.__DSH_MESSAGE_EDIT__ = previous\r\n }\r\n }\r\n }, 'message-edit: 构建诊断')\r\n const controllers = new Map<SessionId, MessageEditController>()\r\n const controllerFor = (sessionId: SessionId): MessageEditController => {\r\n let controller = controllers.get(sessionId)\r\n if (controller === undefined) {\r\n controller = new MessageEditController(ctx, sessionId)\r\n controllers.set(sessionId, controller)\r\n }\r\n return controller\r\n }\r\n\r\n registerUserMessageProjection(ctx, sessionId => controllerFor(sessionId).face)\r\n\r\n ctx.on('connection/reset', () => {\r\n for (const controller of controllers.values()) controller.refreshIfLoaded()\r\n })\r\n\r\n ctx.slots.inject('conversation.view', () => ctx.slots.register({\r\n name: 'conversation.view',\r\n id: 'message-edit-timeline',\r\n order: MESSAGE_EDIT_VIEW_ORDER,\r\n label: 'Timeline',\r\n inject: (sessionId: SessionId) => controllerFor(sessionId).face,\r\n }, MessageEditTimelineView))\r\n\r\n ctx.slots.inject('conversation.session.header.actions', () => ctx.slots.register({\r\n name: 'conversation.session.header.actions',\r\n id: 'message-edit-controls',\r\n order: MESSAGE_EDIT_VIEW_ORDER,\r\n inject: (sessionId: SessionId) => controllerFor(sessionId).face,\r\n }, MessageEditHeader))\r\n}\r\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"client.js","names":["styles","styles","styles","styles","styles","styles","styles"],"sources":["shared.ts","transport.ts","saved-user-messages.ts","build-info.ts","attachmentTools.ts","composerTools.ts","controller.ts","confirmCancelEdit.ts","AttachmentEditor.tsx","fileReferences.ts","RichMessageInput.ts","MessageComposer.ts","InlineMessageEdit.tsx","MessageEditHeader.tsx","MessageEditTimelineView.tsx","UserMessageProjection.tsx","index.ts"],"sourcesContent":["import type { ContentBlock } from '@deepseek-ai/dsh-llm'\r\n\r\n/** Same-origin endpoint owned by the Message Edit host plugin. */\r\nexport const MESSAGE_EDIT_PATH = '/api/message-edit'\r\n\r\n/** Timeline sits between Trajectory (10) and Prompt Studio (20). */\r\nexport const MESSAGE_EDIT_VIEW_ORDER = 15\r\n\r\n/** Downstream-history policy after a historical turn changes. */\r\nexport type CascadePolicy = 'truncate' | 'preserve'\r\n\r\n/** User-visible operation represented by one child version. */\r\nexport type VersionOperation = 'edit' | 'reroll' | 'retry'\r\n\r\n/** Editable model-surface block classification. */\r\nexport type EditableBlockKind = 'user' | 'assistant.reasoning' | 'assistant.response'\r\n\r\n/** 附件沿用宿主的持久内容块,保留显示名称、尺寸和卸载状态。 */\r\nexport type MessageEditAttachmentBlock = Extract<ContentBlock, { type: 'image' | 'file' }>\r\n\r\n/** 已有附件通过当前消息中的内容块位置保留,客户端不提交持久引用。 */\r\nexport interface EditableMessageAttachment {\r\n blockIndex: number\r\n content: MessageEditAttachmentBlock\r\n}\r\n\r\n/** 新附件复用官方草稿序列化格式;文件凭据只能在来源 Agent 内解析。 */\r\nexport type MessageEditAttachmentInput = {\r\n type: 'retained'\r\n blockIndex: number\r\n} | {\r\n type: 'image'\r\n mediaType: 'image/png' | 'image/jpeg' | 'image/webp' | 'image/gif'\r\n data: string\r\n name?: string\r\n} | {\r\n type: 'file'\r\n receiptId: string\r\n}\r\n\r\n/** 编辑器中的会话配置草稿,只有确认保存后才应用到目标会话。 */\r\nexport interface MessageEditSettings {\r\n provider?: string\r\n model?: string\r\n reasoningEffort?: string\r\n permissionPreset?: string\r\n}\r\n\r\n/** 供编辑器复用正常输入框的模型、推理和权限选项。 */\r\nexport interface MessageEditComposerOptions {\r\n current: MessageEditSettings\r\n models: readonly {\r\n provider: string\r\n providerLabel?: string\r\n model: string\r\n label: string\r\n reasoningEfforts: readonly string[]\r\n reasoningEffortLabels?: Readonly<Record<string, string>>\r\n }[]\r\n permissions: readonly { id: string; label: string; description?: string }[]\r\n}\r\n\r\n/** 官方工作区文件候选的编辑器展示格式。 */\r\nexport interface MessageEditReference {\r\n path: string\r\n label: string\r\n kind: 'file' | 'folder'\r\n}\r\n\r\n/** Current durable event schema for structurally paired version effects. */\r\nexport const MESSAGE_EDIT_VERSION_SCHEMA = 2\r\n\r\n/** Forward half of one atomic version effect. */\r\nexport interface MessageEditEffect {\r\n id: string\r\n operation: VersionOperation\r\n cascade: CascadePolicy\r\n targetTurn: number\r\n targetEventSeq: number\r\n targetBlockIndex?: number\r\n blockKind?: EditableBlockKind\r\n before?: string\r\n after?: string\r\n /** 用户消息编辑是否重新请求模型;旧版本未记录时沿用原有行为。 */\r\n regenerate?: boolean\r\n}\r\n\r\n/** Inverse half generated together with a version effect. */\r\nexport interface MessageEditInverse {\r\n kind: 'restore-version'\r\n sessionId: string\r\n}\r\n\r\n/** Durable effect/inverse pair appended to each branch created by this plugin. */\r\nexport interface MessageEditVersionEvent {\r\n schemaVersion: typeof MESSAGE_EDIT_VERSION_SCHEMA\r\n effect: MessageEditEffect\r\n inverse: MessageEditInverse\r\n}\r\n\r\n/** Read compatibility for branches written before structural pairing. */\r\nexport interface LegacyMessageEditVersionEvent {\r\n sourceSessionId: string\r\n operation: VersionOperation\r\n cascade: CascadePolicy\r\n targetTurn: number\r\n targetEventSeq: number\r\n targetBlockIndex?: number\r\n blockKind?: EditableBlockKind\r\n before?: string\r\n after?: string\r\n}\r\n\r\n/** Every durable event shape accepted by the lineage reader. */\r\nexport type StoredMessageEditVersionEvent = MessageEditVersionEvent | LegacyMessageEditVersionEvent\r\n\r\n/** One text-bearing block that the Timeline editor can replace. */\r\nexport interface EditableMessageBlock {\r\n key: string\r\n turn: number\r\n eventSeq: number\r\n blockIndex: number\r\n kind: EditableBlockKind\r\n text: string\r\n time: number\r\n /** 用户消息的最新完整内容,供官方气泡同时投影正文和附件。 */\r\n content?: readonly ContentBlock[]\r\n attachments?: readonly EditableMessageAttachment[]\r\n}\r\n\r\n/** One completed message-triggered turn eligible for Retry. */\r\nexport interface RetryableTurn {\r\n turn: number\r\n userEventSeq: number\r\n preview: string\r\n time: number\r\n}\r\n\r\n/** One session version in the complete known lineage tree. */\r\nexport interface VersionSummary {\r\n sessionId: string\r\n parentSessionId?: string\r\n effectId?: string\r\n inverseSessionId?: string\r\n createdAt: number\r\n depth: number\r\n current: boolean\r\n onCurrentEffectPath: boolean\r\n /** 其他版本无法读取时保留节点并说明原因,禁止切换到该版本。 */\r\n unavailableReason?: string\r\n operation?: VersionOperation\r\n cascade?: CascadePolicy\r\n targetTurn?: number\r\n blockKind?: EditableBlockKind\r\n before?: string\r\n after?: string\r\n}\r\n\r\n/** Complete value-level projection consumed by both Timeline and header controls. */\r\nexport interface MessageEditTimeline {\r\n sessionId: string\r\n messages: EditableMessageBlock[]\r\n retryableTurns: RetryableTurn[]\r\n versions: VersionSummary[]\r\n /** Atomic inverses from the current version outward, in application order. */\r\n undoStack: string[]\r\n /** Direct child effects that can be re-applied from the current version. */\r\n redoSessionIds: string[]\r\n /** 实际加载的宿主构建,供客户端识别前后端版本不一致。 */\r\n build?: MessageEditBuildInfo\r\n}\r\n\r\n/** 构建身份不包含会话内容或本机路径。 */\r\nexport interface MessageEditBuildInfo {\r\n version: string\r\n buildId: string\r\n targetDshVersion: string\r\n}\r\n\r\n/** 原地保存的只读修订链;active 为 false 时禁止拿旧节点直接执行操作。 */\r\nexport interface MessageEditRevision {\r\n originalEventSeq: number\r\n replacementEventSeq: number\r\n revisionEventSeqs: number[]\r\n active: boolean\r\n}\r\n\r\n/** Edit one text/reasoning block and regenerate from its turn boundary. */\r\nexport interface EditOperation {\r\n action: 'edit'\r\n sessionId: string\r\n eventSeq: number\r\n blockIndex: number\r\n text: string\r\n cascade: CascadePolicy\r\n /** 用户消息默认重新生成,false 表示保留已有对话且只保存文本。 */\r\n regenerate?: boolean\r\n /** 未提供时保留当前附件,空数组移除全部;仅用户消息接受此字段。 */\r\n attachments?: readonly MessageEditAttachmentInput[]\r\n settings?: MessageEditSettings\r\n}\r\n\r\n/** 在当前会话保存用户文本,不创建分支、不排入模型输入。 */\r\nexport interface SaveOperation {\r\n action: 'save'\r\n sessionId: string\r\n eventSeq: number\r\n blockIndex: number\r\n text: string\r\n /** 未提供时保留当前附件,空数组移除全部。 */\r\n attachments?: readonly MessageEditAttachmentInput[]\r\n settings?: MessageEditSettings\r\n}\r\n\r\n/** Regenerate the latest completed assistant reply. */\r\nexport interface RerollOperation {\r\n action: 'reroll'\r\n sessionId: string\r\n}\r\n\r\n/** Regenerate any selected historical turn. */\r\nexport interface RetryOperation {\r\n action: 'retry'\r\n sessionId: string\r\n turn: number\r\n cascade: CascadePolicy\r\n}\r\n\r\n/** Mutation accepted by the host route. */\r\nexport type MessageEditOperation = SaveOperation | EditOperation | RerollOperation | RetryOperation\r\n\r\n/** 当前会话保存或新版本创建完成后的宿主确认。 */\r\nexport interface MessageEditOperationResult {\r\n sessionId: string\r\n queuedTurns: number\r\n /** 仅保存时为 true,且 sessionId 必须仍为来源会话。 */\r\n saved?: boolean\r\n /** 内容及设置没有变化,未写事件、未创建分支,也未请求模型。 */\r\n unchanged?: boolean\r\n}\r\n","import type { ClientTransportHooks } from '@deepseek-ai/dsh-client-connection/client'\n\n/** 使用页面提供的宿主传输,兼容桌面端的自定义协议和普通 Web 页面。 */\nexport function hostFetch(input: string, init: RequestInit): Promise<Response> {\n const globals = globalThis as typeof globalThis & { __DSH_TRANSPORT__?: ClientTransportHooks }\n const path = input.replace(/^\\//, '')\n const transport = globals.__DSH_TRANSPORT__\n return transport?.fetch !== undefined\n ? transport.fetch(path, init)\n : globalThis.fetch(path, init)\n}\n","import type { SessionEvent } from '@deepseek-ai/dsh-session'\nimport type { UserMessage } from '@deepseek-ai/dsh-llm'\n\n/** 使用已知用户消息替换事件记录编辑,原日志与消息身份保持不变。 */\nexport interface SavedUserMessageSource {\n messageEdit?: { originalEventSeq: number }\n}\n\nexport function savedUserMessageSeq(event: SessionEvent): number | undefined {\n if (event.type !== 'user/message' || typeof event.surfaceOp !== 'object' || event.surfaceOp.op !== 'replace') return undefined\n const metadata = (event.data.source as UserMessage['source'] & SavedUserMessageSource).messageEdit\n const original = metadata?.originalEventSeq\n return Number.isSafeInteger(original) && (original as number) >= 0 ? original : undefined\n}\n\n/** 为聊天和历史操作还原用户可见文本;官方替换事件本身不增加聊天行。 */\nexport function savedUserMessages(events: readonly SessionEvent[]): Map<number, SessionEvent<'user/message'>> {\n const result = new Map<number, SessionEvent<'user/message'>>()\n for (const event of events) {\n const originalSeq = savedUserMessageSeq(event)\n if (originalSeq === undefined || event.type !== 'user/message') continue\n const original = events[originalSeq]\n if (original?.type !== 'user/message' || original.surfaceOp !== 'append' || original.data.id !== event.data.id) continue\n result.set(originalSeq, event)\n }\n return result\n}\n\nexport function visibleUserEvents(events: readonly SessionEvent[]): readonly SessionEvent[] {\n const saved = savedUserMessages(events)\n if (saved.size === 0) return events\n return events.map(event => {\n const replacement = saved.get(event.seq)\n return replacement === undefined ? event : { ...event, data: replacement.data } as SessionEvent\n })\n}\n","/** 由构建脚本生成;前后端共享同一份构建身份。 */\nexport const MESSAGE_EDIT_BUILD_INFO = Object.freeze({\n \"version\": \"0.3.3\",\n \"buildId\": \"8b68760be79248960bd3\",\n \"targetDshVersion\": \"0.2.1-rc.5\"\n})\n","import type { Context } from '@deepseek-ai/cordis'\nimport type { ImageAttachmentRef } from '@deepseek-ai/dsh-attachment'\nimport type {\n ComposerAttachment,\n ConversationController,\n DraftAttachmentId,\n DraftFileUploads,\n SubmitAttachment,\n} from '@deepseek-ai/dsh-client-ui-conversation/client'\nimport type { SessionId } from '@deepseek-ai/dsh-session/types'\n\n/** 附件草稿独立于主输入框,沿用官方上传、序列化与资源释放流程。 */\nexport interface MessageAttachmentTools {\n create(files: readonly File[]): readonly ComposerAttachment[]\n serialize(ids: readonly DraftAttachmentId[]): Promise<readonly SubmitAttachment[]>\n release(id: DraftAttachmentId): void\n retry(id: DraftAttachmentId): void\n uploads(): DraftFileUploads\n subscribe(listener: () => void): () => void\n imageUrl(attachment: ImageAttachmentRef): Promise<string>\n}\n\nexport function attachmentTools(ctx: Context, sessionId: SessionId): MessageAttachmentTools {\n const conversation = (): ConversationController => {\n const service = ctx.get('conversation') as ConversationController | undefined\n if (service === undefined) throw new Error('DSH 附件服务尚未就绪,请重启后重试。')\n return service\n }\n return {\n create: files => conversation().createDrafts(sessionId, files),\n serialize: async ids => (await conversation().serializeDraftAttachments(ids)).attachments,\n release: id => { conversation().releaseDraftAttachment(id) },\n retry: id => { conversation().retryFileUpload(sessionId, id) },\n uploads: () => conversation().fileUploads.getSnapshot(),\n subscribe: listener => conversation().fileUploads.subscribe(listener),\n imageUrl: attachment => ctx.uiConversation.imageUrl(sessionId, attachment),\n }\n}\n","import type { Context } from '@deepseek-ai/cordis'\nimport type { ISessions } from '@deepseek-ai/dsh-api-session-controller/client'\nimport type { SessionId } from '@deepseek-ai/dsh-session/types'\nimport { MESSAGE_EDIT_PATH, type MessageEditComposerOptions, type MessageEditSettings } from '../shared.ts'\nimport { hostFetch } from './transport.ts'\n\nexport interface ComposerModelOption {\n provider: string\n model: string\n label: string\n reasoningEfforts: readonly string[]\n}\n\nexport type ComposerSettings = MessageEditSettings\nexport type ComposerOptions = MessageEditComposerOptions\n\nexport type ComposerReference = {\n path: string\n label: string\n kind: 'file' | 'folder'\n} | { sessionId: string; mention: string; label: string; kind: 'session' }\n\nexport interface ComposerCommand {\n name: string\n label?: string\n description?: string\n hint?: string\n section?: string\n}\n\ninterface CommandUiService {\n candidates(scope: { sessionId: SessionId }, request: { query: string; position: 'leading'; signal: AbortSignal }): Promise<readonly ComposerCommand[]>\n execute(scope: { sessionId: SessionId }, line: string): Promise<{ kind: 'success' } | { kind: 'error'; text: string }>\n}\n\n/** 编辑器使用同一宿主服务,但不写入主输入框的 SessionInput。 */\nexport interface MessageComposerTools {\n options(): Promise<ComposerOptions>\n references(query: string, signal: AbortSignal): Promise<readonly ComposerReference[]>\n openPath(path: string): Promise<void>\n openSession(sessionId: string): void\n openAttachment(eventSeq: number, blockIndex: number): Promise<void>\n openUpload(receiptId: string): Promise<void>\n command(line: string): Promise<void>\n commands(query: string, signal: AbortSignal): Promise<readonly ComposerCommand[]>\n}\n\nasync function readResponse(response: Response): Promise<unknown> {\n const value = await response.json() as { error?: string }\n if (!response.ok) throw new Error(value.error ?? `请求失败:HTTP ${String(response.status)}`)\n return value\n}\n\nexport function composerTools(ctx: Context, sessionId: SessionId): MessageComposerTools {\n const get = async (query: Record<string, string>, signal?: AbortSignal): Promise<unknown> => {\n const params = new URLSearchParams({ sessionId, ...query })\n return readResponse(await hostFetch(`${MESSAGE_EDIT_PATH}?${params}`, {\n method: 'GET', cache: 'no-store', ...signal === undefined ? {} : { signal },\n }))\n }\n const post = async (operation: Record<string, unknown>): Promise<void> => {\n await readResponse(await hostFetch(MESSAGE_EDIT_PATH, {\n method: 'POST', headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ sessionId, ...operation }),\n }))\n }\n return {\n options: async () => await get({ view: 'options' }) as ComposerOptions,\n references: async (query, signal) => {\n const remote = ctx.get('remote') as unknown as { sessionReferenceResolver?: {\n candidates(sessionId: SessionId, query: string, signal: AbortSignal): Promise<{ ok: true; value: readonly { sessionId: string; mention: string; label: string }[] } | { ok: false; error: { message: string } }>\n } } | undefined\n const [files, sessions] = await Promise.all([\n get({ view: 'references', query }, signal) as Promise<readonly ComposerReference[]>,\n remote?.sessionReferenceResolver?.candidates(sessionId, query, signal),\n ])\n return [...files, ...sessions?.ok ? sessions.value.map(item => ({ ...item, kind: 'session' as const })) : []]\n },\n openPath: path => post({ action: 'open-reference', path }),\n openSession: id => { ctx.uiWorkspace.openSession(id as SessionId) },\n openAttachment: (eventSeq, blockIndex) => post({ action: 'open-attachment', eventSeq, blockIndex }),\n openUpload: receiptId => post({ action: 'open-upload', receiptId }),\n commands: async (query, signal) => {\n const commands = ctx.get('commandUi') as unknown as CommandUiService | undefined\n return commands === undefined ? [] : commands.candidates({ sessionId }, { query, position: 'leading', signal })\n },\n command: async line => {\n const commands = ctx.get('commandUi') as unknown as CommandUiService | undefined\n if (commands !== undefined) {\n const result = await commands.execute({ sessionId }, line)\n if (result.kind === 'error') throw new Error(result.text)\n return\n }\n const sessions = ctx.get('sessions') as unknown as ISessions\n const session = sessions.binding(sessionId)?.session\n if (session === undefined) throw new Error('当前会话尚未就绪,请稍后重试。')\n const result = await session.command(line)\n if (!result.ok) throw new Error(result.error.message)\n if (!result.value.matched) throw new Error('当前 DSH 未提供此指令。')\n },\n }\n}\n","/** Browser controller for one session's Timeline projection and branch mutations. */\r\nimport type { Context } from '@deepseek-ai/cordis'\r\nimport type {\r\n ISessions,\r\n SessionEventSource,\r\n SessionEventWindow,\r\n SessionListState,\r\n} from '@deepseek-ai/dsh-api-session-controller/client'\r\nimport type { SessionId } from '@deepseek-ai/dsh-session/types'\r\nimport { createSnapshotStore, type ObservableSnapshot, type SnapshotStore } from '@deepseek-ai/dsh-client-store'\r\nimport type {} from '@deepseek-ai/dsh-client-ui-workspace/client'\r\nimport { hostFetch } from './transport.ts'\r\nimport { savedUserMessageSeq } from '../saved-user-messages.ts'\r\nimport { MESSAGE_EDIT_BUILD_INFO } from '../build-info.ts'\r\nimport { attachmentTools, type MessageAttachmentTools } from './attachmentTools.ts'\r\nimport { composerTools, type ComposerSettings, type MessageComposerTools } from './composerTools.ts'\r\nimport {\r\n MESSAGE_EDIT_PATH,\r\n type CascadePolicy,\r\n type EditableBlockKind,\r\n type EditableMessageBlock,\r\n type MessageEditAttachmentInput,\r\n type MessageEditOperation,\r\n type MessageEditOperationResult,\r\n type MessageEditTimeline,\r\n type RetryableTurn,\r\n type VersionOperation,\r\n type VersionSummary,\r\n} from '../shared.ts'\r\n\r\n/** Reactive controller state shared by the Timeline and header entries. */\r\nexport interface MessageEditState {\r\n status: 'idle' | 'loading' | 'ready' | 'error'\r\n error: string | null\r\n pending: VersionOperation | null\r\n timeline: MessageEditTimeline | null\r\n}\r\n\r\n/** 合并回合完成时的后台刷新,不延迟首次加载。 */\r\nconst REFRESH_DELAY_MS = 300\r\n\r\n/** Plain business face; the renderer binds the reserved source compartment. */\r\nexport interface MessageEditFace {\r\n hooks: { messageEdit: ObservableSnapshot<MessageEditState> }\r\n acquire(): () => void\r\n load(): void\r\n edit(message: EditableMessageBlock, text: string, cascade: CascadePolicy, regenerate?: boolean, attachments?: readonly MessageEditAttachmentInput[], settings?: ComposerSettings): Promise<boolean>\r\n attachmentTools: MessageAttachmentTools\r\n composerTools: MessageComposerTools\r\n retry(turn: number, cascade: CascadePolicy): Promise<boolean>\r\n reroll(): Promise<boolean>\r\n openVersion(sessionId: string): Promise<void>\r\n}\r\n\r\nfunction messageOf(error: unknown): string {\r\n return error instanceof Error ? error.message : String(error)\r\n}\r\n\r\nfunction objectValue(value: unknown, label: string): Record<string, unknown> {\r\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\r\n throw new TypeError(`${label} 不是对象`)\r\n }\r\n return value as Record<string, unknown>\r\n}\r\n\r\nfunction stringValue(value: unknown, label: string): string {\r\n if (typeof value !== 'string') throw new TypeError(`${label} 不是字符串`)\r\n return value\r\n}\r\n\r\nfunction numberValue(value: unknown, label: string): number {\r\n if (typeof value !== 'number' || !Number.isFinite(value)) throw new TypeError(`${label} 不是数字`)\r\n return value\r\n}\r\n\r\nfunction booleanValue(value: unknown, label: string): boolean {\r\n if (typeof value !== 'boolean') throw new TypeError(`${label} 不是布尔值`)\r\n return value\r\n}\r\n\r\nfunction blockKind(value: unknown): EditableBlockKind {\r\n if (value !== 'user' && value !== 'assistant.reasoning' && value !== 'assistant.response') {\r\n throw new TypeError('消息块类型无效')\r\n }\r\n return value\r\n}\r\n\r\nfunction decodeMessage(value: unknown, index: number): EditableMessageBlock {\r\n const row = objectValue(value, `messages[${String(index)}]`)\r\n return {\r\n key: stringValue(row['key'], '消息 key'),\r\n turn: numberValue(row['turn'], '消息 turn'),\r\n eventSeq: numberValue(row['eventSeq'], '消息 eventSeq'),\r\n blockIndex: numberValue(row['blockIndex'], '消息 blockIndex'),\r\n kind: blockKind(row['kind']),\r\n text: stringValue(row['text'], '消息 text'),\r\n time: numberValue(row['time'], '消息 time'),\r\n ...row['content'] === undefined ? {} : { content: arrayValue(row['content'], '消息 content') as EditableMessageBlock['content'] & {} },\r\n ...row['attachments'] === undefined ? {} : { attachments: arrayValue(row['attachments'], '消息 attachments') as EditableMessageBlock['attachments'] & {} },\r\n }\r\n}\r\n\r\nfunction decodeRetryable(value: unknown, index: number): RetryableTurn {\r\n const row = objectValue(value, `retryableTurns[${String(index)}]`)\r\n return {\r\n turn: numberValue(row['turn'], '回合 turn'),\r\n userEventSeq: numberValue(row['userEventSeq'], '回合 userEventSeq'),\r\n preview: stringValue(row['preview'], '回合 preview'),\r\n time: numberValue(row['time'], '回合 time'),\r\n }\r\n}\r\n\r\nfunction optionalOperation(value: unknown): VersionOperation | undefined {\r\n if (value === undefined) return undefined\r\n if (value === 'edit' || value === 'reroll' || value === 'retry') return value\r\n throw new TypeError('版本 operation 无效')\r\n}\r\n\r\nfunction decodeVersion(value: unknown, index: number): VersionSummary {\r\n const row = objectValue(value, `versions[${String(index)}]`)\r\n const operation = optionalOperation(row['operation'])\r\n const cascade = row['cascade']\r\n if (cascade !== undefined && cascade !== 'truncate' && cascade !== 'preserve') {\r\n throw new TypeError('版本 cascade 无效')\r\n }\r\n const kind = row['blockKind'] === undefined ? undefined : blockKind(row['blockKind'])\r\n return {\r\n sessionId: stringValue(row['sessionId'], '版本 sessionId'),\r\n ...row['parentSessionId'] === undefined\r\n ? {}\r\n : { parentSessionId: stringValue(row['parentSessionId'], '版本 parentSessionId') },\r\n ...row['effectId'] === undefined\r\n ? {}\r\n : { effectId: stringValue(row['effectId'], '版本 effectId') },\r\n ...row['inverseSessionId'] === undefined\r\n ? {}\r\n : { inverseSessionId: stringValue(row['inverseSessionId'], '版本 inverseSessionId') },\r\n createdAt: numberValue(row['createdAt'], '版本 createdAt'),\r\n depth: numberValue(row['depth'], '版本 depth'),\r\n current: booleanValue(row['current'], '版本 current'),\r\n onCurrentEffectPath: booleanValue(row['onCurrentEffectPath'], '版本 onCurrentEffectPath'),\r\n ...operation === undefined ? {} : { operation },\r\n ...cascade === undefined ? {} : { cascade },\r\n ...row['targetTurn'] === undefined ? {} : { targetTurn: numberValue(row['targetTurn'], '版本 targetTurn') },\r\n ...kind === undefined ? {} : { blockKind: kind },\r\n ...row['before'] === undefined ? {} : { before: stringValue(row['before'], '版本 before') },\r\n ...row['after'] === undefined ? {} : { after: stringValue(row['after'], '版本 after') },\r\n ...row['unavailableReason'] === undefined ? {} : { unavailableReason: stringValue(row['unavailableReason'], '版本 unavailableReason') },\r\n }\r\n}\r\n\r\nfunction arrayValue(value: unknown, label: string): unknown[] {\r\n if (!Array.isArray(value)) throw new TypeError(`${label} 不是数组`)\r\n return value\r\n}\r\n\r\nfunction stringArray(value: unknown, label: string): string[] {\r\n return arrayValue(value, label).map((item, index) => stringValue(item, `${label}[${String(index)}]`))\r\n}\r\n\r\nfunction decodeTimeline(value: unknown): MessageEditTimeline {\r\n const data = objectValue(value, 'Timeline 响应')\r\n return {\r\n sessionId: stringValue(data['sessionId'], 'Timeline sessionId'),\r\n messages: arrayValue(data['messages'], 'Timeline messages').map(decodeMessage),\r\n retryableTurns: arrayValue(data['retryableTurns'], 'Timeline retryableTurns').map(decodeRetryable),\r\n versions: arrayValue(data['versions'], 'Timeline versions').map(decodeVersion),\r\n undoStack: stringArray(data['undoStack'], 'Timeline undoStack'),\r\n redoSessionIds: stringArray(data['redoSessionIds'], 'Timeline redoSessionIds'),\r\n }\r\n}\r\n\r\nfunction decodeOperationResult(value: unknown): MessageEditOperationResult {\r\n const data = objectValue(value, '操作响应')\r\n return {\r\n sessionId: stringValue(data['sessionId'], '操作 sessionId'),\r\n queuedTurns: numberValue(data['queuedTurns'], '操作 queuedTurns'),\r\n ...data['saved'] === undefined ? {} : { saved: booleanValue(data['saved'], '操作 saved') },\r\n ...data['unchanged'] === undefined ? {} : { unchanged: booleanValue(data['unchanged'], '操作 unchanged') },\r\n }\r\n}\r\n\r\nasync function responseValue(response: Response): Promise<unknown> {\r\n const value = await response.json() as unknown\r\n if (response.ok) return value\r\n const error = objectValue(value, '错误响应')['error']\r\n throw new Error(typeof error === 'string' ? error : `请求失败:HTTP ${String(response.status)}`)\r\n}\r\n\r\nfunction conversationRevision(snapshot: SessionEventWindow): string {\r\n const changes = snapshot.entries.flatMap(entry => {\r\n if (entry.type !== 'event') return []\r\n if (entry.event.type === 'turn/end') return [`turn:${String(entry.event.data.turn)}:${String(entry.event.seq)}`]\r\n if (savedUserMessageSeq(entry.event) !== undefined) return [`save:${String(entry.event.seq)}`]\r\n return []\r\n })\r\n return [snapshot.hasMore, changes.join(',')].join('|')\r\n}\r\n\r\nfunction lineageRevision(snapshot: SessionListState, sessionId: SessionId): string {\r\n let root = sessionId\r\n const ancestorIds = new Set<SessionId>()\r\n while (!ancestorIds.has(root)) {\r\n ancestorIds.add(root)\r\n const parent = snapshot.byId[root]?.parentId\r\n if (parent === undefined || snapshot.byId[parent] === undefined) break\r\n root = parent\r\n }\r\n\r\n const connected: string[] = []\r\n for (const rawId of Object.keys(snapshot.byId).sort()) {\r\n const id = rawId as SessionId\r\n const seen = new Set<SessionId>()\r\n let cursor: SessionId | undefined = id\r\n while (cursor !== undefined && !seen.has(cursor)) {\r\n if (cursor === root) {\r\n connected.push(`${id}>${snapshot.byId[id]?.parentId ?? ''}`)\r\n break\r\n }\r\n seen.add(cursor)\r\n cursor = snapshot.byId[cursor]?.parentId\r\n }\r\n }\r\n return connected.join('|')\r\n}\r\n\r\n/** One stable controller is shared by all entries mounted for the same session. */\r\nexport class MessageEditController {\r\n readonly store: SnapshotStore<MessageEditState> = createSnapshotStore<MessageEditState>({\r\n status: 'idle',\r\n error: null,\r\n pending: null,\r\n timeline: null,\r\n })\r\n\r\n readonly face: MessageEditFace\r\n private generation = 0\r\n private readonly ctx: Context\r\n private readonly sessions: ISessions\r\n private sessionSource: SessionEventSource | undefined\r\n private sessionSourceDispose: (() => void) | undefined\r\n private sessionRevision: string | undefined\r\n private listRevision = ''\r\n private refreshScheduled = false\r\n private refreshTimer: ReturnType<typeof setTimeout> | undefined\r\n private observing = false\r\n private disposeObservation: (() => Promise<void>) | undefined = undefined\r\n private inflight: Promise<void> | null = null\r\n private rerunAfter = false\r\n private abort: AbortController | null = null\r\n private disposed = false\r\n private users = 0\r\n\r\n constructor(\r\n ctx: Context,\r\n private readonly sessionId: SessionId,\r\n ) {\r\n this.ctx = ctx\r\n this.sessions = ctx.get('sessions') as unknown as ISessions\r\n this.face = {\r\n hooks: { messageEdit: this.store },\r\n acquire: () => {\r\n this.users += 1\r\n if (this.users === 1 && this.disposed) this.revive()\r\n return () => this.release()\r\n },\r\n load: () => {\r\n const status = this.store.getSnapshot().status\r\n if (status === 'idle' || status === 'error') void this.load()\r\n },\r\n attachmentTools: attachmentTools(ctx, this.sessionId),\r\n composerTools: composerTools(ctx, this.sessionId),\r\n edit: (message, text, cascade, regenerate = true, attachments, settings) => this.mutate(message.kind === 'user' && !regenerate ? {\r\n action: 'save',\r\n sessionId: this.sessionId,\r\n eventSeq: message.eventSeq,\r\n blockIndex: message.blockIndex,\r\n text,\r\n ...attachments === undefined ? {} : { attachments },\r\n ...settings === undefined ? {} : { settings },\r\n } : {\r\n action: 'edit',\r\n sessionId: this.sessionId,\r\n eventSeq: message.eventSeq,\r\n blockIndex: message.blockIndex,\r\n text,\r\n cascade,\r\n regenerate,\r\n ...attachments === undefined ? {} : { attachments },\r\n ...settings === undefined ? {} : { settings },\r\n }),\r\n retry: (turn, cascade) => this.mutate({\r\n action: 'retry',\r\n sessionId: this.sessionId,\r\n turn,\r\n cascade,\r\n }),\r\n reroll: () => this.mutate({ action: 'reroll', sessionId: this.sessionId }),\r\n openVersion: sessionId => this.openWhenListed(sessionId as SessionId),\r\n }\r\n this.observe()\r\n }\r\n\r\n private observe(): void {\r\n this.disposeObservation = this.ctx.effect(\r\n () => this.observeDependencies(),\r\n `message-edit: observe ${this.sessionId}`,\r\n )\r\n }\r\n\r\n private release(): void {\r\n this.users -= 1\r\n if (this.users <= 0) this.dispose()\r\n }\r\n\r\n /** Tear subscriptions down once no mounted entry uses this controller. */\r\n private dispose(): void {\r\n if (this.disposed) return\r\n this.disposed = true\r\n this.generation += 1\r\n if (this.refreshTimer !== undefined) {\r\n clearTimeout(this.refreshTimer)\r\n this.refreshTimer = undefined\r\n this.refreshScheduled = false\r\n }\r\n this.abort?.abort()\r\n this.abort = null\r\n void this.disposeObservation?.()\r\n this.disposeObservation = undefined\r\n }\r\n\r\n /** Re-observe after a transient zero; the retained store keeps old data\r\n * until the immediate refetch below commits. */\r\n private revive(): void {\r\n this.disposed = false\r\n this.observe()\r\n this.refresh()\r\n }\r\n\r\n /** Bind to replaceable value sources instead of retaining a Session object. */\r\n private observeDependencies(): () => void {\r\n this.observing = true\r\n this.listRevision = lineageRevision(this.sessions.list.getSnapshot(), this.sessionId)\r\n this.bindSessionSource()\r\n const disposeList = this.sessions.list.subscribe(() => {\r\n const rebound = this.bindSessionSource()\r\n const nextRevision = lineageRevision(this.sessions.list.getSnapshot(), this.sessionId)\r\n if (nextRevision === this.listRevision && !rebound) return\r\n this.listRevision = nextRevision\r\n this.invalidate()\r\n })\r\n return () => {\r\n this.observing = false\r\n this.generation += 1\r\n disposeList()\r\n this.sessionSourceDispose?.()\r\n this.sessionSourceDispose = undefined\r\n this.sessionSource = undefined\r\n this.sessionRevision = undefined\r\n }\r\n }\r\n\r\n private bindSessionSource(): boolean {\r\n const source = this.sessions.binding(this.sessionId)?.eventSource\r\n if (source === this.sessionSource) return false\r\n this.sessionSourceDispose?.()\r\n this.sessionSource = source\r\n this.sessionRevision = source === undefined ? undefined : conversationRevision(source.getSnapshot())\r\n this.sessionSourceDispose = source?.subscribe(() => {\r\n if (this.sessionSource !== source) return\r\n const revision = conversationRevision(source.getSnapshot())\r\n if (revision === this.sessionRevision) return\r\n this.sessionRevision = revision\r\n this.invalidate()\r\n })\r\n return true\r\n }\r\n\r\n private invalidate(): void {\r\n if (!this.observing || this.store.getSnapshot().status === 'idle' || this.refreshScheduled) return\r\n this.refreshScheduled = true\r\n this.refreshTimer = setTimeout(() => {\r\n this.refreshTimer = undefined\r\n this.refreshScheduled = false\r\n if (this.observing && this.store.getSnapshot().status !== 'idle') this.refresh()\r\n }, REFRESH_DELAY_MS)\r\n }\r\n\r\n /** Invalidation-driven refetch: one in-flight request absorbs the demand\r\n * and commits a single rerun once it settles. */\r\n private refresh(): void {\r\n if (this.disposed) return\r\n if (this.inflight !== null) {\r\n this.rerunAfter = true\r\n return\r\n }\r\n void this.load()\r\n }\r\n\r\n /** Refetch the full value-level projection; concurrent callers share one\r\n * request, and an invalidation during flight schedules exactly one rerun. */\r\n async load(): Promise<void> {\r\n if (this.disposed) return\r\n if (this.inflight !== null) return this.inflight\r\n const generation = ++this.generation\r\n this.abort?.abort()\r\n const abort = new AbortController()\r\n this.abort = abort\r\n this.store.update((state) => {\r\n // 已确认的消息在后台刷新时保持可操作,首次加载及错误恢复仍等待验证。\r\n if (state.status !== 'ready') state.status = 'loading'\r\n state.error = null\r\n })\r\n const run = this.performLoad(generation, abort)\r\n this.inflight = run\r\n try {\r\n await run\r\n } finally {\r\n if (this.inflight === run) this.inflight = null\r\n if (this.rerunAfter && !this.disposed) {\r\n this.rerunAfter = false\r\n void this.load()\r\n }\r\n }\r\n }\r\n\r\n private async performLoad(generation: number, abort: AbortController): Promise<void> {\r\n try {\r\n const response = await hostFetch(`${MESSAGE_EDIT_PATH}?sessionId=${encodeURIComponent(this.sessionId)}`, {\r\n method: 'GET',\r\n headers: { accept: 'application/json' },\r\n cache: 'no-store',\r\n signal: abort.signal,\r\n })\r\n const value = await responseValue(response)\r\n const build = objectValue(value, 'Timeline 响应')['build']\r\n if (build !== undefined) {\r\n const identity = objectValue(build, '宿主构建')\r\n if (identity['version'] !== MESSAGE_EDIT_BUILD_INFO.version || identity['buildId'] !== MESSAGE_EDIT_BUILD_INFO.buildId) {\r\n throw new Error('消息编辑插件的前后端版本不一致,请彻底退出 DSH 后重新启动;浏览器页面请刷新。')\r\n }\r\n }\r\n const timeline = decodeTimeline(value)\r\n if (generation !== this.generation) return\r\n this.store.update((state) => {\r\n state.status = 'ready'\r\n state.error = null\r\n state.timeline = timeline\r\n })\r\n } catch (error) {\r\n if (generation !== this.generation) return\r\n this.store.update((state) => {\r\n state.status = 'error'\r\n state.error = messageOf(error)\r\n })\r\n }\r\n }\r\n\r\n /** Refresh only controllers whose projection has already been requested. */\r\n refreshIfLoaded(): void {\r\n if (this.disposed || this.store.getSnapshot().status === 'idle') return\r\n this.refresh()\r\n }\r\n\r\n private async mutate(operation: MessageEditOperation): Promise<boolean> {\r\n const current = this.store.getSnapshot()\r\n if (current.pending !== null || current.status !== 'ready') return false\r\n this.store.update((state) => {\r\n state.pending = operation.action === 'save' ? 'edit' : operation.action\r\n state.error = null\r\n })\r\n try {\r\n const response = await hostFetch(MESSAGE_EDIT_PATH, {\r\n method: 'POST',\r\n headers: {\r\n accept: 'application/json',\r\n 'content-type': 'application/json',\r\n },\r\n body: JSON.stringify(operation),\r\n })\r\n const result = decodeOperationResult(await responseValue(response))\r\n if (result.unchanged === true && (result.sessionId !== this.sessionId || result.queuedTurns !== 0)) {\r\n throw new Error('宿主未确认无修改保存,请更新插件并重启 DSH。')\r\n }\r\n if (operation.action === 'save'\r\n && (result.sessionId !== this.sessionId || result.queuedTurns !== 0 || result.saved !== true)) {\r\n throw new Error('宿主未确认在当前会话保存,请更新插件并彻底重启 DSH。')\r\n }\r\n if (!this.disposed && result.unchanged !== true) {\r\n if (operation.action === 'save') {\r\n // 保存期间保留忙碌状态,并确保刷新不被保存前的在途请求吸收。\r\n if (this.inflight !== null) {\r\n this.rerunAfter = true\r\n await this.load()\r\n }\r\n await this.load()\r\n } else await this.openWhenListed(result.sessionId as SessionId)\r\n }\r\n this.store.update((state) => { state.pending = null })\r\n return true\r\n } catch (error) {\r\n this.store.update((state) => {\r\n state.pending = null\r\n if (!this.disposed) state.error = messageOf(error)\r\n })\r\n return false\r\n }\r\n }\r\n\r\n /** 通过新版工作区导航持有会话引用,并同步切换主视图。 */\r\n private async openWhenListed(sessionId: SessionId): Promise<void> {\r\n if (this.disposed) return\r\n await this.sessions.refresh()\r\n if (!this.disposed) this.ctx.uiWorkspace.openSession(sessionId)\r\n }\r\n}\r\n","import styles from './InlineMessageEdit.module.css'\n\n/** 确认取消时保留原编辑器,只有选择“是”才提交关闭操作。 */\nexport function confirmCancelEdit(onConfirm: () => void, onReject: () => void): () => void {\n const overlay = document.createElement('div')\n overlay.className = `${styles['overlay'] ?? ''} ${styles['confirmationOverlay'] ?? ''}`\n const panel = document.createElement('div')\n panel.className = styles['confirmPanel'] ?? ''\n panel.setAttribute('role', 'alertdialog')\n panel.setAttribute('aria-modal', 'true')\n panel.setAttribute('aria-label', '是否确认取消编辑')\n const title = document.createElement('div')\n title.className = styles['title'] ?? ''\n title.textContent = '是否确认取消编辑'\n const footer = document.createElement('div')\n footer.className = styles['footer'] ?? ''\n const yes = document.createElement('button')\n yes.type = 'button'\n yes.textContent = '是'\n const no = document.createElement('button')\n no.type = 'button'\n no.textContent = '否'\n footer.append(yes, no)\n panel.append(title, footer)\n overlay.appendChild(panel)\n document.body.appendChild(overlay)\n let mounted = true\n const dispose = (): void => {\n if (!mounted) return\n mounted = false\n yes.removeEventListener('click', confirm)\n no.removeEventListener('click', reject)\n overlay.removeEventListener('keydown', onKeyDown)\n overlay.remove()\n }\n const confirm = (): void => {\n if (!mounted) return\n dispose()\n onConfirm()\n }\n const reject = (): void => {\n if (!mounted) return\n dispose()\n onReject()\n }\n const onKeyDown = (event: KeyboardEvent): void => {\n if (event.key === 'Escape') {\n event.preventDefault()\n reject()\n } else if (event.key === 'Tab') {\n event.preventDefault()\n if (document.activeElement === no) yes.focus()\n else no.focus()\n }\n }\n yes.addEventListener('click', confirm)\n no.addEventListener('click', reject)\n overlay.addEventListener('keydown', onKeyDown)\n no.focus()\n return dispose\n}\n","import { useEffect, useRef, type ReactNode } from 'react'\nimport type { ComposerAttachment } from '@deepseek-ai/dsh-client-ui-conversation/client'\nimport type { EditableMessageAttachment, MessageEditAttachmentInput } from '../shared.ts'\nimport type { MessageAttachmentTools } from './attachmentTools.ts'\nimport styles from './InlineMessageEdit.module.css'\n\ntype AttachmentItem = { existing: EditableMessageAttachment } | { draft: ComposerAttachment }\n\nexport interface AttachmentEditorHandle {\n addFiles(files: readonly File[]): void\n pickFiles(): void\n serialize(): Promise<readonly MessageEditAttachmentInput[]>\n setDisabled(disabled: boolean): void\n dispose(): void\n}\n\nexport interface AttachmentEditorOptions {\n onFiles?(files: readonly File[]): void\n hideAdd?: boolean\n openExisting?(blockIndex: number): Promise<void>\n openDraft?(draft: ComposerAttachment): Promise<void>\n}\n\nfunction sizeLabel(bytes: number): string {\n if (bytes < 1024) return `${String(bytes)} B`\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`\n}\n\n/** 两种编辑入口共享附件草稿,关闭编辑器时仅释放新增附件。 */\nexport function mountAttachmentEditor(\n container: HTMLElement,\n initial: readonly EditableMessageAttachment[],\n tools: MessageAttachmentTools,\n onBusy: (busy: boolean) => void,\n actions?: HTMLElement,\n options: AttachmentEditorOptions = {},\n): AttachmentEditorHandle {\n const items: AttachmentItem[] = initial.map(existing => ({ existing }))\n const list = document.createElement('div')\n list.className = styles['attachmentList'] ?? ''\n list.setAttribute('aria-label', '消息附件')\n const add = document.createElement('button')\n add.type = 'button'\n add.className = `${styles['attachmentAdd'] ?? ''} ${styles['attachmentAddCircle'] ?? ''}`\n add.textContent = '+'\n add.setAttribute('aria-label', '添加附件')\n add.title = '添加图片或文件;替换附件时,先移除原附件再添加新文件。'\n const picker = document.createElement('input')\n picker.type = 'file'\n picker.multiple = true\n picker.hidden = true\n picker.setAttribute('aria-label', '选择消息附件')\n const notice = document.createElement('div')\n notice.className = styles['attachmentNotice'] ?? ''\n notice.setAttribute('role', 'alert')\n if (actions === undefined) container.append(list, ...options.hideAdd ? [] : [add], picker, notice)\n else {\n container.append(list, notice)\n actions.prepend(...options.hideAdd ? [] : [add], picker)\n }\n let disposed = false\n let disabled = false\n let unsubscribe: (() => void) | undefined\n const imageUrls = new Map<number, Promise<string>>()\n let previewItem: AttachmentItem | undefined\n let previewRevision = 0\n let dismissPreview: (() => void) | undefined\n\n const closePreview = (): void => {\n previewRevision += 1\n previewItem = undefined\n dismissPreview?.()\n dismissPreview = undefined\n }\n const imageUrl = (existing: EditableMessageAttachment): Promise<string> => {\n if (existing.content.type !== 'image') throw new Error('此附件不是图片。')\n let url = imageUrls.get(existing.blockIndex)\n if (url === undefined) {\n url = tools.imageUrl(existing.content.attachment)\n imageUrls.set(existing.blockIndex, url)\n void url.catch(() => {\n if (imageUrls.get(existing.blockIndex) === url) imageUrls.delete(existing.blockIndex)\n })\n }\n return url\n }\n const showPreview = (src: string, name: string, item: AttachmentItem): void => {\n closePreview()\n previewItem = item\n const previousFocus = document.activeElement as HTMLElement | null\n const overlay = document.createElement('div')\n overlay.className = styles['attachmentLightbox'] ?? ''\n overlay.setAttribute('role', 'dialog')\n overlay.setAttribute('aria-modal', 'true')\n overlay.setAttribute('aria-label', '图片预览')\n const image = document.createElement('img')\n image.className = styles['attachmentOriginal'] ?? ''\n image.src = src\n image.alt = name\n const close = document.createElement('button')\n close.type = 'button'\n close.className = styles['attachmentPreviewClose'] ?? ''\n close.textContent = '×'\n close.setAttribute('aria-label', '关闭图片预览')\n const outside = (event: MouseEvent): void => { if (event.target === overlay) closePreview() }\n const key = (event: KeyboardEvent): void => {\n if (event.key !== 'Escape' && event.key !== 'Tab') return\n event.preventDefault()\n event.stopPropagation()\n if (event.key === 'Escape') closePreview()\n else close.focus()\n }\n overlay.append(image, close)\n overlay.addEventListener('click', outside)\n close.addEventListener('click', closePreview)\n document.addEventListener('keydown', key, true)\n dismissPreview = () => {\n document.removeEventListener('keydown', key, true)\n overlay.removeEventListener('click', outside)\n close.removeEventListener('click', closePreview)\n overlay.remove()\n if (previousFocus?.isConnected) previousFocus.focus()\n }\n // 挂到 body 避免编辑弹窗的滚动和变换裁切图片原图。\n document.body.append(overlay)\n close.focus()\n }\n const openAttachment = async (item: AttachmentItem, name: string): Promise<void> => {\n if (disabled || disposed || !items.includes(item)) return\n notice.textContent = ''\n const content = 'existing' in item ? item.existing.content : undefined\n const draft = 'draft' in item ? item.draft : undefined\n try {\n if (content?.type === 'image' || draft?.kind === 'image') {\n closePreview()\n const revision = previewRevision\n previewItem = item\n let src: string\n if (draft?.kind === 'image') src = draft.previewUrl\n else if ('existing' in item) src = await imageUrl(item.existing)\n else return\n if (!disabled && !disposed && items.includes(item) && revision === previewRevision) showPreview(src, name, item)\n } else if ('existing' in item) {\n if (options.openExisting === undefined) throw new Error('当前编辑入口尚不支持打开文件。')\n await options.openExisting(item.existing.blockIndex)\n } else {\n if (options.openDraft === undefined) throw new Error('当前编辑入口尚不支持打开文件。')\n await options.openDraft(item.draft)\n }\n } catch (error) {\n if (!disposed) notice.textContent = error instanceof Error ? error.message : String(error)\n }\n }\n\n const refresh = (): void => {\n if (disposed) return\n const uploads = items.some(item => 'draft' in item && item.draft.kind === 'file') ? tools.uploads() : {}\n const pending = items.some(item => 'draft' in item && item.draft.kind === 'file'\n && uploads[item.draft.id]?.status !== 'ready')\n const cards = items.map((item) => {\n const card = document.createElement('div')\n card.className = styles['attachmentCard'] ?? ''\n const content = 'existing' in item ? item.existing.content : undefined\n const draft = 'draft' in item ? item.draft : undefined\n const name = content?.attachment.name ?? draft?.file.name ?? '图片附件'\n const bytes = content?.attachment.bytes ?? draft?.file.size ?? 0\n const isImage = content?.type === 'image' || draft?.kind === 'image'\n const open = document.createElement('button')\n open.type = 'button'\n open.className = styles['attachmentOpen'] ?? ''\n open.setAttribute('data-kind', isImage ? 'image' : 'file')\n open.setAttribute('aria-label', isImage ? `放大图片:${name}` : `打开文件:${name}`)\n open.title = isImage ? '点击放大图片' : '使用默认应用打开文件'\n open.disabled = disabled\n open.addEventListener('click', () => { void openAttachment(item, name) })\n const preview = document.createElement(isImage ? 'img' : 'span')\n preview.className = styles['attachmentPreview'] ?? ''\n if (isImage) {\n const image = preview as HTMLImageElement\n image.alt = name\n if (draft?.kind === 'image') image.src = draft.previewUrl\n if (content?.type === 'image' && 'existing' in item) {\n const url = imageUrl(item.existing)\n void url.then(value => { if (!disposed) image.src = value }).catch(() => {\n if (!disposed) image.alt = `${name}(预览暂不可用)`\n })\n }\n } else {\n preview.textContent = '文件'\n }\n const info = document.createElement('div')\n info.className = styles['attachmentInfo'] ?? ''\n const label = document.createElement('span')\n label.textContent = name\n label.title = name\n const status = document.createElement('span')\n status.className = styles['attachmentStatus'] ?? ''\n const upload = draft?.kind === 'file' ? uploads[draft.id] : undefined\n status.textContent = upload?.status === 'error' ? `上传失败:${upload.message}`\n : draft?.kind === 'file' && upload?.status !== 'ready'\n ? upload?.status === 'uploading' && upload.total\n ? `上传中 ${String(Math.round(upload.loaded / upload.total * 100))}%`\n : '正在上传…'\n : sizeLabel(bytes)\n info.append(label, status)\n const remove = document.createElement('button')\n remove.type = 'button'\n remove.className = styles['attachmentRemove'] ?? ''\n remove.textContent = '×'\n remove.title = `移除 ${name}`\n remove.setAttribute('aria-label', `移除附件:${name}`)\n remove.disabled = disabled\n remove.addEventListener('click', () => {\n if (disabled || disposed) return\n const index = items.indexOf(item)\n if (index < 0) return\n items.splice(index, 1)\n if (previewItem === item) closePreview()\n if ('draft' in item) tools.release(item.draft.id)\n refresh()\n })\n open.append(preview, info)\n card.append(open, remove)\n if (upload?.status === 'error' && draft !== undefined) {\n const retry = document.createElement('button')\n retry.type = 'button'\n retry.textContent = '重试上传'\n retry.disabled = disabled\n retry.addEventListener('click', () => { if (!disabled && !disposed) tools.retry(draft.id) })\n card.append(retry)\n }\n return card\n })\n list.replaceChildren(...cards)\n add.disabled = disabled\n picker.disabled = disabled\n onBusy(pending)\n }\n const addFiles = (files: readonly File[]): void => {\n if (disabled || disposed || files.length === 0) return\n try {\n for (const draft of tools.create(files)) items.push({ draft })\n unsubscribe ??= tools.subscribe(refresh)\n notice.textContent = ''\n refresh()\n } catch (error) {\n notice.textContent = error instanceof Error ? error.message : String(error)\n }\n }\n const openPicker = (): void => { if (!disabled && !disposed) picker.click() }\n const picked = (): void => {\n try {\n if (!disabled && !disposed) {\n const files = Array.from(picker.files ?? [])\n if (files.length > 0) (options.onFiles ?? addFiles)(files)\n }\n } catch (error) {\n notice.textContent = error instanceof Error ? error.message : String(error)\n } finally {\n picker.value = ''\n }\n }\n add.addEventListener('click', openPicker)\n picker.addEventListener('change', picked)\n refresh()\n return {\n addFiles,\n pickFiles: openPicker,\n serialize: async () => {\n const drafts = items.flatMap(item => 'draft' in item ? [item.draft.id] : [])\n const uploaded = drafts.length === 0 ? [] : await tools.serialize(drafts)\n let index = 0\n return items.map(item => {\n if ('existing' in item) return { type: 'retained', blockIndex: item.existing.blockIndex }\n const attachment = uploaded[index++]\n if (attachment === undefined) throw new Error('附件尚未准备完成,请稍后重试。')\n return attachment\n })\n },\n setDisabled: value => { disabled = value; if (value) closePreview(); refresh() },\n dispose: () => {\n if (disposed) return\n disposed = true\n closePreview()\n unsubscribe?.()\n add.removeEventListener('click', openPicker)\n picker.removeEventListener('change', picked)\n for (const item of items) if ('draft' in item) tools.release(item.draft.id)\n add.remove()\n picker.remove()\n container.replaceChildren()\n },\n }\n}\n\n/** Timeline 复用弹窗的附件编辑器,不把主输入框的草稿带入历史消息。 */\nexport function AttachmentEditor({ initial, tools, onMount, onBusy, disabled }: {\n initial: readonly EditableMessageAttachment[]\n tools: MessageAttachmentTools\n onMount(handle: AttachmentEditorHandle | undefined): void\n onBusy(busy: boolean): void\n disabled: boolean\n}): ReactNode {\n const container = useRef<HTMLDivElement>(null)\n const editor = useRef<AttachmentEditorHandle | undefined>(undefined)\n const callbacks = useRef({ onMount, onBusy })\n callbacks.current = { onMount, onBusy }\n useEffect(() => {\n if (container.current === null) return\n const handle = mountAttachmentEditor(container.current, initial, tools, busy => callbacks.current.onBusy(busy))\n editor.current = handle\n callbacks.current.onMount(handle)\n return () => {\n callbacks.current.onMount(undefined)\n handle.dispose()\n editor.current = undefined\n }\n }, [initial, tools])\n useEffect(() => { editor.current?.setDisabled(disabled) }, [disabled])\n return <div ref={container} className={styles['attachmentEditor']} />\n}\n","export interface FileReferenceToken {\n readonly start: number\n readonly end: number\n readonly path: string\n readonly token: string\n readonly label: string\n}\n\nexport interface SessionReferenceToken {\n readonly start: number\n readonly end: number\n readonly sessionId: string\n readonly token: string\n readonly label: string\n}\n\ninterface HostPathBridge {\n pathFor(file: File): string\n}\n\nconst invalidPathCharacters = /[\\u0000-\\u001f\\u007f-\\u009f\"]/u\n\n/** 使用桌面端提供的真实路径;浏览器内创建的文件没有宿主路径。 */\nexport function filePathFor(file: File): string | undefined {\n const bridge = (globalThis as typeof globalThis & { __DSH_HOST_PATHS__?: HostPathBridge }).__DSH_HOST_PATHS__\n try {\n const path = bridge?.pathFor(file)\n return path === undefined || path === '' ? undefined : path\n } catch {\n return undefined\n }\n}\n\n/** 对齐官方 @ 文件语法,空格使用双引号,路径分隔符统一为斜杠。 */\nexport function formatFileReference(path: string): string {\n if (path === '' || invalidPathCharacters.test(path)) throw new Error('文件路径无法表示为 DSH 引用。')\n const normalized = path.replace(/\\\\/gu, '/')\n return /\\s/u.test(normalized) ? `@\"${normalized}\"` : `@${normalized}`\n}\n\nfunction pathFromClipboardLine(line: string): string | undefined {\n let path = line.trim()\n if (path.startsWith('\"') && path.endsWith('\"')) path = path.slice(1, -1)\n if (/^file:/iu.test(path)) {\n try {\n const address = new URL(path)\n if (address.protocol !== 'file:' || address.search !== '' || address.hash !== '') return undefined\n path = decodeURIComponent(address.pathname)\n if (address.hostname !== '' && address.hostname !== 'localhost') path = `//${address.hostname}${path}`\n else if (/^\\/[a-z]:\\//iu.test(path)) path = path.slice(1)\n } catch {\n return undefined\n }\n }\n if (invalidPathCharacters.test(path)) return undefined\n if (/^\\/[^/]*$/u.test(path) && !/^\\/[^\\s]+\\.[a-z0-9]+$/iu.test(path)) return undefined\n if (!/^(?:[a-z]:[\\\\/]|\\\\\\\\[^\\\\/]+[\\\\/]|\\/)/iu.test(path)) return undefined\n return path.replace(/\\\\/gu, '/')\n}\n\n/** 只读取剪贴板的路径文本;实际 File 由 filePathFor 处理,图片不会重复添加。 */\nexport function pastedFilePaths(data: DataTransfer): readonly string[] {\n const result: string[] = []\n const seen = new Set<string>()\n const read = (type: string): string => {\n try { return data.getData(type) } catch { return '' }\n }\n for (const type of ['text/uri-list', 'text/plain']) {\n const lines = read(type).split(/\\r\\n|\\n|\\r/u).filter(line => line.trim() !== '' && (type !== 'text/uri-list' || !line.trimStart().startsWith('#')))\n const paths = lines.map(pathFromClipboardLine)\n // 一段普通说明中夹有路径不应丢掉说明文字,只有整批为路径时才接管粘贴。\n if (paths.some(path => path === undefined)) continue\n for (const path of paths) {\n if (path === undefined || seen.has(path)) continue\n seen.add(path)\n result.push(path)\n }\n }\n return result\n}\n\n/** 提取完整文件引用与文本位置;邮件地址和 @ 会话引用保留为普通文字。 */\nexport function parseFileReferences(text: string): readonly FileReferenceToken[] {\n const result: FileReferenceToken[] = []\n const pattern = /(?:^|\\s)(@(?:\"([^\"\\r\\n]+)\"|([^\\s\"]+)))/gu\n for (const match of text.matchAll(pattern)) {\n const token = match[1]\n const path = match[2] ?? match[3]\n if (token === undefined || path === undefined || invalidPathCharacters.test(path)) continue\n if (path.startsWith('[') || path.startsWith('dsh-session:')) continue\n const start = match.index + match[0].length - token.length\n const normalized = path.replace(/\\\\/gu, '/')\n const folder = normalized.endsWith('/')\n const segments = normalized.replace(/\\/+$/u, '').split('/')\n const name = segments.at(-1) || normalized\n result.push({ start, end: start + token.length, path, token, label: `${name}${folder ? '/' : ''}` })\n }\n return result\n}\n\nfunction sessionReferenceUri(sessionId: string): string {\n const bytes = new TextEncoder().encode(JSON.stringify(sessionId))\n const binary = Array.from(bytes, byte => String.fromCharCode(byte)).join('')\n return `dsh-session:${btoa(binary).replace(/\\+/gu, '-').replace(/\\//gu, '_').replace(/=+$/u, '')}`\n}\n\n/** 保持官方会话引用的 UTF-8 JSON 与 base64url 编码,显示名称独立于会话身份。 */\nexport function formatSessionReference(sessionId: string, label: string = sessionId): string {\n return `@[${label.replace(/[\\\\\\]]/gu, character => `\\\\${character}`)}](${sessionReferenceUri(sessionId)})`\n}\n\n/** 识别 canonical 会话引用;错误 URI 继续保留文字,不生成可导航 chip。 */\nexport function parseSessionReferences(text: string): readonly SessionReferenceToken[] {\n const result: SessionReferenceToken[] = []\n const pattern = /@\\[((?:\\\\.|[^\\\\\\]])*)\\]\\((dsh-session:[^\\s)]*)\\)|(dsh-session:[A-Za-z0-9_-]+)/gu\n for (const match of text.matchAll(pattern)) {\n const uri = match[2] ?? match[3]\n if (uri === undefined) continue\n const payload = uri.slice('dsh-session:'.length)\n if (!/^[A-Za-z0-9_-]+$/u.test(payload)) continue\n try {\n const binary = atob(payload.replace(/-/gu, '+').replace(/_/gu, '/'))\n const bytes = Uint8Array.from(binary, character => character.charCodeAt(0))\n const sessionId: unknown = JSON.parse(new TextDecoder('utf-8', { fatal: true }).decode(bytes))\n if (typeof sessionId !== 'string' || sessionReferenceUri(sessionId) !== uri) continue\n const token = match[0]\n const label = match[1] === undefined ? sessionId : match[1].replace(/\\\\(.)/gu, '$1')\n result.push({ start: match.index, end: match.index + token.length, sessionId, token, label })\n } catch {\n continue\n }\n }\n return result\n}\n","import { parseFileReferences, parseSessionReferences, pastedFilePaths } from './fileReferences.ts'\nimport styles from './InlineMessageEdit.module.css'\n\nexport interface RichMessageInputHandle {\n text(): string\n insert(text: string): void\n replaceTrailing(token: string, text: string): void\n focus(): void\n setDisabled(disabled: boolean): void\n dispose(): void\n}\n\nfunction escapeHtml(text: string): string {\n return text.replace(/[&<>\"']/g, value => ({ '&': '&', '<': '<', '>': '>', '\"': '"', \"'\": ''' })[value]!)\n}\n\n/** 引用以原生 @路径持久化,显示节点只负责高亮和点击。 */\nfunction referenceHtml(text: string): string {\n let result = ''\n let offset = 0\n const sessions = parseSessionReferences(text)\n const files = parseFileReferences(text).filter(file => !sessions.some(session => file.start >= session.start && file.start < session.end))\n for (const reference of [...files, ...sessions].sort((left, right) => left.start - right.start)) {\n result += escapeHtml(text.slice(offset, reference.start)).replace(/\\n/g, '<br>')\n const location = 'path' in reference ? `data-file-path=\"${escapeHtml(reference.path)}\"` : `data-session-id=\"${escapeHtml(reference.sessionId)}\"`\n result += `<span class=\"${styles['fileReference'] ?? ''}\" contenteditable=\"false\" role=\"link\" tabindex=\"0\" ${location} data-file-token=\"${escapeHtml(reference.token)}\" title=\"${escapeHtml('path' in reference ? reference.path : reference.label)}\">${'path' in reference ? '▤' : '@'} ${escapeHtml(reference.label)}</span>`\n offset = reference.end\n }\n return result + escapeHtml(text.slice(offset)).replace(/\\n/g, '<br>')\n}\n\n/** 同时处理浏览器生成的段落和粘贴插入的换行,保留多行正文。 */\nexport function messageInputText(node: Node): string {\n if (node.nodeType === 3) return node.textContent ?? ''\n const element = node as HTMLElement\n if (element.dataset?.['fileToken'] !== undefined) return element.dataset['fileToken']\n if (element.tagName === 'BR') return '\\n'\n const children = Array.from(node.childNodes ?? [])\n let result = ''\n for (const child of children) {\n const block = child.nodeType === 1 && /^(DIV|P)$/.test((child as HTMLElement).tagName)\n if (block && result !== '' && !result.endsWith('\\n')) result += '\\n'\n result += messageInputText(child)\n if (block && child !== children.at(-1) && !result.endsWith('\\n')) result += '\\n'\n }\n return children.length === 0 ? node.textContent ?? '' : result.replace(/\\u00a0/g, ' ')\n}\n\n/** 独立内容框使用浏览器编辑历史,不绑定主会话的单例草稿。 */\nexport function mountRichMessageInput(\n container: HTMLElement,\n initialText: string,\n options: {\n addFiles(files: readonly File[]): void\n addPaths(paths: readonly string[]): void\n openPath(path: string): Promise<void>\n openSession(sessionId: string): void\n onError(error: unknown): void\n onSend(): void\n onSave(): void\n onChange?(text: string): void\n onKeydown?(event: KeyboardEvent): boolean\n },\n): RichMessageInputHandle {\n const input = document.createElement('div')\n input.className = `${styles['input'] ?? ''} ${styles['richInput'] ?? ''}`\n input.contentEditable = 'true'\n input.setAttribute('role', 'textbox')\n input.setAttribute('aria-label', '消息正文')\n input.setAttribute('aria-multiline', 'true')\n input.setAttribute('data-placeholder', '编辑消息,粘贴文件,输入 / 调用指令、@ 引用文件或对话')\n input.innerHTML = referenceHtml(initialText)\n container.append(input)\n let disabled = false\n let disposed = false\n let composing = false\n let edited = false\n let caret: Range | undefined\n const selection = (): Selection | null => document.getSelection()\n const remember = (): void => {\n const current = selection()\n if (current?.rangeCount && input.contains(current.anchorNode)) caret = current.getRangeAt(0).cloneRange()\n }\n const focus = (): void => {\n input.focus()\n const current = selection()\n if (current === null) return\n const range = caret ?? document.createRange()\n if (caret === undefined) { range.selectNodeContents(input); range.collapse(false) }\n current.removeAllRanges()\n current.addRange(range)\n }\n const changed = (): void => {\n if (composing) return\n edited = true\n remember()\n const current = selection()\n const prefix = document.createRange()\n prefix.selectNodeContents(input)\n if (current?.rangeCount && input.contains(current.anchorNode)) {\n const range = current.getRangeAt(0)\n prefix.setEnd(range.endContainer, range.endOffset)\n }\n options.onChange?.(messageInputText(prefix.cloneContents()))\n }\n const insert = (text: string): void => {\n if (disabled || disposed) return\n focus()\n const current = selection()\n if (current?.rangeCount && (parseFileReferences(text)[0]?.start === 0 || parseSessionReferences(text)[0]?.start === 0)) {\n const range = current.getRangeAt(0)\n const prefix = document.createRange()\n prefix.selectNodeContents(input)\n prefix.setEnd(range.startContainer, range.startOffset)\n const before = messageInputText(prefix.cloneContents())\n if (before !== '' && !/\\s$/.test(before)) text = ` ${text}`\n }\n // 所有 HTML 来自转义后的文本与固定引用模板,富文本剪贴板不进入正文。\n document.execCommand('insertHTML', false, referenceHtml(text))\n changed()\n }\n const paste = (event: ClipboardEvent): void => {\n if (disabled || event.clipboardData === null) return\n const files = Array.from(event.clipboardData.files)\n if (!files.length) for (const item of Array.from(event.clipboardData.items)) {\n const file = item.kind === 'file' ? item.getAsFile() : null\n if (file !== null) files.push(file)\n }\n const paths = files.length === 0 ? pastedFilePaths(event.clipboardData) : []\n event.preventDefault()\n if (files.length) options.addFiles(files)\n else if (paths.length) options.addPaths(paths)\n else insert(event.clipboardData.getData('text/plain'))\n }\n const drop = (event: DragEvent): void => {\n if (disabled || event.dataTransfer === null) return\n event.preventDefault()\n const files = Array.from(event.dataTransfer.files)\n if (files.length) options.addFiles(files)\n else {\n const paths = pastedFilePaths(event.dataTransfer)\n if (paths.length) options.addPaths(paths)\n else insert(event.dataTransfer.getData('text/plain'))\n }\n }\n const dragOver = (event: DragEvent): void => { if (!disabled) event.preventDefault() }\n const openReference = (event: MouseEvent | KeyboardEvent): void => {\n const chip = (event.target as HTMLElement).closest<HTMLElement>('[data-file-path], [data-session-id]')\n if (chip === null || !input.contains(chip)) return\n if (event instanceof KeyboardEvent && event.key !== 'Enter' && event.key !== ' ') return\n event.preventDefault()\n const path = chip.dataset['filePath']\n if (path !== undefined) void options.openPath(path).catch(options.onError)\n const sessionId = chip.dataset['sessionId']\n if (sessionId !== undefined) options.openSession(sessionId)\n }\n const keydown = (event: KeyboardEvent): void => {\n if (composing || event.isComposing || event.keyCode === 229 || disabled) return\n if ((event.target as HTMLElement).dataset['fileToken'] !== undefined) { openReference(event); return }\n if (options.onKeydown?.(event)) return\n if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === 's') {\n event.preventDefault(); options.onSave()\n } else if (event.key === 'Enter' && !event.shiftKey && !event.altKey) {\n event.preventDefault(); options.onSend()\n }\n }\n const copy = (event: ClipboardEvent): void => {\n const current = selection()\n if (current?.rangeCount && input.contains(current.anchorNode) && event.clipboardData !== null) {\n event.clipboardData.setData('text/plain', messageInputText(current.getRangeAt(0).cloneContents()))\n event.preventDefault()\n if (event.type === 'cut' && !disabled) document.execCommand('delete')\n }\n }\n const compositionStart = (): void => { composing = true }\n const compositionEnd = (): void => { composing = false; changed() }\n input.addEventListener('compositionstart', compositionStart)\n input.addEventListener('compositionend', compositionEnd)\n input.addEventListener('input', changed)\n input.addEventListener('keyup', remember)\n input.addEventListener('mouseup', remember)\n input.addEventListener('blur', remember)\n input.addEventListener('paste', paste)\n input.addEventListener('drop', drop)\n input.addEventListener('dragover', dragOver)\n input.addEventListener('click', openReference)\n input.addEventListener('keydown', keydown)\n input.addEventListener('copy', copy)\n input.addEventListener('cut', copy)\n return {\n // 未输入时直接使用原始值,避免浏览器的空白归一化制造虚假修改。\n text: () => edited ? messageInputText(input) : initialText, insert, focus,\n replaceTrailing: (token, text) => {\n if (disabled || disposed) return\n focus()\n const current = selection()\n if (current === null) return\n for (let index = 0; index < token.length; index++) current.modify('extend', 'backward', 'character')\n remember()\n insert(text)\n },\n setDisabled: value => { disabled = value; input.contentEditable = String(!value); input.setAttribute('aria-disabled', String(value)) },\n dispose: () => {\n disposed = true\n input.removeEventListener('compositionstart', compositionStart)\n input.removeEventListener('compositionend', compositionEnd)\n input.removeEventListener('input', changed)\n input.removeEventListener('keyup', remember)\n input.removeEventListener('mouseup', remember)\n input.removeEventListener('blur', remember)\n input.removeEventListener('paste', paste)\n input.removeEventListener('drop', drop)\n input.removeEventListener('dragover', dragOver)\n input.removeEventListener('click', openReference)\n input.removeEventListener('keydown', keydown)\n input.removeEventListener('copy', copy)\n input.removeEventListener('cut', copy)\n input.remove()\n },\n }\n}\n","import type { EditableMessageBlock, MessageEditAttachmentInput } from '../shared.ts'\nimport type { MessageAttachmentTools } from './attachmentTools.ts'\nimport type { ComposerOptions, ComposerSettings, MessageComposerTools } from './composerTools.ts'\nimport { mountAttachmentEditor, type AttachmentEditorHandle } from './AttachmentEditor.tsx'\nimport { filePathFor, formatFileReference } from './fileReferences.ts'\nimport { mountRichMessageInput, type RichMessageInputHandle } from './RichMessageInput.ts'\nimport styles from './InlineMessageEdit.module.css'\n\nexport interface MessageComposerHandle {\n text(): string\n settings(regenerate?: boolean): ComposerSettings | undefined\n serialize(): Promise<readonly MessageEditAttachmentInput[]>\n focus(): void\n setDisabled(disabled: boolean): void\n dispose(): void\n}\n\nfunction button(label: string, className?: string): HTMLButtonElement {\n const element = document.createElement('button')\n element.type = 'button'\n element.textContent = label\n if (className !== undefined) element.className = className\n return element\n}\n\n/** 弹窗与 Timeline 共用独立的正文、附件及提交选项。 */\nexport function mountMessageComposer(container: HTMLElement, block: EditableMessageBlock,\n attachmentTools: MessageAttachmentTools, tools: MessageComposerTools,\n events: { onBusy(busy: boolean): void; onSend(): void; onSave(): void },\n): MessageComposerHandle {\n const frame = document.createElement('div')\n frame.className = styles['composer'] ?? ''\n const attachments = document.createElement('div')\n const inputContainer = document.createElement('div')\n const toolbar = document.createElement('div')\n toolbar.className = styles['composerToolbar'] ?? ''\n const plus = button('+', styles['composerPlus'])\n plus.setAttribute('aria-label', '添加文件')\n plus.title = '添加文件'\n const permission = button('权限 ▾', styles['composerControl'])\n permission.setAttribute('aria-label', '修改权限')\n const model = button('模型 ▾', styles['composerModel'])\n model.setAttribute('aria-label', '修改模型和推理等级')\n const status = document.createElement('div')\n status.className = styles['attachmentNotice'] ?? ''\n status.setAttribute('role', 'status')\n const popup = document.createElement('div')\n popup.className = styles['composerMenu'] ?? ''\n popup.hidden = true\n const suggestions = document.createElement('div')\n suggestions.className = styles['referenceSuggestions'] ?? ''\n suggestions.hidden = true\n toolbar.append(plus, permission, model)\n frame.append(attachments, inputContainer, suggestions, popup, toolbar)\n container.append(frame, status)\n let disabled = false\n let disposed = false\n let options: ComposerOptions | undefined\n let draftSettings: ComposerSettings = {}\n let search: AbortController | undefined\n let searchTimer: ReturnType<typeof setTimeout> | undefined\n let highlighted = 0\n let richInput: RichMessageInputHandle\n let attachmentEditor: AttachmentEditorHandle\n const showError = (error: unknown): void => { if (!disposed) status.textContent = error instanceof Error ? error.message : String(error) }\n const addPaths = (paths: readonly string[]): void => {\n richInput.insert(paths.map(path => formatFileReference(path)).join(' ') + ' ')\n }\n const addFiles = (files: readonly File[]): void => {\n if (disabled || disposed) return\n const uploads: File[] = []\n const paths: string[] = []\n for (const file of files) {\n const path = filePathFor(file)\n if (path !== undefined && !/^image\\/(png|jpeg|webp|gif)$/.test(file.type)) paths.push(path)\n else uploads.push(file)\n }\n if (paths.length) addPaths(paths)\n if (uploads.length) attachmentEditor.addFiles(uploads)\n }\n const closeMenu = (): void => {\n popup.hidden = true\n permission.setAttribute('aria-expanded', 'false')\n model.setAttribute('aria-expanded', 'false')\n }\n const beginMenu = (label: string, kind: 'permission' | 'model' | 'modelList' | 'command' = 'command'): void => {\n popup.replaceChildren()\n popup.setAttribute('role', 'menu')\n popup.setAttribute('aria-label', label)\n popup.dataset['kind'] = kind\n popup.hidden = false\n permission.setAttribute('aria-expanded', String(kind === 'permission'))\n model.setAttribute('aria-expanded', String(kind === 'model' || kind === 'modelList'))\n }\n const menuItem = (label: string, description: string, act: () => void, selected?: boolean, target = popup): HTMLButtonElement => {\n const item = button('')\n const text = document.createElement('span')\n text.className = styles['menuItemLabel'] ?? ''\n text.textContent = label\n item.setAttribute('role', selected === undefined ? 'menuitem' : 'menuitemradio')\n if (selected !== undefined) item.setAttribute('aria-checked', String(selected))\n item.title = label\n const hint = document.createElement('span')\n hint.className = styles['menuValue'] ?? ''\n hint.textContent = selected === undefined ? description : selected ? '✓' : ''\n if (selected !== undefined) hint.setAttribute('aria-hidden', 'true')\n item.append(text, hint)\n item.disabled = disabled\n item.addEventListener('click', () => { closeMenu(); act() })\n target.append(item)\n return item\n }\n const permissionLabel = (id: string | undefined): string => {\n const labels: Record<string, string> = {\n 'read-only': '仅可查看', 'workspace-write': '工作区内修改',\n 'danger-full-access': '完全权限', 'auto-review': 'Auto review',\n }\n return id === undefined ? '权限' : labels[id] ?? options?.permissions.find(preset => preset.id === id)?.label ?? (id === 'custom' ? '自定义权限' : id)\n }\n const effortLabel = (effort: string | undefined): string => {\n if (!effort) return '默认'\n const values = { ...options?.current, ...draftSettings }\n const selected = options?.models.find(entry => entry.provider === values.provider && entry.model === values.model)\n return selected?.reasoningEffortLabels?.[effort] ?? ({ off: 'Off', low: 'Low', medium: 'Medium', high: 'High', max: 'Max' } as Record<string, string>)[effort] ?? effort\n }\n const updateControls = (): void => {\n const values = { ...options?.current, ...draftSettings }\n permission.textContent = `${permissionLabel(values.permissionPreset)} ▾`\n const selected = options?.models.find(entry => entry.provider === values.provider && entry.model === values.model)\n model.textContent = `${selected?.label ?? values.model ?? '模型'}${values.reasoningEffort ? ` ${effortLabel(values.reasoningEffort)}` : ''} ▾`\n model.title = model.textContent\n }\n const permissionMenu = (): void => {\n beginMenu('选择权限', 'permission')\n const values = { ...options?.current, ...draftSettings }\n for (const preset of options?.permissions ?? []) {\n const item = menuItem(permissionLabel(preset.id), '', () => { draftSettings.permissionPreset = preset.id; updateControls(); richInput.focus() }, preset.id === values.permissionPreset)\n item.title = preset.description ?? permissionLabel(preset.id)\n }\n if (options === undefined) menuItem('重新加载选项', '', () => { void loadOptions() })\n }\n const modelMenu = (): void => {\n beginMenu('选择模型和推理等级', 'model')\n const values = { ...options?.current, ...draftSettings }\n const selected = options?.models.find(entry => entry.provider === values.provider && entry.model === values.model)\n menuItem('模型', `${selected?.label ?? values.model ?? '选择模型'} ›`, modelList)\n if (selected?.reasoningEfforts.length) {\n menuItem('推理等级', `${effortLabel(values.reasoningEffort)} ›`, () => {\n beginMenu('选择推理等级', 'model')\n menuItem('‹ 推理等级', '', modelMenu)\n for (const effort of ['', ...selected.reasoningEfforts]) menuItem(effortLabel(effort), '', () => {\n draftSettings = { ...draftSettings, provider: selected.provider, model: selected.model, reasoningEffort: effort }\n updateControls(); richInput.focus()\n }, effort === (values.reasoningEffort ?? ''))\n })\n }\n if (options === undefined) menuItem('重新加载选项', '', () => { void loadOptions() })\n }\n const modelList = (): void => {\n beginMenu('选择模型', 'modelList')\n const back = menuItem('‹ 模型', '', modelMenu)\n back.className = styles['menuBack'] ?? ''\n const field = document.createElement('input')\n field.placeholder = '搜索模型…'\n field.setAttribute('aria-label', '搜索模型')\n field.className = styles['modelSearch'] ?? ''\n const list = document.createElement('div')\n list.className = styles['modelList'] ?? ''\n popup.append(field, list)\n const render = (): void => {\n // 搜索框保持挂载,筛选时不丢失焦点和光标。\n list.replaceChildren()\n const values = { ...options?.current, ...draftSettings }\n const query = field.value.trim().toLocaleLowerCase()\n const groups = new Map<string, ComposerOptions['models'][number][]>()\n for (const entry of options?.models ?? []) {\n if (query && !`${entry.label} ${entry.model} ${entry.providerLabel ?? entry.provider}`.toLocaleLowerCase().includes(query)) continue\n const group = groups.get(entry.provider) ?? []\n group.push(entry); groups.set(entry.provider, group)\n }\n for (const entries of groups.values()) {\n const heading = document.createElement('div')\n heading.className = styles['menuHeading'] ?? ''\n heading.textContent = entries[0]?.providerLabel ?? entries[0]?.provider ?? ''\n list.append(heading)\n for (const entry of entries) menuItem(entry.label, '', () => {\n draftSettings = { ...draftSettings, provider: entry.provider, model: entry.model }\n if (!entry.reasoningEfforts.includes(values.reasoningEffort ?? '')) {\n // 不将旧模型不支持的推理等级传给新模型。\n draftSettings.reasoningEffort = ''\n }\n updateControls(); richInput.focus()\n }, entry.provider === values.provider && entry.model === values.model, list)\n }\n if (!groups.size) {\n const empty = document.createElement('div')\n empty.className = styles['menuHeading'] ?? ''\n empty.textContent = '没有找到匹配的模型'\n list.append(empty)\n }\n }\n field.addEventListener('input', render)\n render()\n field.focus()\n }\n const executeCommand = (line: string): void => {\n if (disabled) return\n status.textContent = '正在执行指令…'\n void tools.command(line).then(() => { if (!disposed) status.textContent = '指令已执行。' }).catch(showError)\n }\n const commandForm = (name: string, label: string, placeholder: string): void => {\n beginMenu(label)\n const field = document.createElement('input')\n field.placeholder = placeholder\n field.setAttribute('aria-label', label)\n const run = button(label)\n run.addEventListener('click', () => { closeMenu(); executeCommand(`/${name}${field.value.trim() ? ` ${field.value.trim()}` : ''}`) })\n popup.append(field, run)\n field.focus()\n }\n const planMenu = (): void => {\n beginMenu('计划模式')\n menuItem('进入计划模式', '先规划,再执行', () => executeCommand('/plan'))\n menuItem('退出计划模式', '恢复正常对话', () => executeCommand('/plan off'))\n }\n const chooseCommand = (name: string): void => {\n switch (name) {\n case 'file': attachmentEditor.pickFiles(); break\n case 'goal': commandForm('goal', '设置或查看目标', '输入目标;留空查看当前目标'); break\n case 'plan': planMenu(); break\n case 'feedback': commandForm('feedback', '发送反馈', '输入反馈内容'); break\n case 'permission': permissionMenu(); break\n case 'model': modelMenu(); break\n default: executeCommand(`/${name}`)\n }\n }\n const suggestReferences = (text: string): void => {\n search?.abort()\n if (searchTimer !== undefined) clearTimeout(searchTimer)\n suggestions.hidden = true\n const slash = /^\\/([^\\s]*)$/.exec(text)\n const match = /(?:^|\\s)@([^\\s@]*)$/.exec(text)\n if (slash !== null) {\n const controller = new AbortController()\n search = controller\n void tools.commands(slash[1] ?? '', controller.signal).then(commands => {\n if (disposed || controller.signal.aborted || !commands.length) return\n suggestions.replaceChildren()\n suggestions.setAttribute('role', 'listbox')\n suggestions.setAttribute('aria-label', '指令候选')\n for (const command of commands.slice(0, 12)) {\n const item = button(`${command.label ?? command.name} /${command.name}`)\n item.setAttribute('role', 'option')\n item.addEventListener('mousedown', event => event.preventDefault())\n item.addEventListener('click', () => {\n suggestions.hidden = true\n richInput.replaceTrailing(`/${slash[1] ?? ''}`, '')\n chooseCommand(command.name)\n })\n suggestions.append(item)\n }\n highlighted = 0\n suggestions.hidden = false\n suggestions.children[0]?.setAttribute('aria-selected', 'true')\n }).catch(error => { if (!controller.signal.aborted) showError(error) })\n return\n }\n if (match === null) return\n const query = match[1] ?? ''\n searchTimer = setTimeout(() => {\n const controller = new AbortController()\n search = controller\n void tools.references(query, controller.signal).then(results => {\n if (disposed || controller.signal.aborted || !results.length) return\n suggestions.replaceChildren()\n suggestions.setAttribute('role', 'listbox')\n suggestions.setAttribute('aria-label', '文件引用候选')\n for (const reference of results.slice(0, 12)) {\n const item = button(`${reference.kind === 'folder' ? '▱' : reference.kind === 'session' ? '@' : '▤'} ${reference.label}`)\n item.title = reference.kind === 'session' ? reference.label : reference.path\n item.setAttribute('role', 'option')\n item.addEventListener('mousedown', event => event.preventDefault())\n item.addEventListener('click', () => {\n richInput.replaceTrailing(`@${query}`, `${reference.kind === 'session' ? reference.mention : formatFileReference(reference.path)} `)\n suggestions.hidden = true\n })\n suggestions.append(item)\n }\n suggestions.hidden = false\n highlighted = 0\n suggestions.children[0]?.setAttribute('aria-selected', 'true')\n }).catch(error => { if (!controller.signal.aborted) showError(error) })\n }, 150)\n }\n richInput = mountRichMessageInput(inputContainer, block.text, {\n addFiles, addPaths, openPath: tools.openPath, openSession: tools.openSession, onError: showError,\n onSend: events.onSend, onSave: events.onSave, onChange: suggestReferences,\n onKeydown: event => {\n if (suggestions.hidden) return false\n if (event.key === 'Escape') { suggestions.hidden = true; event.preventDefault(); return true }\n if (event.key === 'ArrowUp' || event.key === 'ArrowDown') {\n const direction = event.key === 'ArrowUp' ? -1 : 1\n highlighted = (highlighted + direction + suggestions.children.length) % suggestions.children.length\n for (const [index, item] of Array.from(suggestions.children).entries()) item.setAttribute('aria-selected', String(index === highlighted))\n event.preventDefault(); return true\n }\n if (event.key === 'Enter' || event.key === 'Tab') {\n (suggestions.children[highlighted] as HTMLButtonElement | undefined)?.click()\n event.preventDefault(); return true\n }\n return false\n },\n })\n attachmentEditor = mountAttachmentEditor(attachments, block.attachments ?? [], attachmentTools, events.onBusy, undefined, {\n hideAdd: true, onFiles: addFiles,\n openExisting: blockIndex => tools.openAttachment(block.eventSeq, blockIndex),\n openDraft: async draft => {\n const path = filePathFor(draft.file)\n if (path !== undefined) return tools.openPath(path)\n const [payload] = await attachmentTools.serialize([draft.id])\n if (payload?.type !== 'file') throw new Error('附件尚未准备完成,请稍后重试。')\n await tools.openUpload(payload.receiptId)\n },\n })\n const loadOptions = async (): Promise<void> => {\n try {\n const result = await tools.options()\n if (!Array.isArray(result.models) || !Array.isArray(result.permissions)) throw new Error('宿主尚未提供编辑选项,请安装新版插件并重启 DSH。')\n if (disposed) return\n options = result\n updateControls()\n } catch (error) { showError(error) }\n }\n const outside = (event: MouseEvent): void => {\n const path = event.composedPath()\n if (!path.includes(popup) && !path.includes(plus) && !path.includes(permission) && !path.includes(model)) closeMenu()\n }\n const togglePermission = (): void => {\n if (!popup.hidden && popup.getAttribute('aria-label') === '选择权限') closeMenu()\n else permissionMenu()\n }\n const toggleModel = (): void => {\n if (!popup.hidden && (popup.dataset['kind'] === 'model' || popup.dataset['kind'] === 'modelList')) closeMenu()\n else modelMenu()\n }\n const dropTarget = container.closest<HTMLElement>('[role=\"dialog\"]') ?? frame\n const fileDrag = (event: DragEvent): void => {\n const transfer = event.dataTransfer\n if (transfer === null || !Array.from(transfer.types).includes('Files')) return\n // 宿主在 document 冒泡接收文件;先于正文接管,避免两个草稿重复收取。\n event.preventDefault()\n event.stopPropagation()\n if (event.type === 'dragenter' || event.type === 'dragover') transfer.dropEffect = disabled ? 'none' : 'copy'\n if (event.type !== 'drop' || disabled || disposed) return\n try { addFiles(Array.from(transfer.files)) } catch (error) { showError(error) }\n }\n const fileDragEvents = ['dragenter', 'dragover', 'dragleave', 'drop'] as const\n for (const name of fileDragEvents) dropTarget.addEventListener(name, fileDrag, true)\n frame.addEventListener('keydown', event => {\n if (event.isComposing || event.keyCode === 229) return\n if (event.key === 'Escape' && !popup.hidden) { closeMenu(); richInput.focus(); event.stopPropagation() }\n })\n plus.addEventListener('click', () => { closeMenu(); attachmentEditor.pickFiles() })\n permission.addEventListener('click', togglePermission)\n model.addEventListener('click', toggleModel)\n document.addEventListener('click', outside)\n void loadOptions()\n return {\n text: richInput.text,\n settings: regenerate => {\n const settings = { ...regenerate ? options?.current : {}, ...draftSettings }\n if (settings.permissionPreset !== undefined && !options?.permissions.some(item => item.id === settings.permissionPreset)) {\n delete settings.permissionPreset\n }\n if (settings.reasoningEffort === '') delete settings.reasoningEffort\n return Object.keys(settings).length ? settings : undefined\n },\n serialize: () => attachmentEditor.serialize(),\n focus: richInput.focus,\n setDisabled: value => {\n disabled = value\n richInput.setDisabled(value)\n attachmentEditor.setDisabled(value)\n plus.disabled = value; permission.disabled = value; model.disabled = value\n if (value) { closeMenu(); suggestions.hidden = true }\n },\n dispose: () => {\n disposed = true\n search?.abort()\n if (searchTimer !== undefined) clearTimeout(searchTimer)\n document.removeEventListener('click', outside)\n for (const name of fileDragEvents) dropTarget.removeEventListener(name, fileDrag, true)\n attachmentEditor.dispose()\n richInput.dispose()\n frame.remove(); status.remove()\n },\n }\n}\n","/**\r\n * Message-row edit affordance: injects retry + edit icon buttons into each\r\n * settled message's icon-actions row (the official MessageIconActions has no\r\n * plugin slot, so injection rides a MutationObserver over action rows).\r\n * Icons are the official outline-16 SVGs inlined to avoid bundling the\r\n * primitives package.\r\n */\r\nimport { useLayoutEffect, useRef } from 'react'\r\nimport type { EditableMessageBlock } from '../shared.ts'\r\nimport type { MessageEditFace } from './controller.ts'\r\nimport { confirmCancelEdit } from './confirmCancelEdit.ts'\r\nimport { mountMessageComposer, type MessageComposerHandle } from './MessageComposer.ts'\r\nimport styles from './InlineMessageEdit.module.css'\r\n\r\nconst BLOCK_TITLE: Record<EditableMessageBlock['kind'], string> = {\r\n user: '编辑用户消息',\r\n 'assistant.reasoning': '编辑助手思考',\r\n 'assistant.response': '编辑助手回复',\r\n}\r\n\r\nconst STYLE = {\r\n overlay: styles['overlay'] ?? '',\r\n panel: styles['panel'] ?? '',\r\n title: styles['title'] ?? '',\r\n input: styles['input'] ?? '',\r\n footer: styles['footer'] ?? '',\r\n iconButton: styles['iconButton'] ?? '',\r\n picker: styles['picker'] ?? '',\r\n pickerItem: styles['pickerItem'] ?? '',\r\n pickerItemActive: styles['pickerItemActive'] ?? '',\r\n}\r\n\r\n/** Official ic_ds_refresh_outline_16 path (dsh-client-ui-primitives). */\r\nconst REFRESH_PATH = 'M7.92136 0.349152C10.3744 0.349234 12.5564 1.5052 13.9557 3.29894L15.1281 2.12759C15.3303 1.92546 15.6767 2.06943 15.6767 2.35538V5.53923C15.6766 5.71626 15.5329 5.85976 15.3559 5.86002H12.171C11.8854 5.8597 11.7426 5.51465 11.9443 5.31249L12.9641 4.29056C11.8237 2.74305 9.98908 1.74106 7.92136 1.74097C4.46436 1.74097 1.66233 4.543 1.66233 8C1.66233 11.457 4.46436 14.259 7.92136 14.259C11.3782 14.2589 14.1804 11.4569 14.1804 8H15.5722C15.5722 12.2251 12.1465 15.6507 7.92136 15.6508C3.69614 15.6508 0.270508 12.2252 0.270508 8C0.270508 3.77478 3.69614 0.349152 7.92136 0.349152Z'\r\n\r\n/** Official ic_ds_edit_outline_16 path (dsh-client-ui-primitives). */\r\nconst EDIT_PATH = 'M9.94076 1.34942C10.7047 0.90231 11.6503 0.902415 12.4143 1.34942C12.7061 1.52015 12.9688 1.79118 13.3104 2.13284C13.6521 2.47448 13.9231 2.73721 14.0939 3.02894C14.5408 3.79294 14.5409 4.73856 14.0939 5.50251C13.9231 5.79415 13.652 6.05704 13.3104 6.39861L6.65932 13.0497C6.28068 13.4284 6.00695 13.7108 5.66543 13.9097C5.32391 14.1085 4.94315 14.2074 4.42705 14.3498L3.24394 14.6761C2.77527 14.8054 2.34538 14.9262 2.00131 14.9684C1.65196 15.0112 1.17964 15.0013 0.810764 14.6325C0.441921 14.2637 0.432107 13.7913 0.47486 13.442C0.517035 13.0979 0.6379 12.668 0.767181 12.1993L1.09352 11.0162C1.23588 10.5001 1.33481 10.1193 1.5336 9.77784C1.7325 9.43632 2.0149 9.1626 2.39355 8.78395L9.04466 2.13284C9.38625 1.79126 9.64911 1.52016 9.94076 1.34942ZM15.5427 14.8398H7.55223L8.96707 13.425H15.5427V14.8398ZM3.39382 9.78422C2.965 10.213 2.84244 10.3436 2.75709 10.49C2.67183 10.6366 2.61862 10.8079 2.45733 11.3925L2.13099 12.5756C2.00183 13.0439 1.92194 13.3419 1.88863 13.5536C2.10041 13.5204 2.39872 13.4416 2.86764 13.3123L4.05075 12.9859C4.63544 12.8246 4.80669 12.7715 4.95323 12.6862C5.09968 12.6008 5.23022 12.4783 5.65905 12.0494L10.721 6.98644L8.45577 4.72121L3.39382 9.78422ZM11.7 2.57079C11.3774 2.38198 10.9777 2.38198 10.6551 2.57079C10.5602 2.62647 10.4487 2.72931 10.0449 3.13311L9.45604 3.72094L11.7213 5.98617L12.3102 5.39833C12.7139 4.99457 12.8168 4.88307 12.8725 4.78818C13.0613 4.46561 13.0612 4.06585 12.8725 3.74326C12.8169 3.64827 12.7146 3.53752 12.3102 3.13311C11.9057 2.72863 11.795 2.6264 11.7 2.57079Z'\r\n\r\nfunction svgIcon(path: string): SVGSVGElement {\r\n const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg')\r\n svg.setAttribute('width', '16')\r\n svg.setAttribute('height', '16')\r\n svg.setAttribute('viewBox', '0 0 16 16')\r\n svg.setAttribute('fill', 'none')\r\n const p = document.createElementNS('http://www.w3.org/2000/svg', 'path')\r\n p.setAttribute('d', path)\r\n p.setAttribute('fill', 'currentColor')\r\n svg.appendChild(p)\r\n return svg\r\n}\r\n\r\nfunction blockTitle(kind: EditableMessageBlock['kind']): string {\r\n return BLOCK_TITLE[kind] ?? '编辑消息'\r\n}\r\n\r\ntype OverlayCleanup = () => void\r\n\r\n/** 编辑器支持用户消息只保存或保存并发送,关闭前确认取消。 */\r\nexport function mountEditor(\r\n block: EditableMessageBlock,\r\n edit: MessageEditFace['edit'],\r\n close: () => void,\r\n attachmentTools: MessageEditFace['attachmentTools'],\r\n composerTools: MessageEditFace['composerTools'],\r\n): OverlayCleanup {\r\n const overlay = document.createElement('div')\r\n overlay.className = STYLE.overlay\r\n const panel = document.createElement('div')\r\n panel.className = STYLE.panel\r\n panel.setAttribute('role', 'dialog')\r\n panel.setAttribute('aria-modal', 'true')\r\n panel.setAttribute('aria-label', blockTitle(block.kind))\r\n const title = document.createElement('div')\r\n title.className = STYLE.title\r\n title.textContent = blockTitle(block.kind)\r\n const input = document.createElement('textarea')\r\n input.className = STYLE.input\r\n input.value = block.text\r\n input.setAttribute('aria-label', '消息正文')\r\n const attachments = document.createElement('div')\r\n attachments.className = styles['attachmentEditor'] ?? ''\r\n const error = document.createElement('div')\r\n error.className = styles['attachmentNotice'] ?? ''\r\n error.setAttribute('role', 'alert')\r\n const footer = document.createElement('div')\r\n footer.className = STYLE.footer\r\n const save = document.createElement('button')\r\n save.type = 'button'\r\n save.textContent = '保存'\r\n const send = block.kind === 'user' ? document.createElement('button') : undefined\r\n if (send !== undefined) {\r\n send.type = 'button'\r\n send.textContent = '保存并发送'\r\n }\r\n const cancel = document.createElement('button')\r\n cancel.type = 'button'\r\n cancel.textContent = '取消'\r\n footer.append(save, ...send === undefined ? [] : [send], cancel)\r\n panel.append(title, ...block.kind === 'user' ? [attachments] : [input], error, footer)\r\n overlay.appendChild(panel)\r\n document.body.appendChild(overlay)\r\n let mounted = true\r\n let saving = false\r\n let uploading = false\r\n let composer: MessageComposerHandle | undefined\r\n let closeConfirmation: OverlayCleanup | undefined\r\n const updateButtons = (): void => {\r\n save.disabled = saving || uploading\r\n if (send !== undefined) send.disabled = saving || uploading\r\n cancel.disabled = saving\r\n input.readOnly = saving\r\n }\r\n const applyEdit = (regenerate: boolean): void => {\r\n if (saving || uploading) return\r\n saving = true\r\n updateButtons()\r\n composer?.setDisabled(true)\r\n error.textContent = ''\r\n void (async () => {\r\n try {\r\n const payload = await composer?.serialize()\r\n if (!mounted) return\r\n const applied = await edit(block, composer?.text() ?? input.value, 'truncate', regenerate, payload, composer?.settings(regenerate))\r\n if (!mounted) return\r\n if (applied) close()\r\n else error.textContent = '保存失败,请检查消息状态后重试。'\r\n } catch (cause) {\r\n if (mounted) error.textContent = cause instanceof Error ? cause.message : String(cause)\r\n } finally {\r\n if (mounted) {\r\n saving = false\r\n composer?.setDisabled(false)\r\n updateButtons()\r\n }\r\n }\r\n })()\r\n }\r\n const saveEdit = (): void => { applyEdit(block.kind !== 'user') }\r\n const saveAndSend = (): void => { applyEdit(true) }\r\n const cancelEdit = (): void => {\r\n if (saving || closeConfirmation !== undefined) return\r\n closeConfirmation = confirmCancelEdit(() => {\r\n closeConfirmation = undefined\r\n close()\r\n }, () => {\r\n closeConfirmation = undefined\r\n if (composer === undefined) input.focus()\r\n else composer.focus()\r\n })\r\n }\r\n const dismiss = (event: MouseEvent): void => { if (event.target === overlay) cancelEdit() }\r\n if (block.kind === 'user') {\r\n composer = mountMessageComposer(attachments, block, attachmentTools, composerTools, {\r\n onBusy: busy => { uploading = busy; updateButtons() },\r\n onSave: saveEdit, onSend: saveAndSend,\r\n })\r\n composer.focus()\r\n } else {\r\n input.focus()\r\n input.setSelectionRange(input.value.length, input.value.length)\r\n }\r\n save.addEventListener('click', saveEdit)\r\n send?.addEventListener('click', saveAndSend)\r\n cancel.addEventListener('click', cancelEdit)\r\n overlay.addEventListener('click', dismiss)\r\n return () => {\r\n mounted = false\r\n composer?.dispose()\r\n closeConfirmation?.()\r\n save.removeEventListener('click', saveEdit)\r\n send?.removeEventListener('click', saveAndSend)\r\n cancel.removeEventListener('click', cancelEdit)\r\n overlay.removeEventListener('click', dismiss)\r\n overlay.remove()\r\n }\r\n}\r\n\r\n/** Mount one block-picker DOM effect and return its exact inverse. */\r\nfunction mountPicker(\r\n blocks: readonly EditableMessageBlock[],\r\n select: (block: EditableMessageBlock) => void,\r\n close: () => void,\r\n): OverlayCleanup {\r\n const overlay = document.createElement('div')\r\n overlay.className = STYLE.overlay\r\n const panel = document.createElement('div')\r\n panel.className = STYLE.panel\r\n const title = document.createElement('div')\r\n title.className = STYLE.title\r\n title.textContent = blocks.some(block => block.kind === 'user') ? '编辑消息' : '编辑助手消息'\r\n const picker = document.createElement('div')\r\n picker.className = STYLE.picker\r\n const itemListeners: Array<{ item: HTMLButtonElement; listener: () => void }> = []\r\n for (const block of blocks) {\r\n const item = document.createElement('button')\r\n item.className = STYLE.pickerItem\r\n item.textContent = `${blockTitle(block.kind)}:${block.text.slice(0, 24)}${block.text.length > 24 ? '…' : ''}`\r\n const listener = (): void => { select(block) }\r\n item.addEventListener('click', listener)\r\n itemListeners.push({ item, listener })\r\n picker.appendChild(item)\r\n }\r\n const cancel = document.createElement('button')\r\n cancel.textContent = '取消'\r\n cancel.className = STYLE.pickerItemActive\r\n const cancelPicker = (): void => { close() }\r\n cancel.addEventListener('click', cancelPicker)\r\n panel.append(title, picker, cancel)\r\n overlay.appendChild(panel)\r\n document.body.appendChild(overlay)\r\n return () => {\r\n for (const { item, listener } of itemListeners) item.removeEventListener('click', listener)\r\n cancel.removeEventListener('click', cancelPicker)\r\n overlay.remove()\r\n }\r\n}\r\n\r\n/** Compose every overlay with a single idempotent active inverse. */\r\nfunction createOverlayHost(edit: MessageEditFace['edit'], attachmentTools: MessageEditFace['attachmentTools'], composerTools: MessageEditFace['composerTools']): {\r\n editBlock(block: EditableMessageBlock): void\r\n chooseBlock(blocks: readonly EditableMessageBlock[]): void\r\n dispose(): void\r\n} {\r\n let active: OverlayCleanup | undefined\r\n const mount = (effect: (close: () => void) => OverlayCleanup): void => {\r\n active?.()\r\n let cleanup: OverlayCleanup = () => {}\r\n let mounted = true\r\n const close = (): void => {\r\n if (!mounted) return\r\n mounted = false\r\n cleanup()\r\n if (active === close) active = undefined\r\n }\r\n active = close\r\n try {\r\n cleanup = effect(close)\r\n } catch (error: unknown) {\r\n active = undefined\r\n mounted = false\r\n throw error\r\n }\r\n }\r\n const editBlock = (block: EditableMessageBlock): void => {\r\n mount(close => mountEditor(block, edit, close, attachmentTools, composerTools))\r\n }\r\n const chooseBlock = (blocks: readonly EditableMessageBlock[]): void => {\r\n mount(close => mountPicker(blocks, (block) => {\r\n close()\r\n editBlock(block)\r\n }, close))\r\n }\r\n return {\r\n editBlock,\r\n chooseBlock,\r\n dispose: () => { active?.() },\r\n }\r\n}\r\n\r\n/** 按消息标识更新操作按钮,数据刷新时保留按钮与正在编辑的弹窗。 */\r\nexport function InlineMessageEdit({\r\n messages,\r\n edit,\r\n retry,\r\n attachmentTools,\r\n composerTools,\r\n disabled = false,\r\n}: {\r\n messages: readonly EditableMessageBlock[]\r\n edit: MessageEditFace['edit']\r\n retry: MessageEditFace['retry']\r\n attachmentTools: MessageEditFace['attachmentTools']\r\n composerTools: MessageEditFace['composerTools']\r\n disabled?: boolean\r\n}): null {\r\n const current = useRef({ messages, disabled })\r\n current.current = { messages, disabled }\r\n const synchronize = useRef<(() => void) | undefined>(undefined)\r\n useLayoutEffect(() => {\r\n const bindings = new Map<HTMLElement, {\r\n eventSeq: number\r\n blocks: readonly EditableMessageBlock[]\r\n editButton: HTMLButtonElement\r\n retryButton: HTMLButtonElement\r\n dispose(): void\r\n }>()\r\n const overlays = createOverlayHost(edit, attachmentTools, composerTools)\r\n let observer: MutationObserver | undefined\r\n let alive = true\r\n let frame: number | undefined\r\n let scheduled = false\r\n\r\n const sync = (): void => {\r\n const actionRows = Array.from(document.querySelectorAll<HTMLElement>('[data-clock=\"start\"], [data-clock=\"end\"]'))\r\n const presentRows = new Set(actionRows)\r\n for (const [row, binding] of bindings) {\r\n if (presentRows.has(row)) continue\r\n binding.dispose()\r\n bindings.delete(row)\r\n }\r\n const blocksByEvent = new Map<number, EditableMessageBlock[]>()\r\n const turns = new Map<number, { user?: number; assistant?: number }>()\r\n for (const message of current.current.messages) {\r\n let blocks = blocksByEvent.get(message.eventSeq)\r\n if (blocks === undefined) { blocks = []; blocksByEvent.set(message.eventSeq, blocks) }\r\n blocks.push(message)\r\n let turn = turns.get(message.turn)\r\n if (turn === undefined) { turn = {}; turns.set(message.turn, turn) }\r\n if (message.kind === 'user') turn.user ??= message.eventSeq\r\n else turn.assistant = message.eventSeq\r\n }\r\n const claimedEvents = new Set<number>()\r\n for (const row of actionRows) {\r\n const marker = row as HTMLElement & {\r\n __messageEditInjected?: boolean\r\n __messageEditEventSeq?: number\r\n }\r\n let binding = bindings.get(row)\r\n if (marker.__messageEditInjected === true && binding === undefined) {\r\n if (marker.__messageEditEventSeq !== undefined) claimedEvents.add(marker.__messageEditEventSeq)\r\n continue\r\n }\r\n // 新版将助手操作栏放在回合尾部,按 DOM 的回合标识匹配,避免重复文本串到其他消息。\r\n const node = row.closest<HTMLElement>('[data-chat-flow-kind]')\r\n const kind = node?.dataset['chatFlowKind']\r\n const turn = Number(node?.dataset['chatTurn'])\r\n const eventSeq = !Number.isSafeInteger(turn) || turn < 1 ? undefined\r\n : kind === 'user' ? turns.get(turn)?.user\r\n : kind === 'turn-tail' ? turns.get(turn)?.assistant : undefined\r\n const blocks = eventSeq === undefined ? undefined : blocksByEvent.get(eventSeq)\r\n if (eventSeq === undefined || blocks === undefined || claimedEvents.has(eventSeq)) {\r\n binding?.dispose()\r\n bindings.delete(row)\r\n continue\r\n }\r\n claimedEvents.add(eventSeq)\r\n if (binding?.eventSeq === eventSeq && row.contains(binding.editButton) && row.contains(binding.retryButton)) {\r\n binding.blocks = blocks\r\n binding.editButton.disabled = current.current.disabled\r\n binding.retryButton.disabled = current.current.disabled\r\n continue\r\n }\r\n binding?.dispose()\r\n bindings.delete(row)\r\n const previousMarker = marker.__messageEditInjected\r\n const previousEventSeq = marker.__messageEditEventSeq\r\n marker.__messageEditInjected = true\r\n marker.__messageEditEventSeq = eventSeq\r\n\r\n const editButton = document.createElement('button')\r\n editButton.type = 'button'\r\n editButton.className = STYLE.iconButton\r\n editButton.setAttribute('aria-label', '编辑消息')\r\n editButton.title = '编辑消息'\r\n editButton.setAttribute('data-message-edit-control', '')\r\n editButton.disabled = current.current.disabled\r\n editButton.appendChild(svgIcon(EDIT_PATH))\r\n const editMessage = (): void => {\r\n if (current.current.disabled || binding === undefined) return\r\n if (binding.blocks.length === 1 && binding.blocks[0] !== undefined) overlays.editBlock(binding.blocks[0])\r\n else overlays.chooseBlock(binding.blocks)\r\n }\r\n editButton.addEventListener('click', editMessage)\r\n\r\n const retryButton = document.createElement('button')\r\n retryButton.type = 'button'\r\n retryButton.className = STYLE.iconButton\r\n retryButton.setAttribute('aria-label', '重试此回合')\r\n retryButton.title = '重试此回合'\r\n retryButton.setAttribute('data-message-edit-control', '')\r\n retryButton.disabled = current.current.disabled\r\n retryButton.appendChild(svgIcon(REFRESH_PATH))\r\n const retryTurn = (): void => {\r\n if (current.current.disabled) return\r\n const targetTurn = binding?.blocks[0]?.turn\r\n if (targetTurn !== undefined) void retry(targetTurn, 'truncate')\r\n }\r\n retryButton.addEventListener('click', retryTurn)\r\n\r\n // 仅跟随操作行的直接按钮,避免进入用量或反馈的子容器而丢失原生间距。\r\n const officialButtons = Array.from(row.querySelectorAll('button'))\r\n .filter(button => button.parentElement === row && button !== editButton && button !== retryButton)\r\n const lastOfficial = officialButtons.at(-1)\r\n if (lastOfficial !== undefined) {\r\n lastOfficial.insertAdjacentElement('afterend', retryButton)\r\n lastOfficial.insertAdjacentElement('afterend', editButton)\r\n } else {\r\n row.appendChild(editButton)\r\n row.appendChild(retryButton)\r\n }\r\n const dispose = (): void => {\r\n editButton.removeEventListener('click', editMessage)\r\n retryButton.removeEventListener('click', retryTurn)\r\n editButton.remove()\r\n retryButton.remove()\r\n if (previousMarker === undefined) delete marker.__messageEditInjected\r\n else marker.__messageEditInjected = previousMarker\r\n if (previousEventSeq === undefined) delete marker.__messageEditEventSeq\r\n else marker.__messageEditEventSeq = previousEventSeq\r\n }\r\n binding = { eventSeq, blocks, editButton, retryButton, dispose }\r\n bindings.set(row, binding)\r\n }\r\n }\r\n\r\n synchronize.current = sync\r\n sync()\r\n observer = new MutationObserver(() => {\r\n if (!alive || scheduled) return\r\n scheduled = true\r\n frame = requestAnimationFrame(() => {\r\n frame = undefined\r\n scheduled = false\r\n if (alive) sync()\r\n })\r\n })\r\n observer.observe(document.body, { childList: true, subtree: true })\r\n\r\n return () => {\r\n alive = false\r\n if (frame !== undefined) cancelAnimationFrame(frame)\r\n observer?.disconnect()\r\n overlays.dispose()\r\n for (const binding of bindings.values()) binding.dispose()\r\n bindings.clear()\r\n if (synchronize.current === sync) synchronize.current = undefined\r\n }\r\n }, [edit, retry, attachmentTools, composerTools])\r\n\r\n // 在浏览器绘制前同步消息与可用状态,不留下看似可点但事件拒绝操作的间隙。\r\n useLayoutEffect(() => { synchronize.current?.() }, [messages, disabled])\r\n\r\n return null\r\n}\r\n","import { useEffect, type ReactNode } from 'react'\r\nimport type { InjectFace, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'\r\nimport type { MessageEditFace } from './controller.ts'\r\nimport { InlineMessageEdit } from './InlineMessageEdit.tsx'\r\nimport styles from './MessageEditHeader.module.css'\r\n\r\ntype MessageEditHeaderProps = PropsRuntime<'conversation.session.header.actions'> & InjectFace<MessageEditFace>\r\n\r\n/** Header contribution shared with the Timeline controller. */\r\nexport function MessageEditHeader({\r\n useMessageEdit,\r\n acquire,\r\n load,\r\n openVersion,\r\n reroll,\r\n edit,\r\n retry,\r\n attachmentTools,\r\n composerTools,\r\n}: MessageEditHeaderProps): ReactNode {\r\n const state = useMessageEdit(value => value)\r\n\r\n useEffect(() => {\r\n const release = acquire()\r\n load()\r\n return release\r\n }, [acquire, load])\r\n\r\n const timeline = state.timeline\r\n const versions = state.timeline?.versions ?? []\r\n const undoSessionId = timeline?.undoStack[0]\r\n const redoSessionId = timeline?.redoSessionIds.at(-1)\r\n const effectDepth = timeline?.undoStack.length ?? 0\r\n const busy = state.pending !== null || state.status !== 'ready'\r\n const loadFailed = state.status === 'error'\r\n\r\n return (\r\n <>\r\n <InlineMessageEdit\r\n messages={timeline?.messages ?? []}\r\n edit={edit}\r\n retry={retry}\r\n attachmentTools={attachmentTools}\r\n composerTools={composerTools}\r\n disabled={busy}\r\n />\r\n <div className={styles['root']}>\r\n <button\r\n type=\"button\"\r\n className={styles['iconButton']}\r\n aria-label=\"撤销当前版本效果\"\r\n title=\"撤销当前效果,保留更早效果\"\r\n disabled={undoSessionId === undefined || busy}\r\n onClick={() => { if (undoSessionId !== undefined) void openVersion(undoSessionId) }}\r\n >\r\n ←\r\n </button>\r\n <span className={styles['counter']} role={loadFailed ? 'alert' : undefined}>\r\n {loadFailed ? '消息加载失败'\r\n : state.status === 'idle' || state.status === 'loading' ? '正在载入…'\r\n : versions.length === 0 ? '效果 —' : `效果 ${String(effectDepth)} 层 · ${String(versions.length)} 版`}\r\n </span>\r\n <button\r\n type=\"button\"\r\n className={styles['iconButton']}\r\n aria-label=\"重施加下一版本效果\"\r\n title={timeline !== null && timeline.redoSessionIds.length > 1\r\n ? `重施加最新效果(另有 ${String(timeline.redoSessionIds.length - 1)} 个分支)`\r\n : '重施加下一效果'}\r\n disabled={redoSessionId === undefined || busy}\r\n onClick={() => { if (redoSessionId !== undefined) void openVersion(redoSessionId) }}\r\n >\r\n →\r\n </button>\r\n {loadFailed\r\n ? <button type=\"button\" className={styles['rerollButton']} aria-label=\"重新载入消息时间线\" onClick={load}>重新载入</button>\r\n : <button\r\n type=\"button\"\r\n className={styles['rerollButton']}\r\n disabled={busy || state.timeline === null}\r\n onClick={() => { void reroll() }}\r\n >\r\n {state.pending === 'reroll' ? '正在重生成…' : '重生成'}\r\n </button>}\r\n </div>\r\n </>\r\n )\r\n}\r\n","/** Timeline tab: durable version tree plus turn/block edit and retry controls. */\r\nimport { useEffect, useMemo, useRef, useState, type CSSProperties, type ReactNode } from 'react'\r\nimport type { ConvViewProps } from '@deepseek-ai/dsh-client-ui-conversation/client'\r\nimport type { InjectFace } from '@deepseek-ai/dsh-client-ui-slots'\r\nimport type {\r\n CascadePolicy,\r\n EditableBlockKind,\r\n EditableMessageBlock,\r\n RetryableTurn,\r\n VersionOperation,\r\n VersionSummary,\r\n} from '../shared.ts'\r\nimport type { MessageEditFace } from './controller.ts'\r\nimport { mountEditor } from './InlineMessageEdit.tsx'\r\nimport styles from './MessageEditTimelineView.module.css'\r\n\r\ntype MessageEditTimelineViewProps = ConvViewProps & InjectFace<MessageEditFace>\r\n\r\ninterface TurnSection {\r\n retry: RetryableTurn\r\n messages: EditableMessageBlock[]\r\n}\r\n\r\ninterface EditingState {\r\n message: EditableMessageBlock\r\n}\r\n\r\nconst BLOCK_LABEL: Record<EditableBlockKind, string> = {\r\n user: '用户消息',\r\n 'assistant.reasoning': '助手思考',\r\n 'assistant.response': '助手回复',\r\n}\r\n\r\nconst OPERATION_LABEL: Record<VersionOperation, string> = {\r\n edit: '编辑',\r\n reroll: '重生成',\r\n retry: '重试',\r\n}\r\n\r\nfunction timeLabel(value: number): string {\r\n return new Date(value).toLocaleString('zh-CN', {\r\n month: '2-digit',\r\n day: '2-digit',\r\n hour: '2-digit',\r\n minute: '2-digit',\r\n second: '2-digit',\r\n })\r\n}\r\n\r\nfunction turnSections(\r\n turns: readonly RetryableTurn[],\r\n messages: readonly EditableMessageBlock[],\r\n): TurnSection[] {\r\n return turns.map(retry => ({\r\n retry,\r\n messages: messages.filter(message => message.turn === retry.turn),\r\n }))\r\n}\r\n\r\nfunction VersionRow({ version, disabled, onOpen }: {\r\n version: VersionSummary\r\n disabled: boolean\r\n onOpen: (sessionId: string) => void\r\n}): ReactNode {\r\n const depthStyle = { '--message-edit-depth': String(version.depth) } as CSSProperties\r\n const operation = version.unavailableReason !== undefined ? '历史版本'\r\n : version.operation === undefined\r\n ? version.parentSessionId === undefined ? '原始版本' : '外部分支'\r\n : OPERATION_LABEL[version.operation]\r\n return (\r\n <li className={styles['versionItem']} style={depthStyle}>\r\n <button\r\n type=\"button\"\r\n className={styles['versionButton']}\r\n data-current={version.current || undefined}\r\n data-unavailable={version.unavailableReason === undefined ? undefined : true}\r\n disabled={version.current || disabled || version.unavailableReason !== undefined}\r\n onClick={() => { if (version.unavailableReason === undefined) onOpen(version.sessionId) }}\r\n >\r\n <span className={styles['versionLine']} aria-hidden />\r\n <span className={styles['versionDot']} aria-hidden />\r\n <span className={styles['versionMain']}>\r\n <span className={styles['versionTitle']}>\r\n {operation}\r\n {version.targetTurn === undefined ? null : ` · 回合 ${String(version.targetTurn)}`}\r\n </span>\r\n <span className={styles['versionMeta']}>\r\n {timeLabel(version.createdAt)} · {version.sessionId.slice(0, 12)}\r\n </span>\r\n {version.unavailableReason === undefined ? null\r\n : <span className={styles['versionUnavailable']}>{version.unavailableReason}</span>}\r\n {version.before === undefined && version.after === undefined\r\n ? null\r\n : (\r\n <span className={styles['versionDiff']}>\r\n <span>原:{version.before || '(空)'}</span>\r\n <span>新:{version.after || '(空)'}</span>\r\n </span>\r\n )}\r\n </span>\r\n {version.unavailableReason !== undefined\r\n ? <span className={styles['unavailableBadge']}>无法读取</span>\r\n : version.current\r\n ? <span className={styles['currentBadge']}>当前</span>\r\n : version.onCurrentEffectPath\r\n ? <span className={styles['pathBadge']}>链上</span>\r\n : null}\r\n </button>\r\n </li>\r\n )\r\n}\r\n\r\nfunction MessageCard({ message, disabled, onBeginEdit }: {\n message: EditableMessageBlock\n disabled: boolean\n onBeginEdit(message: EditableMessageBlock): void\n}): ReactNode {\n return (\n <article className={styles['messageCard']}>\n <div className={styles['messageHeader']}>\n <span className={styles['kindBadge']} data-kind={message.kind}>{BLOCK_LABEL[message.kind]}</span>\n <span className={styles['messageTime']}>{timeLabel(message.time)}</span>\n <button type=\"button\" className={styles['textButton']} disabled={disabled} onClick={() => onBeginEdit(message)}>编辑</button>\n </div>\n {message.attachments?.length ? <p className={styles['messageTime']}>\n 附件:{message.attachments.map(item => item.content.attachment.name ?? '图片附件').join('、')}\n </p> : null}\n <pre className={styles['messageText']}>{message.text || '(空正文)'}</pre>\n </article>\n )\n}\n\n/** Conversation-view entry point. */\r\nexport function MessageEditTimelineView({\r\n useMessageEdit,\r\n acquire,\r\n load,\r\n edit,\r\n retry,\r\n reroll,\r\n openVersion,\r\n attachmentTools,\r\n composerTools,\r\n}: MessageEditTimelineViewProps): ReactNode {\r\n const state = useMessageEdit(value => value)\r\n const [cascade, setCascade] = useState<CascadePolicy>('truncate')\r\n const [editing, setEditing] = useState<EditingState | null>(null)\r\n useEffect(() => {\r\n const release = acquire()\r\n load()\r\n return release\r\n }, [acquire, load])\r\n\r\n const timeline = state.timeline\r\n const sections = useMemo(\r\n () => timeline === null ? [] : turnSections(timeline.retryableTurns, timeline.messages),\r\n [timeline],\r\n )\r\n const busy = state.pending !== null || state.status !== 'ready'\r\n\r\n useEffect(() => {\r\n setEditing((current) => {\r\n if (current === null || timeline === null) return current\r\n return timeline.messages.some(message => message.key === current.message.key) ? current : null\r\n })\r\n }, [timeline])\r\n\r\n const cascadeRef = useRef(cascade)\n cascadeRef.current = cascade\n useEffect(() => {\n if (editing === null) return\n return mountEditor(editing.message, (message, text, _policy, regenerate, attachments, settings) =>\n edit(message, text, cascadeRef.current, regenerate, attachments, settings),\n () => setEditing(null), attachmentTools, composerTools)\n }, [editing, edit, attachmentTools, composerTools])\n\n if (timeline === null && (state.status === 'idle' || state.status === 'loading')) {\r\n return <div className={styles['status']}>正在载入消息时间线…</div>\r\n }\r\n if (timeline === null && state.status === 'error') {\r\n return (\r\n <div className={styles['status']}>\r\n <p className={styles['error']}>{state.error}</p>\r\n <button type=\"button\" className={styles['secondaryButton']} onClick={load}>重新载入</button>\r\n </div>\r\n )\r\n }\r\n if (timeline === null) return null\r\n\r\n return (\r\n <div className={styles['root']}>\r\n <header className={styles['pageHeader']}>\r\n <div>\r\n <h1 className={styles['title']}>消息编辑与重生成</h1>\r\n <p className={styles['intro']}>每次修改都会与其恢复版本成对记录;回合及其完整工具链作为一个整体重新计算。</p>\r\n </div>\r\n <div className={styles['headerActions']}>\r\n <label className={styles['cascadeField']}>\r\n <span>后续策略</span>\r\n <select\r\n className={styles['select']}\r\n value={cascade}\r\n disabled={busy}\r\n onChange={(event) => { setCascade(event.currentTarget.value as CascadePolicy) }}\r\n >\r\n <option value=\"truncate\">截断后续(默认)</option>\r\n <option value=\"preserve\">保留输入并重生成后续</option>\r\n </select>\r\n </label>\r\n <button\r\n type=\"button\"\r\n className={styles['primaryButton']}\r\n disabled={busy}\r\n onClick={() => { void reroll() }}\r\n >\r\n {state.pending === 'reroll' ? '正在重生成…' : '重生成最后回复'}\r\n </button>\r\n </div>\r\n </header>\r\n\r\n {state.error === null ? null : <p className={styles['error']}>{state.error}</p>}\r\n {state.status === 'loading' ? <p className={styles['notice']}>正在刷新时间线…</p> : null}\r\n\r\n <div className={styles['columns']}>\r\n <aside className={styles['versionsPanel']} aria-label=\"版本时间线\">\r\n <div className={styles['sectionHeading']}>\r\n <h2 className={styles['subtitle']}>版本时间线</h2>\r\n <span className={styles['count']}>{String(timeline.versions.length)}</span>\r\n </div>\r\n <div className={styles['effectControls']}>\r\n <span className={styles['effectDepth']}>当前效果链 {String(timeline.undoStack.length)} 层</span>\r\n <div className={styles['effectButtons']}>\r\n <button\r\n type=\"button\"\r\n className={styles['secondaryButton']}\r\n disabled={busy || timeline.undoStack[0] === undefined}\r\n onClick={() => {\r\n const target = timeline.undoStack[0]\r\n if (target !== undefined) void openVersion(target)\r\n }}\r\n >\r\n 撤销当前效果\r\n </button>\r\n <button\r\n type=\"button\"\r\n className={styles['secondaryButton']}\r\n disabled={busy || timeline.redoSessionIds.length === 0}\r\n onClick={() => {\r\n const target = timeline.redoSessionIds.at(-1)\r\n if (target !== undefined) void openVersion(target)\r\n }}\r\n >\r\n {timeline.redoSessionIds.length > 1\r\n ? `重施加最新分支(${String(timeline.redoSessionIds.length)})`\r\n : '重施加下一效果'}\r\n </button>\r\n </div>\r\n </div>\r\n <ol className={styles['versionList']}>\r\n {timeline.versions.map(version => (\r\n <VersionRow\r\n key={version.sessionId}\r\n version={version}\r\n disabled={busy}\r\n onOpen={(sessionId) => { void openVersion(sessionId) }}\r\n />\r\n ))}\r\n </ol>\r\n </aside>\r\n\r\n <main className={styles['turnsPanel']}>\r\n <div className={styles['sectionHeading']}>\r\n <h2 className={styles['subtitle']}>已落定消息</h2>\r\n <span className={styles['count']}>{String(timeline.messages.length)}</span>\r\n </div>\r\n {sections.length === 0\r\n ? <p className={styles['empty']}>当前会话还没有可编辑的已落定回合。</p>\r\n : (\r\n <ol className={styles['turnList']}>\r\n {sections.map(section => (\r\n <li key={section.retry.turn} className={styles['turnSection']}>\r\n <div className={styles['turnHeader']}>\r\n <div>\r\n <h3 className={styles['turnTitle']}>回合 {String(section.retry.turn)}</h3>\r\n <p className={styles['turnPreview']}>{section.retry.preview || '(空用户输入)'}</p>\r\n </div>\r\n <button\r\n type=\"button\"\r\n className={styles['secondaryButton']}\r\n disabled={busy}\r\n onClick={() => { void retry(section.retry.turn, cascade) }}\r\n >\r\n {state.pending === 'retry' ? '正在重试…' : '重试此回合'}\r\n </button>\r\n </div>\r\n <div className={styles['messageList']}>\r\n {section.messages.map(message => (\r\n <MessageCard\r\n key={message.key}\r\n message={message}\r\n disabled={busy}\r\n onBeginEdit={value => { setEditing({ message: value }) }}\r\n />\r\n ))}\r\n </div>\r\n </li>\r\n ))}\r\n </ol>\r\n )}\r\n </main>\r\n </div>\r\n </div>\r\n )\r\n}\r\n","import { createElement, useEffect, type ComponentType, type ReactNode } from 'react'\nimport type { Context } from '@deepseek-ai/cordis'\nimport type { ContentBlock } from '@deepseek-ai/dsh-llm'\nimport type { SessionId } from '@deepseek-ai/dsh-session/types'\nimport type { InjectFace, StoredEntry } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { MessageEditFace } from './controller.ts'\n\nconst CHAT_NODE_SLOT = 'conversation.chat.node'\nconst USER_NODE_KEYS = ['user', 'steering'] as const\n\ninterface UserNode {\n readonly data: {\n readonly seq: number\n readonly content: readonly ContentBlock[]\n }\n}\n\ntype UserNodeProps = Record<string, unknown> & { readonly node: UserNode } & InjectFace<MessageEditFace>\n\ninterface UserSlotOptions {\n name: typeof CHAT_NODE_SLOT\n key: typeof USER_NODE_KEYS[number]\n priority: number\n locale?: string\n inject(sessionId: SessionId): MessageEditFace\n}\n\n/** 通过公开的动态插槽接口接入,避免把整个官方聊天插件打进浏览器包。 */\ninterface ChatNodeSlots {\n entries(name: string): readonly StoredEntry[]\n subscribe(name: string, listener: () => void): () => void\n register(options: UserSlotOptions, component: ComponentType<UserNodeProps>): () => void\n}\n\nfunction equalContentValue(left: unknown, right: unknown): boolean {\n if (left === right) return true\n if (left === null || right === null || typeof left !== 'object' || typeof right !== 'object') return false\n if (Array.isArray(left) !== Array.isArray(right)) return false\n if (Array.isArray(left) && Array.isArray(right)) {\n return left.length === right.length && left.every((value, index) => equalContentValue(value, right[index]))\n }\n const leftRecord = left as Record<string, unknown>\n const rightRecord = right as Record<string, unknown>\n const keys = Object.keys(leftRecord)\n return keys.length === Object.keys(rightRecord).length && keys.every(key =>\n Object.prototype.hasOwnProperty.call(rightRecord, key) && equalContentValue(leftRecord[key], rightRecord[key]))\n}\n\nfunction projectedRenderer(original: StoredEntry): ComponentType<UserNodeProps> {\n const Original = original.component as ComponentType<Record<string, unknown>>\n return function UserMessageProjection(props: UserNodeProps): ReactNode {\n const { acquire, load, node, useMessageEdit } = props\n const messages = useMessageEdit(state => state.timeline?.messages)\n useEffect(() => {\n const release = acquire()\n load()\n return release\n }, [acquire, load])\n\n const savedContent = messages?.find(message => message.kind === 'user'\n && message.eventSeq === node.data.seq && message.content !== undefined)?.content\n let projected = node\n if (savedContent !== undefined) {\n if (!equalContentValue(node.data.content, savedContent)) {\n projected = { ...node, data: { ...node.data, content: savedContent } }\n }\n } else {\n // 兼容未提供完整内容的旧记录,仍按原内容块位置覆盖文本。\n let changed = false\n const content = node.data.content.map((block, blockIndex) => {\n if (block.type !== 'text') return block\n const saved = messages?.find(message => message.kind === 'user'\n && message.eventSeq === node.data.seq && message.blockIndex === blockIndex)\n if (saved === undefined || saved.text === block.text) return block\n changed = true\n return { ...block, text: saved.text }\n })\n if (changed) projected = { ...node, data: { ...node.data, content } }\n }\n return createElement(Original, { ...props, node: projected })\n }\n}\n\n/** 覆写用户消息的显示内容,复用官方气泡、附件和复制操作,不修改宿主的只读事件源。 */\nexport function registerUserMessageProjection(\n ctx: Context,\n faceFor: (sessionId: SessionId) => MessageEditFace,\n): void {\n const slots = ctx.slots as unknown as ChatNodeSlots\n // 旧宿主缺少公开的插槽检查接口时,仍保留 Timeline 的编辑入口。\n if (typeof slots.entries !== 'function' || typeof slots.subscribe !== 'function') return\n ctx.effect(() => {\n const active = new Map<string, { original: StoredEntry; component: ComponentType<UserNodeProps>; dispose(): void }>()\n let disposed = false\n const sync = (): void => {\n if (disposed) return\n for (const key of USER_NODE_KEYS) {\n const current = active.get(key)\n const original = slots.entries(CHAT_NODE_SLOT).find(entry => entry.options.key === key\n && !Array.from(active.values()).some(wrapper => wrapper.component === entry.component))\n if (current?.original === original) continue\n current?.dispose()\n active.delete(key)\n if (original === undefined) continue\n const component = projectedRenderer(original)\n const dispose = slots.register({\n name: CHAT_NODE_SLOT,\n key,\n priority: (original.options.priority ?? 0) - 1,\n ...original.locale === undefined ? {} : { locale: original.locale },\n inject: faceFor,\n }, component)\n active.set(key, { original, component, dispose })\n }\n }\n const unsubscribe = slots.subscribe(CHAT_NODE_SLOT, sync)\n sync()\n return () => {\n disposed = true\n unsubscribe()\n for (const wrapper of active.values()) wrapper.dispose()\n active.clear()\n }\n }, 'message-edit: 用户消息显示投影')\n}\n","/** Message Edit browser half: Timeline view and compact conversation-header controls. */\r\nimport type { Context } from '@deepseek-ai/cordis'\r\nimport type { SessionId } from '@deepseek-ai/dsh-session/types'\r\nimport type {} from '@deepseek-ai/dsh-client-ui-conversation/client'\r\nimport type {} from '@deepseek-ai/dsh-client-ui-renderer/client'\r\nimport { MESSAGE_EDIT_VIEW_ORDER } from '../shared.ts'\r\nimport { MessageEditController } from './controller.ts'\r\nimport { MessageEditHeader } from './MessageEditHeader.tsx'\r\nimport { MessageEditTimelineView } from './MessageEditTimelineView.tsx'\r\nimport { registerUserMessageProjection } from './UserMessageProjection.tsx'\r\nimport { MESSAGE_EDIT_BUILD_INFO } from '../build-info.ts'\r\nimport { MESSAGE_EDIT_PATH } from '../shared.ts'\r\nimport { hostFetch } from './transport.ts'\r\n\r\nexport { MESSAGE_EDIT_BUILD_INFO } from '../build-info.ts'\r\n\r\n/** Explicit value sources and slot declaration-order edges. */\r\nexport const inject = ['slots', 'uiConversation', 'conversation', 'uiWorkspace', 'connection', 'sessions',\r\n 'commandUi', 'remote.commands', 'remote.sessionReferenceResolver']\r\n\r\n/** Register both UI contributions over one per-session controller identity. */\r\nexport function apply(ctx: Context): void {\r\n const globals = globalThis as typeof globalThis & { __DSH_MESSAGE_EDIT__?: unknown }\r\n const diagnostics = Object.freeze({\r\n build: MESSAGE_EDIT_BUILD_INFO,\r\n diagnostics: async () => {\r\n const response = await hostFetch(`${MESSAGE_EDIT_PATH}?view=diagnostics`, {\r\n method: 'GET', headers: { accept: 'application/json' }, cache: 'no-store',\r\n })\r\n if (!response.ok) throw new Error(`无法读取插件诊断:HTTP ${String(response.status)}`)\r\n const host = await response.json() as { build?: { version?: string; buildId?: string } }\r\n return { client: MESSAGE_EDIT_BUILD_INFO, host,\r\n matched: host.build?.version === MESSAGE_EDIT_BUILD_INFO.version && host.build?.buildId === MESSAGE_EDIT_BUILD_INFO.buildId }\r\n },\r\n })\r\n ctx.effect(() => {\r\n const previous = globals.__DSH_MESSAGE_EDIT__\r\n globals.__DSH_MESSAGE_EDIT__ = diagnostics\r\n return () => {\r\n if (globals.__DSH_MESSAGE_EDIT__ === diagnostics) {\r\n if (previous === undefined) delete globals.__DSH_MESSAGE_EDIT__\r\n else globals.__DSH_MESSAGE_EDIT__ = previous\r\n }\r\n }\r\n }, 'message-edit: 构建诊断')\r\n const controllers = new Map<SessionId, MessageEditController>()\r\n const controllerFor = (sessionId: SessionId): MessageEditController => {\r\n let controller = controllers.get(sessionId)\r\n if (controller === undefined) {\r\n controller = new MessageEditController(ctx, sessionId)\r\n controllers.set(sessionId, controller)\r\n }\r\n return controller\r\n }\r\n\r\n registerUserMessageProjection(ctx, sessionId => controllerFor(sessionId).face)\r\n\r\n ctx.on('connection/reset', () => {\r\n for (const controller of controllers.values()) controller.refreshIfLoaded()\r\n })\r\n\r\n ctx.slots.inject('conversation.view', () => ctx.slots.register({\r\n name: 'conversation.view',\r\n id: 'message-edit-timeline',\r\n order: MESSAGE_EDIT_VIEW_ORDER,\r\n label: 'Timeline',\r\n inject: (sessionId: SessionId) => controllerFor(sessionId).face,\r\n }, MessageEditTimelineView))\r\n\r\n ctx.slots.inject('conversation.session.header.actions', () => ctx.slots.register({\r\n name: 'conversation.session.header.actions',\r\n id: 'message-edit-controls',\r\n order: MESSAGE_EDIT_VIEW_ORDER,\r\n inject: (sessionId: SessionId) => controllerFor(sessionId).face,\r\n }, MessageEditHeader))\r\n}\r\n"],"mappings":"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"}
|