Merge 5a53d83ad5 into 83e891d7b2
This commit is contained in:
commit
03a41d19e3
|
|
@ -1,6 +1,6 @@
|
|||
# `/autofix-pr` 命令实现规格文档
|
||||
|
||||
> **状态**:规划阶段(2026-04-29),等待评审通过后进入实施。
|
||||
> **状态**:已实现(598 行代码 + 5 个测试文件)。
|
||||
> **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 探测)。
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# BASH_CLASSIFIER — Bash 命令分类器
|
||||
|
||||
> Feature Flag: `FEATURE_BASH_CLASSIFIER=1`
|
||||
> 实现状态:bashClassifier.ts 全部 Stub,yoloClassifier.ts 完整实现可参考
|
||||
> 实现状态:bashClassifier.ts 为 ANT-ONLY stub(需要 Anthropic 内部 API);开源版使用 yoloClassifier.ts (1496行) 作为完整替代方案
|
||||
> 引用数:45
|
||||
|
||||
## 一、功能概述
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ export function isCoordinatorMode(): boolean {
|
|||
|
||||
文件:`src/coordinator/workerAgent.ts`
|
||||
|
||||
当前为 stub。Worker 实际使用通用 AgentTool 的 `worker` subagent_type。
|
||||
Worker 使用通用 AgentTool 的 `worker` subagent_type。工具过滤通过 `getWorkerTools()` 排除内部编排工具(TeamCreate/TeamDelete/SendMessage/SyntheticOutput)。
|
||||
|
||||
### 3.6 数据流
|
||||
|
||||
|
|
@ -147,5 +147,5 @@ CLAUDE_CODE_SIMPLE=1 bun run dev
|
|||
| 文件 | 行数 | 职责 |
|
||||
|------|------|------|
|
||||
| `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` 工具白名单 |
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ Agent({ subagent_type: "general-purpose", prompt: "..." })
|
|||
|
||||
### /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 恢复 |
|
||||
| `src/constants/xml.ts` | — | XML 标签常量 |
|
||||
| `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 技能发现
|
||||
|
||||
> Feature Flag: `FEATURE_MCP_SKILLS=1`
|
||||
> 实现状态:功能性实现(config 门控筛选器完整,核心 fetcher 为 stub)
|
||||
> 实现状态:完整实现(fetcher + 缓存 + 实时刷新 + 安全措施)
|
||||
> 引用数:9
|
||||
|
||||
## 一、功能概述
|
||||
|
|
@ -86,7 +86,7 @@ const fetchMcpSkillsForClient = feature('MCP_SKILLS')
|
|||
## 三、关键设计决策
|
||||
|
||||
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` 循环
|
||||
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/mcpSkillBuilders.ts` | Stub | 技能构建器注册(避免循环依赖) |
|
||||
| `src/skills/mcpSkills.ts` | 143 行 | `fetchMcpSkillsForClient()` — 从 MCP 资源列表中筛选 `skill://` URI 并转换为 Command 对象 |
|
||||
| `src/skills/mcpSkillBuilders.ts` | 45 行 | 技能构建器注册(避免循环依赖) |
|
||||
|
||||
## 六、文件索引
|
||||
|
||||
|
|
@ -115,4 +115,4 @@ FEATURE_MCP_SKILLS=1 bun run dev
|
|||
| `src/commands.ts:547-608` | 技能命令过滤 |
|
||||
| `src/services/mcp/client.ts:117-2358` | 技能获取 + 缓存管理 |
|
||||
| `src/services/mcp/useManageMCPConnections.ts` | 实时刷新 |
|
||||
| `src/skills/mcpSkills.ts` | 核心转换逻辑(stub) |
|
||||
| `src/skills/mcpSkills.ts` | 核心转换逻辑(完整实现) |
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# WEB_BROWSER_TOOL — 浏览器工具
|
||||
|
||||
> Feature Flag: `FEATURE_WEB_BROWSER_TOOL=1`
|
||||
> 实现状态:核心工具已实现,面板为 Stub,布线完整
|
||||
> 实现状态:核心工具已实现,面板故意为 null(结果在对话中内联显示)
|
||||
> 引用数: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` | **已实现** |
|
||||
| REPL 集成 | `src/screens/REPL.tsx` | **布线** — 渲染 WebBrowserPanel |
|
||||
| 工具注册 | `src/tools.ts` | **布线** — 动态加载 |
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# WORKFLOW_SCRIPTS — 工作流自动化
|
||||
|
||||
> Feature Flag: `FEATURE_WORKFLOW_SCRIPTS=1`
|
||||
> 实现状态:全部 Stub(7 个文件),布线完整
|
||||
> 实现状态:已实现 — WorkflowTool (432行), LocalWorkflowTask (212行), WorkflowDetailDialog (103行), 含测试
|
||||
> 引用数: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()` 方法**:遍历 `openedFiles` Map,对每个文件发送 `didClose` 通知,然后清空 Map。Best-effort 错误处理。
|
||||
1. **`closeAllFiles()` 方法**(LSPServerManager.ts:414):遍历 `openedFiles` Map,对每个文件发送 `didClose` 通知,然后清空 Map。Best-effort 错误处理。
|
||||
|
||||
```typescript
|
||||
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
|
||||
// postCompactCleanup.ts
|
||||
try {
|
||||
const lspManager = getLspServerManager()
|
||||
if (lspManager) {
|
||||
await lspManager.closeAllFiles()
|
||||
}
|
||||
} catch {
|
||||
// LSP module may not be available in all environments
|
||||
}
|
||||
// postCompactCleanup.ts — isMainThreadCompact guard
|
||||
void import('../lsp/manager.js')
|
||||
.then(m => {
|
||||
const manager = m.getLspServerManager()
|
||||
if (manager) return manager.closeAllFiles()
|
||||
})
|
||||
.catch(error => { logError(error) })
|
||||
```
|
||||
|
||||
---
|
||||
|
|
@ -632,7 +623,7 @@ try {
|
|||
|
||||
```
|
||||
确认已实现 (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 项
|
||||
> 优先级: P3
|
||||
> 工作量: 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 {
|
||||
// Reuse AgentTool logic for fork path.
|
||||
// Omitting subagent_type triggers implicit fork.
|
||||
// Omitting subagent_type triggers the fork path in AgentTool:
|
||||
// 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 = {
|
||||
prompt: directive,
|
||||
fork: true, // 触发 AgentTool 的 fork 路径:继承父会话上下文 + system prompt + 模型
|
||||
run_in_background: true, // fork always runs async
|
||||
// description 只显示在底部 selector / BackgroundTasksDialog,保持简短标签
|
||||
// 即可;用户输入的 prompt 会作为第一条用户消息呈现在主视图里,这里不要
|
||||
// 重复显示。
|
||||
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 => {
|
||||
logForDebugging(`Fork subagent async error: ${error}`, { level: 'error' });
|
||||
});
|
||||
|
|
|
|||
|
|
@ -99,6 +99,22 @@ export function runPostCompactCleanup(querySource?: QuerySource): void {
|
|||
})
|
||||
}
|
||||
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) {
|
||||
try {
|
||||
cb()
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user