资讯详情

qwen-code WebShell 只读转录渲染:WebShellTranscript 组件的设计与实现解析

📅 2026/9/15 15:54:09 | 华诺云谱 👁 阅读
qwen-code WebShell 只读转录渲染:WebShellTranscript 组件的设计与实现解析
qwen-code WebShell 只读转录渲染WebShellTranscript 组件的设计与实现解析【免费下载链接】qwen-codeAn open-source AI coding agent that lives in your terminal.项目地址: https://gitcode.com/GitHub_Trending/qw/qwen-code本文聚焦 qwen-code 开源仓库中qwen-code/web-shell的只读会话转录daemon transcript渲染能力。WebShell 原本只能在完整交互式会话App/ChatPane中展示 daemon 转录而WebShellTranscript组件允许宿主只传入一份DaemonTranscriptBlock[]即可复用MessageList的全部渲染能力且不连接 daemon、不产生任何会话变更。读完本文你将掌握该组件的公共 API、只读边界约定、底层实现原理共享转换、渲染模式上下文、portal 隔离以及如何在无 daemon 环境下独立渲染历史会话。1. 背景从间接复用到独立只读入口在设计落地之前WebShell 已经具备完整的 daemon 转录渲染链路但只能通过App或ChatPane分屏视图间接使用组件先从DaemonSessionProvider读取转录块把块转换为 WebShell 内部消息再交给MessageList渲染。新的使用场景例如只读的历史会话视图、ChatRecord JSONL 回放已经直接持有DaemonTranscriptBlock[]只需要 WebShell 的消息样式与渲染能力来展示历史内容不需要建立 daemon 会话连接也必须避免任何会话变更session mutation。明确排除在目标之外的交互包括工具审批tool approval、AskUserQuestion、重试retry、分支branch、提示词提交prompt submission以及一切会修改会话状态的面板。如果让宿主直接消费transcriptBlocksToDaemonMessages()的返回值并自行拼装内部组件会暴露 WebShell 私有的DaemonMessage模型、内部 Context 和 CSS 约束还会在MessageList演进时与受支持的渲染行为发生漂移。因此qwen-code/web-shell需要一个稳定、公开的入口。2. 设计目标与非目标2.1 目标提供公开 React 组件直接接收并渲染readonly DaemonTranscriptBlock[]。复用现有transcriptBlocksToDaemonMessages()与同一个MessageList让用户消息、助手回复、思考、工具、子代理、计划、状态、Markdown、时间线、长会话虚拟滚动等能力随MessageList自动演进。组件可脱离DaemonWorkspaceProvider、DaemonSessionProvider与网络连接独立渲染。在只读边界内不调用任何 daemon/session 变更不为待决权限或AskUserQuestion展示响应式 UI。主要新增导出不改变现有WebShell、WebShellWithProviders、App、ChatPane的运行时路径、默认值或 DOM 行为。补齐组件单元测试并保证 WebShell 既有测试套件、构建、lint、typecheck 全部通过。2.2 非目标不新增转录获取、分页、缓存或 SSE 订阅能力blocks 由宿主提供。不在现有WebShellProps中插入只读模式也不给App增加readOnly/blocks双数据源分支。不导出内部MessageList、Message、DaemonMessage类型。不展示或处理未解决的工具审批与AskUserQuestion。不提供 App 壳层的 composer、排队提示、流式状态、侧边栏、分屏、对话框、产物右侧面板等能力MessageList内置的会话时间线保留。不从 blocks 推断或加载独立的会话产物文件变更、产物、定时任务的 turn 级输出卡片不在范围内。不阻止仅修改本地展示状态的交互如复制、折叠/展开工具、展开已完成 turn、表格过滤、时间线导航。3. 术语与只读边界设计中的一个关键界定只读意味着不读写 daemon/session 运行时状态而不是对整棵 DOM 设置pointer-events: none。类别行为是否保留被动展示文本、Markdown、图片、diff、shell 输出、工具/子代理状态保留本地查看复制、折叠、展开、虚拟滚动、时间线、表格排序/过滤保留宿主定制展示Markdown/代码块渲染器、消息内容渲染器保留副作用由宿主承担普通外部链接浏览器安全 URL 转换后新窗口导航保留WebShell 语义导航qwen-session://派发全局qwen:open-session事件不保留作为非交互文本渲染会话变更发送提示、取消、重试、分支、回退、切换模型/模式不保留权限变更批准/拒绝工具、提交/忽略AskUserQuestion不保留外部数据加载组件发起的会话挂载、转录/产物/任务/MCP 拉取不保留该边界既保留了MessageList的阅读体验又保证组件自身不具备写入 daemon 的能力。4. 现状与调用方地图模块当前职责与本设计的关系packages/sdk-typescript/src/daemon/ui/types.ts定义DaemonTranscriptBlock联合类型新组件的公共输入模型packages/web-shell/client/adapters/transcriptToMessages.ts把块合并为 WebShellDaemonMessage[]直接复用不新建转换器packages/web-shell/client/hooks/useMessages.ts从会话 hook 读取块并提供本地化转换选项抽取共享纯转换入口可接受外部 blockspackages/web-shell/client/components/MessageList.tsxturn 折叠、工具/子代理分组、时间线、虚拟滚动、逐消息渲染新旧路径共享的唯一列表实现packages/web-shell/client/components/MessageItem.tsx按消息角色派发具体渲染器无需改动packages/web-shell/client/App.tsx完整单会话 WebShell、审批、composer、侧面板现有路径保持不变packages/web-shell/client/components/ChatPane.tsx分屏视图中的完整交互式会话现有路径保持不变packages/web-shell/client/index.tsx/index.ts包运行时/源码导出导出新组件与类型现有主路径如下新的只读路径绕开会话 Provider 与权限分支一个值得注意的细节在 WebShell 主编辑器里/tasks与/mcp命令在App内部被拦截只更新对话框 React 状态既不调用sendPrompt()也不写入会话 JSONL。因此持久化转录中不存在这两个本地面板的哨兵标记新入口也不需要为它们增加识别或过滤分支。5. 公共 APIWebShellTranscript组件命名为WebShellTranscript从qwen-code/web-shell包根导出export interface WebShellTranscriptProps { /** Ordered transcript blocks from one logical session. */ blocks: readonly DaemonTranscriptBlock[]; theme?: WebShellTheme; language?: en | zh-CN | zh | zh-cn; className?: string; style?: React.CSSProperties; chatMaxWidth?: number; workspaceCwd?: string; compactThinking?: boolean; collapseCompletedTurns?: boolean; markdownTableMode?: MarkdownTableMode; virtualScrollThreshold?: number; markdown?: WebShellMarkdownCustomization; composerTagIcons?: WebShellComposerTagIconMap; renderToolHeaderExtra?: ToolHeaderExtraRenderer; parseUserMessageContent?: UserMessageContentParser; renderUserMessageContent?: UserMessageContentRenderer; renderComposerTag?: ComposerTagRenderer; renderComposerTagTooltip?: ComposerTagRenderer; renderAssistantTurnFooter?: AssistantTurnFooterRenderer; } export function WebShellTranscript( props: WebShellTranscriptProps, ): React.ReactElement;要点说明blocks为必填项组件既不拷贝也不修改它。调用方应保持数组内块所属会话与顺序一致。视觉类 props 复用WebShellProps中的命名与类型避免同一能力出现两套配置语义。不暴露onComposerTagClick、onRetryClick、onBranchSession、onTurnOutputOpen、权限回调与 composer 回调。theme默认dark省略language时使用 WebShell 的 URL/浏览器语言解析规则chatMaxWidth默认 1000px。compactThinking默认falsecollapseCompletedTurns默认true与现有WebShell一致。组件把转录视为静态/已回放完成的数据向MessageList传入isResponding{false}实时流式不在当前 API 范围内。使用示例import { WebShellTranscript } from qwen-code/web-shell/transcript; import type { DaemonTranscriptBlock } from qwen-code/sdk/daemon; export function HistoryView({ blocks, }: { blocks: readonly DaemonTranscriptBlock[]; }) { return ( WebShellTranscript blocks{blocks} themedark languagezh-CN workspaceCwd/workspace/project style{{ height: 640 }} / ); }宿主必须给组件一个可用高度。组件本身保留 WebShell 的height: 100%、内部滚动与内容宽度行为。5.1 源码中的实际实现差异对照 WebShellTranscript.tsx落地实现比设计文档更进一步主要体现在新增document渲染模式renderMode?: readonly | document。document模式下虚拟滚动阈值被强制设为Number.MAX_SAFE_INTEGER即不启用虚拟滚动、hideSessionTimeline为true、collapseCompletedTurns默认展开、Markdown 表格固定为basic模式适合全文导出/打印场景。语言解析逻辑resolveLanguage优先使用显式传入的languageSSR 下回退en浏览器端按?language、?lang查询参数、再到navigator.language的顺序解析。宽度计算getChatWidthStylechatMaxWidth需为正有限数值否则回退 1000px生成--chat-regular-content-width、--chat-regular-shell-width、--chat-content-width、--chat-shell-width四个 CSS 变量shell 宽度 内容宽度 40px 水平内边距。根节点标记根节点带data-web-shell-root、data-web-shell-shadcn、data-transcript-render-mode与lang属性用于匹配 WebShell 库注入的 CSS 作用域规则。6. 详细设计6.1 共享本地化转换保持transcriptBlocksToDaemonMessages()作为唯一的块到消息适配器并在useMessages.ts中抽取内部纯函数export function transcriptBlocksToLocalizedMessages( blocks: readonly DaemonTranscriptBlock[], t: Translator, ): Message[];该函数只从内部包模块导出供新组件复用不从包根公开。它组装当前useMessages()使用的本地化标签再调用既有适配器现有useMessages()与新组件都调用它从而防止提示取消、分支、mid-turn 插入、流中断等文案产生漂移。这是现有渲染路径中唯一的内部重构。函数输入、输出与既有转换结果保持不变适配器的块合并规则也不修改。源码印证转换逻辑最终落在 localizedMessages.ts 这个叶子模块。文件头注释明确说明之所以放在hooks/useMessages.ts之外是因为后者是 daemon 消费端会从daemon-react-sdkbarrel 引入useConnection/useTranscriptBlocks/useWorkspace直接引用它会把 daemon Provider 栈拖进只读入口。client/build-artifact.test.ts还专门断言dist/transcript.js不携带任何 daemon Provider 代码。转换时传入safeToolProjectiondocument 模式下为true与includeSourceIdentity: true并注入promptCancelled、branchSuccess、modelStreamInterrupted、loopDetected四个本地化标签。6.2WebShellTranscript组件结构新增 WebShellTranscript.tsx内部执行顺序解析 theme 与 language 并创建翻译器。用useMemo把blocks转换为Message[]。构建与现有 App 相同的消息层定制值。挂载 WebShell 的 theme、i18n、customization、compact-mode、只读 render-mode 与 portal 上下文。创建独立根节点data-web-shell-rootdata-web-shell-shadcn复用 App 的主题类、基础变量、字体、背景与 CSS 隔离规则。渲染同一个MessageList。固定的MessageList输入MessageList messages{messages} pendingApproval{null} isResponding{false} workspaceCwd{workspaceCwd ?? } virtualScrollThreshold{virtualScrollThreshold} /绝不传递以下动作 propsonShowContextDetailonRetryClickonBranchSessiononReviewChangesonOpenArtifactonOpenScheduledTaskonTurnOutputOpen也不传递 loading、catch-up、tail、turn-output 数据避免依赖 App 的连接状态与外部资源模型。6.3 交互渲染器隔离只向MessageList传pendingApproval{null}并不能完全保证只读行为目标状态、Markdown、工具结果中的会话链接不走MessageList回调而是向window派发全局语义事件可能影响同页面上另一个 WebShell 的 footer 或活动会话。为此在 transcriptRenderMode.ts 中新增包内部转录渲染模式上下文默认值为interactive。现有App与ChatPane无需新增 Provider行为保持不变WebShellTranscript将其设置为readonly或document。实际实现中该上下文还扩展出useTranscriptRenderMode()与useTranscriptDocumentExpanded()两个 hook以及TranscriptDocumentExpandedProvider。只读模式仅施加以下限制保留qwen-session://链接的文本与样式但不派发qwen:open-session。GoalStatusMessage不派发GOAL_STATUS_ACTIVE_EVENT。不拦截普通 HTTPS 链接或复制、折叠、排序等本地查看交互。源码印证在 Markdown.tsx 中MarkdownLink通过useTranscriptRenderMode()判断当渲染模式不是interactive时qwen-session://链接直接渲染为span文本不再生成带onClick派发事件的a。与此同时markdownUrlTransform专门放行qwen-session://schemereact-markdown 默认的defaultUrlTransform只会保留 http(s)/irc(s)/mailto/xmpp其余一律改写为空串注释明确指出这种放行是安全的MarkdownLink从不把该 scheme 放进 DOM只会以href#渲染并派发 id 事件。只读模式下 Mermaid 渲染还进入hardened配置分支untrustedMode与交互式runtime配置区分。该上下文只改变Markdown、ToolGroup、GoalStatusMessage中的语义事件出口默认锁定为interactive避免给MessageList的每个渲染器都穿线传readOnlyprop。新单元测试必须同时证明默认交互行为不变、只读行为被抑制。6.4 主题、CSS 与 PortalWebShell 库构建会把组件 CSS 注入并限定在[data-web-shell-root]或[data-web-shell-portal-root]作用域下。新组件必须创建自己的 WebShell 根节点否则MessageList产生的 DOM 可能匹配不上 CSS 模块规则。时间线 tooltip 与高级 Markdown 表格使用 portal。为完整继承这些能力新组件采用与 App 等价的 portal-host 生命周期挂载时向document.body追加带data-web-shell-portal-root与data-web-shell-shadcn的节点。同步该根节点的主题类与 CSS 变量。通过WebShellPortalRootContext提供该节点。卸载时移除节点及其 observer/listener。源码印证实际实现通过useLayoutEffect创建 portal 根节点另一个useLayoutEffect用requestAnimationFrameMutationObserver同步根节点与 portal 根之间的全部 CSS 变量遍历getComputedStyle中以--开头的属性同时同步dark类与lang属性并监听window.resize重新调度同步清理阶段会断开 observer、移除 resize 监听并取消动画帧。该生命周期只保留在新组件内部不重构 App 既有 portal 代码把对现有行为的回归面限制在新入口上。SSR 期间不访问documentportal 仅在客户端挂载后启用。6.5 错误隔离新入口有外层公共边界与内层内容组件。块转换、Provider/portal 初始化、MessageList渲染全部发生在外层边界ErrorBoundary的子节点中任何阶段的失败都会落入与公共 WebShell 入口相同的RootErrorFallback。每条消息仍由MessageItem自身的边界隔离因此单个 Markdown、KaTeX、Mermaid 或工具渲染器失败不会导致整份转录空白。源码印证WebShellTranscript外层用ErrorBoundarylabelweb-shell-transcript-rootresetKeys为[props.blocks, language]包裹fallback 为RootErrorFallback内层WebShellTranscriptContent负责全部实际渲染。6.6 块渲染策略所有策略继续使用既有适配器新组件内不新增第二套 switch 分支DaemonTranscriptBlock.kind只读渲染结果user用户消息、图片与输入注解assistant助手 Markdown连续块合并子代理内容按父级归属thought思考消息连续块合并tool工具组、diff/read/shell/fetch/todo/子代理的既有卡片shell关联到最近的执行工具不可用时回退既有 raw-shell 展示user_shell用户 shell 命令/输出status/debug计划或系统/状态消息error无重试动作的错误系统消息prompt_cancelled本地化取消状态未解决的permission不转换、不展示、不提供动作入口已解决的permission沿用适配器的历史工具占位/结果规则AskUserQuestion权限不展示表单仅当后续存在真实工具块时展示历史结果6.7 更新与性能仅在blocks引用或语言变化时重新执行 O(n) 转换。MessageList保留既有 memoization、turn 分组与虚拟滚动阈值。不深拷贝 blocks也不为每个块新建 React Provider。调用方频繁传入内容相同但引用全新的数组会触发重复转换这是可接受的与当前useTranscriptBlocks()的更新模型一致。本版本不新增增量适配器只有测量表明大型外部转录更新成为瓶颈时才单独设计增量转换。源码印证WebShellTranscriptContent中messages、todoDetails、todoTimeline、customization均为useMemo转换依赖[blocks, documentMode, t]todo 时间线与详情由computeTodoDetails/computeTodoTimeline从消息中计算并通过TodoContextsProvider提供给MessageList。组件还通过CompactModeContext.Provider value{false}强制关闭紧凑模式注释说明这是为了让宿主看到完整记录不受主应用常开紧凑视图的影响。7. 兼容性与回归控制7.1 现有路径保持不变WebShellProps不新增必填字段不改变任何默认值。WebShell与WebShellWithProviders继续渲染App。App与ChatPane继续从各自 Provider/hook 读取会话状态。审批浮层、composer、侧边栏、分屏、产物面板不经过新组件。MessageList不新增readOnlyprop 分支。新调用方通过传pendingApprovalnull、省略动作回调、使用默认保持interactive的内部渲染模式上下文来建立只读行为隔离少量全局语义事件。7.2 包导出同时更新client/index.tsx与client/index.ts两个 barrelexport { WebShellTranscript } from ./components/WebShellTranscript; export type { WebShellTranscriptProps } from ./components/WebShellTranscript;两个 barrel 都必须修改以避免当前双运行时入口与声明/源码入口路径产生运行时已导出但类型声明缺失的问题。不新增包子路径导出client/index.tsx第 15–16 行已确认两处导出存在。另外README 与构建产物测试要求构建后检查dist/types/index.d.ts同时包含WebShellTranscript及其 props 的导出防止两个入口声明漂移。7.3 安全新入口不 importuseActions()、useTranscriptStore()、useConnection()或fetch。待决权限内容不会进入交互式渲染器。不检查或改写状态消息内容/tasks与/mcp的对话框状态天然不存在于持久化转录中。只读渲染模式不派发可能影响同页另一个 WebShell 的会话/目标全局事件。Markdown URL 与 HTML 处理继续沿用 WebShell 既有 sanitizer/transform不新增dangerouslySetInnerHTML或其他绕过。自定义渲染器是宿主代码宿主渲染器执行的副作用不在组件保证的只读边界内README 必须明确声明这一点README.md 第 309–310 行已注明自定义 renderer 的副作用仍由宿主负责。8. 只读回放的端到端用法从 ChatRecord JSONL 到转录视图README 的只读 ChatRecord JSONL章节给出了一个完整可运行的宿主集成示例浏览器宿主可以逐行解析 JSONL再通过 SDK 的 opt-in facade 投影为转录块后交给WebShellTranscript。导入路径提示只渲染 transcript 的宿主应从qwen-code/web-shell/transcript子路径导入。包根会连带App、daemon providers 与编辑器/终端相关代码不要依赖 tree shaking 把它们摇掉。import { projectChatRecordsToDaemonTranscript } from qwen-code/sdk/daemon/transcript; import { WebShellTranscript } from qwen-code/web-shell/transcript; const records jsonl .split(/\r?\n/) .filter((line) line.trim()) .map((line) JSON.parse(line) as unknown); const projection projectChatRecordsToDaemonTranscript(records); WebShellTranscript blocks{projection.blocks} themedark languagezh-CN style{{ height: 640 }} /;宿主应展示projection.diagnostics并在completefalse或truncatedtrue时提示历史可能不完整。组件需要一个可用高度自定义 renderer 的副作用由宿主负责。9. 测试设计9.1 组件契约单元测试WebShellTranscript.test.tsxmockMessageList共享本地化适配器按正确顺序与内容把块转换为消息。pendingApproval恒为null。会话变更、权限、重试、分支、turn-output 回调全部缺失。isResponding默认falseworkspace 与虚拟滚动配置正确转发。theme、language、compact/collapse 行为与消息定制进入正确上下文。blocks 或 language 变化时重新生成消息且不重复旧内容。空 blocks 渲染空列表且不抛异常。9.2 DOM 集成单元测试WebShellTranscript.dom.test.tsx使用真实MessageList在无 daemon Provider 的 React 树中成功渲染。代表性的 user、assistant Markdown、thought、tool、子代理、plan、status、error、prompt-cancelled 块进入对应 WebShell DOM。本地折叠/展开、复制、时间线导航仍可用证明复用了MessageList能力。未解决的普通权限不产生审批面板。未解决的AskUserQuestion不产生选项、输入、提交或忽略 UI。已解决的历史工具/AskUser 结果遵循适配器既有展示规则。只读会话链接与目标状态不派发全局语义事件既有组件测试继续证明默认交互行为不变。深色/浅色类、语言、本地化文本、聊天最大宽度与 CSS 根标记正确。portal 根正确挂载/卸载portal 内容处于作用域根下。单个自定义渲染器抛错时回退内置渲染器消息其余部分保留。9.3 共享转换与导出测试扩展useMessages/适配器测试证明既有 hook 与外部 blocks 使用完全相同的本地化选项。扩展index.test.tsx或构建产物测试验证运行时具名导出存在。构建后验证dist/types/index.d.ts包含WebShellTranscript及其 props 导出。9.4 回归验证序列实现后的最小验证命令序列cd packages/web-shell npm run build npx vitest run --config vitest.config.ts \ client/components/WebShellTranscript.test.tsx \ client/components/WebShellTranscript.dom.test.tsx \ client/hooks/useMessages.test.ts \ client/adapters/transcriptToMessages.test.ts \ client/components/MessageList.test.ts \ client/components/MessageList.dom.test.tsx \ client/components/messages/Markdown.test.ts \ client/components/messages/ToolGroup.test.tsx \ client/components/messages/SystemMessage.test.tsx \ client/index.test.tsx npm test npm run format:check npm run lint npm run typecheck cd ../.. npm run build npm run typechecknpm test是既有完整 WebShell 套件必须通过。该变更不新增独立页面也不改变既有 Playwright smoke 测试的 App/daemon 协议因此不新增浏览器 E2E 测试WebShellTranscript.dom.test.tsx已覆盖真实 DOM 行为。10. 实施步骤回顾在useMessages.ts抽取共享本地化块转换保持现有 hook 输出不变。新增内部转录渲染模式上下文并在会话链接/目标事件出口消费它默认保持interactive。新增WebShellTranscript及其 props实现根节点/Provider/portal/MessageList装配。在两个公共 barrel 增加运行时与类型导出。更新packages/web-shell/README.md补充只读集成示例、宿主高度要求与只读边界说明。新增契约、DOM、交互隔离、导出/类型声明测试。运行定向测试、完整 WebShell 套件、构建、lint、typecheck。按仓库规范审阅完整 diff任何修复后重跑第 7 步。11. 方案取舍Alternatives11.1 给现有WebShell增加blocks与readOnly被否决。App现在无条件消费多个 daemon hook并管理审批、composer、会话、侧边栏与面板。双数据源会给App全篇增加条件分支既需要 Provider 又需要防变更回归面远大于本需求。11.2 公开导出MessageList被否决。调用方仍会依赖私有Message[]、多个 Context、CSS 根约定与 portal 约定内部模型会变成长期公共 API。11.3 为只读场景复制一套渲染器被否决。复制会立刻分叉 Markdown、工具/子代理、turn 折叠、时间线与虚拟滚动行为无法满足继承MessageList渲染能力的要求。11.4 在新组件中展示禁用态权限/AskUserQuestion被否决。禁用表单仍会制造交互语义与额外状态分支还会误导用户在历史视图中以为自己可以作答。本版本隐藏待决权限后续工具块携带历史结果。12. 风险与缓解风险缓解措施新入口与 App 的本地化转换漂移两者调用同一个本地化转换 helperportal 缺失 CSS 作用域创建独立data-web-shell-portal-root、同步变量并用 DOM 测试覆盖意外 daemon 变更新组件不 import 任何 action hook、不暴露变更回调契约测试锁定App 本地对话框状态被误认为转录数据明确文档化/tasks与/mcp不写 JSONL新入口不复制 App 对话框状态全局语义事件影响同页其他 WebShell只读渲染模式抑制会话/目标事件回归测试覆盖默认行为新块类型无展示继续通过共享适配器支持不在组件中复制 switch包运行时与类型导出分叉同时更新两个 barrel 并检查构建后的声明文件大转录重算成本useMemo 既有虚拟滚动增量转换推迟到有测量数据支持时再做自定义渲染器引入副作用文档化宿主责任默认渲染器保持只读13. 验收标准宿主只需提供 blocks即可在无 daemon Provider 的环境中渲染 WebShell 转录。代表性块与既有 WebShellMessageList中相同数据的渲染结果一致。待决工具权限与AskUserQuestion不产生交互 UI 或提交路径。只读视图不派发任何全局会话/目标语义事件。新组件保留MessageList的本地阅读交互与长列表能力。既有WebShell/WebShellWithProviders的 API、默认值、测试与运行时行为保持不变。qwen-code/web-shell的运行时与.d.ts均导出新组件及其 props。新单元测试、既有完整 WebShell 套件与根构建/typecheck 全部通过。总结WebShellTranscript是 qwen-code WebShell 面向只读消费历史转录场景的稳定公共入口它以DaemonTranscriptBlock[]为唯一输入复用共享本地化转换与MessageList全部渲染能力通过pendingApproval{null}、省略动作回调与interactive默认的渲染模式上下文三重手段锁定只读边界并通过独立 WebShell 根节点与 portal-host 生命周期实现 CSS 隔离。落地实现还在设计基础上扩展了document渲染模式全文导出语义代码层面以叶子模块localizedMessages.ts隔离 daemon 依赖以transcriptRenderMode.ts上下文收敛语义事件出口。对希望在自己的宿主应用中回放 qwen-code 会话历史的开发者而言参照本文第 5 节 API 与第 8 节 JSONL 集成示例即可快速接入。【免费下载链接】qwen-codeAn open-source AI coding agent that lives in your terminal.项目地址: https://gitcode.com/GitHub_Trending/qw/qwen-code创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。