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:
115
src/services/acp/agent/permissionMode.ts
Normal file
115
src/services/acp/agent/permissionMode.ts
Normal file
@@ -0,0 +1,115 @@
|
||||
import type { PermissionMode } from '../../../types/permissions.js'
|
||||
import { resolvePermissionMode } from '../utils.js'
|
||||
|
||||
export const permissionModeIds: readonly PermissionMode[] = [
|
||||
'auto',
|
||||
'default',
|
||||
'acceptEdits',
|
||||
'bypassPermissions',
|
||||
'dontAsk',
|
||||
'plan',
|
||||
]
|
||||
|
||||
export function isPermissionMode(modeId: string): modeId is PermissionMode {
|
||||
return (permissionModeIds as readonly string[]).includes(modeId)
|
||||
}
|
||||
|
||||
export function resolveSessionPermissionMode(
|
||||
metaMode: unknown,
|
||||
hasMetaMode: boolean,
|
||||
settingsMode: unknown,
|
||||
): PermissionMode {
|
||||
if (hasMetaMode) {
|
||||
const metaResolved = resolveRequiredPermissionMode(
|
||||
metaMode,
|
||||
'_meta.permissionMode',
|
||||
)
|
||||
if (
|
||||
metaResolved === 'bypassPermissions' &&
|
||||
!isAcpBypassPermissionModeAvailable(settingsMode)
|
||||
) {
|
||||
throw new Error(
|
||||
'Mode not available: bypassPermissions requires a local ACP bypass opt-in.',
|
||||
)
|
||||
}
|
||||
|
||||
return metaResolved
|
||||
}
|
||||
|
||||
const settingsResolved = resolveConfiguredPermissionMode(settingsMode)
|
||||
return settingsResolved ?? 'default'
|
||||
}
|
||||
|
||||
function resolveRequiredPermissionMode(
|
||||
mode: unknown,
|
||||
source: string,
|
||||
): PermissionMode {
|
||||
if (mode === undefined || mode === null) {
|
||||
throw new Error(`Invalid ${source}: expected a string.`)
|
||||
}
|
||||
|
||||
return resolvePermissionMode(mode, source) as PermissionMode
|
||||
}
|
||||
|
||||
function resolveConfiguredPermissionMode(
|
||||
mode: unknown,
|
||||
): PermissionMode | undefined {
|
||||
if (mode === undefined || mode === null) return undefined
|
||||
|
||||
try {
|
||||
return resolvePermissionMode(
|
||||
mode,
|
||||
'permissions.defaultMode',
|
||||
) as PermissionMode
|
||||
} catch (err: unknown) {
|
||||
const reason = err instanceof Error ? err.message : String(err)
|
||||
console.error(
|
||||
'[ACP] Invalid permissions.defaultMode, using default:',
|
||||
reason,
|
||||
)
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
|
||||
export function hasOwnField(
|
||||
value: Record<string, unknown> | null | undefined,
|
||||
key: string,
|
||||
): boolean {
|
||||
return !!value && Object.hasOwn(value, key)
|
||||
}
|
||||
|
||||
export function isAcpBypassPermissionModeAvailable(
|
||||
settingsMode?: unknown,
|
||||
): boolean {
|
||||
return (
|
||||
isProcessBypassPermissionModeAvailable() &&
|
||||
(isAcpBypassLocallyEnabled() ||
|
||||
isSettingsBypassPermissionMode(settingsMode))
|
||||
)
|
||||
}
|
||||
|
||||
function isProcessBypassPermissionModeAvailable(): boolean {
|
||||
if (process.env.IS_SANDBOX) return true
|
||||
if (typeof process.geteuid === 'function') return process.geteuid() !== 0
|
||||
if (typeof process.getuid === 'function') return process.getuid() !== 0
|
||||
return true
|
||||
}
|
||||
|
||||
function isAcpBypassLocallyEnabled(): boolean {
|
||||
return (
|
||||
process.env.ACP_PERMISSION_MODE === 'bypassPermissions' ||
|
||||
isTruthyEnv(process.env.CLAUDE_CODE_ACP_ALLOW_BYPASS_PERMISSIONS)
|
||||
)
|
||||
}
|
||||
|
||||
function isSettingsBypassPermissionMode(settingsMode: unknown): boolean {
|
||||
try {
|
||||
return resolvePermissionMode(settingsMode) === 'bypassPermissions'
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
function isTruthyEnv(value: string | undefined): boolean {
|
||||
return value === '1' || value?.toLowerCase() === 'true'
|
||||
}
|
||||
Reference in New Issue
Block a user