diff --git a/src/popup/sections/ApiModes.jsx b/src/popup/sections/ApiModes.jsx
index 69f8584b9..37b649795 100644
--- a/src/popup/sections/ApiModes.jsx
+++ b/src/popup/sections/ApiModes.jsx
@@ -26,7 +26,6 @@ import {
getProviderReferenceCheckApiModes,
getReferencedCustomProviderIdsFromSessions,
getSelectableProviders,
- isProviderEndpointRewriteBlockedBySavedConversations,
isProviderDeleteDisabled,
isProviderReferencedByApiModes,
loadSavedConversationState,
@@ -71,7 +70,6 @@ const defaultProviderDraft = {
const defaultProviderDraftValidation = {
name: false,
apiUrl: false,
- savedConversations: false,
}
export function ApiModes({ config, updateConfig }) {
@@ -203,27 +201,6 @@ export function ApiModes({ config, updateConfig }) {
return getConfiguredCustomApiModesForSessionRecovery(recoveryApiModes, recoverySelectedApiMode)
}, [apiModes, config.apiMode, editing, editingApiMode, editingIndex])
- const configuredCustomApiModesForSaveGuard = useMemo(() => {
- let nextApiModes = apiModes
- if (editing && editingIndex !== -1) {
- nextApiModes = apiModes.map((apiMode, index) =>
- index === editingIndex ? editingApiMode : apiMode,
- )
- } else if (
- editing &&
- editingIndex === -1 &&
- editingApiMode.groupName === 'customApiModelKeys'
- ) {
- nextApiModes = [...apiModes, editingApiMode]
- }
- const nextSelectedApiMode =
- editing && editingIndex !== -1 && isApiModeSelected(apiModes[editingIndex], config)
- ? editingApiMode
- : config.apiMode
-
- return getConfiguredCustomApiModesForSessionRecovery(nextApiModes, nextSelectedApiMode)
- }, [apiModes, config, editing, editingApiMode, editingIndex])
-
const sessionReferencedProviderIds = useMemo(
() =>
getReferencedCustomProviderIdsFromSessions(
@@ -314,37 +291,13 @@ export function ApiModes({ config, updateConfig }) {
pendingNewProvider && pendingNewProvider.id === providerEditingId
? pendingNewProvider
: selectedCustomProvider || {}
- const persistedProvider = customProviders.find((provider) => provider.id === providerEditingId)
const endpointDraft = validateProviderEndpointDraft(providerDraft.apiUrl)
const parsedEndpoint = endpointDraft.parsedEndpoint
- const providerEndpointChanged =
- Boolean(providerEditingId) &&
- Boolean(persistedProvider) &&
- parsedEndpoint.valid &&
- parsedEndpoint.chatCompletionsUrl !== resolveProviderChatEndpointUrl(persistedProvider)
- const effectiveProviderSecrets =
- pendingDeletedProviderSecretIds.length > 0
- ? applyDeletedProviderSecrets(config.providerSecrets, pendingDeletedProviderSecretIds)
- : config.providerSecrets
const nextProviderDraftValidation = {
name: !providerName,
apiUrl: !endpointDraft.valid,
- savedConversations:
- providerEndpointChanged &&
- isProviderEndpointRewriteBlockedBySavedConversations(
- providerEditingId,
- sessionsLoaded,
- sessions,
- effectiveProviders,
- configuredCustomApiModesForSaveGuard,
- effectiveProviderSecrets,
- ),
}
- if (
- nextProviderDraftValidation.name ||
- nextProviderDraftValidation.apiUrl ||
- nextProviderDraftValidation.savedConversations
- ) {
+ if (nextProviderDraftValidation.name || nextProviderDraftValidation.apiUrl) {
setProviderDraftValidation(nextProviderDraftValidation)
if (nextProviderDraftValidation.name) {
providerNameInputRef.current?.focus()
@@ -602,11 +555,10 @@ export function ApiModes({ config, updateConfig }) {
placeholder={t('Provider')}
onChange={(e) => {
setProviderDraft({ ...providerDraft, name: e.target.value })
- if (providerDraftValidation.name || providerDraftValidation.savedConversations) {
+ if (providerDraftValidation.name) {
setProviderDraftValidation({
...providerDraftValidation,
name: false,
- savedConversations: false,
})
}
}}
@@ -621,11 +573,10 @@ export function ApiModes({ config, updateConfig }) {
title={t('API Url')}
onChange={(e) => {
setProviderDraft({ ...providerDraft, apiUrl: e.target.value })
- if (providerDraftValidation.apiUrl || providerDraftValidation.savedConversations) {
+ if (providerDraftValidation.apiUrl) {
setProviderDraftValidation({
...providerDraftValidation,
apiUrl: false,
- savedConversations: false,
})
}
}}
@@ -635,15 +586,6 @@ export function ApiModes({ config, updateConfig }) {
{providerDraftValidation.apiUrl && (
{t('Please enter a full Chat Completions URL')}
)}
- {providerDraftValidation.savedConversations && (
-
- {t(
- sessionsLoaded
- ? 'This provider endpoint is still needed by saved conversations'
- : 'Loading saved conversations…',
- )}
-
- )}
normalizeText(provider?.id) === normalizedTargetProviderId,
- )
- if (matchesTargetProvider) return true
- }
-
- return false
-}
-
function getProviderIdsMatchingSessionLabel(session = null, providers = [], apiModes = []) {
if (normalizeText(session?.apiMode?.groupName) !== 'customApiModelKeys') return []
@@ -541,42 +519,6 @@ function getProviderIdsMatchingSessionLabel(session = null, providers = [], apiM
)
}
-function canSessionRecoverViaLegacyLabelFallback(session = null, apiModes = []) {
- if (normalizeText(session?.apiMode?.groupName) !== 'customApiModelKeys') return false
-
- const normalizedSessionLabel = {
- groupName: normalizeText(session?.apiMode?.groupName),
- itemName: normalizeText(session?.apiMode?.itemName),
- isCustom: Boolean(session?.apiMode?.isCustom),
- customName: normalizeText(session?.apiMode?.customName),
- }
- if (!normalizedSessionLabel.customName) return false
-
- const allCandidates = (Array.isArray(apiModes) ? apiModes : []).filter((apiMode) => {
- if (!apiMode || typeof apiMode !== 'object') return false
- return (
- normalizeText(apiMode.groupName) === normalizedSessionLabel.groupName &&
- normalizeText(apiMode.customName) === normalizedSessionLabel.customName
- )
- })
- const exactCandidates = allCandidates.filter(
- (apiMode) =>
- normalizeText(apiMode?.itemName) === normalizedSessionLabel.itemName &&
- Boolean(apiMode?.isCustom) === normalizedSessionLabel.isCustom,
- )
- const matchedApiModes = exactCandidates.length === 1 ? exactCandidates : []
- const isLegacyCustomShape = !normalizedSessionLabel.itemName
- const fallbackApiModes =
- matchedApiModes.length === 0 && isLegacyCustomShape && allCandidates.length === 1
- ? allCandidates
- : matchedApiModes
-
- return fallbackApiModes
- .map((apiMode) => normalizeProviderId(apiMode?.providerId))
- .filter((providerId, index, providerIds) => providerIds.indexOf(providerId) === index)
- .includes('legacy-custom-default')
-}
-
export function getReferencedCustomProviderIdsFromSessions(
sessions = [],
providers = [],
@@ -627,114 +569,6 @@ export function getReferencedCustomProviderIdsFromSessions(
return Array.from(referencedProviderIds)
}
-export function isProviderReferencedBySessionsViaUrl(
- providerId,
- sessions = [],
- providers = [],
- apiModes = [],
- providerSecrets = {},
-) {
- const normalizedTargetProviderId = normalizeText(providerId)
- if (!normalizedTargetProviderId || normalizedTargetProviderId === 'legacy-custom-default') {
- return false
- }
-
- for (const session of Array.isArray(sessions) ? sessions : []) {
- if (normalizeText(session?.apiMode?.groupName) !== 'customApiModelKeys') continue
-
- const matchedByProviderId = getProvidersMatchingSessionProviderId(
- providers,
- session?.apiMode?.providerId,
- )
- if (matchedByProviderId.length > 0) continue
-
- const matchedByCustomUrl = getProvidersMatchingLegacySessionUrl(providers, session)
- const matchesTargetByCustomUrl = matchedByCustomUrl.some(
- (provider) => normalizeText(provider?.id) === normalizedTargetProviderId,
- )
- if (!matchesTargetByCustomUrl) continue
- const sessionApiKey =
- session?.apiMode &&
- typeof session.apiMode === 'object' &&
- typeof session.apiMode.apiKey === 'string'
- ? session.apiMode.apiKey.trim()
- : ''
- if (matchedByCustomUrl.length > 1 && sessionApiKey) {
- const matchedBySessionKey = matchedByCustomUrl.filter((provider) => {
- if (!provider || typeof provider !== 'object') return false
- const providerSecretValue =
- providerSecrets && typeof providerSecrets === 'object' ? providerSecrets[provider.id] : ''
- return String(providerSecretValue || '').trim() === sessionApiKey
- })
- if (
- matchedBySessionKey.length === 1 &&
- normalizeText(matchedBySessionKey[0]?.id) !== normalizedTargetProviderId
- ) {
- continue
- }
- }
-
- const matchedByLabel = getProviderIdsMatchingSessionLabel(session, providers, apiModes)
- if (matchedByLabel.length > 0) continue
- if (canSessionRecoverViaLegacyLabelFallback(session, apiModes)) continue
-
- return true
- }
-
- return false
-}
-
-export function isProviderEndpointRewriteBlockedBySavedConversations(
- providerId,
- sessionsLoaded = true,
- sessions = [],
- providers = [],
- apiModes = [],
- providerSecrets = {},
-) {
- if (!sessionsLoaded) return true
-
- const normalizedTargetProviderId = normalizeProviderId(providerId)
- const isProviderReferencedBySessionsViaLabel = () => {
- if (!normalizedTargetProviderId || normalizedTargetProviderId === 'legacy-custom-default') {
- return false
- }
-
- for (const session of Array.isArray(sessions) ? sessions : []) {
- if (normalizeText(session?.apiMode?.groupName) !== 'customApiModelKeys') continue
- if (
- getProvidersMatchingSessionProviderId(providers, session?.apiMode?.providerId).length > 0
- ) {
- continue
- }
- if (getProvidersMatchingLegacySessionUrl(providers, session).length > 0) {
- continue
- }
- if (
- getProviderIdsMatchingSessionLabel(session, providers, apiModes).includes(
- normalizedTargetProviderId,
- )
- ) {
- return true
- }
- }
-
- return false
- }
-
- return (
- isProviderReferencedBySessionsViaProviderId(providerId, sessions, providers) ||
- isProviderReferencedBySessionsViaUrl(
- providerId,
- sessions,
- providers,
- apiModes,
- providerSecrets,
- ) ||
- isProviderReferencedBySessionsViaLabel()
- )
-}
-
export function getApiModeDisplayLabel(apiMode, t, providers = []) {
const modelName = apiModeToModelName(apiMode)
const fallbackLabel = modelNameToDesc(modelName, t)
diff --git a/tests/unit/popup/api-modes-provider-utils.test.mjs b/tests/unit/popup/api-modes-provider-utils.test.mjs
index 167dc4732..520e57d73 100644
--- a/tests/unit/popup/api-modes-provider-utils.test.mjs
+++ b/tests/unit/popup/api-modes-provider-utils.test.mjs
@@ -11,11 +11,9 @@ import {
getSelectedApiModeOptionValue,
getConfiguredCustomApiModesForSessionRecovery,
getProviderDeleteDisabledReasonKey,
- isProviderEndpointRewriteBlockedBySavedConversations,
getProviderReferenceCheckApiModes,
getReferencedCustomProviderIdsFromSessions,
getSelectableProviders,
- isProviderReferencedBySessionsViaUrl,
isProviderDeleteDisabled,
isProviderReferencedByApiModes,
parseChatCompletionsEndpointUrl,
@@ -761,313 +759,6 @@ test('isProviderReferencedByApiModes only matches custom modes with the same pro
assert.equal(isProviderReferencedByApiModes('provider-b', apiModes), false)
})
-test('provider endpoint rewrite stays fail-closed while saved conversations load', () => {
- assert.equal(
- isProviderEndpointRewriteBlockedBySavedConversations('provider-a', false, [], []),
- true,
- )
-})
-
-test('provider endpoint rewrite is blocked by direct saved conversation provider id reference', () => {
- const sessions = [
- {
- apiMode: {
- groupName: 'customApiModelKeys',
- providerId: 'provider-a',
- },
- },
- ]
- const providers = [{ id: 'provider-a', enabled: true }]
-
- assert.equal(
- isProviderEndpointRewriteBlockedBySavedConversations('provider-a', true, sessions, providers),
- true,
- )
-})
-
-test('provider endpoint rewrite is blocked by migrated saved conversation provider id reference', () => {
- const sessions = [
- {
- apiMode: {
- groupName: 'customApiModelKeys',
- providerId: 'Provider A',
- },
- },
- ]
- const providers = [{ id: 'provider-a', enabled: true }]
-
- assert.equal(
- isProviderEndpointRewriteBlockedBySavedConversations('provider-a', true, sessions, providers),
- true,
- )
-})
-
-test('provider endpoint rewrite does not treat legacy custom provider id as direct reference', () => {
- const sessions = [
- {
- apiMode: {
- groupName: 'customApiModelKeys',
- providerId: 'legacy-custom-default',
- customUrl: '',
- },
- },
- ]
- const providers = [{ id: 'provider-a', enabled: true }]
-
- assert.equal(
- isProviderEndpointRewriteBlockedBySavedConversations('provider-a', true, sessions, providers),
- false,
- )
-})
-
-test('provider endpoint rewrite is blocked by url-only saved conversation recovery', () => {
- const sessions = [
- {
- apiMode: {
- groupName: 'customApiModelKeys',
- providerId: 'stale-provider',
- customUrl: 'https://old.example.com/v1/chat/completions',
- },
- },
- ]
- const providers = [
- {
- id: 'provider-a',
- enabled: true,
- chatCompletionsUrl: 'https://old.example.com/v1/chat/completions',
- },
- ]
-
- assert.equal(
- isProviderEndpointRewriteBlockedBySavedConversations('provider-a', true, sessions, providers),
- true,
- )
-})
-
-test('provider endpoint rewrite is blocked by label-only saved conversation recovery targeting provider', () => {
- const sessions = [
- {
- apiMode: {
- groupName: 'customApiModelKeys',
- itemName: 'customModel',
- isCustom: true,
- providerId: 'stale-provider-id',
- customName: 'proxy-model',
- customUrl: '',
- },
- },
- ]
- const providers = [{ id: 'provider-a', enabled: true }]
- const apiModes = [
- {
- groupName: 'customApiModelKeys',
- itemName: 'customModel',
- isCustom: true,
- customName: 'proxy-model',
- providerId: 'provider-a',
- active: true,
- },
- ]
-
- assert.equal(
- isProviderEndpointRewriteBlockedBySavedConversations(
- 'provider-a',
- true,
- sessions,
- providers,
- apiModes,
- ),
- true,
- )
-})
-
-test('provider endpoint rewrite is allowed when providerId recovery already matches another provider', () => {
- const sessions = [
- {
- apiMode: {
- groupName: 'customApiModelKeys',
- itemName: 'customModel',
- isCustom: true,
- providerId: 'provider-b',
- customName: 'proxy-model',
- customUrl: '',
- },
- },
- ]
- const providers = [
- { id: 'provider-a', enabled: true },
- { id: 'provider-b', enabled: true },
- ]
- const apiModes = [
- {
- groupName: 'customApiModelKeys',
- itemName: 'customModel',
- isCustom: true,
- customName: 'proxy-model',
- providerId: 'provider-a',
- active: true,
- },
- ]
-
- assert.equal(
- isProviderEndpointRewriteBlockedBySavedConversations(
- 'provider-a',
- true,
- sessions,
- providers,
- apiModes,
- ),
- false,
- )
-})
-
-test('provider endpoint rewrite is allowed when customUrl recovery already matches another provider', () => {
- const sessions = [
- {
- apiMode: {
- groupName: 'customApiModelKeys',
- itemName: 'customModel',
- isCustom: true,
- providerId: 'stale-provider-id',
- customName: 'proxy-model',
- customUrl: 'https://provider-b.example.com/v1/chat/completions',
- },
- },
- ]
- const providers = [
- { id: 'provider-a', enabled: true },
- {
- id: 'provider-b',
- enabled: true,
- chatCompletionsUrl: 'https://provider-b.example.com/v1/chat/completions',
- },
- ]
- const apiModes = [
- {
- groupName: 'customApiModelKeys',
- itemName: 'customModel',
- isCustom: true,
- customName: 'proxy-model',
- providerId: 'provider-a',
- active: true,
- },
- ]
-
- assert.equal(
- isProviderEndpointRewriteBlockedBySavedConversations(
- 'provider-a',
- true,
- sessions,
- providers,
- apiModes,
- ),
- false,
- )
-})
-
-test('provider endpoint rewrite is allowed when label-only recovery targets another provider', () => {
- const sessions = [
- {
- apiMode: {
- groupName: 'customApiModelKeys',
- itemName: 'customModel',
- isCustom: true,
- providerId: 'stale-provider-id',
- customName: 'proxy-model',
- customUrl: '',
- },
- },
- ]
- const providers = [
- { id: 'provider-a', enabled: true },
- { id: 'provider-b', enabled: true },
- ]
- const apiModes = [
- {
- groupName: 'customApiModelKeys',
- itemName: 'customModel',
- isCustom: true,
- customName: 'proxy-model',
- providerId: 'provider-b',
- active: true,
- },
- ]
-
- assert.equal(
- isProviderEndpointRewriteBlockedBySavedConversations(
- 'provider-a',
- true,
- sessions,
- providers,
- apiModes,
- ),
- false,
- )
-})
-
-test('provider endpoint rewrite ignores legacy label fallback for non-legacy providers', () => {
- const sessions = [
- {
- apiMode: {
- groupName: 'customApiModelKeys',
- itemName: '',
- isCustom: false,
- providerId: 'stale-provider-id',
- customName: 'proxy-model',
- customUrl: '',
- },
- },
- ]
- const providers = [{ id: 'provider-a', enabled: true }]
- const apiModes = [
- {
- groupName: 'customApiModelKeys',
- itemName: 'customModel',
- isCustom: true,
- customName: 'proxy-model',
- providerId: 'legacy-custom-default',
- active: true,
- },
- ]
-
- assert.equal(
- isProviderEndpointRewriteBlockedBySavedConversations(
- 'provider-a',
- true,
- sessions,
- providers,
- apiModes,
- ),
- false,
- )
-})
-
-test('provider endpoint rewrite is allowed when saved conversations do not reference provider', () => {
- const sessions = [
- {
- apiMode: {
- groupName: 'customApiModelKeys',
- providerId: 'provider-b',
- },
- },
- {
- apiMode: {
- groupName: 'chatgptWebModelKeys',
- providerId: 'provider-a',
- },
- },
- ]
- const providers = [
- { id: 'provider-a', enabled: true },
- { id: 'provider-b', enabled: true },
- ]
-
- assert.equal(
- isProviderEndpointRewriteBlockedBySavedConversations('provider-a', true, sessions, providers),
- false,
- )
-})
-
test('getProviderReferenceCheckApiModes excludes the currently edited mode from delete checks', () => {
const apiModes = [
{ groupName: 'customApiModelKeys', providerId: 'provider-a' },
@@ -1231,207 +922,77 @@ test('session recovery excludes the edited selected custom mode and uses in-flig
recoveryApiModes,
recoverySelectedApiMode,
)
- const referencedProviderIds = getReferencedCustomProviderIdsFromSessions(
- sessions,
- providers,
- configuredApiModes,
- )
-
- assert.deepEqual(configuredApiModes, [editingApiMode])
- assert.deepEqual(referencedProviderIds, ['new-provider'])
-})
-
-test('session recovery still keeps persisted selected mode when editing a different row', () => {
- const apiModes = [
- {
- groupName: 'customApiModelKeys',
- itemName: 'customModel',
- isCustom: true,
- customName: 'mode-a',
- providerId: 'provider-a',
- active: true,
- },
- ]
- const configApiMode = {
- groupName: 'customApiModelKeys',
- itemName: 'customModel',
- isCustom: true,
- customName: 'mode-b',
- providerId: 'provider-b',
- active: true,
- }
- const editingApiMode = {
- ...apiModes[0],
- providerId: 'provider-a-updated',
- }
- const sessions = [
- {
- apiMode: {
- groupName: 'customApiModelKeys',
- itemName: 'customModel',
- isCustom: true,
- customName: 'mode-b',
- providerId: 'stale-provider-id',
- customUrl: '',
- },
- },
- ]
- const providers = [
- { id: 'provider-a', enabled: true },
- { id: 'provider-b', enabled: true },
- ]
-
- const recoveryApiModes = getProviderReferenceCheckApiModes(apiModes, true, 0)
- const recoverySelectedApiMode = shouldIncludeSelectedApiModeInReferenceCheck(
- apiModes,
- true,
- 0,
- configApiMode,
- )
- ? configApiMode
- : editingApiMode
- const configuredApiModes = getConfiguredCustomApiModesForSessionRecovery(
- recoveryApiModes,
- recoverySelectedApiMode,
- )
- const referencedProviderIds = getReferencedCustomProviderIdsFromSessions(
- sessions,
- providers,
- configuredApiModes,
- )
-
- assert.deepEqual(configuredApiModes, [configApiMode])
- assert.deepEqual(referencedProviderIds, ['provider-b'])
-})
-
-test('save guard migration can use in-flight replacement provider and mode', () => {
- const apiModes = [
- {
- groupName: 'customApiModelKeys',
- itemName: 'customModel',
- isCustom: true,
- customName: 'old-mode',
- providerId: 'old-provider',
- active: true,
- },
- ]
- const configApiMode = {
- groupName: 'gptApiModelKeys',
- itemName: 'gpt-4',
- active: true,
- }
- const editingApiMode = {
- ...apiModes[0],
- customName: 'proxy-model',
- providerId: 'new-provider',
- }
- const sessions = [
- {
- apiMode: {
- groupName: 'customApiModelKeys',
- itemName: 'customModel',
- isCustom: true,
- providerId: 'stale-provider-id',
- customName: 'proxy-model',
- customUrl: 'https://old.example.com/v1/chat/completions',
- },
- },
- ]
- const persistedProviders = [
- {
- id: 'old-provider',
- enabled: true,
- chatCompletionsUrl: 'https://old.example.com/v1/chat/completions',
- },
- ]
- const effectiveProviders = [
- ...persistedProviders,
- {
- id: 'new-provider',
- enabled: true,
- chatCompletionsUrl: 'https://new.example.com/v1/chat/completions',
- },
- ]
- const saveGuardApiModes = getConfiguredCustomApiModesForSessionRecovery(
- apiModes.map((apiMode, index) => (index === 0 ? editingApiMode : apiMode)),
- configApiMode,
- )
-
- assert.equal(
- isProviderReferencedBySessionsViaUrl('old-provider', sessions, persistedProviders, apiModes),
- true,
- )
- assert.equal(
- isProviderReferencedBySessionsViaUrl(
- 'old-provider',
- sessions,
- effectiveProviders,
- saveGuardApiModes,
- ),
- false,
+ const referencedProviderIds = getReferencedCustomProviderIdsFromSessions(
+ sessions,
+ providers,
+ configuredApiModes,
)
+
+ assert.deepEqual(configuredApiModes, [editingApiMode])
+ assert.deepEqual(referencedProviderIds, ['new-provider'])
})
-test('save guard create flow can use in-flight new custom mode for label recovery', () => {
- const apiModes = []
+test('session recovery still keeps persisted selected mode when editing a different row', () => {
+ const apiModes = [
+ {
+ groupName: 'customApiModelKeys',
+ itemName: 'customModel',
+ isCustom: true,
+ customName: 'mode-a',
+ providerId: 'provider-a',
+ active: true,
+ },
+ ]
const configApiMode = {
- groupName: 'gptApiModelKeys',
- itemName: 'gpt-4',
- active: true,
- }
- const editingApiMode = {
groupName: 'customApiModelKeys',
itemName: 'customModel',
isCustom: true,
- customName: 'proxy-model',
- providerId: 'new-provider',
+ customName: 'mode-b',
+ providerId: 'provider-b',
active: true,
}
+ const editingApiMode = {
+ ...apiModes[0],
+ providerId: 'provider-a-updated',
+ }
const sessions = [
{
apiMode: {
groupName: 'customApiModelKeys',
itemName: 'customModel',
isCustom: true,
+ customName: 'mode-b',
providerId: 'stale-provider-id',
- customName: 'proxy-model',
- customUrl: 'https://old.example.com/v1/chat/completions',
+ customUrl: '',
},
},
]
- const persistedProviders = [
- {
- id: 'old-provider',
- enabled: true,
- chatCompletionsUrl: 'https://old.example.com/v1/chat/completions',
- },
- ]
- const effectiveProviders = [
- ...persistedProviders,
- {
- id: 'new-provider',
- enabled: true,
- chatCompletionsUrl: 'https://new.example.com/v1/chat/completions',
- },
+ const providers = [
+ { id: 'provider-a', enabled: true },
+ { id: 'provider-b', enabled: true },
]
- const saveGuardApiModes = getConfiguredCustomApiModesForSessionRecovery(
- [...apiModes, editingApiMode],
- configApiMode,
- )
- assert.equal(
- isProviderReferencedBySessionsViaUrl('old-provider', sessions, persistedProviders, apiModes),
+ const recoveryApiModes = getProviderReferenceCheckApiModes(apiModes, true, 0)
+ const recoverySelectedApiMode = shouldIncludeSelectedApiModeInReferenceCheck(
+ apiModes,
true,
+ 0,
+ configApiMode,
)
- assert.equal(
- isProviderReferencedBySessionsViaUrl(
- 'old-provider',
- sessions,
- effectiveProviders,
- saveGuardApiModes,
- ),
- false,
+ ? configApiMode
+ : editingApiMode
+ const configuredApiModes = getConfiguredCustomApiModesForSessionRecovery(
+ recoveryApiModes,
+ recoverySelectedApiMode,
+ )
+ const referencedProviderIds = getReferencedCustomProviderIdsFromSessions(
+ sessions,
+ providers,
+ configuredApiModes,
)
+
+ assert.deepEqual(configuredApiModes, [configApiMode])
+ assert.deepEqual(referencedProviderIds, ['provider-b'])
})
test('createProviderId reuses missing provider ids that only stale modes still reference', () => {
@@ -1812,216 +1373,6 @@ test('getReferencedCustomProviderIdsFromSessions conservatively returns all lega
])
})
-test('isProviderReferencedBySessionsViaUrl returns true when a session only recovers via customUrl', () => {
- const sessions = [
- {
- apiMode: {
- groupName: 'customApiModelKeys',
- providerId: '',
- customUrl: 'https://proxy.example.com/v1/chat/completions',
- },
- },
- ]
- const providers = [
- {
- id: 'provider-a',
- enabled: true,
- chatCompletionsUrl: 'https://proxy.example.com/v1/chat/completions',
- },
- ]
-
- assert.equal(isProviderReferencedBySessionsViaUrl('provider-a', sessions, providers), true)
-})
-
-test('isProviderReferencedBySessionsViaUrl keeps multi-match customUrl sessions protected', () => {
- const sessions = [
- {
- apiMode: {
- groupName: 'customApiModelKeys',
- providerId: '',
- customUrl: 'https://proxy.example.com/v1/chat/completions',
- },
- },
- ]
- const providers = [
- {
- id: 'provider-a',
- enabled: true,
- chatCompletionsUrl: 'https://proxy.example.com/v1/chat/completions',
- },
- {
- id: 'provider-b',
- enabled: true,
- chatCompletionsUrl: 'https://proxy.example.com/v1/chat/completions',
- },
- ]
-
- assert.equal(isProviderReferencedBySessionsViaUrl('provider-a', sessions, providers), true)
-})
-
-test('isProviderReferencedBySessionsViaUrl returns false when apiKey uniquely resolves to another provider', () => {
- const sessions = [
- {
- apiMode: {
- groupName: 'customApiModelKeys',
- providerId: '',
- apiKey: 'provider-b-secret',
- customUrl: 'https://proxy.example.com/v1/chat/completions',
- },
- },
- ]
- const providers = [
- {
- id: 'provider-a',
- enabled: true,
- chatCompletionsUrl: 'https://proxy.example.com/v1/chat/completions',
- },
- {
- id: 'provider-b',
- enabled: true,
- chatCompletionsUrl: 'https://proxy.example.com/v1/chat/completions',
- },
- ]
- const providerSecrets = {
- 'provider-a': 'provider-a-secret',
- 'provider-b': 'provider-b-secret',
- }
-
- assert.equal(
- isProviderReferencedBySessionsViaUrl('provider-a', sessions, providers, [], providerSecrets),
- false,
- )
-})
-
-test('isProviderReferencedBySessionsViaUrl returns false for exact and normalized providerId recovery', () => {
- const exactSessions = [
- {
- apiMode: {
- groupName: 'customApiModelKeys',
- providerId: 'provider-a',
- customUrl: 'https://old.example.com/v1/chat/completions',
- },
- },
- ]
- const normalizedSessions = [
- {
- apiMode: {
- groupName: 'customApiModelKeys',
- providerId: ' Provider A ',
- customUrl: 'https://old.example.com/v1/chat/completions',
- },
- },
- ]
- const providers = [
- {
- id: 'provider-a',
- enabled: true,
- chatCompletionsUrl: 'https://proxy.example.com/v1/chat/completions',
- },
- ]
-
- assert.equal(isProviderReferencedBySessionsViaUrl('provider-a', exactSessions, providers), false)
- assert.equal(
- isProviderReferencedBySessionsViaUrl('provider-a', normalizedSessions, providers),
- false,
- )
-})
-
-test('isProviderReferencedBySessionsViaUrl returns false for label-only recovery', () => {
- const sessions = [
- {
- apiMode: {
- groupName: 'customApiModelKeys',
- itemName: 'customModel',
- isCustom: true,
- providerId: 'stale-provider-id',
- customName: 'proxy-model',
- customUrl: '',
- },
- },
- ]
- const providers = [
- {
- id: 'provider-a',
- enabled: true,
- chatCompletionsUrl: 'https://proxy.example.com/v1/chat/completions',
- },
- ]
- const apiModes = [
- {
- groupName: 'customApiModelKeys',
- itemName: 'customModel',
- isCustom: true,
- customName: 'proxy-model',
- providerId: 'provider-a',
- active: true,
- },
- ]
-
- assert.equal(
- isProviderReferencedBySessionsViaUrl('provider-a', sessions, providers, apiModes),
- false,
- )
-})
-
-test('isProviderReferencedBySessionsViaUrl returns false for legacy label fallback recovery', () => {
- const sessions = [
- {
- apiMode: {
- groupName: 'customApiModelKeys',
- itemName: 'customModel',
- isCustom: true,
- providerId: 'stale-provider-id',
- customName: 'proxy-model',
- customUrl: 'https://proxy.example.com/v1/chat/completions',
- },
- },
- ]
- const providers = [
- {
- id: 'provider-a',
- enabled: true,
- chatCompletionsUrl: 'https://proxy.example.com/v1/chat/completions',
- },
- ]
- const apiModes = [
- {
- groupName: 'customApiModelKeys',
- itemName: 'customModel',
- isCustom: true,
- customName: 'proxy-model',
- providerId: 'legacy-custom-default',
- active: true,
- },
- ]
-
- assert.equal(
- isProviderReferencedBySessionsViaUrl('provider-a', sessions, providers, apiModes),
- false,
- )
-})
-
-test('isProviderReferencedBySessionsViaUrl returns false when there is no recover path', () => {
- const sessions = [
- {
- apiMode: {
- groupName: 'customApiModelKeys',
- providerId: '',
- customUrl: 'https://missing.example.com/v1/chat/completions',
- },
- },
- ]
- const providers = [
- {
- id: 'provider-a',
- enabled: true,
- chatCompletionsUrl: 'https://proxy.example.com/v1/chat/completions',
- },
- ]
-
- assert.equal(isProviderReferencedBySessionsViaUrl('provider-a', sessions, providers), false)
-})
-
test('getApiModeDisplayLabel shows provider name for custom provider-backed modes', () => {
const apiMode = {
groupName: 'customApiModelKeys',