Refactor macLocalAFM references to apple across model capabilities, refresh model service, and settings types for consistency and clarity.

This commit is contained in:
Jérôme Commaret 2026-04-24 01:19:24 +02:00
parent a5320a2538
commit f7257cc7be
4 changed files with 19 additions and 18 deletions

View file

@ -61,7 +61,7 @@ export const defaultProviderSettings = {
region: 'us-east-1', // add region setting
endpoint: '', // optionally allow overriding default
},
macLocalAFM: {
apple: {
endpoint: 'http://localhost:9999',
},
@ -155,7 +155,7 @@ export const defaultModelsOfProvider = {
microsoftAzure: [],
awsBedrock: [],
liteLLM: [],
macLocalAFM: [], // autodetected via afm list endpoint
apple: [], // autodetected via afm list endpoint
} as const satisfies Record<ProviderName, string[]>
@ -1464,7 +1464,7 @@ const openRouterSettings: VoidStaticProviderInfo = {
// ---------------- MAC LOCAL AFM (Apple Foundation Model / MLX via afm) ----------------
const macLocalAFMSettings: VoidStaticProviderInfo = {
const appleSettings: VoidStaticProviderInfo = {
modelOptionsFallback: (modelName) => extensiveModelOptionsFallback(modelName, { downloadable: false }),
modelOptions: {
'foundation': {
@ -1505,7 +1505,8 @@ const modelSettingsOfProvider: { [providerName in ProviderName]: VoidStaticProvi
googleVertex: googleVertexSettings,
microsoftAzure: microsoftAzureSettings,
awsBedrock: awsBedrockSettings,
macLocalAFM: macLocalAFMSettings,
// Local Apple model
apple: appleSettings,
} as const

View file

@ -47,7 +47,7 @@ const refreshBasedOn: { [k in RefreshableProviderName]: (keyof SettingsOfProvide
ollama: ['_didFillInProviderSettings', 'endpoint'],
vLLM: ['_didFillInProviderSettings', 'endpoint'],
lmStudio: ['_didFillInProviderSettings', 'endpoint'],
macLocalAFM: ['_didFillInProviderSettings', 'endpoint'],
apple: ['_didFillInProviderSettings', 'endpoint'],
mistral: ['_didFillInProviderSettings', 'apiKey'],
// openAICompatible: ['_didFillInProviderSettings', 'endpoint', 'apiKey'],
}
@ -146,7 +146,7 @@ export class RefreshModelService extends Disposable implements IRefreshModelServ
ollama: { state: 'init', timeoutId: null },
vLLM: { state: 'init', timeoutId: null },
lmStudio: { state: 'init', timeoutId: null },
macLocalAFM: { state: 'init', timeoutId: null },
apple: { state: 'init', timeoutId: null },
mistral: { state: 'init', timeoutId: null },
}
@ -180,7 +180,7 @@ export class RefreshModelService extends Disposable implements IRefreshModelServ
if (providerName === 'ollama') return (model as OllamaModelResponse).name;
else if (providerName === 'vLLM') return (model as OpenaiCompatibleModelResponse).id;
else if (providerName === 'lmStudio') return (model as OpenaiCompatibleModelResponse).id;
else if (providerName === 'macLocalAFM') return (model as OpenaiCompatibleModelResponse).id;
else if (providerName === 'apple') return (model as OpenaiCompatibleModelResponse).id;
else if (providerName === 'mistral') return (model as OpenaiCompatibleModelResponse).id;
else throw new Error('refreshMode fn: unknown provider', providerName);
}),

View file

@ -16,11 +16,11 @@ type UnionOfKeys<T> = T extends T ? keyof T : never;
export type ProviderName = keyof typeof defaultProviderSettings
export const providerNames = Object.keys(defaultProviderSettings) as ProviderName[]
export const localProviderNames = ['ollama', 'vLLM', 'lmStudio', 'macLocalAFM'] satisfies ProviderName[] // all local names (no API key, endpoint-based)
export const localProviderNames = ['ollama', 'vLLM', 'lmStudio', 'apple'] satisfies ProviderName[] // all local names (no API key, endpoint-based)
export const nonlocalProviderNames = providerNames.filter((name) => !(localProviderNames as string[]).includes(name)) // all non-local names
// providers whose model list can be fetched and auto-refreshed (local + cloud providers with a /v1/models endpoint)
export const refreshableProviderNames = ['ollama', 'vLLM', 'lmStudio', 'macLocalAFM', 'mistral'] satisfies ProviderName[]
export const refreshableProviderNames = ['ollama', 'vLLM', 'lmStudio', 'apple', 'mistral'] satisfies ProviderName[]
type CustomSettingName = UnionOfKeys<typeof defaultProviderSettings[ProviderName]>
type CustomProviderSettings<providerName extends ProviderName> = {
@ -109,7 +109,7 @@ export const displayInfoOfProviderName = (providerName: ProviderName): DisplayIn
else if (providerName === 'awsBedrock') {
return { title: 'AWS Bedrock', }
}
else if (providerName === 'macLocalAFM') {
else if (providerName === 'apple') {
return { title: 'Apple & MLX', }
}
@ -134,7 +134,7 @@ export const subTextMdOfProviderName = (providerName: ProviderName): string => {
if (providerName === 'vLLM') return 'Read more about custom [Endpoints here](https://docs.vllm.ai/en/latest/getting_started/quickstart.html#openai-compatible-server).'
if (providerName === 'lmStudio') return 'Read more about custom [Endpoints here](https://lmstudio.ai/docs/app/api/endpoints/openai).'
if (providerName === 'liteLLM') return 'Read more about endpoints [here](https://docs.litellm.ai/docs/providers/openai_compatible).'
if (providerName === 'macLocalAFM') return 'Run Apple\'s on-device Foundation Model or any MLX model locally. Install [afm](https://github.com/scouzi1966/maclocal-api) and start with `afm` (Foundation Model) or `afm mlx -m <model>` (MLX). Requires macOS 26+, Apple Silicon, and Apple Intelligence enabled.'
if (providerName === 'apple') return 'Run Apple\'s on-device Foundation Model or any MLX model locally. Install [afm](https://github.com/scouzi1966/maclocal-api) and start with `afm` (Foundation Model) or `afm mlx -m <model>` (MLX). Requires macOS 26+, Apple Silicon, and Apple Intelligence enabled.'
throw new Error(`subTextMdOfProviderName: Unknown provider name: "${providerName}"`)
}
@ -173,7 +173,7 @@ export const displayInfoOfSettingName = (providerName: ProviderName, settingName
title: providerName === 'ollama' ? 'Endpoint' :
providerName === 'vLLM' ? 'Endpoint' :
providerName === 'lmStudio' ? 'Endpoint' :
providerName === 'macLocalAFM' ? 'Endpoint' :
providerName === 'apple' ? 'Endpoint' :
providerName === 'openAICompatible' ? 'baseURL' : // (do not include /chat/completions)
providerName === 'googleVertex' ? 'baseURL' :
providerName === 'microsoftAzure' ? 'baseURL' :
@ -185,7 +185,7 @@ export const displayInfoOfSettingName = (providerName: ProviderName, settingName
: providerName === 'vLLM' ? defaultProviderSettings.vLLM.endpoint
: providerName === 'openAICompatible' ? 'https://my-website.com/v1'
: providerName === 'lmStudio' ? defaultProviderSettings.lmStudio.endpoint
: providerName === 'macLocalAFM' ? defaultProviderSettings.macLocalAFM.endpoint
: providerName === 'apple' ? defaultProviderSettings.apple.endpoint
: providerName === 'liteLLM' ? 'http://localhost:4000'
: providerName === 'awsBedrock' ? 'http://localhost:4000/v1'
: '(never)',
@ -361,10 +361,10 @@ export const defaultSettingsOfProvider: SettingsOfProvider = {
...modelInfoOfDefaultModelNames(defaultModelsOfProvider.awsBedrock),
_didFillInProviderSettings: undefined,
},
macLocalAFM: {
apple: {
...defaultCustomSettings,
...defaultProviderSettings.macLocalAFM,
...modelInfoOfDefaultModelNames([...defaultModelsOfProvider.macLocalAFM]),
...defaultProviderSettings.apple,
...modelInfoOfDefaultModelNames([...defaultModelsOfProvider.apple]),
_didFillInProviderSettings: undefined,
},
}

View file

@ -167,7 +167,7 @@ const newOpenAICompatibleSDK = async ({ settingsOfProvider, providerName, includ
const thisConfig = settingsOfProvider[providerName]
return new OpenAI({ baseURL: 'https://api.mistral.ai/v1', apiKey: thisConfig.apiKey, ...commonPayloadOpts })
}
else if (providerName === 'macLocalAFM') {
else if (providerName === 'apple') {
const thisConfig = settingsOfProvider[providerName]
const endpoint = thisConfig.endpoint || 'http://localhost:9999'
return new OpenAI({ baseURL: `${endpoint}/v1`, apiKey: 'noop', ...commonPayloadOpts })
@ -942,7 +942,7 @@ export const sendLLMMessageToProviderImplementation = {
sendFIM: null,
list: null,
},
macLocalAFM: {
apple: {
sendChat: (params) => _sendOpenAICompatibleChat(params),
sendFIM: null,
list: (params) => _openaiCompatibleList(params),