diff --git a/internal/app/mcp_authorization.go b/internal/app/mcp_authorization.go index cd933a79..6526de7d 100644 --- a/internal/app/mcp_authorization.go +++ b/internal/app/mcp_authorization.go @@ -382,7 +382,13 @@ func authorizeProjectTool(ctx context.Context, principal authctx.Principal, db * return fmt.Errorf("no access to conversation %s", conversationID) } projectID, err := db.GetConversationProjectID(conversationID) - if err != nil || strings.TrimSpace(projectID) == "" || !db.UserCanAccessResource(principal.UserID, principal.ScopeFor(permission), "project", projectID) { + if err != nil { + return fmt.Errorf("no access to project: %w", err) + } + if strings.TrimSpace(projectID) == "" { + return fmt.Errorf("当前对话未绑定项目,无法使用项目黑板工具,请先在对话中选择项目或创建带项目的对话") + } + if !db.UserCanAccessResource(principal.UserID, principal.ScopeFor(permission), "project", projectID) { return fmt.Errorf("no access to project %s", projectID) } return nil diff --git a/internal/database/project.go b/internal/database/project.go index df2604eb..c2201267 100644 --- a/internal/database/project.go +++ b/internal/database/project.go @@ -10,7 +10,7 @@ import ( "github.com/google/uuid" ) -var factKeyPattern = regexp.MustCompile(`^[a-z0-9][a-z0-9._/-]*$`) +var factKeyPattern = regexp.MustCompile(`^[a-zA-Z0-9][a-zA-Z0-9._/-]*$`) // ValidateFactKey 校验事实 key(项目内唯一标识)。 func ValidateFactKey(key string) error { @@ -22,7 +22,7 @@ func ValidateFactKey(key string) error { return fmt.Errorf("fact_key 过长(最多 128 字符)") } if !factKeyPattern.MatchString(key) { - return fmt.Errorf("fact_key 格式无效,仅允许小写字母、数字及 . _ / -,且须以小写字母或数字开头") + return fmt.Errorf("fact_key 格式无效,仅允许字母、数字及 . _ / -,且须以字母或数字开头(支持驼峰命名)") } return nil } diff --git a/internal/project/fact_body_links.go b/internal/project/fact_body_links.go index 0ec69328..8c0bd39c 100644 --- a/internal/project/fact_body_links.go +++ b/internal/project/fact_body_links.go @@ -9,8 +9,8 @@ import ( ) var ( - bodyDepFactLine = regexp.MustCompile(`(?im)^[\s\-*]*依赖事实\s*[::]\s*([a-z0-9][a-z0-9._/-]*)`) - bodyRelFactLine = regexp.MustCompile(`(?im)^[\s\-*]*相关\s*fact_key\s*[::]\s*([a-z0-9][a-z0-9._/-]*)`) + bodyDepFactLine = regexp.MustCompile(`(?im)^[\s\-*]*依赖事实\s*[::]\s*([a-zA-Z0-9][a-zA-Z0-9._/-]*)`) + bodyRelFactLine = regexp.MustCompile(`(?im)^[\s\-*]*相关\s*fact_key\s*[::]\s*([a-zA-Z0-9][a-zA-Z0-9._/-]*)`) bodyAssocSection = regexp.MustCompile(`(?im)^##\s*关联\s*$`) bodySyncLinksHead = "结构化关系边(自动同步)" )