diff --git a/PRIVACY.md b/PRIVACY.md index 34cd2b9..f1bdf67 100644 --- a/PRIVACY.md +++ b/PRIVACY.md @@ -1,6 +1,6 @@ # Privacy Policy for Panelize -**Last Updated: July 15, 2026** +**Last Updated: July 17, 2026** ## Overview @@ -31,7 +31,6 @@ The following data is stored in browser-managed storage. Prompt library data rem - Enter key behavior preferences - Source URL placement preferences - Language preferences -- Experimental Claude model preference **Purpose:** To maintain your personalized extension configuration. @@ -78,8 +77,6 @@ Panelize loads AI provider websites (ChatGPT, Claude, Gemini, Grok, DeepSeek, Ki When you interact with these AI providers through Panelize, you are subject to their respective privacy policies. Panelize does not collect or store the content of your conversations with these services. -If you explicitly select an experimental Claude model in Panelize, the extension locally processes Claude's outgoing completion request only to insert or replace its top-level model identifier. This processing happens in your browser. Panelize does not log, store, collect, or send the request body or conversation content to Panelize developers or Panelize-operated servers. The modified request continues directly to Claude as part of the chat you initiated. Selecting **Claude default** disables this request modification. - ### Cookie Access Panelize does not access cookie data directly and does not use the cookies API. Provider websites may use your existing browser session cookies when they load inside panels, just like in a normal tab. @@ -216,7 +213,6 @@ If you are a California resident: - Store your prompts and settings locally on your device - Use local browser storage to remember your preferences - Temporarily process selected text or page content on-device when you use the context menu -- Locally set Claude's requested model when you explicitly enable experimental model selection - Load AI provider websites inside embedded panels - Check for updates on GitHub diff --git a/_locales/de/messages.json b/_locales/de/messages.json index 66fee28..f9723e8 100644 --- a/_locales/de/messages.json +++ b/_locales/de/messages.json @@ -813,26 +813,7 @@ "switchToPopupModeTitle": { "message": "Zum Popup-Modus wechseln" }, - "openProviderTopLevel": { "message": "Claude öffnen" }, "openProviderTopLevelTitle": { "message": "In neuem Tab öffnen" }, - "embeddedModelLimitNotice": { "message": "Claude schränkt die Modellauswahl in eingebetteten Ansichten ein. Panelize kann experimentell ein Modell anfordern." }, - "embeddedModelOverrideNotice": { - "message": "Experimentelle Anfrage: $MODEL$. Die Verfügbarkeit hängt von deinem Claude-Konto ab.", - "placeholders": { "model": { "content": "$1" } } - }, - "claudeModelDefault": { "message": "Claude-Standard" }, - "claudeModelExperimentalBadge": { "message": "Experimentell" }, - "claudeModelExperimentalTitle": { "message": "Experimenteller Kompatibilitätsmodus" }, - "claudeModelSelectTitle": { "message": "Claude-Modellanfrage" }, - "claudeModelRequestedStatus": { - "message": "$MODEL$ angefordert", - "placeholders": { "model": { "content": "$1" } } - }, - "claudeModelOverrideUnavailable": { "message": "Die Modellüberschreibung ist nicht verfügbar. Claude-Standard wurde aktiviert." }, - "claudeModelRequestRejected": { - "message": "Die Modellanforderung wurde abgelehnt (HTTP $STATUS$). Claude-Standard wurde aktiviert.", - "placeholders": { "status": { "content": "$1" } } - }, "msgOpenModeUpdated": { "message": "Öffnungsmodus aktualisiert" }, diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 9b58afd..2912820 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -50,54 +50,9 @@ "switchToPopupModeTitle": { "message": "Switch to Popup Mode" }, - "openProviderTopLevel": { - "message": "Open Claude" - }, "openProviderTopLevelTitle": { "message": "Open in new tab" }, - "embeddedModelLimitNotice": { - "message": "Claude limits model selection when embedded. Panelize can experimentally request a model." - }, - "embeddedModelOverrideNotice": { - "message": "Experimental request: $MODEL$. Availability depends on your Claude account.", - "placeholders": { - "model": { - "content": "$1" - } - } - }, - "claudeModelDefault": { - "message": "Claude default" - }, - "claudeModelExperimentalBadge": { - "message": "Experimental" - }, - "claudeModelExperimentalTitle": { - "message": "Experimental compatibility mode" - }, - "claudeModelSelectTitle": { - "message": "Claude model request" - }, - "claudeModelRequestedStatus": { - "message": "Requested $MODEL$", - "placeholders": { - "model": { - "content": "$1" - } - } - }, - "claudeModelOverrideUnavailable": { - "message": "Model override is unavailable. Switched to Claude default." - }, - "claudeModelRequestRejected": { - "message": "Model request was rejected (HTTP $STATUS$). Switched to Claude default.", - "placeholders": { - "status": { - "content": "$1" - } - } - }, "msgOpenModeUpdated": { "message": "Open mode updated" }, diff --git a/_locales/es/messages.json b/_locales/es/messages.json index 6631ef0..2982269 100644 --- a/_locales/es/messages.json +++ b/_locales/es/messages.json @@ -813,26 +813,7 @@ "switchToPopupModeTitle": { "message": "Cambiar a modo ventana emergente" }, - "openProviderTopLevel": { "message": "Abrir Claude" }, "openProviderTopLevelTitle": { "message": "Abrir en una pestaña nueva" }, - "embeddedModelLimitNotice": { "message": "Claude limita la selección de modelos cuando está integrado. Panelize puede solicitar un modelo de forma experimental." }, - "embeddedModelOverrideNotice": { - "message": "Solicitud experimental: $MODEL$. La disponibilidad depende de tu cuenta de Claude.", - "placeholders": { "model": { "content": "$1" } } - }, - "claudeModelDefault": { "message": "Predeterminado de Claude" }, - "claudeModelExperimentalBadge": { "message": "Experimental" }, - "claudeModelExperimentalTitle": { "message": "Modo de compatibilidad experimental" }, - "claudeModelSelectTitle": { "message": "Solicitud de modelo de Claude" }, - "claudeModelRequestedStatus": { - "message": "Solicitado $MODEL$", - "placeholders": { "model": { "content": "$1" } } - }, - "claudeModelOverrideUnavailable": { "message": "La selección experimental no está disponible. Se cambió al modelo predeterminado de Claude." }, - "claudeModelRequestRejected": { - "message": "La solicitud de modelo fue rechazada (HTTP $STATUS$). Se cambió al modelo predeterminado de Claude.", - "placeholders": { "status": { "content": "$1" } } - }, "msgOpenModeUpdated": { "message": "Modo de apertura actualizado" }, diff --git a/_locales/fr/messages.json b/_locales/fr/messages.json index 02d41d7..1d90b02 100644 --- a/_locales/fr/messages.json +++ b/_locales/fr/messages.json @@ -813,26 +813,7 @@ "switchToPopupModeTitle": { "message": "Passer au mode fenêtre popup" }, - "openProviderTopLevel": { "message": "Ouvrir Claude" }, "openProviderTopLevelTitle": { "message": "Ouvrir dans un nouvel onglet" }, - "embeddedModelLimitNotice": { "message": "Claude limite la sélection des modèles lorsqu’il est intégré. Panelize peut demander un modèle de manière expérimentale." }, - "embeddedModelOverrideNotice": { - "message": "Demande expérimentale : $MODEL$. La disponibilité dépend de votre compte Claude.", - "placeholders": { "model": { "content": "$1" } } - }, - "claudeModelDefault": { "message": "Modèle Claude par défaut" }, - "claudeModelExperimentalBadge": { "message": "Expérimental" }, - "claudeModelExperimentalTitle": { "message": "Mode de compatibilité expérimental" }, - "claudeModelSelectTitle": { "message": "Demande de modèle Claude" }, - "claudeModelRequestedStatus": { - "message": "$MODEL$ demandé", - "placeholders": { "model": { "content": "$1" } } - }, - "claudeModelOverrideUnavailable": { "message": "La sélection expérimentale n’est pas disponible. Retour au modèle Claude par défaut." }, - "claudeModelRequestRejected": { - "message": "La demande de modèle a été refusée (HTTP $STATUS$). Retour au modèle Claude par défaut.", - "placeholders": { "status": { "content": "$1" } } - }, "msgOpenModeUpdated": { "message": "Mode d'ouverture mis à jour" }, diff --git a/_locales/it/messages.json b/_locales/it/messages.json index dce5ee4..bf67125 100644 --- a/_locales/it/messages.json +++ b/_locales/it/messages.json @@ -813,26 +813,7 @@ "switchToPopupModeTitle": { "message": "Passa alla modalità finestra popup" }, - "openProviderTopLevel": { "message": "Apri Claude" }, "openProviderTopLevelTitle": { "message": "Apri in una nuova scheda" }, - "embeddedModelLimitNotice": { "message": "Claude limita la selezione dei modelli quando è incorporato. Panelize può richiedere un modello in via sperimentale." }, - "embeddedModelOverrideNotice": { - "message": "Richiesta sperimentale: $MODEL$. La disponibilità dipende dal tuo account Claude.", - "placeholders": { "model": { "content": "$1" } } - }, - "claudeModelDefault": { "message": "Predefinito di Claude" }, - "claudeModelExperimentalBadge": { "message": "Sperimentale" }, - "claudeModelExperimentalTitle": { "message": "Modalità di compatibilità sperimentale" }, - "claudeModelSelectTitle": { "message": "Richiesta modello Claude" }, - "claudeModelRequestedStatus": { - "message": "Richiesto $MODEL$", - "placeholders": { "model": { "content": "$1" } } - }, - "claudeModelOverrideUnavailable": { "message": "La selezione sperimentale non è disponibile. È stato ripristinato il modello predefinito di Claude." }, - "claudeModelRequestRejected": { - "message": "La richiesta del modello è stata rifiutata (HTTP $STATUS$). È stato ripristinato il modello predefinito di Claude.", - "placeholders": { "status": { "content": "$1" } } - }, "msgOpenModeUpdated": { "message": "Modalità di apertura aggiornata" }, diff --git a/_locales/ja/messages.json b/_locales/ja/messages.json index 099d056..4841512 100644 --- a/_locales/ja/messages.json +++ b/_locales/ja/messages.json @@ -813,26 +813,7 @@ "switchToPopupModeTitle": { "message": "ポップアップモードに切り替え" }, - "openProviderTopLevel": { "message": "Claude を開く" }, "openProviderTopLevelTitle": { "message": "新しいタブで開く" }, - "embeddedModelLimitNotice": { "message": "埋め込み表示では Claude のモデル選択が制限されます。Panelize から実験的にモデルを指定できます。" }, - "embeddedModelOverrideNotice": { - "message": "実験的なリクエスト:$MODEL$。利用可否は Claude アカウントによって異なります。", - "placeholders": { "model": { "content": "$1" } } - }, - "claudeModelDefault": { "message": "Claude のデフォルト" }, - "claudeModelExperimentalBadge": { "message": "実験的" }, - "claudeModelExperimentalTitle": { "message": "実験的な互換モード" }, - "claudeModelSelectTitle": { "message": "Claude モデルのリクエスト" }, - "claudeModelRequestedStatus": { - "message": "$MODEL$ をリクエストしました", - "placeholders": { "model": { "content": "$1" } } - }, - "claudeModelOverrideUnavailable": { "message": "モデル指定を利用できません。Claude のデフォルトに戻しました。" }, - "claudeModelRequestRejected": { - "message": "モデルのリクエストが拒否されました(HTTP $STATUS$)。Claude のデフォルトに戻しました。", - "placeholders": { "status": { "content": "$1" } } - }, "msgOpenModeUpdated": { "message": "開くモードを更新しました" }, diff --git a/_locales/ko/messages.json b/_locales/ko/messages.json index fc8cb3a..e3cc462 100644 --- a/_locales/ko/messages.json +++ b/_locales/ko/messages.json @@ -813,26 +813,7 @@ "switchToPopupModeTitle": { "message": "팝업 모드로 전환" }, - "openProviderTopLevel": { "message": "Claude 열기" }, "openProviderTopLevelTitle": { "message": "새 탭에서 열기" }, - "embeddedModelLimitNotice": { "message": "Claude는 임베드된 화면에서 모델 선택을 제한합니다. Panelize가 실험적으로 모델을 요청할 수 있습니다." }, - "embeddedModelOverrideNotice": { - "message": "실험적 요청: $MODEL$. 사용 가능 여부는 Claude 계정에 따라 달라집니다.", - "placeholders": { "model": { "content": "$1" } } - }, - "claudeModelDefault": { "message": "Claude 기본값" }, - "claudeModelExperimentalBadge": { "message": "실험적" }, - "claudeModelExperimentalTitle": { "message": "실험적 호환 모드" }, - "claudeModelSelectTitle": { "message": "Claude 모델 요청" }, - "claudeModelRequestedStatus": { - "message": "$MODEL$ 요청됨", - "placeholders": { "model": { "content": "$1" } } - }, - "claudeModelOverrideUnavailable": { "message": "모델 재정의를 사용할 수 없습니다. Claude 기본값으로 전환했습니다." }, - "claudeModelRequestRejected": { - "message": "모델 요청이 거부되었습니다(HTTP $STATUS$). Claude 기본값으로 전환했습니다.", - "placeholders": { "status": { "content": "$1" } } - }, "msgOpenModeUpdated": { "message": "열기 모드가 업데이트되었습니다" }, diff --git a/_locales/ru/messages.json b/_locales/ru/messages.json index cecca22..d9587a4 100644 --- a/_locales/ru/messages.json +++ b/_locales/ru/messages.json @@ -813,26 +813,7 @@ "switchToPopupModeTitle": { "message": "Переключиться в режим всплывающего окна" }, - "openProviderTopLevel": { "message": "Открыть Claude" }, "openProviderTopLevelTitle": { "message": "Открыть в новой вкладке" }, - "embeddedModelLimitNotice": { "message": "Claude ограничивает выбор моделей во встроенном режиме. Panelize может экспериментально запросить определённую модель." }, - "embeddedModelOverrideNotice": { - "message": "Экспериментальный запрос: $MODEL$. Доступность зависит от вашей учётной записи Claude.", - "placeholders": { "model": { "content": "$1" } } - }, - "claudeModelDefault": { "message": "Модель Claude по умолчанию" }, - "claudeModelExperimentalBadge": { "message": "Экспериментально" }, - "claudeModelExperimentalTitle": { "message": "Экспериментальный режим совместимости" }, - "claudeModelSelectTitle": { "message": "Запрос модели Claude" }, - "claudeModelRequestedStatus": { - "message": "Запрошена модель $MODEL$", - "placeholders": { "model": { "content": "$1" } } - }, - "claudeModelOverrideUnavailable": { "message": "Переопределение модели недоступно. Выбрана модель Claude по умолчанию." }, - "claudeModelRequestRejected": { - "message": "Запрос модели отклонён (HTTP $STATUS$). Выбрана модель Claude по умолчанию.", - "placeholders": { "status": { "content": "$1" } } - }, "msgOpenModeUpdated": { "message": "Режим открытия обновлен" }, diff --git a/_locales/zh_CN/messages.json b/_locales/zh_CN/messages.json index 397b743..5ef0091 100644 --- a/_locales/zh_CN/messages.json +++ b/_locales/zh_CN/messages.json @@ -807,54 +807,9 @@ "switchToPopupModeTitle": { "message": "切换到弹出窗口模式" }, - "openProviderTopLevel": { - "message": "打开 Claude" - }, "openProviderTopLevelTitle": { "message": "在新标签页中打开" }, - "embeddedModelLimitNotice": { - "message": "Claude 会限制内嵌页面中的模型选择。Panelize 可以通过实验性方式请求指定模型。" - }, - "embeddedModelOverrideNotice": { - "message": "实验性请求:$MODEL$。是否可用取决于你的 Claude 账号。", - "placeholders": { - "model": { - "content": "$1" - } - } - }, - "claudeModelDefault": { - "message": "Claude 默认模型" - }, - "claudeModelExperimentalBadge": { - "message": "实验性" - }, - "claudeModelExperimentalTitle": { - "message": "实验性兼容模式" - }, - "claudeModelSelectTitle": { - "message": "Claude 模型请求" - }, - "claudeModelRequestedStatus": { - "message": "已请求 $MODEL$", - "placeholders": { - "model": { - "content": "$1" - } - } - }, - "claudeModelOverrideUnavailable": { - "message": "模型覆盖不可用,已切换到 Claude 默认模型。" - }, - "claudeModelRequestRejected": { - "message": "模型请求被拒绝(HTTP $STATUS$),已切换到 Claude 默认模型。", - "placeholders": { - "status": { - "content": "$1" - } - } - }, "msgOpenModeUpdated": { "message": "打开模式已更新" }, diff --git a/_locales/zh_TW/messages.json b/_locales/zh_TW/messages.json index 5f96691..a417d5b 100644 --- a/_locales/zh_TW/messages.json +++ b/_locales/zh_TW/messages.json @@ -807,54 +807,9 @@ "switchToPopupModeTitle": { "message": "切換到彈出視窗模式" }, - "openProviderTopLevel": { - "message": "開啟 Claude" - }, "openProviderTopLevelTitle": { "message": "在新分頁中開啟" }, - "embeddedModelLimitNotice": { - "message": "Claude 會限制內嵌頁面中的模型選擇。Panelize 可以透過實驗性方式請求指定模型。" - }, - "embeddedModelOverrideNotice": { - "message": "實驗性請求:$MODEL$。是否可用取決於你的 Claude 帳號。", - "placeholders": { - "model": { - "content": "$1" - } - } - }, - "claudeModelDefault": { - "message": "Claude 預設模型" - }, - "claudeModelExperimentalBadge": { - "message": "實驗性" - }, - "claudeModelExperimentalTitle": { - "message": "實驗性相容模式" - }, - "claudeModelSelectTitle": { - "message": "Claude 模型請求" - }, - "claudeModelRequestedStatus": { - "message": "已請求 $MODEL$", - "placeholders": { - "model": { - "content": "$1" - } - } - }, - "claudeModelOverrideUnavailable": { - "message": "模型覆寫不可用,已切換至 Claude 預設模型。" - }, - "claudeModelRequestRejected": { - "message": "模型請求遭到拒絕(HTTP $STATUS$),已切換至 Claude 預設模型。", - "placeholders": { - "status": { - "content": "$1" - } - } - }, "msgOpenModeUpdated": { "message": "開啟模式已更新" }, diff --git a/background/service-worker.js b/background/service-worker.js index a991cf2..d3dd37d 100644 --- a/background/service-worker.js +++ b/background/service-worker.js @@ -1,6 +1,7 @@ import { notifyMessage } from '../modules/messaging.js'; import { t, initializeLanguage } from '../modules/i18n.js'; import { migrateEnabledProvidersOnUpdate } from '../modules/provider-defaults.js'; +import { removeDeprecatedClaudeModelMode } from '../modules/settings.js'; import { reconcileOptionalProviderAccess } from '../modules/optional-provider-access.js'; @@ -127,6 +128,9 @@ function scheduleOptionalProviderReconcile() { chrome.runtime.onInstalled.addListener(async (details) => { await migrateProviderSettingsForUpdate(details); + if (details?.reason === 'update') { + await removeDeprecatedClaudeModelMode(); + } await scheduleOptionalProviderReconcile(); await createContextMenus(); await loadShortcutSetting(); diff --git a/content-scripts/claude-model-request-interceptor.js b/content-scripts/claude-model-request-interceptor.js deleted file mode 100644 index 5a8f6e7..0000000 --- a/content-scripts/claude-model-request-interceptor.js +++ /dev/null @@ -1,192 +0,0 @@ -(function initializeClaudeModelRequestInterceptor() { - 'use strict'; - - if (window.self === window.top) { - return; - } - - const utils = globalThis.PanelizeClaudeModelRequestUtils; - if (!utils) { - return; - } - - const MESSAGE_OVERRIDE = 'PANELIZE_CLAUDE_MODEL_OVERRIDE'; - const MESSAGE_PROBE = 'PANELIZE_CLAUDE_MODEL_PROBE'; - const DEFAULT_MODE = 'default'; - const MODELS_BY_MODE = Object.freeze({ - 'sonnet-5': 'claude-sonnet-5', - 'opus-4-8': 'claude-opus-4-8', - 'haiku-4-5': 'claude-haiku-4-5-20251001' - }); - const overrideState = { - mode: DEFAULT_MODE, - model: '' - }; - let parentOrigin = ''; - - function reportProbe(event, details = {}) { - window.parent.postMessage({ - type: MESSAGE_PROBE, - event, - ...details - }, parentOrigin || '*'); - } - - function isExtensionParentMessage(event) { - return event.source === window.parent && - typeof event.origin === 'string' && - event.origin.startsWith('chrome-extension://'); - } - - function disableOverride(event, details = {}) { - overrideState.mode = DEFAULT_MODE; - overrideState.model = ''; - reportProbe(event, details); - } - - window.addEventListener('message', event => { - if (!isExtensionParentMessage(event) || event.data?.type !== MESSAGE_OVERRIDE) { - return; - } - - parentOrigin = event.origin; - const mode = typeof event.data.mode === 'string' ? event.data.mode : DEFAULT_MODE; - const expectedModel = MODELS_BY_MODE[mode] || ''; - const requestedModel = typeof event.data.model === 'string' ? event.data.model : ''; - - if (mode === DEFAULT_MODE && !requestedModel) { - overrideState.mode = DEFAULT_MODE; - overrideState.model = ''; - reportProbe('override-configured', { mode: DEFAULT_MODE }); - return; - } - - if (!expectedModel || requestedModel !== expectedModel || !utils.isAllowedModelId(requestedModel)) { - disableOverride('override-config-rejected'); - return; - } - - overrideState.mode = mode; - overrideState.model = requestedModel; - reportProbe('override-configured', { mode }); - }); - - function rewriteBodyIfNeeded(url, body) { - if (!overrideState.model || !utils.isClaudeCompletionUrl(url, window.location.href)) { - return { - body, - overridden: false - }; - } - - const result = utils.rewriteCompletionBody(body, overrideState.model); - if (!result.overridden) { - disableOverride('override-schema-unsupported', { reason: result.reason }); - return { - body, - overridden: false - }; - } - - reportProbe('request-overridden', { - mode: overrideState.mode, - changed: result.changed !== false, - inserted: result.inserted === true - }); - return { - body: result.body, - overridden: true, - mode: overrideState.mode - }; - } - - function handleResponseStatus(status, requestMode) { - const classification = utils.classifyResponseStatus(status); - if (classification === 'accepted' && overrideState.mode === requestMode) { - reportProbe('override-request-accepted', { - mode: requestMode, - status - }); - return; - } - - if (classification === 'rejected' && overrideState.mode === requestMode) { - disableOverride('override-request-rejected', { status }); - } - } - - const nativeFetch = window.fetch; - window.fetch = async function panelizeClaudeModelFetch(input, init) { - const inputUrl = input instanceof Request ? input.url : input; - if (!overrideState.model || !utils.isClaudeCompletionUrl(inputUrl, window.location.href)) { - return nativeFetch.call(this, input, init); - } - - let requestMode = DEFAULT_MODE; - let response; - - if (init && typeof init.body === 'string') { - const result = rewriteBodyIfNeeded(inputUrl, init.body); - requestMode = result.mode || DEFAULT_MODE; - response = await nativeFetch.call(this, input, { - ...init, - body: result.body - }); - } else { - try { - const request = input instanceof Request && !init - ? input - : new Request(input, init); - - if (request.bodyUsed || ['GET', 'HEAD'].includes(request.method)) { - disableOverride('override-schema-unsupported', { reason: 'unreadable-body' }); - return nativeFetch.call(this, input, init); - } - - const originalBody = await request.clone().text(); - const result = rewriteBodyIfNeeded(request.url, originalBody); - requestMode = result.mode || DEFAULT_MODE; - response = result.overridden - ? await nativeFetch.call(this, new Request(request, { body: result.body })) - : await nativeFetch.call(this, input, init); - } catch (_error) { - disableOverride('override-schema-unsupported', { reason: 'request-inspection-failed' }); - return nativeFetch.call(this, input, init); - } - } - - if (requestMode !== DEFAULT_MODE) { - handleResponseStatus(response.status, requestMode); - } - return response; - }; - - const nativeXhrOpen = XMLHttpRequest.prototype.open; - const nativeXhrSend = XMLHttpRequest.prototype.send; - const xhrMetadata = new WeakMap(); - - XMLHttpRequest.prototype.open = function panelizeClaudeModelXhrOpen(method, url, ...rest) { - xhrMetadata.set(this, { - url: new URL(url, window.location.href).href - }); - return nativeXhrOpen.call(this, method, url, ...rest); - }; - - XMLHttpRequest.prototype.send = function panelizeClaudeModelXhrSend(body) { - const metadata = xhrMetadata.get(this); - if (!metadata || !overrideState.model || !utils.isClaudeCompletionUrl(metadata.url)) { - return nativeXhrSend.call(this, body); - } - - const result = rewriteBodyIfNeeded(metadata.url, body); - if (result.overridden) { - const requestMode = result.mode; - this.addEventListener('loadend', () => { - handleResponseStatus(this.status, requestMode); - }, { once: true }); - } - return nativeXhrSend.call(this, result.body); - }; - - reportProbe('probe-ready'); -})(); diff --git a/content-scripts/claude-model-request-utils.js b/content-scripts/claude-model-request-utils.js deleted file mode 100644 index 225de43..0000000 --- a/content-scripts/claude-model-request-utils.js +++ /dev/null @@ -1,116 +0,0 @@ -(function initializeClaudeModelRequestUtils(globalScope) { - 'use strict'; - - const CLAUDE_ORIGIN = 'https://claude.ai'; - const CLAUDE_COMPLETION_PATH_SUFFIX = '/completion'; - const ALLOWED_MODEL_IDS = new Set([ - 'claude-sonnet-5', - 'claude-opus-4-8', - 'claude-haiku-4-5-20251001' - ]); - - function isAllowedModelId(modelId) { - return typeof modelId === 'string' && ALLOWED_MODEL_IDS.has(modelId); - } - - function isClaudeCompletionUrl(value, baseUrl = `${CLAUDE_ORIGIN}/`) { - try { - const url = new URL(value, baseUrl); - return url.origin === CLAUDE_ORIGIN && - url.pathname.endsWith(CLAUDE_COMPLETION_PATH_SUFFIX); - } catch (_error) { - return false; - } - } - - function rewriteCompletionBody(body, targetModel) { - if (!isAllowedModelId(targetModel)) { - return { - body, - overridden: false, - reason: 'unsupported-model' - }; - } - - if (typeof body !== 'string') { - return { - body, - overridden: false, - reason: 'unsupported-body' - }; - } - - let value; - try { - value = JSON.parse(body); - } catch (_error) { - return { - body, - overridden: false, - reason: 'invalid-json' - }; - } - - if (!value || typeof value !== 'object' || Array.isArray(value)) { - return { - body, - overridden: false, - reason: 'unsupported-shape' - }; - } - - if ( - Object.prototype.hasOwnProperty.call(value, 'model') && - typeof value.model !== 'string' - ) { - return { - body, - overridden: false, - reason: 'unsupported-model-field' - }; - } - - if (value.model === targetModel) { - return { - body, - overridden: true, - changed: false, - reason: 'already-selected' - }; - } - - const inserted = !Object.prototype.hasOwnProperty.call(value, 'model'); - value.model = targetModel; - - return { - body: JSON.stringify(value), - overridden: true, - changed: true, - inserted, - reason: inserted ? 'model-injected' : 'model-replaced' - }; - } - - function classifyResponseStatus(status) { - if (!Number.isInteger(status)) { - return 'unknown'; - } - if (status >= 200 && status < 300) { - return 'accepted'; - } - if (status >= 400 && status < 500) { - return 'rejected'; - } - if (status >= 500) { - return 'server-error'; - } - return 'unknown'; - } - - globalScope.PanelizeClaudeModelRequestUtils = { - classifyResponseStatus, - isAllowedModelId, - isClaudeCompletionUrl, - rewriteCompletionBody - }; -})(globalThis); diff --git a/manifest.json b/manifest.json index 89bc7d3..4e9e42e 100644 --- a/manifest.json +++ b/manifest.json @@ -71,18 +71,6 @@ "128": "icons/icon-128.png" }, "content_scripts": [ - { - "matches": [ - "https://claude.ai/*" - ], - "js": [ - "content-scripts/claude-model-request-utils.js", - "content-scripts/claude-model-request-interceptor.js" - ], - "run_at": "document_start", - "all_frames": true, - "world": "MAIN" - }, { "matches": [ "https://chatgpt.com/*", diff --git a/modules/claude-model-mode.js b/modules/claude-model-mode.js deleted file mode 100644 index 13e0526..0000000 --- a/modules/claude-model-mode.js +++ /dev/null @@ -1,72 +0,0 @@ -export const CLAUDE_MODEL_OVERRIDE_MESSAGE_TYPE = 'PANELIZE_CLAUDE_MODEL_OVERRIDE'; - -export const CLAUDE_MODEL_MODE_DEFAULT = 'default'; -export const CLAUDE_MODEL_MODE_SONNET_5 = 'sonnet-5'; -export const CLAUDE_MODEL_MODE_OPUS_4_8 = 'opus-4-8'; -export const CLAUDE_MODEL_MODE_HAIKU_4_5 = 'haiku-4-5'; -export const DEFAULT_CLAUDE_MODEL_MODE = CLAUDE_MODEL_MODE_DEFAULT; - -/** Supported user-facing Claude model modes and their request identifiers. */ -export const CLAUDE_MODEL_OPTIONS = Object.freeze([ - Object.freeze({ - mode: CLAUDE_MODEL_MODE_DEFAULT, - label: 'Claude default', - modelId: '' - }), - Object.freeze({ - mode: CLAUDE_MODEL_MODE_OPUS_4_8, - label: 'Opus 4.8', - modelId: 'claude-opus-4-8' - }), - Object.freeze({ - mode: CLAUDE_MODEL_MODE_SONNET_5, - label: 'Sonnet 5', - modelId: 'claude-sonnet-5' - }), - Object.freeze({ - mode: CLAUDE_MODEL_MODE_HAIKU_4_5, - label: 'Haiku 4.5', - modelId: 'claude-haiku-4-5-20251001' - }) -]); - -const CLAUDE_MODEL_OPTIONS_BY_MODE = new Map( - CLAUDE_MODEL_OPTIONS.map(option => [option.mode, option]) -); - -/** - * Normalize a stored Claude model mode to a supported value. - * - * @param {unknown} mode Stored model mode. - * @returns {string} A supported Claude model mode. - */ -export function normalizeClaudeModelMode(mode) { - return CLAUDE_MODEL_OPTIONS_BY_MODE.has(mode) - ? mode - : DEFAULT_CLAUDE_MODEL_MODE; -} - -/** - * Get the display and request metadata for a Claude model mode. - * - * @param {unknown} mode Claude model mode. - * @returns {{mode: string, label: string, modelId: string}} - */ -export function getClaudeModelOption(mode) { - return CLAUDE_MODEL_OPTIONS_BY_MODE.get(normalizeClaudeModelMode(mode)); -} - -/** - * Build the parent-to-frame message used to configure Claude request overrides. - * - * @param {unknown} mode Claude model mode. - * @returns {{type: string, mode: string, model: string}} - */ -export function createClaudeModelOverrideMessage(mode) { - const option = getClaudeModelOption(mode); - return { - type: CLAUDE_MODEL_OVERRIDE_MESSAGE_TYPE, - mode: option.mode, - model: option.modelId - }; -} diff --git a/modules/providers.js b/modules/providers.js index 8c5c7a0..bb4fbc7 100644 --- a/modules/providers.js +++ b/modules/providers.js @@ -21,9 +21,7 @@ export const PROVIDERS = [ topLevelUrl: 'https://claude.ai/new', icon: '/icons/providers/claude.png', iconDark: '/icons/providers/dark/claude.png', - enabled: true, - // Claude can serve a limited model selector when embedded in an extension iframe. - embeddedModelSelectionLimited: true + enabled: true }, { id: 'gemini', diff --git a/modules/settings.js b/modules/settings.js index bc6421e..2be883e 100644 --- a/modules/settings.js +++ b/modules/settings.js @@ -1,11 +1,9 @@ import { DEFAULT_GOOGLE_PROVIDER_MODE } from './google-mode.js'; -import { DEFAULT_CLAUDE_MODEL_MODE } from './claude-model-mode.js'; import { DEFAULT_PROVIDER_IDS } from './provider-defaults.js'; const DEFAULT_SETTINGS = { enabledProviders: DEFAULT_PROVIDER_IDS, googleProviderMode: DEFAULT_GOOGLE_PROVIDER_MODE, - claudeModelMode: DEFAULT_CLAUDE_MODEL_MODE, providerOrder: null, defaultProvider: 'chatgpt', lastSelectedProvider: 'chatgpt', @@ -91,6 +89,31 @@ export async function saveSettings(settings) { } } +/** + * Remove the retired Claude model override preference from browser storage. + * + * This is a best-effort upgrade cleanup. Each storage area is handled + * independently so one unavailable area does not prevent cleaning the other. + * + * @returns {Promise} + */ +export async function removeDeprecatedClaudeModelMode() { + if (!isChromeApiAvailable()) { + return; + } + + const storageAreas = [chrome.storage.sync, chrome.storage.local] + .filter(area => typeof area?.remove === 'function'); + + await Promise.all(storageAreas.map(async area => { + try { + await area.remove('claudeModelMode'); + } catch { + // Ignore storage errors during best-effort upgrade cleanup. + } + })); +} + export async function resetSettings() { if (!isChromeApiAvailable()) { console.warn('Chrome API not available, cannot reset settings'); diff --git a/multi-panel/multi-panel.css b/multi-panel/multi-panel.css index 92d6bd4..8ea458e 100644 --- a/multi-panel/multi-panel.css +++ b/multi-panel/multi-panel.css @@ -473,8 +473,7 @@ body { min-width: 0; } -.panel-google-mode-select, -.panel-claude-model-select { +.panel-google-mode-select { height: 24px; padding: 0 24px 0 6px; border: 1px solid #d9d9d9; @@ -495,22 +494,7 @@ body { max-width: 100%; } -.claude-model-experimental-badge { - padding: 2px 5px; - border: 1px solid #e0a93f; - border-radius: 999px; - color: #8a5a00; - font-size: 9px; - font-weight: 600; - line-height: 1.2; - white-space: nowrap; -} - @container (max-width: 380px) { - .claude-model-experimental-badge { - display: none; - } - .panel-header { padding-inline: 8px; } @@ -524,10 +508,6 @@ body { .panel-header-left span { display: none; } - - .panel-claude-model-select { - max-width: 105px; - } } @container (max-width: 180px) { @@ -545,12 +525,6 @@ body { width: 100%; gap: 2px; } - - .panel-claude-model-select { - flex: 1; - width: auto !important; - max-width: calc(100% - 26px); - } } .panel-header-right button { @@ -591,93 +565,6 @@ body { border: none; } -.embedded-model-limit-notice { - display: flex; - align-items: center; - gap: 8px; - padding: 6px 10px; - background: #fff7e6; - border-bottom: 1px solid #ffe0a3; - color: #8a5a00; - font-size: 12px; - line-height: 1.4; -} - -.embedded-model-limit-notice-content { - display: flex; - flex: 1; - min-width: 0; - flex-wrap: wrap; - align-items: center; - gap: 4px 10px; -} - -.embedded-model-limit-notice-text { - flex: 1 1 320px; - min-width: 0; -} - -.claude-model-override-status { - color: #7a6740; - white-space: nowrap; -} - -.claude-model-override-status[data-state="active"], -.claude-model-override-status[data-state="success"] { - color: #2e7d32; -} - -.claude-model-override-status[data-state="error"] { - color: #b3261e; - flex: 1 1 100%; - white-space: normal; -} - -.embedded-model-limit-notice .open-provider-top-level-inline-btn { - flex: none; - padding: 4px 10px; - border: 1px solid #e0a93f; - border-radius: 4px; - background: #ffefcc; - color: #8a5a00; - font-size: 12px; - cursor: pointer; - white-space: nowrap; -} - -.embedded-model-limit-notice .open-provider-top-level-inline-btn:hover { - background: #ffe4ad; -} - -[data-theme="dark"] .embedded-model-limit-notice { - background: #3a2f1a; - border-bottom-color: #5a4a26; - color: #f0c674; -} - -[data-theme="dark"] .embedded-model-limit-notice .open-provider-top-level-inline-btn { - border-color: #6b572c; - background: #4a3c1f; - color: #f0c674; -} - -[data-theme="dark"] .embedded-model-limit-notice .open-provider-top-level-inline-btn:hover { - background: #5a4a26; -} - -[data-theme="dark"] .claude-model-override-status { - color: #d4bd89; -} - -[data-theme="dark"] .claude-model-override-status[data-state="active"], -[data-theme="dark"] .claude-model-override-status[data-state="success"] { - color: #81c784; -} - -[data-theme="dark"] .claude-model-override-status[data-state="error"] { - color: #ff8a80; -} - .panel-loading { position: absolute; top: 0; @@ -1417,19 +1304,13 @@ body { color: #aaa; } -[data-theme="dark"] .panel-google-mode-select, -[data-theme="dark"] .panel-claude-model-select { +[data-theme="dark"] .panel-google-mode-select { background-color: #333; border-color: #555; color: #e0e0e0; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 14 14'%3E%3Cpath d='M3.5 5.25L7 8.75l3.5-3.5' fill='none' stroke='%23e0e0e0' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); } -[data-theme="dark"] .claude-model-experimental-badge { - border-color: #8b7136; - color: #f0c674; -} - [data-theme="dark"] .panel-header-right button:hover { background: #555; color: #e0e0e0; diff --git a/multi-panel/multi-panel.js b/multi-panel/multi-panel.js index e15c853..62e2b27 100644 --- a/multi-panel/multi-panel.js +++ b/multi-panel/multi-panel.js @@ -19,14 +19,6 @@ import { isProviderAllowedUrl, isProviderCurrentUrl } from '../modules/provider-open-url.js'; -import { - CLAUDE_MODEL_MODE_DEFAULT, - CLAUDE_MODEL_OPTIONS, - DEFAULT_CLAUDE_MODEL_MODE, - getClaudeModelOption, - normalizeClaudeModelMode, - createClaudeModelOverrideMessage -} from '../modules/claude-model-mode.js'; import { saveSetting } from '../modules/settings.js'; import { applyTheme } from '../modules/theme-manager.js'; import { t, initializeLanguage } from '../modules/i18n.js'; @@ -113,7 +105,6 @@ function refreshThemeAwareProviderIcons() { }); } let currentGoogleProviderMode = DEFAULT_GOOGLE_PROVIDER_MODE; -let currentClaudeModelMode = DEFAULT_CLAUDE_MODEL_MODE; // 提示词编辑器状态 let currentEditingPromptId = null; @@ -135,7 +126,6 @@ const PANELIZE_PROVIDER_IDLE = 'PANELIZE_PROVIDER_IDLE'; const PANELIZE_PROVIDER_USER_INTERACTION = 'PANELIZE_PROVIDER_USER_INTERACTION'; const PANELIZE_TEMP_CHAT_ENABLED = 'PANELIZE_TEMP_CHAT_ENABLED'; const PANELIZE_PROVIDER_LOCATION = 'PANELIZE_PROVIDER_LOCATION'; -const PANELIZE_CLAUDE_MODEL_PROBE = 'PANELIZE_CLAUDE_MODEL_PROBE'; const TEMP_CHAT_RETRY_DELAYS = [1200, 2500, 4000]; const TEMP_CHAT_OPERATION_TIMEOUT_MS = 5000; const TEMP_CHAT_SUPPORTED_PROVIDERS = new Set(['chatgpt', 'gemini', 'claude', 'grok']); @@ -246,11 +236,6 @@ function isChatgptProvider(providerId) { return providerId === 'chatgpt'; } -function providerHasEmbeddedModelSelectionLimit(providerId) { - const provider = getProviderById(providerId); - return Boolean(provider && provider.embeddedModelSelectionLimited); -} - function isTemporaryChatSupportedProvider(providerId) { return TEMP_CHAT_SUPPORTED_PROVIDERS.has(providerId); } @@ -323,27 +308,6 @@ function getGoogleModeSelectHtml(mode = currentGoogleProviderMode) { `; } -function getClaudeModelLabel(option) { - if (option.mode === CLAUDE_MODEL_MODE_DEFAULT) { - return getLocalizedText('claudeModelDefault', 'Claude default'); - } - return option.label; -} - -function getClaudeModelSelectHtml(mode = currentClaudeModelMode) { - const normalizedMode = normalizeClaudeModelMode(mode); - const options = CLAUDE_MODEL_OPTIONS.map(option => ` - - `).join(''); - - return ` - ${getLocalizedText('claudeModelExperimentalBadge', 'Experimental')} - - `; -} - function fitPanelSelectWidth(select) { if (!(select instanceof HTMLSelectElement)) { return; @@ -383,9 +347,6 @@ function getPanelHeaderRightHtml(providerId) { const googleModeSelect = isGoogleProvider(providerId) ? getGoogleModeSelectHtml() : ''; - const claudeModelSelect = providerId === 'claude' - ? getClaudeModelSelectHtml() - : ''; const openTopLevelBtn = ` - `; -} - -function getClaudeModelOverrideElements(panelEl) { - return { - notice: panelEl?.querySelector('.embedded-model-limit-notice-text') || null, - status: panelEl?.querySelector('.claude-model-override-status') || null - }; -} - -function setClaudeModelOverrideStatus(panelEl, text, state = '') { - const { status } = getClaudeModelOverrideElements(panelEl); - if (!status) { - return; - } - - status.textContent = text; - status.dataset.state = state; -} - -function postClaudeModelOverride(panel, mode = currentClaudeModelMode) { - if (!panel?.iframe?.contentWindow || panel.providerId !== 'claude') { - return; - } - - panel.iframe.contentWindow.postMessage( - createClaudeModelOverrideMessage(mode), - 'https://claude.ai' - ); -} - -function resetClaudeModelModeAfterFailure(panelEl, message) { - updateClaudeModelMode(CLAUDE_MODEL_MODE_DEFAULT, { - persist: true, - broadcast: true - }).then(() => { - setClaudeModelOverrideStatus(panelEl, message, 'error'); - }).catch(error => { - console.error('Failed to reset Claude model mode:', error); - setClaudeModelOverrideStatus(panelEl, message, 'error'); - }); -} - -function handleClaudeModelProbeMessage(event, data) { - if (data.type !== PANELIZE_CLAUDE_MODEL_PROBE || event.origin !== 'https://claude.ai') { - return false; - } - - const panel = panels.find(candidate => ( - candidate.providerId === 'claude' && - candidate.iframe?.contentWindow === event.source - )); - const panelEl = panel ? document.getElementById(panel.id) : null; - if (!panel || !panelEl) { - return true; - } - - switch (data.event) { - case 'probe-ready': - postClaudeModelOverride(panel); - break; - case 'override-configured': - setClaudeModelOverrideStatus(panelEl, ''); - break; - case 'request-overridden': { - const option = getClaudeModelOption(data.mode); - setClaudeModelOverrideStatus( - panelEl, - getLocalizedText('claudeModelRequestedStatus', 'Requested $1', option.label), - 'active' - ); - break; - } - case 'override-request-accepted': { - const option = getClaudeModelOption(data.mode); - setClaudeModelOverrideStatus( - panelEl, - getLocalizedText('claudeModelRequestedStatus', 'Requested $1', option.label), - 'success' - ); - break; - } - case 'override-config-rejected': - case 'override-schema-unsupported': - resetClaudeModelModeAfterFailure( - panelEl, - getLocalizedText( - 'claudeModelOverrideUnavailable', - 'Model override is unavailable. Switched to Claude default.' - ) - ); - break; - case 'override-request-rejected': - resetClaudeModelModeAfterFailure( - panelEl, - getLocalizedText( - 'claudeModelRequestRejected', - 'Model request was rejected (HTTP $1). Switched to Claude default.', - String(data.status || '') - ) - ); - break; - default: - break; - } - - return true; -} - -// Keep the embedded model limit notice in sync when a panel's provider changes. -function syncEmbeddedModelLimitNotice(panelEl, providerId) { - const container = panelEl.querySelector('.panel-iframe-container'); - if (!container) { - return; - } - - const existing = container.querySelector('.embedded-model-limit-notice'); - if (providerHasEmbeddedModelSelectionLimit(providerId)) { - if (!existing) { - const iframe = container.querySelector('iframe'); - iframe.insertAdjacentHTML('beforebegin', getEmbeddedModelLimitNoticeHtml()); - } else { - const { notice } = getClaudeModelOverrideElements(panelEl); - if (notice) { - notice.textContent = getClaudeModelNoticeText(); - } - } - } else if (existing) { - existing.remove(); - } -} - function syncGoogleModeControls() { document.querySelectorAll('.panel-google-mode-select').forEach((select) => { if (select.value !== currentGoogleProviderMode) { @@ -568,22 +373,6 @@ function syncGoogleModeControls() { }); } -function syncClaudeModelControls() { - document.querySelectorAll('.panel-claude-model-select').forEach(select => { - if (select.value !== currentClaudeModelMode) { - select.value = currentClaudeModelMode; - } - fitPanelSelectWidth(select); - }); - - document.querySelectorAll('.panel-item').forEach(panelEl => { - const { notice } = getClaudeModelOverrideElements(panelEl); - if (notice) { - notice.textContent = getClaudeModelNoticeText(); - } - }); -} - function showPanelLoadingState(panelEl, provider) { const loadingEl = panelEl.querySelector('.panel-loading'); if (!loadingEl || !provider) { @@ -647,13 +436,6 @@ function bindPanelHeaderActions(panelId) { }); } - const openTopLevelInlineBtn = panelEl.querySelector('.open-provider-top-level-inline-btn'); - if (openTopLevelInlineBtn) { - openTopLevelInlineBtn.addEventListener('click', () => { - openProviderTopLevel(panel); - }); - } - const refreshBtn = panelEl.querySelector('.refresh-panel-btn'); if (refreshBtn) { refreshBtn.addEventListener('click', () => { @@ -682,24 +464,6 @@ function bindPanelHeaderActions(panelId) { await updateGoogleProviderMode(event.target.value, { persist: true, reloadPanels: true }); }); } - - const claudeModelSelect = panelEl.querySelector('.panel-claude-model-select'); - if (claudeModelSelect) { - fitPanelSelectWidth(claudeModelSelect); - claudeModelSelect.addEventListener('click', event => { - event.stopPropagation(); - }); - claudeModelSelect.addEventListener('mousedown', event => { - event.stopPropagation(); - }); - claudeModelSelect.addEventListener('change', async event => { - fitPanelSelectWidth(event.target); - await updateClaudeModelMode(event.target.value, { - persist: true, - broadcast: true - }); - }); - } } async function updateGoogleProviderMode(mode, { persist = false, reloadPanels = false } = {}) { @@ -719,21 +483,6 @@ async function updateGoogleProviderMode(mode, { persist = false, reloadPanels = } } -async function updateClaudeModelMode(mode, { persist = false, broadcast = false } = {}) { - currentClaudeModelMode = normalizeClaudeModelMode(mode); - syncClaudeModelControls(); - - if (broadcast) { - panels - .filter(panel => panel.providerId === 'claude') - .forEach(panel => postClaudeModelOverride(panel)); - } - - if (persist) { - await saveSetting('claudeModelMode', currentClaudeModelMode); - } -} - function registerStorageChangeListener() { if (!chrome?.storage?.onChanged?.addListener) { return; @@ -754,17 +503,6 @@ function registerStorageChangeListener() { }); } } - - if (changes.claudeModelMode) { - const nextMode = normalizeClaudeModelMode(changes.claudeModelMode.newValue); - if (nextMode === currentClaudeModelMode) { - syncClaudeModelControls(); - } else { - updateClaudeModelMode(nextMode, { broadcast: true }).catch(error => { - console.error('Error syncing Claude model mode:', error); - }); - } - } }); } @@ -1057,10 +795,6 @@ function handleProviderStatusMessage(event) { return; } - if (handleClaudeModelProbeMessage(event, data)) { - return; - } - const isTempChatMessage = data.type === PANELIZE_TEMP_CHAT_ENABLED; const isLocationMessage = data.type === PANELIZE_PROVIDER_LOCATION; if (data.context !== MULTI_PANEL_PROVIDER_STATUS_CONTEXT || (!data.requestId && !isTempChatMessage && !isLocationMessage)) { @@ -1203,14 +937,12 @@ async function loadSettings() { multiPanelLayout: '1x3', multiPanelProviders: DEFAULT_PROVIDERS, openMode: 'tab', - googleProviderMode: DEFAULT_GOOGLE_PROVIDER_MODE, - claudeModelMode: DEFAULT_CLAUDE_MODEL_MODE + googleProviderMode: DEFAULT_GOOGLE_PROVIDER_MODE }); currentLayout = normalizeLayout(settings.multiPanelLayout); currentOpenMode = settings.openMode || 'tab'; currentGoogleProviderMode = normalizeGoogleProviderMode(settings.googleProviderMode); - currentClaudeModelMode = normalizeClaudeModelMode(settings.claudeModelMode); // Apply layout const panelGrid = document.getElementById('panel-grid'); @@ -1266,7 +998,6 @@ function collectCurrentState() { providerId: p.providerId })), googleProviderMode: currentGoogleProviderMode, - claudeModelMode: currentClaudeModelMode, timestamp: Date.now() }; return state; @@ -1362,12 +1093,6 @@ async function restoreStateIfNeeded() { }); } - if (state.claudeModelMode) { - await chrome.storage.sync.set({ - claudeModelMode: normalizeClaudeModelMode(state.claudeModelMode) - }); - } - // 清除已恢复的状态 await chrome.storage.session.remove('preservedState'); await chrome.storage.local.remove('preservedState'); @@ -1526,10 +1251,6 @@ async function addPanel(providerId) { const panelGrid = document.getElementById('panel-grid'); - const embeddedModelLimitNotice = providerHasEmbeddedModelSelectionLimit(providerId) - ? getEmbeddedModelLimitNoticeHtml() - : ''; - // Create panel element const panelEl = document.createElement('div'); panelEl.className = 'panel-item'; @@ -1547,7 +1268,6 @@ async function addPanel(providerId) { ${provider.name} Loading ${provider.name}... - ${embeddedModelLimitNotice}