8.5 KiB
8.5 KiB
Findings & Decisions: 用户输入历史 MCP
Requirements
- 新增一个专用 ccweb MCP,只读返回用户输入内容列表。
- 可指定目标对话;未指定时默认当前来源对话。
- 默认返回最近 15 次用户输入。
- 所有返回输入正文合计最多 1000 个 Unicode 字符,并明确标记截断或仍有更早内容。
- 引导表单提交后插入为普通用户消息的内容必须包含在内。
- 结果供 LLM 回看用户要求、作为实现验收参考。
Research Findings
- 当前暴露的
ccweb_list_conversations只返回会话元数据,明确不返回对话正文。 - 当前 ccweb MCP 工具清单没有读取会话用户输入历史的工具。
- 仓库已有其他活跃计划,当前任务使用
.planning/user-input-history-mcp/隔离,避免覆盖根目录或其他任务计划。 - Trellis 开发者身份已初始化为
shiyue;共享.trellis/.current-task指向其他任务,因此本任务不覆盖该共享指针。 - codebase-memory 项目
home-cc-web索引状态为ready(6308 nodes / 14349 edges),可直接用于函数级定位。 - 第二次独立计划审查已通过,契约足以进入代码研究与实施。
- MCP 公共工具定义集中在
lib/ccweb-mcp-server.js的TOOLS;现有ccweb_list_conversations、ccweb_prompt_user均在此声明 schema。 - 内部 MCP 分派入口是
server.js的callInternalMcpTool(tool, args, sourceSessionId, sourceHopCount),现有列表工具转到listConversationSummaries。 listConversationSummaries已提供来源会话清洗、limit clamp、会话文件枚举和运行状态等可复用模式;正文读取应另建只读函数,避免扩大摘要接口职责。- 引导表单链路关键函数为
createCcwebPromptUser、handleCcwebPromptUserResponse、buildCcwebPromptUserResponseText;需读取精确源码确认提交内容最终是否由普通handleMessage持久化为role=user。 - 已确认引导表单提交链路:
handleCcwebPromptUserResponse用buildCcwebPromptUserResponseText生成问题/选择/答案正文,再调用普通handleMessage(..., { emitUserMessage: true });因此提交结果会成为普通role=user消息,新工具只按角色筛选即可自然纳入。 - 待填写的引导卡本身是
role=assistant且携带ccwebPrompt,必须排除;只有用户提交后的普通消息才应返回。 loadSession(id)已是统一、安全的会话 JSON 读取入口,包含 ID 清洗、大小限制、会话规范化和运行时线程索引更新;新查询不应自行读文件。- 公共 MCP
tools/list读取lib/ccweb-mcp-server.js的TOOLS,共享 HTTP/JSON-RPC 调用经handleMcpJsonRpcMessage与isCallableToolName进入callInternalMcpTool。 isCallableToolName会自动接受所有TOOLS中的公开工具;新增工具无需维护额外 allowlist。CODEX_APP_COMMUNICATION_TOOL_NAMES只控制旧 dynamic-tool 兼容集,是否纳入需结合兼容路径调用点判断。- 现有回归函数
assertCcwebListConversationsScopeContract同时断言正式 MCP schema、兼容工具定义和内部分派源码;新工具应补同等级 schema/route 契约,并通过内部 MCP HTTP 做数据行为验证。 server.js的 composer 候选和共享 MCPtools/list都直接展开CCWEB_MCP_TOOLS,因此加入TOOLS后会自动出现在/MCP mention 与正式 MCP 列表中。- 旧 Codex App dynamic-tool 兼容路径由
CODEX_APP_COMMUNICATION_TOOL_NAMES精确筛选,并最终仍调用同一个callInternalMcpTool。新工具与ccweb_list_conversations同属只读会话通信能力,应纳入该兼容集合;正式 MCP 仍是主路径。 - 测试编写阶段检查工作区时,仅本任务计划/Trellis 文件与测试代理临时清单为新增文件,尚无生产代码改动或与用户既有改动冲突。
- 新增聚焦测试
scripts/ccweb-list-user-inputs-unit.js,覆盖正式 schema、JSON-RPC/旧内部路由、默认/指定会话、15 条、角色筛选、引导提交、Unicode 总预算、错误码与只读性。 - 首次执行按预期失败:公开
TOOLS尚无新工具,调用返回unknown_tool;只读 fixture hash/mtime 断言已独立通过,说明红灯指向缺失实现而非测试环境破坏。 - 主审阅发现初版测试有两处需修正:禁止覆盖
HOME;提交表单正文会合法包含表单标题,排除未提交卡应按角色/消息 ID 断言。 - codebase-memory 一次搜索误报项目未索引,但随后的
list_projects/index_status显示home-cc-web仍为 ready(6387 nodes / 14484 edges),属于瞬时查询异常,无需重建索引。 - codebase-memory 收敛重试又返回
Transport closed,已按降级规则停用本轮该查询并改用本地rg/sed;定位范围仅限sanitizeId、truncateTextValue、normalizeSession。 - 测试代理已移除 HOME 覆盖、改用消息 ID 排除未提交引导卡,并增加临时目录清理;复跑仍只因
unknown_tool/缺失 schema 失败。 - 生产实现新增
listUserInputHistory,使用loadSession只读筛选role=user,从最新向前分配 Unicode code point 总预算,再按旧到新返回。 - 正式
TOOLS、Codex App 旧兼容集合和callInternalMcpTool已统一注册ccweb_list_user_inputs,没有第二套实现。 - 主线程与实现代理在交接边界发生一次 apply_patch 上下文冲突;补丁工具安全拒绝覆盖,最终 diff 仅包含代理的目标改动,无丢失或重复代码。
- 语法检查和聚焦测试全部通过,包含 fixture 文件 hash/mtime 不变断言。
- 既有
ccweb-message-reply-unit通过,说明新增 fallback 工具未破坏统一发送/旧别名契约。 - 完整
npm run regression在约 37 秒内通过;git diff --check无空白或补丁格式问题。 - 独立 Trellis 质量审查已通过,无阻断问题;补强了空会话、预算恰好用满(有/无更早输入)和运行时 clamp 测试,复跑通过。
- 运行态检查发现除当前对话外,
63b18af6-1b9a-4ad0-8627-f2b5ba22fc39仍为 running;按仓库运维规则不得重启 cc-web,因此当前进程尚未加载新 MCP,需待其他对话空闲后重启。
Finalized Query Semantics
conversationId:显式传入则读取该会话;缺省才回退到来源会话。显式无效 ID 不得静默回退。limit:默认 15,允许 1–50;先从全部非空role=user文本中取最近 N 条。maxChars:默认 1000,允许 1–1000;以 JavaScript Unicode code point(Array.from)计数,约束所有返回content合计。- 预算分配:从最新候选向更早候选分配;遇到剩余预算不足时保留该消息开头并标记
truncated=true,更早候选不再返回;最后按旧到新排序。 hasMore=true:存在 limit 之外的更早用户输入,或字数预算截断/省略了候选。- 空白/空正文 user 消息不作为“内容”返回;引导表单提交正文是非空普通 user 消息,因此自然包含。
- 缺少来源会话返回
missing_source_conversation;显式无效 ID 返回invalid_conversation_id;会话不存在返回conversation_not_found。 - 返回项包含
messageId|null、createdAt|null、content、contentChars、originalChars、truncated;顶层包含会话 ID、limit/maxChars、总字符数、返回数与hasMore。 - Trellis backend 规范目前大多是占位内容;本改动不涉及“部分 JSON 预览”专项规则。实现应沿用现有
loadSession、mcpToolError和scripts/regression.js的实际项目惯例。 - 已创建隔离 Trellis 任务
.trellis/tasks/08-17-user-input-history-mcp/并写入完整 PRD;因共享 current task 属于其他工作,本任务不改写.trellis/.current-task。
Technical Decisions
| Decision | Rationale |
|---|---|
| 工具采用只读查询 | 不应改变会话、消息或运行状态 |
| 当前会话默认值由 MCP 服务的来源会话上下文解析 | 与已有跨会话工具的线程级来源语义保持一致 |
| 返回最近 N 条后再按旧到新输出 | 查询高效,同时方便 LLM 顺序理解需求演进 |
| 1000 字作为整体硬预算,从最新输入向前填充 | 限制最坏上下文体积并优先保留最新验收要求 |
Issues Encountered
| Issue | Resolution |
|---|---|
| “最多 1000 字”存在逐条或整体预算歧义 | 独立计划审查后选择更保守的整体硬预算,并增加截断/更多标记 |
Resources
.trellis/workflow.mdAGENTS.md中 ccweb MCP 与线程级来源上下文约定