按桌面客户端统一方案 v0.1 + agent_management Sub Mode Runtime 对接,强制全量统一,不留兼容。
命名统一(强制,无兼容):
- 全仓 agnet/Agnet/AGNET → agent/Agent/AGENT:后端 Go(路由 /api/agent/*、env AGENT_*、
结构体/函数、19 个文件改名)、前端(agent-console/agent-hub、/api/agent 调用、i18n)、
DB(表 agent_*、列 agent_id)、compose/.env、文档、脚本。
- DB 加幂等迁移 renameAgnetTablesToAgent():启动时 rename 老 agnet_* 表/列,保住生产数据。
统一方案核心(10 项):
- callback 统一 /api/agent/callbacks/runtime-events(路由/广播URL/函数名)。
- artifact 兜底判定改用 Runtime 权威信号 metadata.synthesized(§7.2)+ 结构化 artifact_type。
- Manager→Runtime 路径对齐 /api/agent/sub-agile/deployments(§2.2),{deployment_id} 回退 swarm_id。
- 状态裁决 display_status:Manager 唯一裁判,completed 无有效产物→needs_codegen/
completed_without_deliverable(§10.6),接入 detail/timeline/workflow。
- GET /api/heicode/capabilities 能力发现(§6)。
- 模型策略 per_role(role_models)+ 收集 allowed_model_ids(§9)。
- resource_binding_id→secret_ref 服务端解析,客户端不再 inline secret_ref(§17.6)。
- 客户端统一路由层 /api/heicode/sub-agile|swarm/*(task≡deployment,复用控制面)+ workflow 投影。
- 日志分层 user_logs/debug_logs(§13)。
验证:go build ./... + go test(controller/router/model/middleware)全绿;前端 tsc -b + rsbuild build 通过。
待部署:VM .env 的 AGNET_*→AGENT_*;启动迁移自动 rename 表;其他三仓库需同步切到 /api/agent。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
165 lines
5.8 KiB
Go
165 lines
5.8 KiB
Go
package controller
|
|
|
|
import (
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/heicode/manager/common"
|
|
)
|
|
|
|
// AgentRoleTemplate is the platform-recommended role catalog Manager
|
|
// surfaces to users when they assemble an AI development team. The
|
|
// six canonical roles come from docs/product-package/13-platform-
|
|
// description.md §3 and 04-platform-usage-guide.md §第五步.
|
|
//
|
|
// Why constants, not a DB table:
|
|
// - Roles are platform-defined contracts, not user-editable data.
|
|
// Treating them like rows would invite drift between deployments.
|
|
// - Permission hints below are *recommendations* the UI uses to
|
|
// pre-fill the "what can this Agent do" confirmation card —
|
|
// the actual permission grant still goes through ResourceGrant.
|
|
// - If we ever need per-tenant role customization, we add an
|
|
// overlay table; the canonical set still lives here as the
|
|
// baseline.
|
|
//
|
|
// Wire-format note: keys (key column) are stable identifiers used
|
|
// across persistence and the client picker. Display strings can
|
|
// be translated, but the key must NEVER change without a coordinated
|
|
// frontend rollout.
|
|
type AgentRoleTemplate struct {
|
|
Key string `json:"key"`
|
|
DisplayName string `json:"display_name"`
|
|
Summary string `json:"summary"`
|
|
DefaultModel string `json:"default_model"`
|
|
DefaultPermissions []string `json:"default_permissions"`
|
|
RiskLevel string `json:"risk_level"`
|
|
}
|
|
|
|
// defaultAgentModelID is the single source of truth for the default sub-agent
|
|
// model. It is aligned to the production-verified NewAPI model and overridable
|
|
// via AGENT_DEFAULT_MODEL_ID, so role templates, deployment drafts and runtime
|
|
// agent refs never fall back to placeholder names (e.g. agent-model-<role>)
|
|
// that production NewAPI cannot route ("No available channel for model ...").
|
|
func defaultAgentModelID() string {
|
|
return common.GetEnvOrDefaultString("AGENT_DEFAULT_MODEL_ID", "gpt-5.4")
|
|
}
|
|
|
|
// agentRoleTemplates returns the canonical six-role catalog. Order
|
|
// matches the typical lifecycle a user walks through when assembling
|
|
// a team: discover -> design -> build -> review -> operate.
|
|
//
|
|
// Permission hints use the verbs from docs §13.3.4 (Resource Grant)
|
|
// and stay deliberately broad — concrete grants come from the user
|
|
// resource-binding flow.
|
|
func agentRoleTemplates() []AgentRoleTemplate {
|
|
return []AgentRoleTemplate{
|
|
{
|
|
Key: "product",
|
|
DisplayName: "Product Agent",
|
|
Summary: "Refines the user idea into product scope, requirements and acceptance criteria.",
|
|
DefaultModel: defaultAgentModelID(),
|
|
DefaultPermissions: []string{
|
|
"read:project_docs",
|
|
"write:product_spec",
|
|
},
|
|
RiskLevel: agentRiskLow,
|
|
},
|
|
{
|
|
Key: "architect",
|
|
DisplayName: "Architect Agent",
|
|
Summary: "Designs the technical approach, picks frameworks, and breaks work into sub-tasks.",
|
|
DefaultModel: defaultAgentModelID(),
|
|
DefaultPermissions: []string{
|
|
"read:repo",
|
|
"write:architecture_doc",
|
|
},
|
|
RiskLevel: agentRiskLow,
|
|
},
|
|
{
|
|
Key: "frontend",
|
|
DisplayName: "Frontend Agent",
|
|
Summary: "Implements UI, components and client-side state per the architect's plan.",
|
|
DefaultModel: defaultAgentModelID(),
|
|
DefaultPermissions: []string{
|
|
"read:repo",
|
|
"write:repo:frontend",
|
|
},
|
|
RiskLevel: agentRiskMedium,
|
|
},
|
|
{
|
|
Key: "backend",
|
|
DisplayName: "Backend Agent",
|
|
Summary: "Implements server-side APIs, data models and integrations.",
|
|
DefaultModel: defaultAgentModelID(),
|
|
DefaultPermissions: []string{
|
|
"read:repo",
|
|
"write:repo:backend",
|
|
"read:dev_database",
|
|
},
|
|
RiskLevel: agentRiskMedium,
|
|
},
|
|
{
|
|
Key: "reviewer",
|
|
DisplayName: "Reviewer Agent",
|
|
Summary: "Performs code review, security checks and runs the test suite.",
|
|
DefaultModel: defaultAgentModelID(),
|
|
DefaultPermissions: []string{
|
|
"read:repo",
|
|
"run:tests",
|
|
"comment:pull_request",
|
|
},
|
|
RiskLevel: agentRiskLow,
|
|
},
|
|
{
|
|
Key: "ops",
|
|
DisplayName: "Ops Agent",
|
|
Summary: "Deploys to test environments, watches logs and prepares production rollouts (production requires approval).",
|
|
DefaultModel: defaultAgentModelID(),
|
|
DefaultPermissions: []string{
|
|
"read:repo",
|
|
"deploy:test_env",
|
|
"read:metrics",
|
|
"approval_required:deploy_prod",
|
|
},
|
|
RiskLevel: agentRiskHigh,
|
|
},
|
|
}
|
|
}
|
|
|
|
// AgentListRoleTemplates is the GET /api/agent/role-templates handler.
|
|
// Returns the canonical six-role catalog so the deployment-creation
|
|
// UI can pre-populate role pickers and the documentation page can
|
|
// render the role overview.
|
|
//
|
|
// Auth: requires UserAuth (mounted by router). Anyone logged in to
|
|
// Manager can read the catalog; there are no secrets in the payload.
|
|
func AgentListRoleTemplates(c *gin.Context) {
|
|
tpls := agentRoleTemplates()
|
|
common.ApiSuccess(c, gin.H{
|
|
"items": tpls,
|
|
"total": len(tpls),
|
|
})
|
|
}
|
|
|
|
// agentRoleTemplateKeys is a helper for validation in deployment
|
|
// creation — checks whether a user-provided role_template string is
|
|
// one of the canonical six. Returns true for any of the canonical
|
|
// keys; returns true for unknown keys too (deployment flow today
|
|
// accepts free-form role_template strings, see agent_control_plane.
|
|
// go:552), so this helper is currently advisory. When we tighten
|
|
// validation (after frontend ships the new picker), flip the
|
|
// fallback to false and add a unit test.
|
|
func agentRoleTemplateKeys() map[string]bool {
|
|
keys := make(map[string]bool)
|
|
for _, t := range agentRoleTemplates() {
|
|
keys[t.Key] = true
|
|
}
|
|
return keys
|
|
}
|
|
|
|
// agentIsCanonicalRoleKey reports whether `key` matches one of the
|
|
// six platform-defined roles. Today the deployment endpoint accepts
|
|
// any non-empty string; this helper is reserved for the next step
|
|
// when we move to a closed set.
|
|
func agentIsCanonicalRoleKey(key string) bool {
|
|
return agentRoleTemplateKeys()[key]
|
|
}
|