mirror of
https://github.com/claude-code-best/claude-code.git
synced 2026-06-23 08:45:50 +00:00
refactor: 拆分 3 个过大 ACP 文件为模块化子文件(每个 <500 行)
通过 4 阶段 workflow(分析 → 计划 → 重构 → 验证)将 3 个超大的 ACP 源文件拆分为 28 个模块化子文件,每个均严格小于 500 行,且完整保留 所有公共 API(barrel 模式重导出)。 变更概要: - packages/acp-link/src/server.ts: 1800 → 20 行(barrel),新增 11 个子模块 (server/types、payload-decode、permission-mode、runtime-state、dispatch、 handlers-agent、handlers-session、acp-client、client-send、start-server、 testing-internals) - src/services/acp/agent.ts: 1297 → 33 行(barrel),新增 9 个子模块 (agent/AcpAgent、sessionTypes、permissionMode、configOptions、promptQueue、 internalAccessors、createSessionMethod、sessionLifecycle、promptFlow) - src/services/acp/bridge.ts: 1516 → 29 行(barrel),新增 8 个子模块 (bridge/types、paths、contentBlocks、toolInfo、toolResults、modelUsage、 notifications、forwarding) 验证: - bun run precheck 全通过(typecheck + lint + 5851 tests) - ACP service tests: 176 pass / 0 fail - ACP link tests: 47 pass / 0 fail - 所有外部消费者(entry.ts、permissions.ts、__tests__/)的 import 路径不变 - 测试文件零修改 迁移计划详见 docs/acp-refactor-plan.md。 Co-Authored-By: glm-5.2 <zai-org@claude-code-best.win>
This commit is contained in:
102
packages/acp-link/src/server/acp-client.ts
Normal file
102
packages/acp-link/src/server/acp-client.ts
Normal file
@@ -0,0 +1,102 @@
|
||||
import type { WSContext } from 'hono/ws'
|
||||
import * as acp from '@agentclientprotocol/sdk'
|
||||
import { send } from './client-send.js'
|
||||
import {
|
||||
PERMISSION_TIMEOUT_MS,
|
||||
generateRequestId,
|
||||
logPerm,
|
||||
logWs,
|
||||
} from './runtime-state.js'
|
||||
import { clients } from './runtime-state.js'
|
||||
import type { ClientState } from './types.js'
|
||||
|
||||
// Create a Client implementation that forwards events to WebSocket
|
||||
export function createClient(
|
||||
ws: WSContext,
|
||||
clientState: ClientState,
|
||||
): acp.Client {
|
||||
return {
|
||||
async requestPermission(params) {
|
||||
const requestId = generateRequestId()
|
||||
logPerm.debug({ requestId, title: params.toolCall.title }, 'requested')
|
||||
|
||||
const outcomePromise = new Promise<
|
||||
{ outcome: 'cancelled' } | { outcome: 'selected'; optionId: string }
|
||||
>(resolve => {
|
||||
const timeout = setTimeout(() => {
|
||||
logPerm.warn({ requestId }, 'timed out')
|
||||
clientState.pendingPermissions.delete(requestId)
|
||||
resolve({ outcome: 'cancelled' })
|
||||
}, PERMISSION_TIMEOUT_MS)
|
||||
|
||||
clientState.pendingPermissions.set(requestId, { resolve, timeout })
|
||||
})
|
||||
|
||||
send(ws, 'permission_request', {
|
||||
requestId,
|
||||
sessionId: params.sessionId,
|
||||
options: params.options,
|
||||
toolCall: params.toolCall,
|
||||
})
|
||||
|
||||
const outcome = await outcomePromise
|
||||
logPerm.debug({ requestId, outcome: outcome.outcome }, 'resolved')
|
||||
|
||||
return { outcome }
|
||||
},
|
||||
|
||||
async sessionUpdate(params) {
|
||||
send(ws, 'session_update', params)
|
||||
},
|
||||
|
||||
async readTextFile(params) {
|
||||
logWs.debug({ path: params.path }, 'readTextFile')
|
||||
return { content: '' }
|
||||
},
|
||||
|
||||
async writeTextFile(params) {
|
||||
logWs.debug({ path: params.path }, 'writeTextFile')
|
||||
return {}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Handle permission response from client
|
||||
export function handlePermissionResponse(
|
||||
ws: WSContext,
|
||||
payload: {
|
||||
requestId: string
|
||||
outcome:
|
||||
| { outcome: 'cancelled' }
|
||||
| { outcome: 'selected'; optionId: string }
|
||||
},
|
||||
): void {
|
||||
const state = clients.get(ws)
|
||||
if (!state) {
|
||||
logPerm.warn('response from unknown client')
|
||||
return
|
||||
}
|
||||
|
||||
const pending = state.pendingPermissions.get(payload.requestId)
|
||||
if (!pending) {
|
||||
logPerm.warn(
|
||||
{ requestId: payload.requestId },
|
||||
'response for unknown request',
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
clearTimeout(pending.timeout)
|
||||
state.pendingPermissions.delete(payload.requestId)
|
||||
pending.resolve(payload.outcome)
|
||||
}
|
||||
|
||||
// Cancel all pending permissions for a client (called on disconnect)
|
||||
export function cancelPendingPermissions(clientState: ClientState): void {
|
||||
for (const [requestId, pending] of clientState.pendingPermissions) {
|
||||
logPerm.debug({ requestId }, 'cancelled on disconnect')
|
||||
clearTimeout(pending.timeout)
|
||||
pending.resolve({ outcome: 'cancelled' })
|
||||
}
|
||||
clientState.pendingPermissions.clear()
|
||||
}
|
||||
Reference in New Issue
Block a user