mirror of
https://github.com/claude-code-best/claude-code.git
synced 2026-06-18 06:15:51 +00:00
* fix: 修复settings.json内存状态溢出的问题 * fix: 修复auto mode gate check未处理的promise rejection 在 bypassPermissionsKillswitch.ts 的 useKickOffCheckAndDisableAutoModeIfNeeded 中,void fire-and-forget 调用缺少 .catch() 处理,导致 verifyAutoModeGateAccess 失败时产生 unhandled promise rejection。同时移除 permissionSetup.ts 中冗余的 null check。 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: 开放 auto mode 和 bypass mode 给所有用户 通过 Shift+Tab 统一循环:default → acceptEdits → plan → auto → bypassPermissions → default - 移除 USER_TYPE 分支判断,所有用户使用同一循环路径 - isBypassPermissionsModeAvailable 始终为 true - isAutoModeAvailable 初始化直接为 true - 移除 AutoModeOptInDialog 确认流程 - 简化 isAutoModeGateEnabled 仅保留快模式熔断器 - 简化 verifyAutoModeGateAccess 仅检查快模式 - 移除 GrowthBook/Statsig 远程门控 - bypass permissions killswitch 改为 no-op - 新增 24 个测试覆盖循环逻辑和门控不变量 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: 为sideQuery添加Langfuse追踪 sideQuery 绕过了 claude.ts 的主 API 路径,导致所有走 sideQuery 的调用 (auto mode classifier、permission explainer、session search 等)都没有 Langfuse 记录。现在为每次 sideQuery 调用创建独立 trace 并记录 LLM observation, 未配置 Langfuse 时全部 no-op。 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: ACP availableModes 补齐 bypassPermissions 并修正测试 import 路径 - ACP agent availableModes 按条件包含 bypassPermissions(非 root/sandbox) - 顺序对齐 REPL 循环:default → acceptEdits → plan → auto → bypassPermissions - 新增 2 个测试验证 availableModes 包含 bypassPermissions 及模式切换 - 修正 getNextPermissionMode.test.ts 和 permissionSetup.test.ts 的 import 路径 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
114 lines
3.5 KiB
TypeScript
114 lines
3.5 KiB
TypeScript
import { feature } from 'bun:bundle'
|
|
import { useEffect, useRef } from 'react'
|
|
import { useNotifications } from 'src/context/notifications.js'
|
|
import { toError } from '../../utils/errors.js'
|
|
import { logError } from '../../utils/log.js'
|
|
import { getIsRemoteMode } from '../../bootstrap/state.js'
|
|
import { useAppState, useAppStateStore, useSetAppState } from '../../state/AppState.js'
|
|
import type { ToolPermissionContext } from '../../Tool.js'
|
|
import {
|
|
verifyAutoModeGateAccess,
|
|
} from './permissionSetup.js'
|
|
|
|
/**
|
|
* No-op — bypass permissions is always available.
|
|
*/
|
|
export async function checkAndDisableBypassPermissionsIfNeeded(
|
|
_toolPermissionContext: ToolPermissionContext,
|
|
_setAppState: (f: (prev: import('../../state/AppState.js').AppState) => import('../../state/AppState.js').AppState) => void,
|
|
): Promise<void> {
|
|
// Bypass permissions is always available — no gate check needed
|
|
}
|
|
|
|
/**
|
|
* Reset stub — kept for interface compatibility.
|
|
*/
|
|
export function resetBypassPermissionsCheck(): void {
|
|
// No-op
|
|
}
|
|
|
|
/**
|
|
* No-op hook — bypass permissions is always available.
|
|
*/
|
|
export function useKickOffCheckAndDisableBypassPermissionsIfNeeded(): void {
|
|
// No-op
|
|
}
|
|
|
|
let autoModeCheckRan = false
|
|
|
|
export async function checkAndDisableAutoModeIfNeeded(
|
|
toolPermissionContext: ToolPermissionContext,
|
|
setAppState: (f: (prev: import('../../state/AppState.js').AppState) => import('../../state/AppState.js').AppState) => void,
|
|
fastMode?: boolean,
|
|
): Promise<void> {
|
|
if (feature('TRANSCRIPT_CLASSIFIER')) {
|
|
if (autoModeCheckRan) {
|
|
return
|
|
}
|
|
autoModeCheckRan = true
|
|
|
|
const { updateContext, notification } = await verifyAutoModeGateAccess(
|
|
toolPermissionContext,
|
|
fastMode,
|
|
)
|
|
setAppState(prev => {
|
|
const nextCtx = updateContext(prev.toolPermissionContext)
|
|
const newState =
|
|
nextCtx === prev.toolPermissionContext
|
|
? prev
|
|
: { ...prev, toolPermissionContext: nextCtx }
|
|
if (!notification) return newState
|
|
return {
|
|
...newState,
|
|
notifications: {
|
|
...newState.notifications,
|
|
queue: [
|
|
...newState.notifications.queue,
|
|
{
|
|
key: 'auto-mode-gate-notification',
|
|
text: notification,
|
|
color: 'warning' as const,
|
|
priority: 'high' as const,
|
|
},
|
|
],
|
|
},
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Reset the run-once flag for checkAndDisableAutoModeIfNeeded.
|
|
* Call this after /login so the gate check re-runs with the new org.
|
|
*/
|
|
export function resetAutoModeGateCheck(): void {
|
|
autoModeCheckRan = false
|
|
}
|
|
|
|
export function useKickOffCheckAndDisableAutoModeIfNeeded(): void {
|
|
const mainLoopModel = useAppState(s => s.mainLoopModel)
|
|
const mainLoopModelForSession = useAppState(s => s.mainLoopModelForSession)
|
|
const fastMode = useAppState(s => s.fastMode)
|
|
const setAppState = useSetAppState()
|
|
const store = useAppStateStore()
|
|
const isFirstRunRef = useRef(true)
|
|
|
|
// Runs on mount (startup check) AND whenever the model or fast mode changes
|
|
useEffect(() => {
|
|
if (getIsRemoteMode()) return
|
|
if (isFirstRunRef.current) {
|
|
isFirstRunRef.current = false
|
|
} else {
|
|
resetAutoModeGateCheck()
|
|
}
|
|
void checkAndDisableAutoModeIfNeeded(
|
|
store.getState().toolPermissionContext,
|
|
setAppState,
|
|
fastMode,
|
|
).catch(error => {
|
|
logError(new Error('Auto mode gate check failed', { cause: toError(error) }))
|
|
})
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, [mainLoopModel, mainLoopModelForSession, fastMode])
|
|
}
|