Skip to content

Commit 22a1e4a

Browse files
committed
fix(core): 修复图像模型配置的删除和容错处理
## 问题 - 开发期间修改配置ID后,旧配置存储在本地但数据结构不完整 - 删除损坏配置时报错"Configuration does not exist" - 即使删除成功,配置仍然存在于列表中 ## 根本原因 - 存储key和配置ID不一致:旧配置自带ID字段与存储key不匹配 - 删除操作使用修复后的ID查找,无法匹配存储中的实际key ## 解决方案 ### 1. deleteConfig - 容错处理 - 移除严格的存在性检查,不再抛出异常 - 允许删除不存在的配置(降级处理) - 添加详细的日志输出用于诊断 ### 2. getConfig - 安全修复 - 尝试修复损坏的配置结构 - 即使修复失败也返回配置,确保可以删除 - 补齐缺失的provider/model字段 ### 3. getAllConfigs - 关键修复 - **强制使用存储key作为配置ID**(最关键) - 保证读写一致性:删除时使用的ID = 存储中的key - 对无法修复的配置返回占位对象,标记为disabled ### 4. ensureSelfContained - 容错降级 - 捕获修复失败的异常 - 创建占位配置,包含完整的provider/model结构 - 自动标记为disabled,引导用户删除 ## 效果 - ✅ 损坏配置可以正常显示和删除 - ✅ 删除操作不再报错 - ✅ ID一致性得到保证 - ✅ 向后兼容,支持配置结构变更 - ✅ 用户无需手动清理本地存储
1 parent 719ce8d commit 22a1e4a

File tree

1 file changed

+86
-24
lines changed

1 file changed

+86
-24
lines changed

packages/core/src/services/image-model/manager.ts

Lines changed: 86 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -132,10 +132,18 @@ export class ImageModelManager implements IImageModelManager {
132132
this.storageKey,
133133
(current) => {
134134
const data = current || {}
135+
136+
// 强制删除:无论配置是否存在都尝试删除
137+
// 这确保损坏的配置也能被清理
135138
if (!data[id]) {
136-
throw new Error(`Configuration with id '${id}' does not exist`)
139+
console.warn(`[ImageModelManager] Config ${id} not found in storage, but proceeding anyway`)
140+
// 仍然返回原数据,因为确实没什么可删的
141+
return data
137142
}
143+
144+
// 配置存在,正常删除
138145
const { [id]: removed, ...rest } = data
146+
console.log(`[ImageModelManager] Successfully deleted config: ${id}`)
139147
return rest
140148
}
141149
)
@@ -146,25 +154,48 @@ export class ImageModelManager implements IImageModelManager {
146154
const data: Record<string, ImageModelConfig> = raw ? JSON.parse(raw) : {}
147155
const cfg = data[id]
148156
if (!cfg) return null
157+
149158
// 轻量迁移兜底:返回前补齐缺失的 id,避免 UI 无法删除
150-
// 说明:旧数据来自开发期,仅补 id 用于删除,不补 providerId/modelId/provider/model
151159
if (!(cfg as any).id) {
152-
return { ...(cfg as any), id } as ImageModelConfig
160+
;(cfg as any).id = id
161+
}
162+
163+
// 尝试修复损坏的配置,确保能够正常读取和删除
164+
try {
165+
return this.ensureSelfContained(cfg)
166+
} catch (error) {
167+
// 即使修复失败,也返回配置(已在ensureSelfContained中标记为disabled)
168+
console.warn(`[ImageModelManager] Failed to fully repair config ${id}, but returning for deletion:`, error)
169+
return cfg
153170
}
154-
return cfg
155171
}
156172

