Skip to content
Open
Show file tree
Hide file tree
Changes from 30 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
bcea35f
feat: implement skills management system with UI and backend integration
Jan 8, 2026
586c50b
feat: implement skills management system with UI and backend integration
Jan 8, 2026
c50217c
feat: add file selection functionality and enhance skill presenter tests
Jan 9, 2026
d9bef6e
feat: document additional issues and recommendations from skills syst…
Jan 9, 2026
bf7f2e7
chore: Merge branch 'dev' into feat/skills
zerob13 Jan 9, 2026
dad5418
feat(skills): Refactor skill metadata prompt building and enhance ski…
Jan 9, 2026
9bcc1ce
fix(skills): Merge branch 'feat/skills' of github.os:ThinkInAIXYZ/dee…
Jan 9, 2026
e03fd04
feat(skills): Add unit tests for security and tool scanning modules
Jan 9, 2026
ee4e72e
feat(agent): gate filesystem writes
zerob13 Jan 9, 2026
0c2cc34
chore(i18n): add skill sync strings
zerob13 Jan 9, 2026
f01a8b0
chore: update i18n
zerob13 Jan 9, 2026
ae603e3
feat(skills): add format adapters for Codex, Copilot User, Goose, Kil…
Jan 10, 2026
5683b52
fix(claudeCodeAdapter): specify types for id and name properties
Jan 10, 2026
bb7f2f1
feat(skills): Update localization files to replace "مهارت‌ها", "Compé…
Jan 11, 2026
425ecdd
feat: add skills panel component and related functionality
Jan 11, 2026
be05e51
feat: enhance mention handling to support slash mentions and improve …
Jan 11, 2026
96e0c94
chore: add i18n translate
zerob13 Jan 12, 2026
31fc271
feat(skills): finish
Jan 13, 2026
cfa3eac
feat: add i18n translate
zerob13 Jan 13, 2026
899dc57
feat: init acp enhance
Jan 13, 2026
eecba09
feat(acp): add model support
Jan 13, 2026
76faecc
feat(acp): merge with dev
Jan 13, 2026
15ea81c
feat(acp): add agent icon
Jan 13, 2026
2c8dab5
feat(acp): enhance warmup process and add workdir change confirmation
Jan 15, 2026
dde9980
chore: Merge branch 'dev' into feat/acp_model_enhance
zerob13 Jan 15, 2026
55732a2
chore: i18n update
zerob13 Jan 15, 2026
961d762
feat(acp): add OpenCode as builtin agent with icon support
Jan 15, 2026
689e48b
feat(acp): add gemini-cli as builtin agent
Jan 15, 2026
eb86fa9
feat(acp): add gemini cli
Jan 16, 2026
2e35285
feat(acp): add qwen code acp
Jan 16, 2026
dc82455
feat: update webcontents refactor specs
Jan 16, 2026
0dad490
feat(chatwindow): refactor
Jan 17, 2026
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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## Unreleased
- 新增 OpenCode 作为内置 ACP Agent,支持开源 AI 编码代理
- Added OpenCode as builtin ACP agent, supporting open-source AI coding agent

## v0.5.6-beta.4 (2025-12-30)
- 全面重构 Agent 与会话架构:拆分 agent/session/loop/tool/persistence,替换 Thread Presenter 为 Session Presenter,强化消息压缩、工具调用、持久化与导出
- 增强搜索体验:新增 Search Presenter 与搜索提示模板,完善搜索助手与搜索引擎配置流程
Expand Down
334 changes: 334 additions & 0 deletions docs/specs/acp-integration/enhancement-spec.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,334 @@
# ACP 用户体验增强设计规格

> 基于 ux-issues-research.md 调研结果的改进设计
>
> 状态: 设计中
> 日期: 2025-01

## 1. 概述

### 1.1 目标

解决 ACP 集成中的三个核心体验问题:

1. **Mode/Model 提前获取**:用户切换到 ACP agent 时,无需手动选择 workdir 即可获取和设置 mode/model
2. **Available Commands 展示**:在 UI 中展示 Agent 提供的可用命令
3. **Workdir 切换体验**:切换 workdir 时提供确认提示,保留对话历史显示

### 1.2 非目标

- 修改 ACP 协议本身
- 实现 loadSession(会话恢复)功能
- 实现 Authentication(认证)功能

---

## 2. 设计方案

### 2.1 Mode/Model 提前获取

#### 2.1.1 核心思路

引入**配置专用 warmup 目录**,在用户切换到 ACP agent 时自动创建 warmup 进程获取配置。

