opencode工具层设计:从能跑到好用的工程实践
1. 从“能跑”到“好用”opencode 工具层的设计哲学很多人第一次接触 opencode 这类终端 AI 编程助手时注意力都放在“它能不能帮我写代码”上。但真正决定它好不好用的其实是工具层——也就是它到底能调用哪些能力、这些能力怎么组合、边界在哪里。上篇我们聊了核心架构和会话管理下篇重点就落在工具、服务面、外壳和实战集成这四个维度上。先说一个我踩过的坑。早期我用某个助手写一个批量重命名脚本它生成的代码逻辑没问题但执行时直接报权限错误。原因很简单它的工具层只有“写文件”能力没有“执行命令”能力而重命名必须调用系统命令。这就是工具层设计差异带来的直接体验差距。opencode 在这块的设计思路是“能力显式声明、调用可审计、结果可回滚”听起来有点抽象我拆开讲。工具层本质上是一组被严格定义的函数接口。每个工具都有明确的输入 schema、输出格式和副作用说明。比如读文件工具只读不写写文件工具会修改磁盘执行命令工具会产生进程。这种显式声明的好处是模型在规划任务时能清楚知道自己能做什么、不能做什么不会“幻觉”出一个不存在的工具。我实测下来这种约束反而让复杂任务的完成率更高因为模型不会在错误的方向上浪费 token。另一个关键点是工具的组合方式。opencode 不是让模型自由发挥去拼工具而是通过“服务面”来暴露一组相关工具。服务面可以理解为一个能力集合比如“文件服务面”包含读、写、列目录、搜索“命令服务面”包含执行、后台运行、终止进程。模型看到的是服务面级别的描述具体调用哪个工具由它自己决定。这种分层设计的好处是扩展新能力时只需要新增一个服务面不用改动核心调度逻辑。提示如果你在自建类似系统建议把工具按“读操作”和“写操作”严格分开。读操作可以宽松授权写操作必须加确认或沙箱。这是血泪教训我见过太多因为写操作失控导致本地文件被覆盖的案例。2. 工具层核心细节参数、返回值与错误处理2.1 工具参数设计的三个原则工具参数看起来简单其实最容易出问题。我总结下来有三个原则必填参数最小化、可选参数有默认、复杂参数用结构化。必填参数最小化是指一个工具必须的参数越少越好。比如“读文件”工具必填的只有路径编码、起始行、结束行都应该是可选参数。这样模型在简单场景下不用纠结参数复杂场景下又能精细控制。我见过一些设计把编码设为必填结果模型每次都要猜文件编码浪费大量 token 还容易出错。可选参数有默认是指每个可选参数都要有合理的默认值。比如“执行命令”工具的超时时间默认 30 秒模型不指定就用这个值。默认值的选择要基于常见场景太短会导致正常命令被误杀太长会让卡死的命令占用资源。我一般建议命令执行默认 30 到 60 秒文件操作默认 5 到 10 秒。复杂参数用结构化是指当一个工具需要多个相关参数时用对象或数组而不是平铺。比如“搜索文件”工具条件可能包括文件名模式、内容模式、排除目录、最大深度。这些如果平铺成七八个参数模型很容易漏填或填错。结构化成一个conditions对象每个字段有明确类型和说明模型的理解准确率会高很多。2.2 返回值格式与截断策略工具返回值的设计直接影响模型下一步的决策。返回值太啰嗦token 爆炸太简略模型信息不足。我的经验是结构化返回、关键信息前置、超长内容截断并标注。结构化返回是指返回值用 JSON 或类似格式包含状态码、数据、错误信息三个部分。状态码让模型快速判断成功失败数据是实际内容错误信息在失败时给出原因。这样模型不用解析自然语言就能做分支判断。关键信息前置是指把模型最需要的信息放在返回值最前面。比如读文件返回前几行应该是文件路径、总行数、编码然后才是内容。执行命令返回前面是退出码、执行时长然后才是标准输出和标准错误。我实测下来这种前置能让模型在只看前 100 个 token 的情况下就做出正确决策。超长内容截断是必须的。一个日志文件可能几万行全塞给模型既浪费又没必要。我的做法是默认只返回前 N 行和后 N 行中间用省略标记同时告诉模型总行数和截断位置。如果模型需要更多它可以再次调用工具并指定范围。这样既控制了单次 token 消耗又保留了按需获取的能力。2.3 错误处理的分类与恢复错误处理是工具层最容易被忽视的部分。很多实现只返回“失败”两个字模型完全不知道下一步该怎么办。我的分类是参数错误、权限错误、资源错误、超时错误、未知错误。参数错误是模型自己能修的比如路径不存在、参数类型不对。这类错误要明确告诉模型哪个参数有问题、期望什么格式。权限错误是模型修不了的需要用户介入比如没有写权限。这类错误要明确说“需要用户授权”。资源错误比如磁盘满、内存不足模型可以尝试清理或换路径。超时错误可以重试或调整超时时间。未知错误就如实上报让模型决定是否重试。注意错误信息里千万不要包含敏感路径或系统信息。我见过一些实现直接把完整堆栈返回给模型里面可能有用户名、内部路径等。正确做法是脱敏后再返回只保留模型决策必需的信息。3. 服务面能力暴露的边界与组合3.1 什么是服务面为什么需要它服务面是我自己起的一个词对应英文里的 service surface。它指的是“一组相关工具的集合对外暴露为一个逻辑单元”。比如文件服务面、命令服务面、网络服务面、数据库服务面。每个服务面有自己的描述、工具列表和权限要求。为什么需要服务面因为模型面对几十个散落的工具时选择成本很高。它需要理解每个工具的用途、参数、返回值然后决定用哪个。如果按服务面组织模型可以先选服务面“我要操作文件”再选具体工具“读还是写”决策路径更清晰。我实测下来服务面分组能让工具选择的准确率提升 20% 以上尤其是在工具数量超过 15 个之后。另一个好处是权限管理。你可以按服务面授权比如允许文件服务面的读操作但禁止写操作允许命令服务面执行白名单内的命令但禁止任意命令。这种粒度比单个工具授权更实用因为用户通常关心的是“能不能改我的文件”而不是“能不能调用 write_file 这个函数”。3.2 服务面的组合与依赖服务面之间不是孤立的它们有依赖关系。比如“代码重构”这个任务可能需要文件服务面读代码、命令服务面跑测试、文件服务面写回修改。模型需要知道这些服务面可以组合使用。我的做法是在系统提示里明确列出可用的服务面及其能力但不强制规定组合方式。模型自己会规划先读、再改、再验证。如果某个服务面不可用模型应该能感知到并调整计划。比如没有命令服务面模型就不应该计划“跑测试验证”而应该改为“静态检查”。这里有个坑服务面的描述要准确不能夸大也不能遗漏。我见过一个实现把“网络请求”服务面描述成“可以访问任何 URL”结果模型真的去请求内网地址触发了安全告警。正确做法是明确列出允许的域名或协议让模型知道边界在哪里。3.3 服务面的扩展与热插拔好的架构应该支持服务面的热插拔。也就是说新增一个能力时不需要重启整个系统只需要注册一个新的服务面。这对实际使用很重要因为不同项目需要的能力不同。前端项目可能需要浏览器服务面后端项目可能需要数据库服务面运维项目可能需要容器服务面。实现热插拔的关键是接口标准化。每个服务面实现统一的注册接口提供名称、描述、工具列表、权限声明。核心调度器只依赖这个接口不依赖具体实现。这样新增服务面就像插一块积木即插即用。我自己的项目里服务面注册是通过配置文件驱动的。配置文件里写清楚要加载哪些服务面、每个服务面的参数比如命令白名单、允许的目录。启动时读取配置动态加载。这样换项目只需要换配置文件不用改代码。4. 外壳层终端交互的体验打磨4.1 外壳的职责不只是显示外壳层shell layer是用户直接接触的部分很多人以为它只是“把结果显示出来”。其实外壳的职责远不止于此它要处理输入解析、命令补全、历史记录、输出渲染、进度提示、中断处理。这些细节决定了用起来是“顺手”还是“别扭”。输入解析是第一个坎。用户在终端里输入的可能是一条自然语言指令也可能是一个斜杠命令还可能是一个文件路径。外壳需要准确区分。我的做法是以斜杠开头的当命令处理以 开头的当文件引用处理其他当自然语言处理。这样用户不用记复杂语法直觉操作就行。命令补全能大幅提升效率。当用户输入斜杠时弹出可用命令列表输入 时弹出当前目录的文件列表。补全不仅要快还要准。我见过一些实现补全时卡顿明显原因是每次按键都去扫描整个目录树。正确做法是缓存目录结构只在目录变化时刷新。4.2 输出渲染的取舍终端里的输出渲染是个技术活。纯文本最简单但信息密度低。Markdown 渲染好看但终端支持有限。表格清晰但宽度受限。我的取舍是代码块用语法高亮普通文本用颜色区分表格用等宽对齐超宽内容自动换行。语法高亮能帮用户快速识别代码。终端里实现高亮不需要完整解析器简单的关键字匹配就够了。颜色区分要克制不要五颜六色。我一般只用三种颜色绿色表示成功红色表示错误黄色表示警告。其他信息用默认色。表格在终端里容易错位因为中英文字符宽度不同。我的做法是计算显示宽度而不是字符数中文算两个宽度英文算一个。这样对齐才准确。超宽内容自动换行但换行后要缩进保持可读性。提示终端宽度不是固定的用户可能随时调整窗口大小。外壳应该监听 SIGWINCH 信号动态调整输出宽度。这个细节很多实现都忽略了导致用户调整窗口后输出错乱。4.3 中断处理与状态恢复用户按 CtrlC 时外壳要正确处理。不能直接退出也不能让后台任务失控。我的做法是第一次 CtrlC 取消当前操作第二次 CtrlC 退出程序。取消操作时要清理临时文件、终止子进程、恢复终端状态。终端状态恢复很重要。如果程序在运行中修改了终端模式比如关闭回显退出时必须恢复。否则用户会发现终端“坏了”输入不显示。我一般用 try-finally 确保恢复逻辑一定执行即使程序崩溃。后台任务的清理也容易出问题。如果模型启动了一个长时间运行的命令用户中断后这个命令可能还在跑。外壳需要跟踪所有子进程中断时统一终止。我一般用进程组来管理启动时创建新进程组中断时向整个组发信号。5. 实战集成从单次对话到工作流5.1 集成到现有开发流程opencode 这类工具最大的价值不是单次对话而是集成到日常开发流程里。我自己的用法是把它当作一个“可编程的结对伙伴”而不是“问答机器人”。具体来说我会在几个场景固定使用写新功能时让它先生成骨架代码我再填充细节改 bug 时让它分析日志和堆栈给出可能原因重构时让它批量修改重复模式写测试时让它根据实现生成用例。这些场景的共同点是“有明确输入和输出”模型容易发挥。集成方式上我倾向于用命令行管道。比如把 git diff 的输出传给 opencode让它生成 commit message把测试失败输出传给它让它分析原因。这种管道方式灵活不依赖特定编辑器或 IDE。5.2 多轮对话的状态管理多轮对话是实战集成的核心。单次问答只能解决简单问题复杂任务需要多轮交互。状态管理的关键是保留必要上下文、丢弃无关信息、支持手动重置。保留必要上下文是指模型需要知道之前做了什么、结果如何。比如第一轮读了文件第二轮改文件模型需要记得文件内容。我的做法是把工具调用和结果都保留在上下文里但只保留最近 N 轮更早的做摘要。丢弃无关信息是指不要把整个终端历史都塞给模型。用户可能中间执行了无关命令这些不应该影响模型判断。我一般只保留与当前任务相关的工具调用记录。手动重置是指用户可以随时清空上下文重新开始。这在切换任务时很有用。我一般用/clear命令实现清空后模型回到初始状态。5.3 与版本控制的配合和版本控制配合是实战集成的亮点。我常用的几个模式生成 commit message、解释 diff、生成 changelog、冲突解决建议。生成 commit message 时把 staged 的 diff 传给模型让它用约定式提交格式生成。我一般会加一句“用中文不超过 50 字”这样生成的 message 简洁明了。解释 diff 时把两个版本的差异传给模型让它用自然语言描述改了什么、为什么改。这对 review 很有帮助尤其是别人写的代码。冲突解决建议时把冲突标记的文件传给模型让它给出合并建议。模型不一定能完全解决但能提供思路减少人工判断时间。注意传给模型的代码可能包含敏感信息。我一般会先过滤掉密钥、密码、内部地址等再传给模型。这个步骤不能省否则可能泄露敏感信息。6. 常见问题与排查技巧实录6.1 工具调用失败排查表现象可能原因排查方法解决方案工具不存在服务面未加载检查配置文件加载对应服务面参数错误模型理解偏差查看工具 schema补充参数说明权限拒绝未授权检查权限配置按需授权超时命令卡死查看进程状态调整超时或终止返回截断内容过长查看总长度分段获取编码乱码编码不匹配检查文件编码指定编码参数这个表是我从实际排查中总结的覆盖了 90% 以上的常见问题。遇到问题时按表排查基本能快速定位。6.2 模型“幻觉”工具的应对模型有时会调用不存在的工具或者用错误的参数格式。这是常见问题应对方法是在系统提示里明确列出可用工具、在工具调用失败时返回明确错误、在错误后引导模型重试。系统提示里列出工具时要包含名称、用途、参数说明。不要只写名称模型不知道用途就容易乱用。工具调用失败时错误信息要具体比如“工具 read_file 不存在可用工具read_file_v2、write_file”。这样模型能立即纠正。如果模型连续多次调用失败可以主动提示它“请检查工具名称和参数”。我实测下来这种主动引导能显著减少无效调用。6.3 性能优化的几个技巧性能问题主要体现在响应慢和 token 消耗大。我的优化技巧缓存常用结果、压缩上下文、并行调用独立工具。缓存常用结果是指读过的文件、列过的目录可以缓存一段时间。模型再次请求时直接返回缓存不用重新读。缓存要有过期策略文件修改后要失效。压缩上下文是指把长文本做摘要后再放入上下文。比如读了一个大文件不要全文保留只保留关键部分和摘要。这样能大幅减少 token 消耗。并行调用是指如果多个工具调用之间没有依赖可以同时发起。比如同时读三个文件比串行读快三倍。实现上要注意线程安全和结果顺序。6.4 安全使用的几条红线最后说几条安全红线都是我踩过坑总结的不执行未确认的写操作、不访问未授权的路径、不传输敏感信息、不运行未知来源的代码。不执行未确认的写操作是指模型生成的写文件、删文件、改配置等操作必须经过用户确认。我一般用交互式确认显示将要执行的操作让用户按 y 确认。不访问未授权的路径是指限制模型只能访问项目目录不能访问系统目录或用户主目录。这个通过路径白名单实现。不传输敏感信息是指传给模型的内容要过滤密钥、密码、token。我一般用正则匹配常见敏感模式匹配到就替换成占位符。不运行未知来源的代码是指模型生成的命令要在沙箱里执行限制网络访问和文件系统访问。这个通过容器或命名空间实现。这些红线看起来麻烦但一旦出事代价很大。我自己的原则是宁可多确认一次不要事后后悔。7. 我个人在实际集成中的体会用了一段时间之后我最大的体会是这类工具的价值不在于“替代人”而在于“放大人的能力”。它能把重复的、模式化的、需要查文档的工作自动化让人专注于真正需要判断力的部分。另一个体会是工具层的设计比模型能力更重要。同样的模型工具层设计得好完成率能差一倍以上。所以如果你在自建类似系统建议把 70% 的精力放在工具层和服务面上30% 放在提示词上。最后分享一个小技巧给模型加一个“思考”工具让它显式输出推理过程。这个工具不产生副作用只是把模型的思考记录下来。我实测下来加了思考工具后复杂任务的完成率明显提升因为模型“想清楚再动手”比“边想边做”更靠谱。

