You've already forked agentic-coding-workflow
修改
This commit is contained in:
@@ -176,6 +176,9 @@ func newACPIntegrationSuite(t *testing.T) *acpIntegrationSuite {
|
||||
ShutdownGrace: 5 * time.Second,
|
||||
}
|
||||
sup := acp.NewSupervisor(acpRepo, auditRec, disp, nil, nil, nil, enc, supCfg, log)
|
||||
permSvc := acp.NewPermissionService(acpRepo, auditRec, 0, log)
|
||||
sup.SetPermissionService(permSvc)
|
||||
permSvc.SetRelayLocator(sup)
|
||||
|
||||
// Minimal stubs for SessionService dependencies — sufficient for branch=main
|
||||
// path (no wtSvc / wsRepo calls) and tests that exercise quota/conflict logic.
|
||||
@@ -192,7 +195,7 @@ func newACPIntegrationSuite(t *testing.T) *acpIntegrationSuite {
|
||||
r.Use(middleware.RequestID)
|
||||
user.NewHandler(userSvc).Mount(r)
|
||||
acp.NewHandler(
|
||||
akSvc, sessSvc, sup, acpRepo,
|
||||
akSvc, sessSvc, sup, acpRepo, permSvc,
|
||||
userSvc,
|
||||
acpUserAdminAdapter{svc: userSvc},
|
||||
enc,
|
||||
|
||||
+22
-2
@@ -32,7 +32,6 @@ import (
|
||||
"github.com/yan1h/agent-coding-workflow/internal/acp"
|
||||
"github.com/yan1h/agent-coding-workflow/internal/audit"
|
||||
"github.com/yan1h/agent-coding-workflow/internal/chat"
|
||||
mcp "github.com/yan1h/agent-coding-workflow/internal/mcp"
|
||||
"github.com/yan1h/agent-coding-workflow/internal/config"
|
||||
"github.com/yan1h/agent-coding-workflow/internal/infra/clock"
|
||||
"github.com/yan1h/agent-coding-workflow/internal/infra/crypto"
|
||||
@@ -45,6 +44,7 @@ import (
|
||||
"github.com/yan1h/agent-coding-workflow/internal/jobs"
|
||||
"github.com/yan1h/agent-coding-workflow/internal/jobs/handlers"
|
||||
"github.com/yan1h/agent-coding-workflow/internal/jobs/runners"
|
||||
mcp "github.com/yan1h/agent-coding-workflow/internal/mcp"
|
||||
"github.com/yan1h/agent-coding-workflow/internal/project"
|
||||
httpx "github.com/yan1h/agent-coding-workflow/internal/transport/http"
|
||||
"github.com/yan1h/agent-coding-workflow/internal/transport/http/middleware"
|
||||
@@ -300,6 +300,11 @@ func New(ctx context.Context, cfg *config.Config, dist embed.FS) (*App, error) {
|
||||
"session_id", sess.ID, "err", rerr.Error())
|
||||
}
|
||||
}
|
||||
// 该会话已被标 crashed,其挂起的权限请求也应一并标 expired,避免悬挂。
|
||||
if _, rerr := acpRepo.ExpirePendingPermissionRequestsBySession(ctx, sess.ID); rerr != nil {
|
||||
log.Warn("acp.startup_reaper.expire_permissions_failed",
|
||||
"session_id", sess.ID, "err", rerr.Error())
|
||||
}
|
||||
uid := sess.UserID
|
||||
if rerr := auditRec.Record(ctx, audit.Entry{
|
||||
UserID: &uid, Action: "acp.session.aborted_on_restart",
|
||||
@@ -369,6 +374,11 @@ func New(ctx context.Context, cfg *config.Config, dist embed.FS) (*App, error) {
|
||||
},
|
||||
log,
|
||||
)
|
||||
// 权限审批服务:与 supervisor 互相依赖,构造后回填(SetPermissionService /
|
||||
// SetRelayLocator),再注入 handler。
|
||||
acpPermSvc := acp.NewPermissionService(acpRepo, auditRec, cfg.Acp.PermissionTimeout, log)
|
||||
acpSup.SetPermissionService(acpPermSvc)
|
||||
acpPermSvc.SetRelayLocator(acpSup)
|
||||
sessSvc := acp.NewSessionService(
|
||||
acpRepo, wsSvc, wtSvc, wsRepo,
|
||||
acpProjAccess, acpSup, auditRec,
|
||||
@@ -380,7 +390,7 @@ func New(ctx context.Context, cfg *config.Config, dist embed.FS) (*App, error) {
|
||||
},
|
||||
mcpTokenSvc,
|
||||
)
|
||||
acp.NewHandler(akSvc, sessSvc, acpSup, acpRepo, userSvc, userAdminAdapter{svc: userSvc}, enc, acp.WSConfig{
|
||||
acp.NewHandler(akSvc, sessSvc, acpSup, acpRepo, acpPermSvc, userSvc, userAdminAdapter{svc: userSvc}, enc, acp.WSConfig{
|
||||
PingInterval: cfg.Acp.WSPingInterval,
|
||||
PongTimeout: cfg.Acp.WSPongTimeout,
|
||||
SendBuffer: cfg.Acp.WSSendBuffer,
|
||||
@@ -543,6 +553,16 @@ func New(ctx context.Context, cfg *config.Config, dist embed.FS) (*App, error) {
|
||||
}
|
||||
}
|
||||
|
||||
// 注册 system 作用域的 prompt 模板为 MCP prompts(spec)。需在 bootstrap 之后
|
||||
// 执行以保证存在 admin;失败仅 warn,不阻断启动。以第一个 admin 的视角加载模板。
|
||||
if admins, err := userSvc.ListAdmins(ctx); err != nil {
|
||||
log.Warn("mcp register_system_prompts: list admins failed", "err", err.Error())
|
||||
} else if len(admins) > 0 {
|
||||
if err := mcp.RegisterSystemPrompts(mcpServer, mcpDeps, admins[0].ID); err != nil {
|
||||
log.Warn("mcp register_system_prompts failed", "err", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
srv := &http.Server{
|
||||
Addr: cfg.HTTP.Addr,
|
||||
Handler: r,
|
||||
|
||||
@@ -47,9 +47,9 @@ import (
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/google/uuid"
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
mcpsdk "github.com/modelcontextprotocol/go-sdk/mcp"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
mcpsdk "github.com/modelcontextprotocol/go-sdk/mcp"
|
||||
tcpg "github.com/testcontainers/testcontainers-go/modules/postgres"
|
||||
|
||||
"github.com/yan1h/agent-coding-workflow/internal/audit"
|
||||
@@ -327,9 +327,9 @@ func (s *mcpIntegrationSuite) seedAdditionalProject(t *testing.T, ownerID uuid.U
|
||||
t.Helper()
|
||||
caller := project.Caller{UserID: ownerID, IsAdmin: ownerID == s.adminID}
|
||||
p, err := s.projectSvc.Create(s.ctx, caller, project.CreateProjectInput{
|
||||
Slug: slug,
|
||||
Name: slug,
|
||||
Visibility: project.VisibilityInternal,
|
||||
Slug: slug,
|
||||
Name: slug,
|
||||
Visibility: project.VisibilityInternal,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
return p.ID
|
||||
@@ -342,9 +342,9 @@ func (s *mcpIntegrationSuite) seedPrivateProjectFor(t *testing.T, ownerID uuid.U
|
||||
slug := fmt.Sprintf("private-%s", uuid.New().String()[:8])
|
||||
caller := project.Caller{UserID: ownerID, IsAdmin: false}
|
||||
p, err := s.projectSvc.Create(s.ctx, caller, project.CreateProjectInput{
|
||||
Slug: slug,
|
||||
Name: "Private " + slug,
|
||||
Visibility: project.VisibilityPrivate,
|
||||
Slug: slug,
|
||||
Name: "Private " + slug,
|
||||
Visibility: project.VisibilityPrivate,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
return p.ID, p.Slug
|
||||
@@ -390,8 +390,8 @@ func (s *mcpIntegrationSuite) queryAuditMetadata(t *testing.T, action string) ma
|
||||
|
||||
// bearerRoundTripper injects an Authorization: Bearer header into every request.
|
||||
type bearerRoundTripper struct {
|
||||
inner http.RoundTripper
|
||||
token string
|
||||
inner http.RoundTripper
|
||||
token string
|
||||
}
|
||||
|
||||
func (rt *bearerRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
|
||||
Reference in New Issue
Block a user