fix: sync outdated stub docs + integrate LSP closeAllFiles with compact
- Remove redundant fork:true and run_in_background params in /fork command - Integrate LSP closeAllFiles() into postCompactCleanup (memory leak #14) - Update 10 docs files: mark implemented features no longer as stubs Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
c982104476
commit
5a53d83ad5
|
|
@ -1,6 +1,6 @@
|
||||||
# `/autofix-pr` 命令实现规格文档
|
# `/autofix-pr` 命令实现规格文档
|
||||||
|
|
||||||
> **状态**:规划阶段(2026-04-29),等待评审通过后进入实施。
|
> **状态**:已实现(598 行代码 + 5 个测试文件)。
|
||||||
> **Worktree**:`E:\Source_code\Claude-code-bast-autofix-pr`,分支 `feat/autofix-pr`,基于 `origin/main` 4f1649e2。
|
> **Worktree**:`E:\Source_code\Claude-code-bast-autofix-pr`,分支 `feat/autofix-pr`,基于 `origin/main` 4f1649e2。
|
||||||
> **架构**:R(Remote-via-CCR),完整版(含 stop 子命令、单例锁、subscribePR、in-process teammate、skills 探测)。
|
> **架构**:R(Remote-via-CCR),完整版(含 stop 子命令、单例锁、subscribePR、in-process teammate、skills 探测)。
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
# BASH_CLASSIFIER — Bash 命令分类器
|
# BASH_CLASSIFIER — Bash 命令分类器
|
||||||
|
|
||||||
> Feature Flag: `FEATURE_BASH_CLASSIFIER=1`
|
> Feature Flag: `FEATURE_BASH_CLASSIFIER=1`
|
||||||
> 实现状态:bashClassifier.ts 全部 Stub,yoloClassifier.ts 完整实现可参考
|
> 实现状态:bashClassifier.ts 为 ANT-ONLY stub(需要 Anthropic 内部 API);开源版使用 yoloClassifier.ts (1496行) 作为完整替代方案
|
||||||
> 引用数:45
|
> 引用数:45
|
||||||
|
|
||||||
## 一、功能概述
|
## 一、功能概述
|
||||||
|
|
|
||||||
|
|
@ -90,7 +90,7 @@ export function isCoordinatorMode(): boolean {
|
||||||
|
|
||||||
文件:`src/coordinator/workerAgent.ts`
|
文件:`src/coordinator/workerAgent.ts`
|
||||||
|
|
||||||
当前为 stub。Worker 实际使用通用 AgentTool 的 `worker` subagent_type。
|
Worker 使用通用 AgentTool 的 `worker` subagent_type。工具过滤通过 `getWorkerTools()` 排除内部编排工具(TeamCreate/TeamDelete/SendMessage/SyntheticOutput)。
|
||||||
|
|
||||||
### 3.6 数据流
|
### 3.6 数据流
|
||||||
|
|
||||||
|
|
@ -147,5 +147,5 @@ CLAUDE_CODE_SIMPLE=1 bun run dev
|
||||||
| 文件 | 行数 | 职责 |
|
| 文件 | 行数 | 职责 |
|
||||||
|------|------|------|
|
|------|------|------|
|
||||||
| `src/coordinator/coordinatorMode.ts` | 370 | 模式检测 + 系统提示 + 用户上下文 |
|
| `src/coordinator/coordinatorMode.ts` | 370 | 模式检测 + 系统提示 + 用户上下文 |
|
||||||
| `src/coordinator/workerAgent.ts` | — | Worker agent 定义(stub) |
|
| `src/coordinator/workerAgent.ts` | 68 | Worker agent 定义(完整) |
|
||||||
| `src/constants/tools.ts` | — | `ASYNC_AGENT_ALLOWED_TOOLS` 工具白名单 |
|
| `src/constants/tools.ts` | — | `ASYNC_AGENT_ALLOWED_TOOLS` 工具白名单 |
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ Agent({ subagent_type: "general-purpose", prompt: "..." })
|
||||||
|
|
||||||
### /fork 命令
|
### /fork 命令
|
||||||
|
|
||||||
注册了 `/fork` 斜杠命令(当前为 stub)。当 FORK_SUBAGENT 开启时,`/branch` 命令失去 `fork` 别名,避免冲突。
|
注册了 `/fork` 斜杠命令。当 FORK_SUBAGENT 开启时,`/branch` 命令失去 `fork` 别名,避免冲突。
|
||||||
|
|
||||||
## 三、实现架构
|
## 三、实现架构
|
||||||
|
|
||||||
|
|
@ -192,4 +192,4 @@ FEATURE_FORK_SUBAGENT=1 bun run dev
|
||||||
| `packages/builtin-tools/src/tools/AgentTool/resumeAgent.ts` | — | Fork agent 恢复 |
|
| `packages/builtin-tools/src/tools/AgentTool/resumeAgent.ts` | — | Fork agent 恢复 |
|
||||||
| `src/constants/xml.ts` | — | XML 标签常量 |
|
| `src/constants/xml.ts` | — | XML 标签常量 |
|
||||||
| `src/utils/forkedAgent.ts` | — | CacheSafeParams + ContentReplacementState 克隆 |
|
| `src/utils/forkedAgent.ts` | — | CacheSafeParams + ContentReplacementState 克隆 |
|
||||||
| `src/commands/fork/index.ts` | — | /fork 命令(stub) |
|
| `src/commands/fork/index.ts` | — | /fork 命令 |
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
# MCP_SKILLS — MCP 技能发现
|
# MCP_SKILLS — MCP 技能发现
|
||||||
|
|
||||||
> Feature Flag: `FEATURE_MCP_SKILLS=1`
|
> Feature Flag: `FEATURE_MCP_SKILLS=1`
|
||||||
> 实现状态:功能性实现(config 门控筛选器完整,核心 fetcher 为 stub)
|
> 实现状态:完整实现(fetcher + 缓存 + 实时刷新 + 安全措施)
|
||||||
> 引用数:9
|
> 引用数:9
|
||||||
|
|
||||||
## 一、功能概述
|
## 一、功能概述
|
||||||
|
|
@ -86,7 +86,7 @@ const fetchMcpSkillsForClient = feature('MCP_SKILLS')
|
||||||
## 三、关键设计决策
|
## 三、关键设计决策
|
||||||
|
|
||||||
1. **Feature gate 隔离**:`feature('MCP_SKILLS')` 守护条件 `require()` 和所有调用点。关闭时无模块加载、无获取操作
|
1. **Feature gate 隔离**:`feature('MCP_SKILLS')` 守护条件 `require()` 和所有调用点。关闭时无模块加载、无获取操作
|
||||||
2. **资源到技能映射**:技能从 MCP 服务器的 `skill://` URI 资源中发现。`fetchMcpSkillsForClient` 负责转换(当前为 stub)
|
2. **资源到技能映射**:技能从 MCP 服务器的 `skill://` URI 资源中发现。`fetchMcpSkillsForClient` 负责转换(LRU 缓存,20 条目)
|
||||||
3. **循环依赖避免**:`mcpSkillBuilders.ts` 作为依赖图叶节点,避免 `client.ts ↔ mcpSkills.ts ↔ loadSkillsDir.ts` 循环
|
3. **循环依赖避免**:`mcpSkillBuilders.ts` 作为依赖图叶节点,避免 `client.ts ↔ mcpSkills.ts ↔ loadSkillsDir.ts` 循环
|
||||||
4. **服务器能力检查**:技能获取还需要 MCP 服务器支持 resources (`!!client.capabilities?.resources`)
|
4. **服务器能力检查**:技能获取还需要 MCP 服务器支持 resources (`!!client.capabilities?.resources`)
|
||||||
|
|
||||||
|
|
@ -105,8 +105,8 @@ FEATURE_MCP_SKILLS=1 bun run dev
|
||||||
|
|
||||||
| 文件 | 状态 | 需要实现 |
|
| 文件 | 状态 | 需要实现 |
|
||||||
|------|------|---------|
|
|------|------|---------|
|
||||||
| `src/skills/mcpSkills.ts` | Stub | `fetchMcpSkillsForClient()` — 从 MCP 资源列表中筛选 `skill://` URI 并转换为 Command 对象 |
|
| `src/skills/mcpSkills.ts` | 143 行 | `fetchMcpSkillsForClient()` — 从 MCP 资源列表中筛选 `skill://` URI 并转换为 Command 对象 |
|
||||||
| `src/skills/mcpSkillBuilders.ts` | Stub | 技能构建器注册(避免循环依赖) |
|
| `src/skills/mcpSkillBuilders.ts` | 45 行 | 技能构建器注册(避免循环依赖) |
|
||||||
|
|
||||||
## 六、文件索引
|
## 六、文件索引
|
||||||
|
|
||||||
|
|
@ -115,4 +115,4 @@ FEATURE_MCP_SKILLS=1 bun run dev
|
||||||
| `src/commands.ts:547-608` | 技能命令过滤 |
|
| `src/commands.ts:547-608` | 技能命令过滤 |
|
||||||
| `src/services/mcp/client.ts:117-2358` | 技能获取 + 缓存管理 |
|
| `src/services/mcp/client.ts:117-2358` | 技能获取 + 缓存管理 |
|
||||||
| `src/services/mcp/useManageMCPConnections.ts` | 实时刷新 |
|
| `src/services/mcp/useManageMCPConnections.ts` | 实时刷新 |
|
||||||
| `src/skills/mcpSkills.ts` | 核心转换逻辑(stub) |
|
| `src/skills/mcpSkills.ts` | 核心转换逻辑(完整实现) |
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
# WEB_BROWSER_TOOL — 浏览器工具
|
# WEB_BROWSER_TOOL — 浏览器工具
|
||||||
|
|
||||||
> Feature Flag: `FEATURE_WEB_BROWSER_TOOL=1`
|
> Feature Flag: `FEATURE_WEB_BROWSER_TOOL=1`
|
||||||
> 实现状态:核心工具已实现,面板为 Stub,布线完整
|
> 实现状态:核心工具已实现,面板故意为 null(结果在对话中内联显示)
|
||||||
> 引用数:4
|
> 引用数:4
|
||||||
|
|
||||||
## 一、功能概述
|
## 一、功能概述
|
||||||
|
|
@ -14,7 +14,7 @@ WEB_BROWSER_TOOL 让模型可以启动浏览器实例、导航网页、与页面
|
||||||
|
|
||||||
| 模块 | 文件 | 状态 |
|
| 模块 | 文件 | 状态 |
|
||||||
|------|------|------|
|
|------|------|------|
|
||||||
| 浏览器面板 | `packages/builtin-tools/src/tools/WebBrowserTool/WebBrowserPanel.ts` | **Stub** — 返回 null |
|
| 浏览器面板 | `packages/builtin-tools/src/tools/WebBrowserTool/WebBrowserPanel.ts` | **Null by design** — 结果内联显示,不需面板 |
|
||||||
| 浏览器工具 | `packages/builtin-tools/src/tools/WebBrowserTool/WebBrowserTool.ts` | **已实现** |
|
| 浏览器工具 | `packages/builtin-tools/src/tools/WebBrowserTool/WebBrowserTool.ts` | **已实现** |
|
||||||
| REPL 集成 | `src/screens/REPL.tsx` | **布线** — 渲染 WebBrowserPanel |
|
| REPL 集成 | `src/screens/REPL.tsx` | **布线** — 渲染 WebBrowserPanel |
|
||||||
| 工具注册 | `src/tools.ts` | **布线** — 动态加载 |
|
| 工具注册 | `src/tools.ts` | **布线** — 动态加载 |
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
# WORKFLOW_SCRIPTS — 工作流自动化
|
# WORKFLOW_SCRIPTS — 工作流自动化
|
||||||
|
|
||||||
> Feature Flag: `FEATURE_WORKFLOW_SCRIPTS=1`
|
> Feature Flag: `FEATURE_WORKFLOW_SCRIPTS=1`
|
||||||
> 实现状态:全部 Stub(7 个文件),布线完整
|
> 实现状态:已实现 — WorkflowTool (432行), LocalWorkflowTask (212行), WorkflowDetailDialog (103行), 含测试
|
||||||
> 引用数:10
|
> 引用数:10
|
||||||
|
|
||||||
## 一、功能概述
|
## 一、功能概述
|
||||||
|
|
|
||||||
|
|
@ -581,18 +581,11 @@ if (snipResult !== undefined) {
|
||||||
|
|
||||||
### 问题详情
|
### 问题详情
|
||||||
|
|
||||||
`LSPServerManager` 中的 `openedFiles: Map<string, string>` 追踪所有通过 `didOpen` 打开的文件。`closeFile()` 方法存在可以发送 `didClose` 通知并清理 Map 条目,但代码注释明确标注:
|
`LSPServerManager` 中的 `openedFiles: Map<string, string>` 追踪所有通过 `didOpen` 打开的文件。`closeAllFiles()` 方法已实现,在 compaction 后通过 `postCompactCleanup` 自动调用,释放所有 LSP 服务器端的文件状态。
|
||||||
|
|
||||||
```
|
### 修复方式(已完成)
|
||||||
NOTE: Currently available but not yet integrated with compact flow.
|
|
||||||
TODO: Integrate with compact - call closeFile() when compact removes files from context
|
|
||||||
```
|
|
||||||
|
|
||||||
长时间会话中,每次读取/编辑文件都会通过 `openFile()` 添加条目,但 compaction 不会清理这些条目,导致 Map 无限增长。
|
1. **`closeAllFiles()` 方法**(LSPServerManager.ts:414):遍历 `openedFiles` Map,对每个文件发送 `didClose` 通知,然后清空 Map。Best-effort 错误处理。
|
||||||
|
|
||||||
### 修复方式
|
|
||||||
|
|
||||||
1. **添加 `closeAllFiles()` 方法**:遍历 `openedFiles` Map,对每个文件发送 `didClose` 通知,然后清空 Map。Best-effort 错误处理。
|
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
async function closeAllFiles(): Promise<void> {
|
async function closeAllFiles(): Promise<void> {
|
||||||
|
|
@ -612,18 +605,16 @@ async function closeAllFiles(): Promise<void> {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
2. **集成到 `postCompactCleanup`**:在 compaction 后自动调用 `closeAllFiles()`,释放所有 LSP 服务器端的文件状态。
|
2. **集成到 `postCompactCleanup`**(已完成):在 compaction 后自动调用 `closeAllFiles()`,使用 fire-and-forget async 模式(与 sweepFileContentCache 一致)。
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
// postCompactCleanup.ts
|
// postCompactCleanup.ts — isMainThreadCompact guard
|
||||||
try {
|
void import('../lsp/manager.js')
|
||||||
const lspManager = getLspServerManager()
|
.then(m => {
|
||||||
if (lspManager) {
|
const manager = m.getLspServerManager()
|
||||||
await lspManager.closeAllFiles()
|
if (manager) return manager.closeAllFiles()
|
||||||
}
|
})
|
||||||
} catch {
|
.catch(error => { logError(error) })
|
||||||
// LSP module may not be available in all environments
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
@ -632,7 +623,7 @@ try {
|
||||||
|
|
||||||
```
|
```
|
||||||
确认已实现 (12): #1 图片 #2 /usage #3 进度消息 #4 空闲渲染 #5 虚拟滚动器 #6 管道输出 #10 MCP缓冲区
|
确认已实现 (12): #1 图片 #2 /usage #3 进度消息 #4 空闲渲染 #5 虚拟滚动器 #6 管道输出 #10 MCP缓冲区
|
||||||
已修复 (7): #7 语法加载 #8 NO_FLICKER #9 RC权限 #11 LRU缓存键 #12 snipCompact #17 LSP文件追踪 #18 Permission Polling
|
已修复 (8): #7 语法加载 #8 NO_FLICKER #9 RC权限 #11 LRU缓存键 #12 snipCompact #14 LSP compact集成 #17 LSP文件追踪 #18 Permission Polling
|
||||||
|
|
||||||
### 测试覆盖
|
### 测试覆盖
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
> 来源: [stub-recovery-design-1-4.md](../features/stub-recovery-design-1-4.md) 第 4 项
|
> 来源: [stub-recovery-design-1-4.md](../features/stub-recovery-design-1-4.md) 第 4 项
|
||||||
> 优先级: P3
|
> 优先级: P3
|
||||||
> 工作量: Phase 4A 中等,4A-4D 全做完很大
|
> 工作量: Phase 4A 中等,4A-4D 全做完很大
|
||||||
> 状态: Phase 4A DONE, 4B-4D TODO
|
> 状态: Phase 4A-4D 全部实现 (src/assistant/ 350行, src/commands/assistant/ 完整)
|
||||||
|
|
||||||
## 目标
|
## 目标
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -39,23 +39,16 @@ export async function call(
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Reuse AgentTool logic for fork path.
|
// Omitting subagent_type triggers the fork path in AgentTool:
|
||||||
// Omitting subagent_type triggers implicit fork.
|
// isForkSubagentEnabled() && !subagent_type → fork routing → inherits
|
||||||
|
// parent context + system prompt + model + tools.
|
||||||
|
// run_in_background is omitted: when fork gate is on, all agents are
|
||||||
|
// forced async via forceAsync flag (the param is removed from schema).
|
||||||
const input = {
|
const input = {
|
||||||
prompt: directive,
|
prompt: directive,
|
||||||
fork: true, // 触发 AgentTool 的 fork 路径:继承父会话上下文 + system prompt + 模型
|
|
||||||
run_in_background: true, // fork always runs async
|
|
||||||
// description 只显示在底部 selector / BackgroundTasksDialog,保持简短标签
|
|
||||||
// 即可;用户输入的 prompt 会作为第一条用户消息呈现在主视图里,这里不要
|
|
||||||
// 重复显示。
|
|
||||||
description: 'forked from main',
|
description: 'forked from main',
|
||||||
};
|
};
|
||||||
|
|
||||||
// Call AgentTool with proper parameters:
|
|
||||||
// - input: the agent parameters (no subagent_type => fork path)
|
|
||||||
// - toolUseContext: the current context (ToolUseContext)
|
|
||||||
// - canUseTool: permission-check function from context
|
|
||||||
// - assistantMessage: the last assistant message to fork from
|
|
||||||
AgentTool.call(input, context, context.canUseTool!, lastAssistantMessage).catch(error => {
|
AgentTool.call(input, context, context.canUseTool!, lastAssistantMessage).catch(error => {
|
||||||
logForDebugging(`Fork subagent async error: ${error}`, { level: 'error' });
|
logForDebugging(`Fork subagent async error: ${error}`, { level: 'error' });
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -99,6 +99,22 @@ export function runPostCompactCleanup(querySource?: QuerySource): void {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
clearSessionMessagesCache()
|
clearSessionMessagesCache()
|
||||||
|
|
||||||
|
// Memory leak #14: Release LSP server file tracking state.
|
||||||
|
// closeAllFiles() sends didClose for every tracked file and clears the Map.
|
||||||
|
// Next file access re-opens only what's needed, preventing unbounded growth
|
||||||
|
// in long sessions. Fire-and-forget: best-effort release, non-blocking.
|
||||||
|
if (isMainThreadCompact) {
|
||||||
|
void import('../lsp/manager.js')
|
||||||
|
.then(m => {
|
||||||
|
const manager = m.getLspServerManager()
|
||||||
|
if (manager) return manager.closeAllFiles()
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
logError(error)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
for (const cb of compactCleanupCallbacks) {
|
for (const cb of compactCleanupCallbacks) {
|
||||||
try {
|
try {
|
||||||
cb()
|
cb()
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user