157173
async getAllConfigs(): Promise<ImageModelConfig[]> {
158174
const raw = await this.storage.getItem(this.storageKey)
159175
const data: Record<string, ImageModelConfig> = raw ? JSON.parse(raw) : {}
160-
// 轻量迁移兜底:为缺失 id 的旧记录补齐 id(仅返回层面,不强制持久化)
161-
// 说明:旧数据来自开发期,仅补 id 以便在界面上删除,无需补齐其它字段
176+
177+
// 轻量迁移兜底:为缺失 id 的旧记录补齐 id,并尝试修复损坏的配置
162178
return Object.entries(data).map(([key, cfg]) => {
163-
if (cfg && typeof cfg === 'object' && !(cfg as any).id) {
164-
return { ...(cfg as any), id: key } as ImageModelConfig
179+
if (!cfg || typeof cfg !== 'object') {
180+
return null
165181
}
166-
return cfg
167-
})
182+
183+
// 始终使用存储键作为公开的 id,保持删除等操作一致
184+
;(cfg as any).id = key
185+
186+
// 尝试修复配置,如果失败则返回占位配置(标记为disabled)
187+
try {
188+
return this.ensureSelfContained(cfg)
189+
} catch (error) {
190+
console.warn(`[ImageModelManager] Failed to repair config ${key}, returning placeholder:`, error)
191+
// 返回最小占位配置,确保能在UI中显示和删除
192+
return {
193+
...cfg,
194+
id: key,
195+
enabled: false
196+
} as ImageModelConfig
197+
}
198+
}).filter((cfg): cfg is ImageModelConfig => cfg !== null)
168199
}
169200

170201
async getEnabledConfigs(): Promise<ImageModelConfig[]> {
@@ -249,23 +280,54 @@ export class ImageModelManager implements IImageModelManager {
249280
return config
250281
}
251282

252-
// 获取provider和model信息
253-
const adapter = this.registry.getAdapter(config.providerId)
254-
const provider = adapter.getProvider()
283+
try {
284+
// 获取provider和model信息
285+
const adapter = this.registry.getAdapter(config.providerId)
286+
const provider = adapter.getProvider()
255287

256-
// 尝试从静态模型列表获取模型信息
257-
let model = this.registry.getStaticModels(config.providerId).find(m => m.id === config.modelId)
288+
// 尝试从静态模型列表获取模型信息
289+
let model = this.registry.getStaticModels(config.providerId).find(m => m.id === config.modelId)
258290

259-
// 如果静态模型不存在,使用buildDefaultModel构建
260-
if (!model) {
261-
model = adapter.buildDefaultModel(config.modelId)
262-
}
291+
// 如果静态模型不存在,使用buildDefaultModel构建
292+
if (!model) {
293+
model = adapter.buildDefaultModel(config.modelId)
294+
}
263295

264-
// 返回自包含配置
265-
return {
266-
...config,
267-
provider,
268-
model
296+
// 返回自包含配置
297+
return {
298+
...config,
299+
provider,
300+
model
301+
}
302+
} catch (error) {
303+
// 对于无法修复的旧配置,创建占位数据并禁用,允许用户查看和删除
304+
console.warn(`[ImageModelManager] Cannot repair legacy config ${config.id}, marking as disabled:`, error)
305+
return {
306+
...config,
307+
enabled: false,
308+
provider: {
309+
id: config.providerId || 'unknown',
310+
name: `Unknown Provider (${config.providerId || 'unknown'})`,
311+
description: '此配置损坏,无法修复',
312+
requiresApiKey: false,
313+
supportsDynamicModels: false,
314+
defaultBaseURL: '',
315+
connectionSchema: { required: [], optional: [], fieldTypes: {} }
316+
},
317+
model: {
318+
id: config.modelId || 'unknown',
319+
name: `Unknown Model (${config.modelId || 'unknown'})`,
320+
description: '此配置损坏,请删除后重新创建',
321+
providerId: config.providerId || 'unknown',
322+
capabilities: {
323+
text2image: false,
324+
image2image: false,
325+
multiImage: false
326+
},
327+
parameterDefinitions: [],
328+
defaultParameterValues: {}
329+
}
330+
} as ImageModelConfig
269331
}
270332
}
271333

0 commit comments

Comments
 (0)