主流程

This commit is contained in:
2026-06-10 17:53:09 +08:00
parent c6f239f424
commit b20435c027
66 changed files with 2779 additions and 1181 deletions
+1 -1
View File
@@ -14,7 +14,7 @@ type ServerDeps struct {
Projects project.ProjectService
Reqs project.RequirementService
Issues project.IssueService
Prototypes project.PrototypeService
Artifacts project.ArtifactService
Workspaces workspace.WorkspaceService
Templates chat.TemplateService
Messages chat.MessageService
+13
View File
@@ -95,6 +95,7 @@ type Conversation struct {
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
DeletedAt pgtype.Timestamptz `json:"deleted_at"`
RequirementID pgtype.UUID `json:"requirement_id"`
}
type GitCredential struct {
@@ -276,6 +277,18 @@ type Requirement struct {
WorkspaceID pgtype.UUID `json:"workspace_id"`
}
type RequirementArtifact struct {
ID pgtype.UUID `json:"id"`
RequirementID pgtype.UUID `json:"requirement_id"`
Phase string `json:"phase"`
Version int32 `json:"version"`
Content string `json:"content"`
Note string `json:"note"`
SourceMessageID *int64 `json:"source_message_id"`
CreatedBy pgtype.UUID `json:"created_by"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
}
type User struct {
ID pgtype.UUID `json:"id"`
Email string `json:"email"`
+1 -1
View File
@@ -62,7 +62,7 @@ var defaultSystemTools = []string{
"get_issue", "get_requirement",
"create_issue", "update_issue", "close_issue", "reopen_issue", "assign_issue",
"create_requirement", "update_requirement", "close_requirement", "reopen_requirement", "set_requirement_phase",
"add_requirement_prototype", "list_requirement_prototypes",
"add_requirement_artifact", "list_requirement_artifacts",
}
// NewTokenService 构造 service。now 用于测试注入;nil 时默认 time.Now。
+45 -42
View File
@@ -29,8 +29,8 @@ func registerPMTools(srv *mcpsdk.Server, deps ServerDeps) {
registerCloseRequirement(srv, deps)
registerReopenRequirement(srv, deps)
registerSetRequirementPhase(srv, deps)
registerAddRequirementPrototype(srv, deps)
registerListRequirementPrototypes(srv, deps)
registerAddRequirementArtifact(srv, deps)
registerListRequirementArtifacts(srv, deps)
}
// ===== list_projects =====
@@ -711,93 +711,96 @@ func registerSetRequirementPhase(srv *mcpsdk.Server, deps ServerDeps) {
})
}
// ===== add_requirement_prototype =====
// ===== add_requirement_artifact =====
type addRequirementPrototypeIn struct {
type addRequirementArtifactIn struct {
ProjectSlug string `json:"project_slug" jsonschema:"required field"`
Number int `json:"number" jsonschema:"requirement number (>=1)"`
Content string `json:"content" jsonschema:"prototype content (non-empty)"`
Phase string `json:"phase" jsonschema:"artifact phase: planning|prototyping|auditing"`
Content string `json:"content" jsonschema:"artifact content (non-empty)"`
Note string `json:"note,omitempty"`
}
type prototypeDetail struct {
type artifactDetail struct {
Phase string `json:"phase"`
Version int `json:"version"`
Content string `json:"content"`
Note string `json:"note,omitempty"`
CreatedAt string `json:"created_at"`
}
type prototypeCreateOut struct {
OK bool `json:"ok"`
Prototype prototypeDetail `json:"prototype"`
type artifactCreateOut struct {
OK bool `json:"ok"`
Artifact artifactDetail `json:"artifact"`
}
func registerAddRequirementPrototype(srv *mcpsdk.Server, deps ServerDeps) {
func registerAddRequirementArtifact(srv *mcpsdk.Server, deps ServerDeps) {
mcpsdk.AddTool(srv,
&mcpsdk.Tool{Name: "add_requirement_prototype", Description: "Add a new prototype version to a requirement."},
func(ctx context.Context, _ *mcpsdk.CallToolRequest, in addRequirementPrototypeIn) (*mcpsdk.CallToolResult, prototypeCreateOut, error) {
if err := CheckToolFromCtx(ctx, "add_requirement_prototype"); err != nil {
return nil, prototypeCreateOut{}, err
&mcpsdk.Tool{Name: "add_requirement_artifact", Description: "Add a new phase artifact version (planning/prototyping/auditing) to a requirement."},
func(ctx context.Context, _ *mcpsdk.CallToolRequest, in addRequirementArtifactIn) (*mcpsdk.CallToolResult, artifactCreateOut, error) {
if err := CheckToolFromCtx(ctx, "add_requirement_artifact"); err != nil {
return nil, artifactCreateOut{}, err
}
c, err := deps.Caller.Resolve(ctx)
if err != nil {
return nil, prototypeCreateOut{}, err
return nil, artifactCreateOut{}, err
}
p, err := deps.Projects.Get(ctx, c, in.ProjectSlug)
if err != nil {
return nil, prototypeCreateOut{}, err
return nil, artifactCreateOut{}, err
}
if err := CheckProjectFromCtx(ctx, p.ID); err != nil {
return nil, prototypeCreateOut{}, err
return nil, artifactCreateOut{}, err
}
proto, err := deps.Prototypes.Create(ctx, c, in.ProjectSlug, in.Number, project.CreatePrototypeInput{
Content: in.Content, Note: in.Note,
art, err := deps.Artifacts.Create(ctx, c, in.ProjectSlug, in.Number, project.CreateArtifactInput{
Phase: project.Phase(in.Phase), Content: in.Content, Note: in.Note,
})
if err != nil {
return nil, prototypeCreateOut{}, err
return nil, artifactCreateOut{}, err
}
return nil, prototypeCreateOut{OK: true, Prototype: prototypeDetail{
Version: proto.Version, Content: proto.Content, Note: proto.Note,
CreatedAt: proto.CreatedAt.Format("2006-01-02T15:04:05Z07:00"),
return nil, artifactCreateOut{OK: true, Artifact: artifactDetail{
Phase: string(art.Phase), Version: art.Version, Content: art.Content, Note: art.Note,
CreatedAt: art.CreatedAt.Format("2006-01-02T15:04:05Z07:00"),
}}, nil
})
}
// ===== list_requirement_prototypes =====
// ===== list_requirement_artifacts =====
type listRequirementPrototypesIn struct {
type listRequirementArtifactsIn struct {
ProjectSlug string `json:"project_slug" jsonschema:"required field"`
Number int `json:"number" jsonschema:"requirement number (>=1)"`
Phase string `json:"phase,omitempty" jsonschema:"filter by phase: planning|prototyping|auditing; empty = all"`
}
type listRequirementPrototypesOut struct {
Prototypes []prototypeDetail `json:"prototypes"`
type listRequirementArtifactsOut struct {
Artifacts []artifactDetail `json:"artifacts"`
}
func registerListRequirementPrototypes(srv *mcpsdk.Server, deps ServerDeps) {
func registerListRequirementArtifacts(srv *mcpsdk.Server, deps ServerDeps) {
mcpsdk.AddTool(srv,
&mcpsdk.Tool{Name: "list_requirement_prototypes", Description: "List prototype versions of a requirement."},
func(ctx context.Context, _ *mcpsdk.CallToolRequest, in listRequirementPrototypesIn) (*mcpsdk.CallToolResult, listRequirementPrototypesOut, error) {
if err := CheckToolFromCtx(ctx, "list_requirement_prototypes"); err != nil {
return nil, listRequirementPrototypesOut{}, err
&mcpsdk.Tool{Name: "list_requirement_artifacts", Description: "List phase artifact versions of a requirement."},
func(ctx context.Context, _ *mcpsdk.CallToolRequest, in listRequirementArtifactsIn) (*mcpsdk.CallToolResult, listRequirementArtifactsOut, error) {
if err := CheckToolFromCtx(ctx, "list_requirement_artifacts"); err != nil {
return nil, listRequirementArtifactsOut{}, err
}
c, err := deps.Caller.Resolve(ctx)
if err != nil {
return nil, listRequirementPrototypesOut{}, err
return nil, listRequirementArtifactsOut{}, err
}
p, err := deps.Projects.Get(ctx, c, in.ProjectSlug)
if err != nil {
return nil, listRequirementPrototypesOut{}, err
return nil, listRequirementArtifactsOut{}, err
}
if err := CheckProjectFromCtx(ctx, p.ID); err != nil {
return nil, listRequirementPrototypesOut{}, err
return nil, listRequirementArtifactsOut{}, err
}
protos, err := deps.Prototypes.List(ctx, c, in.ProjectSlug, in.Number)
arts, err := deps.Artifacts.List(ctx, c, in.ProjectSlug, in.Number, project.Phase(in.Phase))
if err != nil {
return nil, listRequirementPrototypesOut{}, err
return nil, listRequirementArtifactsOut{}, err
}
out := listRequirementPrototypesOut{Prototypes: make([]prototypeDetail, 0, len(protos))}
for _, proto := range protos {
out.Prototypes = append(out.Prototypes, prototypeDetail{
Version: proto.Version, Content: proto.Content, Note: proto.Note,
CreatedAt: proto.CreatedAt.Format("2006-01-02T15:04:05Z07:00"),
out := listRequirementArtifactsOut{Artifacts: make([]artifactDetail, 0, len(arts))}
for _, art := range arts {
out.Artifacts = append(out.Artifacts, artifactDetail{
Phase: string(art.Phase), Version: art.Version, Content: art.Content, Note: art.Note,
CreatedAt: art.CreatedAt.Format("2006-01-02T15:04:05Z07:00"),
})
}
return nil, out, nil