相关新闻

Wand-Enhancer 完整指南:3 步本地修改 app.asar,免费解锁 WeMod 专业版与手机远程控制

Wand-Enhancer 完整指南:3 步本地修改 app.asar,免费解锁 WeMod 专业版与手机远程控制

Wand-Enhancer 完整指南:3 步本地修改 app.asar,免费解锁 WeMod 专业版与手机远程控制 【免费下载链接】Wand-Enhancer Advanced UX and interoperability extension for Wand (WeMod) app 项目地址: https://gitcode.com/GitHub_Trending/we/Wand-Enh…

2026/10/11 6:07:02 阅读更多 →
SD-WAN全球智能组网 助企业降本增效实战指南

SD-WAN全球智能组网 助企业降本增效实战指南

在日常经营中,许多跨国企业的 IT 负责人都有过类似经历:海外分公司反馈内部系统卡顿,视频会议频繁掉线,而排查问题时往往需要跨越多个时区,协调不同的运营商,耗时耗力却难以根治。传统的专线方案虽然稳定&a…

2026/10/11 6:07:02 阅读更多 →
手把手:论文润色怎么保持学术语气不跑偏?一套可照做的操作流程

手把手:论文润色怎么保持学术语气不跑偏?一套可照做的操作流程

改到一半发现语气散了,是很多人做论文润色时才察觉的毛病。这篇把流程拆成六步:先立语气判据,再依次处理口语化、主观判断、断言强度、术语人称与整体复核。全程可借助知学术AIPaperGPT 的 AI 无限改稿完成,结尾给出免费智能大纲入…

