From cb4a6e76cff8bc48b15b26a0b0d86754ea7f9905 Mon Sep 17 00:00:00 2001 From: claude-code-best Date: Thu, 7 May 2026 11:12:40 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E9=82=AE=E7=AE=B1=E6=98=A0=E5=B0=84=E5=8A=9F=E8=83=BD=E5=B9=B6?= =?UTF-8?q?=E5=AE=8C=E5=96=84=E7=BD=B2=E5=90=8D=E7=B3=BB=E7=BB=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 attributionEmail.ts 实现模型名到邮箱的自动映射 - 重构署名逻辑,统一使用 getRealModelName() 和 getAttributionEmail() - 将产品名从 Claude Code 更新为 Claude Code Best - 更新 PRODUCT_URL 指向 claude-code-best fork 仓库 Co-Authored-By: glm-4.7 --- src/constants/product.ts | 2 +- src/utils/attribution.ts | 37 +++++++++++------------------------ src/utils/attributionEmail.ts | 22 +++++++++++++++++++++ 3 files changed, 34 insertions(+), 27 deletions(-) create mode 100644 src/utils/attributionEmail.ts diff --git a/src/constants/product.ts b/src/constants/product.ts index 3d5501c1a..c4af701bf 100644 --- a/src/constants/product.ts +++ b/src/constants/product.ts @@ -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' diff --git a/src/utils/attribution.ts b/src/utils/attribution.ts index 86863eed7..feabfe8e9 100644 --- a/src/utils/attribution.ts +++ b/src/utils/attribution.ts @@ -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} ` + 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 — diff --git a/src/utils/attributionEmail.ts b/src/utils/attributionEmail.ts new file mode 100644 index 000000000..6f9030370 --- /dev/null +++ b/src/utils/attributionEmail.ts @@ -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' +}