```
┌─────────────────────────────────────────────────────────────┐
│ 配置获取流程(改进后) │
├─────────────────────────────────────────────────────────────┤
│ 用户切换到 ACP agent │
│ ↓ │
│ 检查是否有用户选择的 workdir │
│ ↓ │
│ [有] → 使用用户 workdir 创建 warmup │
│ [无] → 使用内置 tmp 目录创建 warmup │
│ ↓ │
│ 自动触发 warmupProcess() │
│ ↓ │
│ 获取 modes/models 配置 │
│ ↓ │
│ UI 显示可用的 modes/models │
└─────────────────────────────────────────────────────────────┘
```

#### 2.1.2 配置专用目录

```typescript
// 位置:src/main/presenter/agentPresenter/acp/acpProcessManager.ts

// 新增:获取配置专用 warmup 目录
getConfigWarmupDir(): string {
const userDataPath = app.getPath('userData')
const warmupDir = path.join(userDataPath, 'acp-config-warmup')

// 确保目录存在
if (!fs.existsSync(warmupDir)) {
fs.mkdirSync(warmupDir, { recursive: true })
}

return warmupDir
}
```

#### 2.1.3 自动 Warmup 触发

```typescript
// 位置:src/renderer/src/components/chat-input/composables/useAcpMode.ts

// 改进 loadWarmupModes
const loadWarmupModes = async () => {
if (!isAcpModel.value || hasConversation.value) return
if (!agentId.value) return

// 确定 warmup 目录:优先用户选择,否则使用配置专用目录
const warmupDir = selectedWorkdir.value || null

// 先查询已存在的进程
let result = await sessionPresenter.getAcpProcessModes(agentId.value, warmupDir)

// 如果进程不存在,主动创建
if (!result?.availableModes) {
await sessionPresenter.ensureAcpWarmup(agentId.value, warmupDir)
result = await sessionPresenter.getAcpProcessModes(agentId.value, warmupDir)
}

if (result?.availableModes) {
availableModes.value = result.availableModes
currentMode.value = result.currentModeId ?? result.availableModes[0]?.id ?? 'default'
}
}
```

#### 2.1.4 新增 API

```typescript
// SessionPresenter 新增方法
interface SessionPresenter {
/**
* 确保 ACP agent 的 warmup 进程存在
* 如果 workdir 为 null,使用配置专用目录
*/
ensureAcpWarmup(agentId: string, workdir: string | null): Promise<void>
}
```

---

### 2.2 Available Commands 展示

#### 2.2.1 核心思路

将 `available_commands_update` 通知转换为 UI 可用的命令列表,支持用户通过 `/` 触发。

#### 2.2.2 数据流

```
Agent 发送 available_commands_update
AcpContentMapper 处理通知
发送事件到 Renderer
useAcpCommands composable 接收
ChatInput 显示命令列表
```

#### 2.2.3 类型定义

```typescript
// src/shared/types/acp.ts

interface AcpCommand {
name: string
description: string
input?: {
hint: string
}
}

// 事件类型
interface AcpCommandsUpdateEvent {
sessionId: string
commands: AcpCommand[]
}
```

#### 2.2.4 事件定义

```typescript
// src/main/events.ts

ACP_WORKSPACE_EVENTS = {
SESSION_MODES_READY: 'acp-workspace:session-modes-ready',
SESSION_MODELS_READY: 'acp-workspace:session-models-ready',
// 新增
COMMANDS_UPDATE: 'acp-workspace:commands-update'
}
```

#### 2.2.5 ContentMapper 改进

```typescript
// src/main/presenter/agentPresenter/acp/acpContentMapper.ts

case 'available_commands_update':
// 改进:发送事件到 Renderer
this.emitCommandsUpdate(sessionId, update.availableCommands ?? [])
break

private emitCommandsUpdate(sessionId: string, commands: AcpCommand[]) {
eventBus.sendToRenderer(
ACP_WORKSPACE_EVENTS.COMMANDS_UPDATE,
SendTarget.ALL_WINDOWS,
{ sessionId, commands }
)
}
```

#### 2.2.6 Renderer Composable

