功能修改

This commit is contained in:
npc0-hue
2026-07-20 16:42:33 +08:00
parent 48b8ad8d6c
commit a0e69417db
224 changed files with 22015 additions and 884 deletions
+32 -4
View File
@@ -3,6 +3,7 @@ package service
import (
"errors"
"strings"
"time"
"browser.local/platform/domain"
"browser.local/platform/repo"
@@ -45,7 +46,8 @@ func (svc *CoreService) InvokeAIForSession(sessionID string, request domain.AIIn
if err := validator.ValidateAIInvocationRequest(request); err != nil {
return domain.AIInvocationResponse{}, err
}
if _, err := svc.GetCurrentUser(sessionID); err != nil {
user, err := svc.GetCurrentUser(sessionID)
if err != nil {
return domain.AIInvocationResponse{}, err
}
if request.ServerInstanceID != "" {
@@ -56,6 +58,13 @@ func (svc *CoreService) InvokeAIForSession(sessionID string, request domain.AIIn
if request.PluginID != "" && instance.PluginID != request.PluginID {
return safeAIDenial(request, "plugin scope does not match server instance"), nil
}
if request.Purpose == "config.suggest" || request.Purpose == "config.generate" {
config, err := svc.GetServerConfigForSession(sessionID, instance.ID)
if err != nil {
return domain.AIInvocationResponse{}, err
}
request.CurrentConfig = config.Content
}
}
if request.PluginID != "" {
plugin, err := svc.store.GamePlugins().Get(request.PluginID)
@@ -82,14 +91,24 @@ func (svc *CoreService) InvokeAIForSession(sessionID string, request domain.AIIn
}
result, err := svc.aiProviderClient.Invoke(provider, request)
if err != nil {
auditID, auditErr := svc.recordAuditEventWithID(user.ID, "ai.provider.invoke.failed", "ai-provider", provider.ID, domain.AuditResultFailed, "AI provider invocation failed safely")
if auditErr != nil {
return domain.AIInvocationResponse{}, auditErr
}
svc.productionMu.Lock()
_, alertErr := svc.upsertAlert(domain.AlertRecord{SourceKind: "ai-provider", SourceID: provider.ID, RuleKey: "ai.provider.failed", Severity: domain.AlertSeverityWarning, Title: "AI provider invocation failed", Message: "AI provider invocation failed safely", Retryable: false, LastAuditEventID: auditID})
svc.productionMu.Unlock()
if alertErr != nil {
return domain.AIInvocationResponse{}, alertErr
}
return domain.CopyAIInvocationResponse(domain.AIInvocationResponse{
RequestID: request.RequestID,
Purpose: request.Purpose,
ProviderID: provider.ID,
Model: safeModel(request.Model, provider),
Status: "error",
Usage: domain.AIInvocationUsage{ProviderID: provider.ID, Model: safeModel(request.Model, provider), Mocked: true},
Error: &domain.AIInvocationSafeError{Code: "provider_failed", Message: safeBridgeReason(err.Error())},
Usage: domain.AIInvocationUsage{ProviderID: provider.ID, Model: safeModel(request.Model, provider)},
Error: &domain.AIInvocationSafeError{Code: "provider_failed", Message: "AI provider invocation failed safely"},
}), nil
}
response := domain.AIInvocationResponse{
@@ -102,7 +121,16 @@ func (svc *CoreService) InvokeAIForSession(sessionID string, request domain.AIIn
Usage: result.Usage,
}
if result.SuggestedConfig != "" {
response.ConfigRecommendation = &domain.AIConfigRecommendation{Key: "server.properties", SuggestedConfig: result.SuggestedConfig, DiffSummary: "review required before config write dispatch"}
if request.ServerInstanceID == "" {
return domain.AIInvocationResponse{}, validationError("serverInstanceId is required for AI config recommendations")
}
svc.productionMu.Lock()
preview, persistErr := svc.persistAIConfigDiff(user.ID, provider, request, result)
svc.productionMu.Unlock()
if persistErr != nil {
return domain.AIInvocationResponse{}, persistErr
}
response.ConfigRecommendation = &domain.AIConfigRecommendation{Key: preview.Key, SuggestedConfig: preview.ProposedConfig, DiffSummary: preview.DiffSummary, DiffID: preview.ID, ExpiresAt: preview.ExpiresAt.Format(time.RFC3339)}
}
if err := validator.ValidateAIInvocationResponse(response); err != nil {
return domain.AIInvocationResponse{}, err