2026/10/11 6:07:02 阅读更多 →

最新新闻

Motrix 仓库语言与文档规范:双语发布、公私边界与 Obsidian 文档网关实战

Motrix 仓库语言与文档规范:双语发布、公私边界与 Obsidian 文档网关实战

桌面应用网络后端 【免费下载链接】Motrix A full-featured download manager. 项目地址: https://gitcode.com/GitHub_Trending/mo/Motrix 点击查看 免费下载 本文围绕 Motrix 开源仓库的 .claude/rules/language-and-docs.md 规则文件展开,系统讲解该…

2026/10/11 11:39:11 阅读更多 →
CAN总线仲裁机制详解:从显性位到机器人关节ID分配实战

CAN总线仲裁机制详解:从显性位到机器人关节ID分配实战

1. 从一次关节抖动说起:为什么两个节点同时开口会出事如果你正在做机器人关节控制,大概率遇到过这种场景:一条CAN总线上挂着主控和好几个关节驱动器,主控周期性下发位置指令,某个关节驱动器同时上报状态反馈&#xff0…

2026/10/11 11:39:11 阅读更多 →
CAN总线八字节协议解析:关节电机控制帧与反馈帧实战指南

CAN总线八字节协议解析:关节电机控制帧与反馈帧实战指南

1. 为什么八字节值得单独拎出来讲搞机器人关节控制的人,绕不开CAN总线。但很多人第一次看到关节驱动器的通信协议文档时,脑子里冒出来的第一个问题往往是:八个字节,到底能装下什么?你想想,一个电机要控制的…

