Skip to content

Commit 4b2d305

Browse files
committed
fix: correct deduplication logic to prefer loaded models
- When a loaded model ID is found in any downloaded model key (case-insensitive) - Remove the downloaded model and replace with the loaded model - This ensures loaded models with runtime info take precedence - Updated tests to verify the correct deduplication behavior
1 parent a42c2d0 commit 4b2d305

File tree

2 files changed

+16
-23
lines changed

2 files changed

+16
-23
lines changed

src/api/providers/fetchers/__tests__/lmstudio.test.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -179,12 +179,15 @@ describe("LMStudio Fetcher", () => {
179179

180180
const result = await getLMStudioModels(baseUrl)
181181

182-
// Should only have one model, with the loaded model's runtime info taking precedence
182+
// Should only have one model, with the loaded model replacing the downloaded one
183183
expect(Object.keys(result)).toHaveLength(1)
184184

185-
// The downloaded model's path should be the key, but with loaded model's data
185+
// The loaded model's key should be used, with loaded model's data
186186
const expectedParsedModel = parseLMStudioModel(mockLoadedModel)
187-
expect(result[mockDownloadedModel.path]).toEqual(expectedParsedModel)
187+
expect(result[mockLoadedModel.modelKey]).toEqual(expectedParsedModel)
188+
189+
// The downloaded model should have been removed
190+
expect(result[mockDownloadedModel.path]).toBeUndefined()
188191
})
189192

190193
it("should use default baseUrl if an empty string is provided", async () => {

src/api/providers/fetchers/lmstudio.ts

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -87,31 +87,21 @@ export async function getLMStudioModels(baseUrl = "http://localhost:1234"): Prom
8787
return Promise.all(models.map((m) => m.getModelInfo()))
8888
})) as Array<LLMInstanceInfo>
8989

90-
// Deduplicate loaded models - only add if no existing key contains the model's identifier (case-insensitive)
90+
// Deduplicate: For each loaded model, check if any existing model contains its ID (case-insensitive)
91+
// If found, remove the downloaded version and add the loaded model (prefer loaded over downloaded)
9192
for (const lmstudioModel of loadedModels) {
92-
const modelIdentifier = lmstudioModel.modelKey.toLowerCase()
93+
const loadedModelId = lmstudioModel.modelKey.toLowerCase()
9394

94-
// Check if any existing model key contains this loaded model's identifier
95-
const isDuplicate = Object.keys(models).some(
96-
(existingKey) =>
97-
existingKey.toLowerCase().includes(modelIdentifier) ||
98-
modelIdentifier.includes(existingKey.toLowerCase()),
99-
)
95+
// Find if any existing model key includes the loaded model's ID
96+
const existingKey = Object.keys(models).find((key) => key.toLowerCase().includes(loadedModelId))
10097

101-
if (!isDuplicate) {
102-
// Use modelKey for loaded models to maintain consistency
103-
models[lmstudioModel.modelKey] = parseLMStudioModel(lmstudioModel)
104-
} else {
105-
// If it's a duplicate, update the existing entry with loaded model info for better context data
106-
const existingKey = Object.keys(models).find(
107-
(key) => key.toLowerCase().includes(modelIdentifier) || modelIdentifier.includes(key.toLowerCase()),
108-
)
109-
if (existingKey) {
110-
// Update with loaded model data which has more accurate runtime info
111-
models[existingKey] = parseLMStudioModel(lmstudioModel)
112-
}
98+
if (existingKey) {
99+
// Remove the downloaded version
100+
delete models[existingKey]
113101
}
114102

103+
// Add the loaded model (either as replacement or new entry)
104+
models[lmstudioModel.modelKey] = parseLMStudioModel(lmstudioModel)
115105
modelsWithLoadedDetails.add(lmstudioModel.modelKey)
116106
}
117107
} catch (error) {

0 commit comments

Comments
 (0)