feat: Windows 环境优先使用 PowerShell 工具替代 bash

This commit is contained in:
Rick Ye
2026-09-10 14:18:47 +08:00
parent cafb6f34de
commit 0bae7cdc22
2 changed files with 30 additions and 2 deletions
+29 -1
View File
@@ -9,6 +9,7 @@ import {
createAgentSessionFromServices, createAgentSessionFromServices,
estimateTokens, estimateTokens,
getAgentDir, getAgentDir,
getPowerShellConfig,
SessionManager, SessionManager,
type AgentSession, type AgentSession,
type AgentSessionEvent, type AgentSessionEvent,
@@ -53,7 +54,32 @@ const DELTA_FLUSH_MS = 40
const CUSTOM_TOOL_NAMES = new Set<string>(browserToolNames) const CUSTOM_TOOL_NAMES = new Set<string>(browserToolNames)
/** 需要人工审批的工具名单(高危内置工具;业务演示工具已随 demo-tools.ts 移除) */ /** 需要人工审批的工具名单(高危内置工具;业务演示工具已随 demo-tools.ts 移除) */
const TOOLS_REQUIRING_APPROVAL: ReadonlySet<string> = new Set(['bash', 'write', 'edit']) const TOOLS_REQUIRING_APPROVAL: ReadonlySet<string> = new Set(['bash', 'powershell', 'write', 'edit'])
/** Windows 优先 PowerShell:探测结果进程内缓存(getPowerShellConfig 会 spawnSync where 探测,
* 且平台与安装情况不会在应用运行中变化)。探测失败保持 bash(Git Bash)不动。 */
let powershellProbe: boolean | null = null
/** win32 且存在 pwsh/powershell 可执行文件时,把会话的默认 bash 工具换成 powershell,
* 模型的 shell 调用走原生 PowerShell 而非 Git Bash。幂等:无 bash 或已换过则原样返回。
* 注意不能用 options.tools 传入(那会变成工具白名单,把插件注册的工具全部过滤掉),
* 也不能只传四个基础名调 setActiveToolsByName(那会把已激活的扩展工具一并挤掉),
* 所以按当前激活名单做替换。 */
function preferPowerShell(session: AgentSession): void {
if (process.platform !== 'win32') return
if (powershellProbe === null) {
try {
getPowerShellConfig()
powershellProbe = true
} catch {
powershellProbe = false
}
}
if (!powershellProbe) return
const names = session.getActiveToolNames()
if (!names.includes('bash') || names.includes('powershell')) return
session.setActiveToolsByName(names.map((name) => (name === 'bash' ? 'powershell' : name)))
}
/** /**
* pi 会话运行时的主进程封装: * pi 会话运行时的主进程封装:
@@ -294,6 +320,8 @@ export class AgentService {
// 业务工具(browserTools 等)由插件经 pi.registerTool 注册(聚合 extension), // 业务工具(browserTools 等)由插件经 pi.registerTool 注册(聚合 extension),
// 此处不再传 customTools // 此处不再传 customTools
}) })
// 会话创建是唯一收口点:新建/切换/分叉/重载都会经过这里,统一应用 Windows PowerShell 偏好
preferPowerShell(result.session)
return { ...result, services, diagnostics: services.diagnostics } return { ...result, services, diagnostics: services.diagnostics }
} }
@@ -105,7 +105,7 @@ function extractResultText(result: unknown): string {
function toolMeta(name: string): { icon: keyof typeof STEP_ICONS; label: string } { function toolMeta(name: string): { icon: keyof typeof STEP_ICONS; label: string } {
if (/^read|get|list|查|读|搜/i.test(name)) return { icon: 'read', label: '读取' } if (/^read|get|list|查|读|搜/i.test(name)) return { icon: 'read', label: '读取' }
if (/^write|^edit|^multiedit|写|改|删|建|核/i.test(name)) return { icon: 'write', label: '编辑' } if (/^write|^edit|^multiedit|写|改|删|建|核/i.test(name)) return { icon: 'write', label: '编辑' }
if (/^bash|^shell|^terminal|终端/i.test(name)) return { icon: 'run', label: '终端' } if (/^bash|^shell|^terminal|^powershell|终端/i.test(name)) return { icon: 'run', label: '终端' }
if (/read|get|search|query|fetch|list|查|读|搜/i.test(name)) return { icon: 'read', label: '读取' } if (/read|get|search|query|fetch|list|查|读|搜/i.test(name)) return { icon: 'read', label: '读取' }
if (/write|edit|update|create|delete|patch|save|写|改|删|建|核/i.test(name)) return { icon: 'write', label: '编辑' } if (/write|edit|update|create|delete|patch|save|写|改|删|建|核/i.test(name)) return { icon: 'write', label: '编辑' }
return { icon: 'run', label: name } return { icon: 'run', label: name }