feat: 添加对 langfuse 监控的支持 (#242)

* docs: 更新类型检查的 CLAUDE.md

* feat: 添加模型 1M 上下文切换

* chore: remove prefetchOfficialMcpUrls call on startup

* docs: 添加 git commit 规范

* feat: 第一次接入 langfuse

* fix: 修复 generation 的计时的错误

* feat: 添加多 agent 的监控

* feat: 添加 /poor 省流模式,toggle 关闭 extract_memories 和 prompt_suggestion

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: 修复 lock 文件

* chore: 更新类型依赖

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
claude-code-best
2026-04-11 22:07:38 +08:00
committed by GitHub
parent 6a9da9d546
commit 2fea429dc6
23 changed files with 1242 additions and 6 deletions

View File

@@ -0,0 +1,70 @@
const MAX_OUTPUT_LENGTH = 500
const REDACTED_FILE_TOOLS = new Set(['FileReadTool', 'FileWriteTool', 'FileEditTool'])
const REDACTED_SHELL_TOOLS = new Set(['BashTool', 'PowerShellTool'])
const SENSITIVE_OUTPUT_TOOLS = new Set(['ConfigTool', 'MCPTool'])
const HOME_DIR_PATTERN = new RegExp(
(process.env.HOME ?? '/Users/[^/]+').replace(/[.*+?^${}()|[\]\\]/g, '\\$&'),
'g',
)
const SENSITIVE_KEY_PATTERN = /(?:api_?key|token|secret|password|credential|auth_header)/i
export function sanitizeGlobal(data: unknown): unknown {
if (typeof data === 'string') {
return data.replace(HOME_DIR_PATTERN, '~')
}
if (typeof data === 'object' && data !== null) {
return sanitizeObject(data as Record<string, unknown>)
}
return data
}
function sanitizeObject(obj: Record<string, unknown>): Record<string, unknown> {
const result: Record<string, unknown> = {}
for (const [key, value] of Object.entries(obj)) {
if (SENSITIVE_KEY_PATTERN.test(key)) {
result[key] = '[REDACTED]'
} else if (typeof value === 'string') {
result[key] = value.replace(HOME_DIR_PATTERN, '~')
} else if (typeof value === 'object' && value !== null) {
result[key] = sanitizeObject(value as Record<string, unknown>)
} else {
result[key] = value
}
}
return result
}
export function sanitizeToolInput(toolName: string, input: unknown): unknown {
if (typeof input !== 'object' || input === null) return input
const obj = { ...(input as Record<string, unknown>) }
for (const key of Object.keys(obj)) {
if (SENSITIVE_KEY_PATTERN.test(key)) {
obj[key] = '[REDACTED]'
}
}
for (const key of ['file_path', 'path', 'directory'] as const) {
if (key in obj && typeof obj[key] === 'string') {
obj[key] = (obj[key] as string).replace(HOME_DIR_PATTERN, '~')
}
}
return obj
}
export function sanitizeToolOutput(toolName: string, output: string): string {
if (REDACTED_FILE_TOOLS.has(toolName)) {
return `[file content redacted, ${output.length} chars]`
}
if (REDACTED_SHELL_TOOLS.has(toolName)) {
if (output.length > MAX_OUTPUT_LENGTH) {
return output.slice(0, MAX_OUTPUT_LENGTH) + '\n[truncated]'
}
}
if (SENSITIVE_OUTPUT_TOOLS.has(toolName)) {
return `[${toolName} output redacted, ${output.length} chars]`
}
return output
}