```typescript
// src/renderer/src/components/chat-input/composables/useAcpCommands.ts

export function useAcpCommands(options: UseAcpCommandsOptions) {
const commands = ref<AcpCommand[]>([])

const handleCommandsUpdate = (event: AcpCommandsUpdateEvent) => {
if (event.sessionId === currentSessionId.value) {
commands.value = event.commands
}
}

onMounted(() => {
window.electron.on(ACP_WORKSPACE_EVENTS.COMMANDS_UPDATE, handleCommandsUpdate)
})

onUnmounted(() => {
window.electron.off(ACP_WORKSPACE_EVENTS.COMMANDS_UPDATE, handleCommandsUpdate)
})

return { commands }
}
```

---

### 2.3 Workdir 切换体验

#### 2.3.1 核心思路

1. 切换 workdir 前显示确认对话框
2. 切换后保留对话历史显示(只读)
3. 新会话从新 workdir 开始

#### 2.3.2 确认对话框

```typescript
// src/renderer/src/components/chat-input/composables/useAcpWorkdir.ts

const selectWorkdir = async () => {
// ... 选择目录逻辑

// 如果已有会话,显示确认对话框
if (hasConversation.value && workdir.value !== selectedPath) {
const confirmed = await showWorkdirChangeConfirm({
currentWorkdir: workdir.value,
newWorkdir: selectedPath,
message: t('acp.workdirChangeWarning')
})

if (!confirmed) return
}

// 继续切换逻辑
}
```

#### 2.3.3 对话历史保留

```typescript
// 切换 workdir 时的处理
const handleWorkdirChange = async (newWorkdir: string) => {
// 1. 标记当前会话为"已归档"状态
await sessionPresenter.archiveAcpSession(conversationId.value)

// 2. 设置新 workdir(会清理 session,但保留消息历史)
await sessionPresenter.setAcpWorkdir(conversationId.value, agentId.value, newWorkdir)

// 3. UI 显示分隔线,表示 workdir 已切换
// 消息历史仍然可见,但标记为"来自之前的 workdir"
}
```

---

## 3. 文件变更清单

### 3.1 Main Process

| 文件 | 变更类型 | 说明 |
|------|---------|------|
| `src/main/events.ts` | 修改 | 新增 `COMMANDS_UPDATE` 事件 |
| `src/main/presenter/agentPresenter/acp/acpProcessManager.ts` | 修改 | 新增 `getConfigWarmupDir()` 方法 |
| `src/main/presenter/agentPresenter/acp/acpContentMapper.ts` | 修改 | 处理 `available_commands_update` |
| `src/main/presenter/sessionPresenter/index.ts` | 修改 | 新增 `ensureAcpWarmup()` 方法 |
| `src/main/presenter/llmProviderPresenter/index.ts` | 修改 | 新增 `ensureAcpWarmup()` 方法 |
| `src/main/presenter/llmProviderPresenter/providers/acpProvider.ts` | 修改 | 新增 `ensureWarmup()` 方法 |

### 3.2 Renderer Process

| 文件 | 变更类型 | 说明 |
|------|---------|------|
| `src/renderer/src/components/chat-input/composables/useAcpMode.ts` | 修改 | 改进 `loadWarmupModes()` |
| `src/renderer/src/components/chat-input/composables/useAcpWorkdir.ts` | 修改 | 添加确认对话框 |
| `src/renderer/src/components/chat-input/composables/useAcpCommands.ts` | 新增 | 命令列表 composable |

### 3.3 Shared Types

| 文件 | 变更类型 | 说明 |
|------|---------|------|
| `src/shared/types/presenters/session.presenter.d.ts` | 修改 | 新增 `ensureAcpWarmup` 类型 |
| `src/shared/types/acp.ts` | 新增 | ACP 相关类型定义 |

---

## 4. 实现计划

### Phase 1: Mode/Model 提前获取

1. 实现 `getConfigWarmupDir()` 方法
2. 实现 `ensureAcpWarmup()` API 链路
3. 改进 `loadWarmupModes()` 逻辑
4. 测试验证

### Phase 2: Available Commands 展示

1. 新增事件定义
2. 改进 ContentMapper
3. 实现 `useAcpCommands` composable
4. UI 集成(可选:命令面板)

### Phase 3: Workdir 切换体验

1. 实现确认对话框
2. 实现会话归档逻辑
3. UI 显示 workdir 切换分隔线

---

## 5. 风险与注意事项

### 5.1 配置专用目录的清理

- 需要定期清理 `acp-config-warmup` 目录
- 可在应用启动时清理过期文件

### 5.2 进程资源管理

- 配置专用 warmup 进程应在获取配置后及时释放
- 避免同时存在过多 warmup 进程

### 5.3 向后兼容

- 所有改动应保持向后兼容
- 现有的 workdir 选择流程仍然有效
Loading