refactor: 专员目录收敛为 6 个,重整 AI 路由与系统管理页

一次性提交当天全部改动(110 个文件)。

**未按 TOP_CODING_RULES.md G14.5「一次提交只装一件事」拆分** —— 用户明确要求
单一提交,此处如实记录,不静默忽略该冲突。

提交前验证:后端 go build / go vet / go test ./... 全绿,前端 npm run build
exit 0,/api/health 与管理员 login 均返回 200。

- 专员目录收敛为 6 个:下线 knowledge-operations / process-coordination /
  presentation-briefing / report-generation 四个专员(前后端 manifest 与 seed
  同步删除),新增 general-assistant。专员的归属关系(拥有哪些技能定义、
  哪些目录项、提示词与绑定从哪来)改由 specialists/core 的 ownership.go、
  prompt_provider.go、binding_provider.go 统一提供,seed 与 admin_handlers
  随之内置化,卸载路径统一走 uninstall.go。
- 技能:补齐 text-to-speech 的前端 manifest(后端包在 HEAD 已存在),
  skillcore/ownership.go 提供与专员对称的归属查询。
- AI 路由:ai_config.json 由 OpenRouter/Ollama 切到 LMUAI / SiliconFlow /
  llama.cpp 本地路由,ai_secrets.example.json 与部署 env 样例同步新增
  SILICONFLOW_API_KEY。
- 系统管理页重整:新增 AiAdminPage、OrganizationManagementPage,删除
  AdminOverviewPage、CompanyConfigPage,SystemConfigPage 精简,nav / router /
  config/workbench.js 同步调整。依 G05.5,开发阶段直接收口到新结构,不留旧路由。
- 新增 internal/objectrefs:统一统计对象(专员 / 技能 / xapp)的运行时引用
  (被多少 xapp、项目、任务引用),供管理页做删除前的影响面判断。
- 公众号创作专员:新增 OfficialAccountSpecialistPanel,workflow 与投递链路调整。
- XApp:考试 / 培训 Shell 扩展,XAppDirectoryPage 与 xappDefinition 同步。
- 文档:新增 GW01–GW05 工作台演进系列与 AR12 对话驱动与结构化交互架构;
  同步 AR05 / SY17 / SY23 / SY25 / PL04;TOP_CODING_RULES.md 增补 G05.5。

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
eaiadmin
2026-09-23 09:01:28 +08:00
co-authored by Claude Code
parent 7fc2903827
commit 593323a934
110 changed files with 8295 additions and 1715 deletions
@@ -6,6 +6,8 @@ import (
"github.com/gin-gonic/gin"
"eai_agentplatform/backend/internal/dal"
"eai_agentplatform/backend/internal/objectrefs"
skillcore "eai_agentplatform/backend/internal/skills/core"
skillmodel "eai_agentplatform/backend/internal/skills/model"
"eai_agentplatform/backend/internal/web"
)
@@ -117,6 +119,10 @@ func DeleteSkillDefinition(c *gin.Context) {
web.Fail(c, web.NewNotFoundError("技能定义不存在"))
return
}
if plan, ok := skillcore.BuildRemovePlanByKey(item.Key); ok && plan.Blocked {
web.Fail(c, web.NewConflictError("技能仍被专员、应用或项目引用,请先处理 remove-plan 中的关联项"))
return
}
if !skillDefinitionDAO.Delete(&item) {
web.Fail(c, web.NewBadRequest("删除技能定义失败"))
return
@@ -124,6 +130,52 @@ func DeleteSkillDefinition(c *gin.Context) {
web.OK(c, gin.H{"id": id, "deleted": true})
}
// PreviewSkillRemovePlan GET /api/admin/skills/:id/remove-plan (admin)
func PreviewSkillRemovePlan(c *gin.Context) {
id, ok := parseID(c, "id")
if !ok {
return
}
item, found := skillDefinitionDAO.GetByID(id)
if !found {
web.Fail(c, web.NewNotFoundError("技能定义不存在"))
return
}
if plan, ok := skillcore.BuildRemovePlanByKey(item.Key); ok {
web.OK(c, gin.H{
"id": item.ID,
"key": item.Key,
"label": item.Label,
"source": item.Source,
"state": item.State,
"is_builtin": true,
"plan": plan,
})
return
}
refs := objectrefs.CollectSkillRuntimeRefs(item.Key)
web.OK(c, gin.H{
"id": item.ID,
"key": item.Key,
"label": item.Label,
"source": item.Source,
"state": item.State,
"is_builtin": false,
"plan": gin.H{
"key": item.Key,
"label": item.Label,
"definition_keys": []string{},
"catalog_entries": []string{},
"policy": "",
"runtime_refs": refs,
"blocked": false,
},
})
}
func parseID(c *gin.Context, name string) (uint, bool) {
id, err := strconv.ParseUint(c.Param(name), 10, 64)
if err != nil || id == 0 {