跳到主要内容
轻盈的鱼

← 返回归档

Crispy 后台 AI Agent 完整实现解析

日期:分类:AI 技术标签:AI AgentPayload CMSSSEMCPNext.jsRBACFunction Calling技术架构

Crispy 3 后台 AI Agent 是一套登录态 + Permission 鉴权 + OpenAI Function Calling + SSE 流式的内容运营助手。它与字段 AI、前台只读助手、MCP 并列,但职责与工具集完全独立。本文梳理当前完整实现,方便二次开发与排障。

一句话架构

Admin Cookie 用户在浮窗或 /admin/ai-agent 发消息 → SSE 进入 runAiAgentStream → OpenAI tools 循环(最多 16 轮)执行 AGENT_TOOLS → 每步 Permission assert + overrideAccess: false → 对话落入 ai-chat-sessions;资源边界由 resources.ts 白名单划定,权限真相来自 authz-cache,侧栏导航由 list_admin_menu 与可点击 Markdown 链接对齐真实 Admin。

入口:UI 与 API

Admin 全页

  • Custom View:src/app/(payload)/admin/ai-agent/AiAgentView.tsx
  • 路由:/admin/ai-agent(payload.config.ts → admin.components.views.aiAgent)
  • 侧栏:运营组「AI 内容助手」,anyOf: [ai:use]
  • 服务端先校验登录与 canUseAiAgent,无权限只提示文案

全局浮窗

  • AdminAiAgentProvider 注册在 admin.components.providers
  • 右侧轨道 + Drawer(AdminAiAgentWidget)
  • 与全页共享 AdminAiAgentContext / useAiAgentChat
  • Provider 会挂在登录页,因此会话列表必须等 useAuth().user 就绪后再拉取

API

  • POST /api/ai/agent — SSE 对话主入口
  • GET /api/ai/agent/sessions — 当前用户会话列表
  • GET /api/ai/agent/sessions/:id — 会话详情
  • DELETE /api/ai/agent/sessions/:id — 软删除会话

鉴权链:payload.auth({ headers }) → Cookie 用户 → canUseAiAgent(等价 ai:use)。客户端用 consumeAgentStream 解析 text/event-stream。

Streaming 与 Function Calling 循环

核心在 src/ai/agent/runAgentStream.ts 的 runAiAgentStream:

  • resolveLlmClient({ purpose: 'agent' }) 解析 Catalog LLM
  • 注入 system prompt(含当前用户 authz 权限块)
  • 循环最多 MAX_TOOL_ITERATIONS = 16
  • openAiChatCompletionWithToolsStream(OpenAI 兼容 /v1/chat/completions)
  • 若有 tool_calls:executeAgentTool,把结果写回 conversation 继续
  • 若仅有文本:yield done

SSE 事件

  • text — 增量文本
  • tool_start / tool_result — 工具开始与结果摘要
  • session — API 路由推送,绑定持久化会话 ID
  • done / error — 结束

Agent 统一走 OpenAI 兼容协议(src/ai/providers/openaiCompatible.ts),不单独 fork DeepSeek SDK;字段 AI 仍可走其它 provider 路径。

工具注册表 AGENT_TOOLS

定义与执行均在 src/ai/agent/tools.ts,当前约 24 个工具,按职责分组如下。

元信息与导航

  • get_my_permissions — 当前用户角色与 Permission(authz-cache)
  • list_admin_menu — 当前用户可见 Admin 侧栏(含 href/url,已按权限过滤)
  • list_resources — Agent 可管 Collections / Globals 白名单
  • describe_resource — 查看 collection/global 字段结构(写前应先调)

内容 CRUD

  • semantic_search — 语义搜索 posts/pages/novels/novel-chapters(需 pgvector)
  • find_documents / get_document — 列表与详情
  • create_document / update_document — 新建与更新
  • delete_document / restore_document — 软删除与恢复

运维与媒体

  • get_site_stats / list_audit_logs — 统计与审计
  • list_frontend_cache / purge_frontend_cache / get|update_cache_settings — 前台 HTML 缓存
  • list_query_presets — 查询预设
  • search_stock_images / import_stock_image(s) — Unsplash 检索与导入
  • bulk_add_gallery_images — 批量加入图库
  • get_global / update_global — 读写白名单 Globals