2026/10/11 11:39:11 阅读更多 →
RK3588三系统Ubuntu适配实战:22.04/24.04/26.04刷机与选型指南

RK3588三系统Ubuntu适配实战:22.04/24.04/26.04刷机与选型指南

1. 从一块RK3588开发板说起:为什么三系统适配值得单独聊手里有一块RK3588的开发板,第一件事做什么?绝大多数人的答案都是"刷个系统跑起来看看"。但真正上手之后你会发现,刷系统这件事远没有想象中那么"一次就好&qu…

2026/10/11 11:39:11 阅读更多 →
机器人关节CAN总线控制协议详解:8字节帧结构与通信层实现

机器人关节CAN总线控制协议详解:8字节帧结构与通信层实现

1. 从八个字节说起:为什么CAN协议是机器人关节控制的命脉搞机器人关节控制的人,绕不开一个东西——CAN总线。尤其是做协作机器人、四足机器人、外骨骼这类多关节协同的设备,几乎每个关节的驱动器都挂在同一条CAN总线上。你手里拿着主控板&…

2026/10/11 11:39:11 阅读更多 →
海康工业相机C# SDK开发实战:从示例工程到产线稳定取流

海康工业相机C# SDK开发实战:从示例工程到产线稳定取流

简介:这份资源是面向工业视觉方向C#开发者的海康工业相机SDK示例程序包,适合刚接触相机二次开发、需要快速跑通设备连接与图像采集流程的工程师与学习者。压缩包共29个文件,约518KB,以cs源码、sln与csproj工程文件、exe可执行程序…

2026/10/11 11:38:11 阅读更多 →

日新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 10:45:37 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 21:32:20 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 10:38:42 阅读更多 →