refactor: remove knowledge base references from AI agent model and related services

- Removed KnowledgeIDs from CreateAIAgentRequest and AIAgentResponse.
- Updated buildAIAgentResponseWithLocale to eliminate knowledge base name retrieval.
- Refactored AI agent repository and service to remove knowledge base handling.
- Adjusted dashboard service to no longer track AI agents without knowledge bases.
- Modified knowledge base service to check for workflow references instead of AI agent references.
- Updated frontend components to remove knowledge base selection and display.
- Enhanced workflow validation to ensure knowledge retrieve nodes have associated knowledge bases.
This commit is contained in:
mlogclub
2026-06-30 19:47:29 +08:00
parent fa0010e8be
commit 805ef87278
23 changed files with 575 additions and 243 deletions
@@ -53,6 +53,7 @@ type definitionValidator struct {
func (v *definitionValidator) validate() {
v.validateNodes()
v.validateEdges()
v.validateKnowledgeRetrieveConfigs()
v.validateReachability()
v.validateConfirmationGuards()
v.validateVariableMappings()
@@ -306,6 +307,58 @@ func (v *definitionValidator) validateConditions() {
}
}
func (v *definitionValidator) validateKnowledgeRetrieveConfigs() {
for index, node := range v.def.Nodes {
if strings.TrimSpace(node.Type) != registry.NodeTypeKnowledgeRetrieve {
continue
}
field := fmt.Sprintf("nodes[%d].config.knowledgeBaseIds", index)
ids, ok := readKnowledgeBaseIDsFromConfig(node.Data.Config)
if !ok || len(ids) == 0 {
v.addError(field, "知识检索节点需要选择至少一个知识库")
continue
}
for _, id := range ids {
if id <= 0 {
v.addError(field, "知识库 ID 必须大于 0")
break
}
}
}
}
func readKnowledgeBaseIDsFromConfig(raw json.RawMessage) ([]int64, bool) {
if len(raw) == 0 {
return nil, false
}
var cfg map[string]any
if err := json.Unmarshal(raw, &cfg); err != nil {
return nil, false
}
rawIDs, ok := cfg["knowledgeBaseIds"]
if !ok {
return nil, false
}
values, ok := rawIDs.([]any)
if !ok {
return nil, false
}
ret := make([]int64, 0, len(values))
for _, value := range values {
switch v := value.(type) {
case float64:
ret = append(ret, int64(v))
case int64:
ret = append(ret, v)
case int:
ret = append(ret, int64(v))
default:
return nil, false
}
}
return ret, true
}
func (v *definitionValidator) validateCondition(field string, sourceNodeID string, condition *dsl.Condition) {
if condition == nil {
v.addError(field, "condition branch condition is required")
@@ -213,6 +213,42 @@ func TestValidateDefinitionRejectsUnknownConditionVariable(t *testing.T) {
}
}
func TestValidateDefinitionRejectsKnowledgeRetrieveWithoutKnowledgeBases(t *testing.T) {
def := knowledgeRetrieveDefinition(nil)
result := validator.ValidateDefinition(def, registry.DefaultRegistry())
if result.Valid {
t.Fatalf("expected knowledge_retrieve without knowledge bases to be invalid")
}
if !hasValidationMessage(result, "需要选择至少一个知识库") {
t.Fatalf("expected missing knowledge base error, got %#v", result.Errors)
}
}
func TestValidateDefinitionRejectsKnowledgeRetrieveWithInvalidKnowledgeBaseID(t *testing.T) {
def := knowledgeRetrieveDefinition(map[string]any{"knowledgeBaseIds": []int64{0, -1}})
result := validator.ValidateDefinition(def, registry.DefaultRegistry())
if result.Valid {
t.Fatalf("expected invalid knowledge base id to be invalid")
}
if !hasValidationMessage(result, "知识库 ID 必须大于 0") {
t.Fatalf("expected invalid knowledge base id error, got %#v", result.Errors)
}
}
func TestValidateDefinitionAcceptsKnowledgeRetrieveWithKnowledgeBases(t *testing.T) {
def := knowledgeRetrieveDefinition(map[string]any{"knowledgeBaseIds": []int64{1, 2}})
result := validator.ValidateDefinition(def, registry.DefaultRegistry())
if !result.Valid {
t.Fatalf("expected knowledge_retrieve with knowledge bases to be valid, got %#v", result.Errors)
}
}
func minimalDefinition() dsl.Definition {
return dsl.Definition{
SchemaVersion: dsl.SchemaVersion,
@@ -228,6 +264,21 @@ func minimalDefinition() dsl.Definition {
}
}
func knowledgeRetrieveDefinition(config any) dsl.Definition {
return dsl.Definition{
SchemaVersion: dsl.SchemaVersion,
Nodes: []dsl.Node{
node("start_1", "start", nil, nil),
node("retrieve_1", "knowledge_retrieve", inputs("query", dsl.RefValue("start_1", "userMessage")), config),
node("end_1", "end", nil, nil),
},
Edges: []dsl.Edge{
edge("start_1", "retrieve_1"),
edge("retrieve_1", "end_1"),
},
}
}
func conditionDefinition() dsl.Definition {
conditionConfig := dsl.ConditionConfig{
Branches: []dsl.ConditionBranch{