mirror of
https://github.com/claude-code-best/claude-code.git
synced 2026-06-21 15:55:50 +00:00
* feat: 第一版大重构 * fix: 修复类型问题 * chore: 更新版本到 1.3.2 * Add brave as alternative WebSearchTool * fix: 修正顺序 * fix: 修复对穷鬼模式的 auto dream 和 session memory 越过 * feat: 穷鬼模式去除 session-summary * feat: 创建 builtin-tools 包,搬运所有工具实现 将 src/tools/ 下的全部 60 个工具目录迁移至 packages/builtin-tools/src/tools/, 内部导入路径已更新为 src/ alias 模式。 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: 更新 src/ 中所有工具引用至 builtin-tools 包,删除 src/tools/ - src/tools.ts 及 178 个 src/ 文件的 import 路径从 ./tools/ 改为 builtin-tools/tools/ - 删除 src/tools/ 整个目录(已迁移至 packages/builtin-tools/) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: 添加 builtin-tools 路径别名至 tsconfig,更新 bun.lock - tsconfig.json 新增 builtin-tools/* 和 builtin-tools 路径映射 - 新增 packages/builtin-tools/src 至 include Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: 为 builtin-tools、mcp-client、agent-tools 添加 @claude-code-best 作用域前缀 所有包名及 import 路径统一添加 @claude-code-best/ 前缀: - builtin-tools → @claude-code-best/builtin-tools - mcp-client → @claude-code-best/mcp-client - agent-tools → @claude-code-best/agent-tools Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: 修复 node 环境没有 bun 的问题 --------- Co-authored-by: Eric-Guo <eric.guocz@gmail.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
246 lines
6.9 KiB
TypeScript
246 lines
6.9 KiB
TypeScript
import type { PermissionRule } from 'src/utils/permissions/PermissionRule.js'
|
|
import { getSettingsForSource } from 'src/utils/settings/settings.js'
|
|
import type { SettingsJson } from 'src/utils/settings/types.js'
|
|
import { BASH_TOOL_NAME } from '@claude-code-best/builtin-tools/tools/BashTool/toolName.js'
|
|
import { SAFE_ENV_VARS } from '../../utils/managedEnvConstants.js'
|
|
import { getPermissionRulesForSource } from '../../utils/permissions/permissionsLoader.js'
|
|
|
|
function hasHooks(settings: SettingsJson | null): boolean {
|
|
if (settings === null || settings.disableAllHooks) {
|
|
return false
|
|
}
|
|
if (settings.statusLine) {
|
|
return true
|
|
}
|
|
if (settings.fileSuggestion) {
|
|
return true
|
|
}
|
|
if (!settings.hooks) {
|
|
return false
|
|
}
|
|
for (const hookConfig of Object.values(settings.hooks)) {
|
|
if (hookConfig.length > 0) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
export function getHooksSources(): string[] {
|
|
const sources: string[] = []
|
|
|
|
const projectSettings = getSettingsForSource('projectSettings')
|
|
if (hasHooks(projectSettings)) {
|
|
sources.push('.claude/settings.json')
|
|
}
|
|
|
|
const localSettings = getSettingsForSource('localSettings')
|
|
if (hasHooks(localSettings)) {
|
|
sources.push('.claude/settings.local.json')
|
|
}
|
|
|
|
return sources
|
|
}
|
|
|
|
function hasBashPermission(rules: PermissionRule[]): boolean {
|
|
return rules.some(
|
|
rule =>
|
|
rule.ruleBehavior === 'allow' &&
|
|
(rule.ruleValue.toolName === BASH_TOOL_NAME ||
|
|
rule.ruleValue.toolName.startsWith(BASH_TOOL_NAME + '(')),
|
|
)
|
|
}
|
|
|
|
/**
|
|
* Get which setting sources have bash allow rules.
|
|
* Returns an array of file paths that have bash permissions.
|
|
*/
|
|
export function getBashPermissionSources(): string[] {
|
|
const sources: string[] = []
|
|
|
|
const projectRules = getPermissionRulesForSource('projectSettings')
|
|
if (hasBashPermission(projectRules)) {
|
|
sources.push('.claude/settings.json')
|
|
}
|
|
|
|
const localRules = getPermissionRulesForSource('localSettings')
|
|
if (hasBashPermission(localRules)) {
|
|
sources.push('.claude/settings.local.json')
|
|
}
|
|
|
|
return sources
|
|
}
|
|
|
|
/**
|
|
* Format a list of items with proper "and" conjunction.
|
|
* @param items - Array of items to format
|
|
* @param limit - Optional limit for how many items to show before summarizing (ignored if 0)
|
|
*/
|
|
export function formatListWithAnd(items: string[], limit?: number): string {
|
|
if (items.length === 0) return ''
|
|
|
|
// Ignore limit if it's 0
|
|
const effectiveLimit = limit === 0 ? undefined : limit
|
|
|
|
// If no limit or items are within limit, use normal formatting
|
|
if (!effectiveLimit || items.length <= effectiveLimit) {
|
|
if (items.length === 1) return items[0]!
|
|
if (items.length === 2) return `${items[0]} and ${items[1]}`
|
|
|
|
const lastItem = items[items.length - 1]!
|
|
const allButLast = items.slice(0, -1)
|
|
return `${allButLast.join(', ')}, and ${lastItem}`
|
|
}
|
|
|
|
// If we have more items than the limit, show first few and count the rest
|
|
const shown = items.slice(0, effectiveLimit)
|
|
const remaining = items.length - effectiveLimit
|
|
|
|
if (shown.length === 1) {
|
|
return `${shown[0]} and ${remaining} more`
|
|
}
|
|
|
|
return `${shown.join(', ')}, and ${remaining} more`
|
|
}
|
|
|
|
/**
|
|
* Check if settings have otelHeadersHelper configured
|
|
*/
|
|
function hasOtelHeadersHelper(settings: SettingsJson | null): boolean {
|
|
return !!settings?.otelHeadersHelper
|
|
}
|
|
|
|
/**
|
|
* Get which setting sources have otelHeadersHelper configured.
|
|
* Returns an array of file paths that have otelHeadersHelper.
|
|
*/
|
|
export function getOtelHeadersHelperSources(): string[] {
|
|
const sources: string[] = []
|
|
|
|
const projectSettings = getSettingsForSource('projectSettings')
|
|
if (hasOtelHeadersHelper(projectSettings)) {
|
|
sources.push('.claude/settings.json')
|
|
}
|
|
|
|
const localSettings = getSettingsForSource('localSettings')
|
|
if (hasOtelHeadersHelper(localSettings)) {
|
|
sources.push('.claude/settings.local.json')
|
|
}
|
|
|
|
return sources
|
|
}
|
|
|
|
/**
|
|
* Check if settings have apiKeyHelper configured
|
|
*/
|
|
function hasApiKeyHelper(settings: SettingsJson | null): boolean {
|
|
return !!settings?.apiKeyHelper
|
|
}
|
|
|
|
/**
|
|
* Get which setting sources have apiKeyHelper configured.
|
|
* Returns an array of file paths that have apiKeyHelper.
|
|
*/
|
|
export function getApiKeyHelperSources(): string[] {
|
|
const sources: string[] = []
|
|
|
|
const projectSettings = getSettingsForSource('projectSettings')
|
|
if (hasApiKeyHelper(projectSettings)) {
|
|
sources.push('.claude/settings.json')
|
|
}
|
|
|
|
const localSettings = getSettingsForSource('localSettings')
|
|
if (hasApiKeyHelper(localSettings)) {
|
|
sources.push('.claude/settings.local.json')
|
|
}
|
|
|
|
return sources
|
|
}
|
|
|
|
/**
|
|
* Check if settings have AWS commands configured
|
|
*/
|
|
function hasAwsCommands(settings: SettingsJson | null): boolean {
|
|
return !!(settings?.awsAuthRefresh || settings?.awsCredentialExport)
|
|
}
|
|
|
|
/**
|
|
* Get which setting sources have AWS commands configured.
|
|
* Returns an array of file paths that have awsAuthRefresh or awsCredentialExport.
|
|
*/
|
|
export function getAwsCommandsSources(): string[] {
|
|
const sources: string[] = []
|
|
|
|
const projectSettings = getSettingsForSource('projectSettings')
|
|
if (hasAwsCommands(projectSettings)) {
|
|
sources.push('.claude/settings.json')
|
|
}
|
|
|
|
const localSettings = getSettingsForSource('localSettings')
|
|
if (hasAwsCommands(localSettings)) {
|
|
sources.push('.claude/settings.local.json')
|
|
}
|
|
|
|
return sources
|
|
}
|
|
|
|
/**
|
|
* Check if settings have GCP commands configured
|
|
*/
|
|
function hasGcpCommands(settings: SettingsJson | null): boolean {
|
|
return !!settings?.gcpAuthRefresh
|
|
}
|
|
|
|
/**
|
|
* Get which setting sources have GCP commands configured.
|
|
* Returns an array of file paths that have gcpAuthRefresh.
|
|
*/
|
|
export function getGcpCommandsSources(): string[] {
|
|
const sources: string[] = []
|
|
|
|
const projectSettings = getSettingsForSource('projectSettings')
|
|
if (hasGcpCommands(projectSettings)) {
|
|
sources.push('.claude/settings.json')
|
|
}
|
|
|
|
const localSettings = getSettingsForSource('localSettings')
|
|
if (hasGcpCommands(localSettings)) {
|
|
sources.push('.claude/settings.local.json')
|
|
}
|
|
|
|
return sources
|
|
}
|
|
|
|
/**
|
|
* Check if settings have dangerous environment variables configured.
|
|
* Any env var NOT in SAFE_ENV_VARS is considered dangerous.
|
|
*/
|
|
function hasDangerousEnvVars(settings: SettingsJson | null): boolean {
|
|
if (!settings?.env) {
|
|
return false
|
|
}
|
|
return Object.keys(settings.env).some(
|
|
key => !SAFE_ENV_VARS.has(key.toUpperCase()),
|
|
)
|
|
}
|
|
|
|
/**
|
|
* Get which setting sources have dangerous environment variables configured.
|
|
* Returns an array of file paths that have env vars not in SAFE_ENV_VARS.
|
|
*/
|
|
export function getDangerousEnvVarsSources(): string[] {
|
|
const sources: string[] = []
|
|
|
|
const projectSettings = getSettingsForSource('projectSettings')
|
|
if (hasDangerousEnvVars(projectSettings)) {
|
|
sources.push('.claude/settings.json')
|
|
}
|
|
|
|
const localSettings = getSettingsForSource('localSettings')
|
|
if (hasDangerousEnvVars(localSettings)) {
|
|
sources.push('.claude/settings.local.json')
|
|
}
|
|
|
|
return sources
|
|
}
|