更新ai服务提醒

This commit is contained in:
2026-07-01 11:26:08 +08:00
parent 716f711373
commit f6fa167d76
6 changed files with 111 additions and 57 deletions
+9
View File
@@ -262,6 +262,9 @@ func (s *Service) Enabled() bool {
// ReloadLLMProvider reloads a specific LLM provider configuration // ReloadLLMProvider reloads a specific LLM provider configuration
func (s *Service) ReloadLLMProvider(config interface{}) error { func (s *Service) ReloadLLMProvider(config interface{}) error {
if s == nil {
return nil
}
if !s.enabled || s.LLMState == nil { if !s.enabled || s.LLMState == nil {
return nil return nil
} }
@@ -274,6 +277,9 @@ func (s *Service) ReloadLLMProvider(config interface{}) error {
// AddLLMProvider adds a new LLM provider // AddLLMProvider adds a new LLM provider
func (s *Service) AddLLMProvider(config interface{}) error { func (s *Service) AddLLMProvider(config interface{}) error {
if s == nil {
return nil
}
if !s.enabled || s.LLMState == nil { if !s.enabled || s.LLMState == nil {
return nil return nil
} }
@@ -286,6 +292,9 @@ func (s *Service) AddLLMProvider(config interface{}) error {
// RemoveLLMProvider removes an LLM provider // RemoveLLMProvider removes an LLM provider
func (s *Service) RemoveLLMProvider(name string) error { func (s *Service) RemoveLLMProvider(name string) error {
if s == nil {
return nil
}
if !s.enabled || s.LLMState == nil { if !s.enabled || s.LLMState == nil {
return nil return nil
} }
+23 -9
View File
@@ -298,7 +298,14 @@ func handleCreateLLMProvider(store *storepkg.Store, aiService LLMProviderReloade
} }
// Reload AI service with new provider // Reload AI service with new provider
if aiService != nil { if aiService == nil {
c.JSON(http.StatusOK, gin.H{
"status": "ok",
"item": llmProviderDTO(*record),
"warning": "AI 服务未运行,配置已保存但需重启服务后生效",
})
return
}
providerConfig := map[string]interface{}{ providerConfig := map[string]interface{}{
"Name": record.Name, "Name": record.Name,
"Active": record.Active, "Active": record.Active,
@@ -309,7 +316,6 @@ func handleCreateLLMProvider(store *storepkg.Store, aiService LLMProviderReloade
"ContextWindowTokens": record.ContextWindowTokens, "ContextWindowTokens": record.ContextWindowTokens,
} }
if err := aiService.AddLLMProvider(providerConfig); err != nil { if err := aiService.AddLLMProvider(providerConfig); err != nil {
// Log warning but don't fail the request - database is already updated
c.JSON(http.StatusOK, gin.H{ c.JSON(http.StatusOK, gin.H{
"status": "ok", "status": "ok",
"item": llmProviderDTO(*record), "item": llmProviderDTO(*record),
@@ -317,7 +323,6 @@ func handleCreateLLMProvider(store *storepkg.Store, aiService LLMProviderReloade
}) })
return return
} }
}
c.JSON(http.StatusOK, gin.H{"status": "ok", "item": llmProviderDTO(*record)}) c.JSON(http.StatusOK, gin.H{"status": "ok", "item": llmProviderDTO(*record)})
} }
@@ -385,7 +390,14 @@ func handleUpdateLLMProvider(store *storepkg.Store, aiService LLMProviderReloade
} }
// Reload AI service with updated provider // Reload AI service with updated provider
if aiService != nil { if aiService == nil {
c.JSON(http.StatusOK, gin.H{
"status": "ok",
"item": llmProviderDTO(*record),
"warning": "AI 服务未运行,配置已保存但需重启服务后生效",
})
return
}
providerConfig := map[string]interface{}{ providerConfig := map[string]interface{}{
"Name": record.Name, "Name": record.Name,
"Active": record.Active, "Active": record.Active,
@@ -396,7 +408,6 @@ func handleUpdateLLMProvider(store *storepkg.Store, aiService LLMProviderReloade
"ContextWindowTokens": record.ContextWindowTokens, "ContextWindowTokens": record.ContextWindowTokens,
} }
if err := aiService.ReloadLLMProvider(providerConfig); err != nil { if err := aiService.ReloadLLMProvider(providerConfig); err != nil {
// Log warning but don't fail the request - database is already updated
c.JSON(http.StatusOK, gin.H{ c.JSON(http.StatusOK, gin.H{
"status": "ok", "status": "ok",
"item": llmProviderDTO(*record), "item": llmProviderDTO(*record),
@@ -404,7 +415,6 @@ func handleUpdateLLMProvider(store *storepkg.Store, aiService LLMProviderReloade
}) })
return return
} }
}
c.JSON(http.StatusOK, gin.H{"status": "ok", "item": llmProviderDTO(*record)}) c.JSON(http.StatusOK, gin.H{"status": "ok", "item": llmProviderDTO(*record)})
} }
@@ -424,16 +434,20 @@ func handleDeleteLLMProvider(store *storepkg.Store, aiService LLMProviderReloade
} }
// Remove provider from AI service // Remove provider from AI service
if aiService != nil { if aiService == nil {
c.JSON(http.StatusOK, gin.H{
"status": "ok",
"warning": "AI 服务未运行,配置已删除但需重启服务后生效",
})
return
}
if err := aiService.RemoveLLMProvider(name); err != nil { if err := aiService.RemoveLLMProvider(name); err != nil {
// Log warning but don't fail the request - database is already updated
c.JSON(http.StatusOK, gin.H{ c.JSON(http.StatusOK, gin.H{
"status": "ok", "status": "ok",
"warning": "provider deleted but failed to reload AI service: " + err.Error(), "warning": "provider deleted but failed to reload AI service: " + err.Error(),
}) })
return return
} }
}
c.JSON(http.StatusOK, gin.H{"status": "ok"}) c.JSON(http.StatusOK, gin.H{"status": "ok"})
} }
+5 -1
View File
@@ -475,7 +475,11 @@ func run(cfg *configpkg.Config) error {
return err return err
} }
mqttStatus := webpkg.MQTTRuntimeStatus{Server: server, Address: mqttAddr, TLS: cfg.MQTT.TLS.Enabled, Stats: messageStats, ClientStats: clientStats, DBQueue: dbQueue, DedupQueue: mqttHook.dedupQueue} mqttStatus := webpkg.MQTTRuntimeStatus{Server: server, Address: mqttAddr, TLS: cfg.MQTT.TLS.Enabled, Stats: messageStats, ClientStats: clientStats, DBQueue: dbQueue, DedupQueue: mqttHook.dedupQueue}
handler := webpkg.NewRouter(cfg.Web, cfg.ConsoleLog.Web, store, sessions, mqttStatus, blocking, forwardManager, settings, botSender, aiService) var llmReloader webpkg.LLMProviderReloader
if aiService != nil {
llmReloader = aiService
}
handler := webpkg.NewRouter(cfg.Web, cfg.ConsoleLog.Web, store, sessions, mqttStatus, blocking, forwardManager, settings, botSender, llmReloader)
webAddresses := []string{} webAddresses := []string{}
if cfg.Web.PortEnabled { if cfg.Web.PortEnabled {
httpServer := &http.Server{ httpServer := &http.Server{
+2 -2
View File
@@ -515,8 +515,8 @@ export function updateLLMProvider(name: string, payload: Partial<LLMProviderPayl
return putJSON<LLMProviderResponse>(`/api/admin/llm/providers/${encodeURIComponent(name)}`, payload) return putJSON<LLMProviderResponse>(`/api/admin/llm/providers/${encodeURIComponent(name)}`, payload)
} }
export function deleteLLMProvider(name: string): Promise<{ status: string }> { export function deleteLLMProvider(name: string): Promise<{ status: string; warning?: string }> {
return deleteJSON<{ status: string }>(`/api/admin/llm/providers/${encodeURIComponent(name)}`) return deleteJSON<{ status: string; warning?: string }>(`/api/admin/llm/providers/${encodeURIComponent(name)}`)
} }
// LLM Tool Router API // LLM Tool Router API
@@ -17,6 +17,7 @@ import type { LLMPlatformRouter, LLMTopicConfig, LLMProvider, LLMPrimaryConfig }
const loading = ref(false) const loading = ref(false)
const error = ref('') const error = ref('')
const success = ref('') const success = ref('')
const showWarning = ref(false)
// LLM Provider 相关 // LLM Provider 相关
const providers = ref<LLMProvider[]>([]) const providers = ref<LLMProvider[]>([])
@@ -169,12 +170,18 @@ async function saveProvider() {
} }
try { try {
let response: any
if (isCreatingProvider.value) { if (isCreatingProvider.value) {
await createLLMProvider(providerForm.value) response = await createLLMProvider(providerForm.value)
success.value = '创建成功'
} else if (editingProvider.value) { } else if (editingProvider.value) {
await updateLLMProvider(editingProvider.value.name, providerForm.value) response = await updateLLMProvider(editingProvider.value.name, providerForm.value)
success.value = '更新成功' }
if (response.warning) {
success.value = response.warning
showWarning.value = true
} else {
success.value = isCreatingProvider.value ? '创建成功' : '更新成功'
showWarning.value = false
} }
clearSuccess() clearSuccess()
closeProviderForm() closeProviderForm()
@@ -189,8 +196,14 @@ async function confirmDeleteProvider(name: string) {
return return
} }
try { try {
await deleteLLMProvider(name) const response = await deleteLLMProvider(name)
if (response.warning) {
success.value = response.warning
showWarning.value = true
} else {
success.value = '删除成功' success.value = '删除成功'
showWarning.value = false
}
clearSuccess() clearSuccess()
await loadProviders() await loadProviders()
} catch (err) { } catch (err) {
@@ -299,7 +312,7 @@ onMounted(() => {
<h2>LLM API 配置管理</h2> <h2>LLM API 配置管理</h2>
<p v-if="error" class="error">{{ error }}</p> <p v-if="error" class="error">{{ error }}</p>
<p v-if="success" class="success">{{ success }}</p> <p v-if="success" :class="showWarning ? 'warning' : 'success'">{{ success }}</p>
<!-- LLM Provider 列表 --> <!-- LLM Provider 列表 -->
<div class="admin-section"> <div class="admin-section">
@@ -973,6 +986,19 @@ onMounted(() => {
gap: 0.5rem; gap: 0.5rem;
} }
.warning {
color: #92400e;
padding: 1rem 1.25rem;
background: linear-gradient(135deg, #fef3c7 0%, #fde68a 100%);
border-radius: 10px;
margin-bottom: 1.25rem;
border: 1px solid #fcd34d;
font-weight: 500;
display: flex;
align-items: center;
gap: 0.5rem;
}
.admin-loading { .admin-loading {
padding: 3rem; padding: 3rem;
text-align: center; text-align: center;
+1
View File
@@ -644,6 +644,7 @@ export interface LLMProviderPayload {
export interface LLMProviderResponse { export interface LLMProviderResponse {
item: LLMProvider item: LLMProvider
warning?: string
} }
// LLM Tool Router 相关类型 // LLM Tool Router 相关类型