# 功能对照:实现了什么,还有什么没实现 > 对照对象:`2026-ai-assistant-feature-matrix.md`(2026 主流 AI 个人助理 / Agent 功能对照调研) > 对照方式:逐条到代码里查符号,不凭记忆。生成这份表的脚本是 `scripts/audit-against-research.mjs`,可重跑。 > 结论:**19 条建议里,已实现 10、部分 5、未实现 4**。 --- ## 一、必须有的(入场券) | # | 建议 | 状态 | 证据 | |---|---|---|---| | 1 | 记忆是用户可读可改的对象 | **已实现** | 记忆落成 `$DSH_HOME$DSH_HOME/bot/memory/` 下的 `.md` 文件,面板读的是同一棵树;`MEMORY.md` 的存在本身就是「这一层是记忆」的声明 | | 2 | 记忆随对话实时写入 | **已实现** | `appendMemoryEntry` 在工具调用时立即落盘,没有「对话结束后总结」这个阶段 | | 3 | 记忆有时效语义与过期处理 | **已实现** | `entryAgeDays` + `staleDays`,用 `-1` 表示无法判定——UNKNOWN 不参与比较 | | 4 | 定时 + 事件统一成 Trigger/Condition/Action | **部分** | 定时走 `repeat`,主动走 `AUTONOMY_CONDITIONS`(4 个可检查条件);**两者还没有合成同一个建任务表单** | | 5 | 审批是一等的任务状态 | **已实现** | `TASK_STATES` 里有 `awaiting`,是合法的中间态而不是错误分支 | | 6 | 一键豁免 | **已实现** | `waiverCovers`:只匹配完全相同的工具名,**永远带过期时间**,且不覆盖 `refused` | | 7 | 远程执行,端休眠也照跑 | **未实现** | 执行器跑在 Host 进程里。**这是本机插件的结构性限制**,不是遗漏 | | 8 | 敏感信息分级(默认排除+显式打开+逐条提示+不回溯) | **部分** | 前两项有(`MEMORY_SENSITIVE_MODES` 三档 + `MEMORY_FORBIDDEN_PATTERNS` 硬底线)。**「逐条提示」做成了拒绝而不是询问,「不回溯」语义未在界面里说明** | ## 二、拉开差距的 | # | 建议 | 状态 | 证据 | |---|---|---|---| | 9 | 周期工作可选「续跑」或「另起独立任务」 | **已实现** | `task.continuity`:`continue` 带上上次结论,`fresh` 从零开始 | | 10 | 配置传播语义写清楚 | **未实现** | 代码里的语义是明确的(任务创建时冻结 model / permission,改标题或备注会撤销批准),**但没有任何一处文档把它讲出来**。做对和说清楚是两件事 | | 11 | 知识库容量自动在 in-context 与检索间切换 | **未实现** | 没有向量库。记忆按文件分层进上下文(根文件常驻、子目录只贡献名字和描述),**但没有自动切换** | | 12 | 复用 MCP 而不是自造连接器层 | **已实现** | MCP 客户端 + 用户自填地址;工具名沿用 `mcp__服务器__工具` 的通行约定,**从别的客户端复制过来即可用**。已用独立进程的真实 server 端到端验证 | | 13 | 本地操作分两档:文件夹级 + 每条命令 Allow Once/Always Allow | **部分** | 文件夹级(工作区)+ 停下并展示**完整工具名和参数**都有。**「批准并继续执行」这条路在本次审计中发现是断的,已修**(见下) | | 14 | 浏览器分清本地(带登录态)与云端(隔离) | **未实现** | 没有浏览器集成。DSH 自带的浏览器插件是会话级的,不是 dot 常驻的 | | 15 | 常驻入口:不打开界面也能派活 | **部分** | 有入站连接(Telegram 长轮询 + HTTP 端点,带大小上限与来源标注)。**没有专属邮箱这种零成本入口** | | 16 | 执行环境当产品决策(临时沙箱/持久云机/本机三档) | **部分** | 本机 + 每实例工作区有;**没有临时沙箱与持久云机的区分**(依赖第 7 条的缺失) | ## 三、明确不要做的(已避免) | # | 建议 | 状态 | 证据 | |---|---|---|---| | 17 | 不做「纯记录 + 检索」当核心价值 | **已避免** | 核心是可执行工具(bash / pwsh / vdesk / MCP),记忆是附带的状态 | | 18 | 不把长期记忆当免费能力 | **已避免** | 召回条数、提示里回放的轮数、记忆总量都是可调限额,默认值集中在一处 | | 19 | 不把主动能力用「无需监督」来营销 | **已避免** | 自主时间默认关闭,且它自己的权限默认是 `read`;而且现在没有条件成立就不会动 | --- ## 四、功能矩阵的「能力维度」逐项 | 维度 | 状态 | 说明 | |---|---|---| | 定时任务 | 有 | `repeat`:hour / day / week,可钉时刻 | | 事件触发 | 有 | 4 个可检查条件 + 入站连接 | | 主动提醒 | 有 | 日程到点经连接器发出 | | 长期记忆 | 有 | 文件树,根文件常驻上下文 | | 第三方集成 | 有 | MCP 客户端,用户自填 | | 文件操作 | 有 | 工作区内读写,边界可判定 | | 审批机制 | 有 | `awaiting` 状态 + waiver + 完整参数展示 | | 浏览器操作 | 无 | 未接入 | | 语音 | 无 | 未做 | | 跨设备 | 无 | 本机单点 | --- ## 五、本次审计发现并修好的一个真缺陷 **批准是死循环。** `resolveParkedTask(id, "accept")` 会把任务放回队列并置 `approved = true`——这部分是对的。但**执行器重跑时,同一个边界会再次拦下它**,因为 `guarded` 分支只看 `mode !== "full"`,**没有看 `task.approved`**。 后果不是「多问一次」那么轻:用户看到的是**一模一样的问题**,他会以为自己那次点击没生效。而实际上它生效了,只是没有任何地方记得这件事。 修法是让批准参与判断: ```js if (boundary.decision === "guarded" && mode !== "full" && task.approved !== true) { ``` 理由写在代码注释里:**批准是「这一次可以」,不是「我问过一次了」。** **这个缺陷是审计逼出来的**——静态查符号查不出它,是把「approve 之后会发生什么」这条链读完才发现的。**所以第 13 条从「已实现」降级成了「部分」,而不是反过来。** --- ## 六、未实现的四项,各自的理由 **远程执行(#7)**:本机插件没有云端,这是结构性的,不是待办。 **配置传播语义没写出来(#10)**:代码里的语义是明确的、也是对的——任务创建时冻结 model 和 permission,改标题或备注会撤销批准。**缺的只是把它写出来。** 这是纯粹的文字工作,也是四项里唯一可以立刻做完的。 **in-context/RAG 自动切换(#11)**:没有向量库,而且**在记忆规模到达阈值前,引入 RAG 只会增加一个更不可解释的层**。当前的分层(根文件常驻 + 子目录只贡献描述)是同一问题的另一种解法,明确接受它的规模上限。 **浏览器分本地/云端(#14)**:依赖云端,同 #7。 **四项里有两项是同一个根因**:这是个本机插件。**它们应该被写成取舍,而不是欠账。** 另两项(#10 和 #11)中的 #10 是可以马上补的。 --- ## 七、五处「部分」,具体差在哪 | # | 差的那一步 | |---|---| | 4 | 定时和事件是两套入口,没有统一的 Trigger/Condition/Action 表单 | | 8 | 敏感条目被**拒绝**而不是被**询问**;「不回溯」只在实现层面成立,界面没说 | | 13 | 文件夹级与每条命令两档都有,**批准后的续跑本次才修** | | 15 | 有连接器入口,没有专属邮箱 | | 16 | 只有「本机」这一档 | **这五项都不是重活**——第 4、8 更接近「把已经做对的事说清楚」,第 15 需要一个人力入口,第 16 依赖云。