Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/features/autofix-pr.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# `/autofix-pr` 命令实现规格文档

> **状态**:规划阶段(2026-04-29),等待评审通过后进入实施
> **状态**:已实现(598 行代码 + 5 个测试文件)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

“已实现”状态与后文待办清单冲突。

Line 3 标记为已实现,但 Line 677-695 与 Line 729-737 仍是未完成清单格式,读者会误判当前真实状态。建议将这些清单改为“已完成记录”或补充“历史计划”说明。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/features/autofix-pr.md` at line 3, The README currently marks the
feature as "状态:已实现" while later checkbox lists still look like outstanding
TODOs; update the header label "状态:已实现" (the top-status line) to something that
matches the later checklist context—either "已完成记录 / 历史计划" or "部分已实现(见下方历史计划)"
and convert the checklist items in the sections currently formatted as pending
TODOs into completed entries (e.g., change unchecked boxes to checked or add a
"已完成" prefix) or add a clear "历史计划" note above those lists so readers understand
they are historical records rather than open tasks. Ensure you update the exact
string "状态:已实现" and the checklist lines that use the TODO checkbox format to
keep wording consistent.

> **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 探测)。

Expand Down
2 changes: 1 addition & 1 deletion docs/features/bash-classifier.md
Original file line number Diff line number Diff line change
@@ -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

## 一、功能概述
Expand Down
4 changes: 2 additions & 2 deletions docs/features/coordinator-mode.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 数据流

Expand Down Expand Up @@ -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` 工具白名单 |
4 changes: 2 additions & 2 deletions docs/features/fork-subagent.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Agent({ subagent_type: "general-purpose", prompt: "..." })

### /fork 命令

注册了 `/fork` 斜杠命令(当前为 stub)。当 FORK_SUBAGENT 开启时,`/branch` 命令失去 `fork` 别名,避免冲突。
注册了 `/fork` 斜杠命令。当 FORK_SUBAGENT 开启时,`/branch` 命令失去 `fork` 别名,避免冲突。

## 三、实现架构

Expand Down Expand Up @@ -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 命令 |
10 changes: 5 additions & 5 deletions docs/features/mcp-skills.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# MCP_SKILLS — MCP 技能发现

> Feature Flag: `FEATURE_MCP_SKILLS=1`
> 实现状态:功能性实现(config 门控筛选器完整,核心 fetcher 为 stub
> 实现状态:完整实现(fetcher + 缓存 + 实时刷新 + 安全措施
> 引用数:9

## 一、功能概述
Expand Down Expand Up @@ -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`)

Expand All @@ -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 行 | 技能构建器注册(避免循环依赖) |

Comment thread
coderabbitai[bot] marked this conversation as resolved.
## 六、文件索引

Expand All @@ -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` | 核心转换逻辑(完整实现) |
4 changes: 2 additions & 2 deletions docs/features/web-browser-tool.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# WEB_BROWSER_TOOL — 浏览器工具

> Feature Flag: `FEATURE_WEB_BROWSER_TOOL=1`
> 实现状态:核心工具已实现,面板为 Stub,布线完整
> 实现状态:核心工具已实现,面板故意为 null(结果在对话中内联显示)
Comment thread
coderabbitai[bot] marked this conversation as resolved.
> 引用数:4

## 一、功能概述
Expand All @@ -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` | **布线** — 动态加载 |
Expand Down
2 changes: 1 addition & 1 deletion docs/features/workflow-scripts.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# WORKFLOW_SCRIPTS — 工作流自动化

> Feature Flag: `FEATURE_WORKFLOW_SCRIPTS=1`
> 实现状态:全部 Stub(7 个文件),布线完整
> 实现状态:已实现 — WorkflowTool (432行), LocalWorkflowTask (212行), WorkflowDetailDialog (103行), 含测试
Comment thread
coderabbitai[bot] marked this conversation as resolved.
> 引用数:10

## 一、功能概述
Expand Down
33 changes: 12 additions & 21 deletions docs/memory-leak-audit.md
Original file line number Diff line number Diff line change
Expand Up @@ -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> {
Expand All @@ -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) })
```

---
Expand All @@ -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

### 测试覆盖

Expand Down
2 changes: 1 addition & 1 deletion docs/task/task-004-assistant-session-attach.md
Original file line number Diff line number Diff line change
Expand Up @@ -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/ 完整)
Comment thread
coderabbitai[bot] marked this conversation as resolved.

## 目标

Expand Down
17 changes: 5 additions & 12 deletions src/commands/fork/fork.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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' });
});
Expand Down
16 changes: 16 additions & 0 deletions src/services/compact/postCompactCleanup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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')
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Use src/* alias for the dynamic import on Line 108.

This new relative import path should follow the repo alias convention for source imports.

Suggested change
-    void import('../lsp/manager.js')
+    void import('src/services/lsp/manager.js')

As per coding guidelines, "Import paths must use the src/* alias (e.g., import { ... } from 'src/utils/...'); tsconfig maps src/* to ./src/*."

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
void import('../lsp/manager.js')
void import('src/services/lsp/manager.js')
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/services/compact/postCompactCleanup.ts` at line 108, Replace the relative
dynamic import path used in the expression void import('../lsp/manager.js') with
the repo alias form: use void import('src/lsp/manager.js') so it follows the
tsconfig src/* mapping; update the import expression in postCompactCleanup.ts
where the dynamic import of manager.js occurs to use the 'src/...' alias.

.then(m => {
const manager = m.getLspServerManager()
if (manager) return manager.closeAllFiles()
})
.catch(error => {
logError(error)
})
}

for (const cb of compactCleanupCallbacks) {
try {
cb()
Expand Down
Loading