工具结果有 MAX_RESULT_CHARS = 128000 截断保护;读 ai-settings 时会附带密钥不在 Global 明文的说明。

Access 与 RBAC 双检

总闸:canUseAiAgent → canUseAi → can(user, 'ai:use')。工具层通过 assertAgentCollectionAccess / assertAgentGlobalAccess / assertAgentCacheAccess 等与 Admin Permission 对齐。

  • posts:无 posts:update:any 时仅能管自己的文章
  • media:禁止通过 Agent 删除
  • form-submissions:禁止 create/update
  • Catalog:按 catalog:* 拆分读写

双重校验:工具层先 assert*(Permission),再对 Payload Local API 一律 overrideAccess: false + user: req.user。即使 Permission 映射有疏漏,Collection/Global 自身 access 仍会挡住。

会话持久化

  • Collection:ai-chat-sessions(title、user、lastMessageAt、messages JSON)
  • Admin 列表 hidden,由聊天 API 写入
  • sessionStore:create / append user|assistant / list / get / soft-delete

近期修复:Provider 在登录页也会 mount,未登录请求会 401;现用 userId 驱动 refreshSessions,并用 sessionsFetchedForUserRef 避免失败结果覆盖已成功拉取的侧栏。打开浮窗 / 展开历史时也会再刷一次列表。

资源白名单与禁区

白名单见 src/ai/agent/resources.ts(与 MCP 大致对齐)。可管 Collections 含 posts、pages、taxonomy、运营内容、小说、短链、Catalog、画布元数据、评论、表单、media 等;Globals 含 header/footer/site-settings/cache-settings/ai-settings 等。

明确不可管(勿假装可操作):users、roles、authz-cache、payload-mcp-api-keys、search、imports/exports、api-access-logs、文档版本还原。ai-canvases 只管元数据,不改 graph。

近期能力:list_admin_menu 与可点击链接

  • listAdminMenu.ts 复用 getAccessResults / getVisibleEntities / getNavGroups,并 merge 自定义导航
  • 把 authz-cache permissions 挂到 user,使 admin.hidden 与自定义 anyOf 与真实侧栏一致
  • 返回 href(如 /admin/collections/links)与绝对 url;可按 group 过滤
  • System prompt 要求 Markdown [label](href);ChatPanel 解析 Markdown / 裸 URL / /admin 路径为可点击链接

与前台助手、MCP 的差异

  • Admin Agent:Cookie + ai:use,24 个 CRUD/运维工具,会话落库
  • 前台助手:无需登录,仅公开只读检索,浏览器内存会话
  • MCP:API Key,自动 Collection/Global 工具 + mcpCustomTools;复用部分 assert*,但范围与 Agent 不完全相同

配置

无 .env LLM 回退。Global ai-settings 管总开关与默认 Provider;Collection llm-providers 存 OpenAI 兼容端点与加密 API Key;prompt-templates 主要服务字段 AI / 画布,Agent 对话本身使用固定 systemPrompt.ts。

关键路径地图

1入口 UI
2 src/app/(payload)/admin/ai-agent/
3 src/components/AdminAiAgent/
4
5API
6 src/app/(payload)/api/ai/agent/
7
8Agent 核心
9 src/ai/agent/runAgentStream.ts
10 src/ai/agent/tools.ts
11 src/ai/agent/access.ts
12 src/ai/agent/resources.ts
13 src/ai/agent/systemPrompt.ts
14 src/ai/agent/sessionStore.ts
15 src/ai/agent/listAdminMenu.ts
16
17LLM
18 src/ai/resolveLlmClient.ts
19 src/ai/providers/openaiCompatible.ts

更完整的权限与工具对照表可在后台打开 /admin/dev-docs#ai-agent 与 #permissions 查看。

版权信息

日期2026/07/25
协议CC BY-NC-SA 4.0 转载请注明出处
评论

暂无评论,来抢沙发吧。