feat: 添加自动邮箱映射功能并完善署名系统

- 新增 attributionEmail.ts 实现模型名到邮箱的自动映射
- 重构署名逻辑,统一使用 getRealModelName() 和 getAttributionEmail()
- 将产品名从 Claude Code 更新为 Claude Code Best
- 更新 PRODUCT_URL 指向 claude-code-best fork 仓库

Co-Authored-By: glm-4.7 <noreply@zhipuai.cn>
This commit is contained in:
claude-code-best
2026-05-07 11:12:40 +08:00
parent f7f69b759c
commit cb4a6e76cf
3 changed files with 34 additions and 27 deletions

View File

@@ -1,4 +1,4 @@
export const PRODUCT_URL = 'https://claude.com/claude-code'
export const PRODUCT_URL = 'https://github.com/claude-code-best/claude-code'
// Claude Code Remote session URLs
export const CLAUDE_AI_BASE_URL = 'https://claude.ai'

View File

@@ -18,18 +18,12 @@ import {
type AttributionData,
calculateCommitAttribution,
isInternalModelRepo,
isInternalModelRepoCached,
sanitizeModelName,
} from './commitAttribution.js'
import { logForDebugging } from './debug.js'
import { parseJSONL } from './json.js'
import { logError } from './log.js'
import {
getCanonicalName,
getMainLoopModel,
getPublicModelDisplayName,
getPublicModelName,
} from './model/model.js'
import { getAttributionEmail } from './attributionEmail.js'
import { getRealModelName } from './attributionModel.js'
import { isMemoryFileAccess } from './sessionFileAccessHooks.js'
import { getTranscriptPath } from './sessionStorage.js'
import { readTranscriptForLoad } from './sessionStoragePortable.js'
@@ -44,7 +38,8 @@ export type AttributionTexts = {
/**
* Returns attribution text for commits and PRs based on user settings.
* Handles:
* - Dynamic model name via getPublicModelName()
* - Dynamic model name via getRealModelName()
* - Auto email mapping via getAttributionEmail()
* - Custom attribution settings (settings.attribution.commit/pr)
* - Backward compatibility with deprecated includeCoAuthoredBy setting
* - Remote mode: returns session URL for attribution
@@ -67,17 +62,10 @@ export function getAttributionTexts(): AttributionTexts {
return { commit: '', pr: '' }
}
// @[MODEL LAUNCH]: Update the hardcoded fallback model name below (guards against codename leaks).
// For internal repos, use the real model name. For external repos,
// fall back to "Claude Opus 4.6" for unrecognized models to avoid leaking codenames.
const model = getMainLoopModel()
const isKnownPublicModel = getPublicModelDisplayName(model) !== null
const modelName =
isInternalModelRepoCached() || isKnownPublicModel
? getPublicModelName(model)
: 'Claude Opus 4.7'
const defaultAttribution = `🤖 Generated with [Claude Code](${PRODUCT_URL})`
const defaultCommit = `Co-Authored-By: ${modelName} <noreply@anthropic.com>`
const modelName = getRealModelName()
const email = getAttributionEmail(modelName)
const defaultAttribution = `🤖 Generated with [Claude Code Best](${PRODUCT_URL})`
const defaultCommit = `Co-Authored-By: ${modelName} <${email}>`
const settings = getInitialSettings()
@@ -354,11 +342,8 @@ export async function getEnhancedPRAttribution(
`PR Attribution: claudePercent: ${claudePercent}, promptCount: ${promptCount}, memoryAccessCount: ${memoryAccessCount}`,
)
// Get short model name, sanitized for non-internal repos
const rawModelName = getCanonicalName(getMainLoopModel())
const shortModelName = isInternal
? rawModelName
: sanitizeModelName(rawModelName)
// Get real model name for attribution
const realModelName = getRealModelName()
// If no attribution data, return default
if (claudePercent === 0 && promptCount === 0 && memoryAccessCount === 0) {
@@ -371,7 +356,7 @@ export async function getEnhancedPRAttribution(
memoryAccessCount > 0
? `, ${memoryAccessCount} ${memoryAccessCount === 1 ? 'memory' : 'memories'} recalled`
: ''
const summary = `🤖 Generated with [Claude Code](${PRODUCT_URL}) (${claudePercent}% ${promptCount}-shotted by ${shortModelName}${memSuffix})`
const summary = `🤖 Generated with [Claude Code Best](${PRODUCT_URL}) (${claudePercent}% ${promptCount}-shotted by ${realModelName}${memSuffix})`
// Append trailer lines for squash-merge survival. Only for allowlisted repos
// (INTERNAL_MODEL_REPOS) and only in builds with COMMIT_ATTRIBUTION enabled —

View File

@@ -0,0 +1,22 @@
const MODEL_EMAIL_MAP: Array<{ keywords: string[]; email: string }> = [
{ keywords: ['claude'], email: 'noreply@anthropic.com' },
{
keywords: ['gpt', 'dall-e', 'o1-', 'o3-', 'o4-'],
email: 'noreply@openai.com',
},
{ keywords: ['gemini'], email: 'noreply@google.com' },
{ keywords: ['grok'], email: 'noreply@xai.com' },
{ keywords: ['glm'], email: 'noreply@zhipuai.cn' },
{ keywords: ['deepseek'], email: 'noreply@deepseek.com' },
{ keywords: ['qwen'], email: 'noreply@alibabacloud.com' },
]
export function getAttributionEmail(modelName: string): string {
const lower = modelName.toLowerCase()
for (const { keywords, email } of MODEL_EMAIL_MAP) {
if (keywords.some(kw => lower.includes(kw))) {
return email
}
}
return 'noreply@anthropic.com'
}