Files
Agent-System/internal/bizdev/doc_id.go
T
weichenandCursor 6f0057c014 fix(docgov): pin task routing to active controlled doc on current-doc deixis
When the user refers to the current document, keep task_key/doc_id on the selected registered doc_proj instead of rerouting by domain keywords.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-13 15:43:42 +00:00

70 lines
2.1 KiB
Go

package bizdev
import (
"context"
"fmt"
"regexp"
"strings"
)
var (
legacyDocPPattern = regexp.MustCompile(`^doc-p(\d+)-(.+)$`)
legacyDocProjHyphenPattern = regexp.MustCompile(`^doc-proj(\d+)-(.+)$`)
)
// normalizeDocID 将 legacy 本地 ID 映射为服务端权威 doc_id。
func normalizeDocID(docID string, projectID int64, taskKey string) string {
docID = strings.TrimSpace(docID)
if docID == "" {
return canonicalDocID(projectID, taskKey)
}
if m := legacyDocPPattern.FindStringSubmatch(docID); len(m) == 3 {
return fmt.Sprintf("doc_proj%s_%s", m[1], m[2])
}
if m := legacyDocProjHyphenPattern.FindStringSubmatch(docID); len(m) == 3 {
return fmt.Sprintf("doc_proj%s_%s", m[1], m[2])
}
return docID
}
func canonicalDocID(projectID int64, taskKey string) string {
if projectID <= 0 || taskKey == "" {
return ""
}
return fmt.Sprintf("doc_proj%d_%s", projectID, taskKey)
}
// ResolveAndValidateDocID 解析权威 doc_id;若客户端传入则校验归属。
func (s *Service) ResolveAndValidateDocID(ctx context.Context, req TaskRunRequest) (string, error) {
rawDocID := strings.TrimSpace(req.DocID)
docID := normalizeDocID(rawDocID, req.ProjectID, req.TaskKey)
if docID == "" {
return "", nil
}
if s.docGov == nil {
return docID, nil
}
doc, err := s.docGov.GetDocument(ctx, docID)
if err != nil {
// 尚未建档:与空 doc_id 行为一致,交由 CreateOrGetDocument 创建
if fallback := canonicalDocID(req.ProjectID, req.TaskKey); fallback != "" {
return fallback, nil
}
lookupID := rawDocID
if lookupID == "" {
lookupID = docID
}
return "", fmt.Errorf("doc_id not found: %s", lookupID)
}
if req.ProjectID > 0 && doc.ProjectID != req.ProjectID {
return "", fmt.Errorf("doc_id %s does not belong to project %d", docID, req.ProjectID)
}
// 已注册文档的 task_key 以账本为准;客户端 doc_id 不得改写或覆盖请求 task_key。
if req.TaskKey != "" && doc.TaskKey != "" && doc.TaskKey != req.TaskKey {
return "", fmt.Errorf("doc_id %s task_key mismatch: expected %s got %s", docID, req.TaskKey, doc.TaskKey)
}
return doc.DocID, nil
}