用途
unopim-ai-agent 用于在 UnoPim 中添加、修改或调试 AI 智能体聊天工具(chat tool),包括一个 PimTool 类、它在 ToolRegistry 中的注册项,或 ai-agent.tools 配置;也用于运行或编写 ai-agent:* 命令。
该智能体聊天逻辑位于 packages/Webkul/AiAgent;其调用的 provider/platform 层位于 packages/Webkul/MagicAI。由 LLM 决定调用哪个工具,并使用它自创的参数。因此每个工具都是不可信输入入口,每一次读取都可能被要求返回整个目录(catalog)。
必需背景
- unopim-standards(security.md、scale.md、localization.md):提供规则;
- unopim-exec:用于解析命令;
- unopim-verify:在宣布完成前使用。
AI 连接器的凭据存储见 unopim-plugin-development 的 credentials.md,此处不再重新推导。
参考文件
- tools.md:在添加、覆盖或禁用聊天工具;权限层;审批模式;安全查询;测试工具时阅读;
- commands.md:在运行或编写 ai-agent:* 命令;调度;unopim:magic-ai:platform:* 命令时阅读。
范例(可复制其结构)
- 契约:packages/Webkul/AiAgent/src/Chat/Contracts/PimTool.php
- 注册与元数据:packages/Webkul/AiAgent/src/Chat/ToolRegistry.php、packages/Webkul/AiAgent/Config/ai-agent.php
- 读取工具、可移植 JSON SQL、限制上限:packages/Webkul/AiAgent/src/Chat/Tools/SearchProducts.php
- 遵守 review 模式的写入工具:packages/Webkul/AiAgent/src/Chat/Tools/CreateProduct.php
- 按请求的可用性门控:packages/Webkul/AiAgent/src/Chat/Contracts/AuthorizesContext.php
- 工具输出中的 PII:packages/Webkul/AiAgent/src/Chat/Tools/ManageUsers.php
- 批处理、可恢复命令:packages/Webkul/AiAgent/src/Console/Commands/IndexProductEmbeddings.php
- 注册表测试:packages/Webkul/AiAgent/tests/Unit/ToolRegistryExtensibilityTest.php
臆想 API 与真实 API
- 直接注册实现 Laravel\Ai\Contracts\Tool 的类 → 应实现 PimTool::register(ChatContext $context): Tool;返回一个继承 Chat\Tools\ContextualTool 的匿名类。
- 把工具放在 config/ai.php 或 AiAgent::tool() → 应放在 ai-agent.tools 映射(class => metadata),由 ToolRegistry 单例读取一次。
- 用插件的 mergeConfigFrom(…, 'ai-agent') 添加工具 → 浅合并会丢掉插件的工具或抹掉核心工具。应使用 callAfterResolving(ToolRegistry::class, …);见 tools.md。
- 在 handle() 中用 auth()->user()->can(...) → 应通过 ChecksPermission trait 使用 $this->context->hasPermission($key)。
- php artisan ai-agent:enrich-products、ai-agent:analyze-image → 这些类在 packages/Webkul/AiAgent/src/Examples/ 中,从未注册,命令并不存在。
- AiAgent 中的 src/Database/Migrations/ 文件夹 → 应为根级 packages/Webkul/AiAgent/Database/Migration(单数),provider 只加载该路径。
决策流程——新增聊天工具
- 先搜索 packages/Webkul/AiAgent/src/Chat/Tools/。现有工具的缺口应是它的一个参数,而不是另一个描述重叠的第二个工具——模型会在近似重复项之间随机选择。
- 选择该工具动作在现有 acl.php 中对应的 ACL 键(catalog.products、catalog.products.edit 等)。不匹配任何内容的键在 permission_type = all roles 时仍会通过,所以拼写错误会隐形上线——见 tools.md。
- 编写类:implements PimTool;匿名 ContextualTool,包含 name()、description()、schema()、handle();使用 ChecksPermission 并在 handle() 中首先调用 denyUnlessAllowed()。
- 约束每一次读取:用 min(max(…)) 收紧 limit,设置硬上限、显式 orderBy,并在进入 SQL 前对模型传入的每个 code 做允许列表校验。
- 写入工具:设置 'write' => true,在变更前调用 shouldQueueForApproval() / queueChange(),并通过 repositories 或 ProductWriterService,使事件、历史与完整性计算触发。
- 注册:核心 → 在 Config/ai-agent.php 加一行;插件 → 在其 provider 中 callAfterResolving。
- 在 packages/Webkul/AiAgent/tests/Unit/Tools/ 中测试——这是 phpunit.xml 套件中唯一的 AiAgent 目录。其同级 Feature 文件夹不属于任何套件,CI 中从不运行。覆盖:权限被拒、limit 收紧、非法 code 被拒、review 模式排队。
UnoPim 特有陷阱
- 两层权限都必需。permission 元数据在 ToolRegistry::build() 中向 LLM 隐藏工具;handle() 中的 denyUnlessAllowed() 才是执行。用 permission => null 注册的工具会提供给每个能打开聊天的管理员。
- 审批模式主要是提示文本。suggest 和 review 是对模型的指令(AgentRunner::buildSystemPrompt());只有调用 shouldQueueForApproval() 的工具才真正排队。没有它的写入工具在任何模式下都会直接变更。
- write 元数据驱动 UI。AgentRunner::flagMutation() 读取它来通知 widget 重载。一个变更类工具若 write => false,会留下过期的产品页面。
- 单例捕获(Octane)。ToolRegistry 是单例,每个 worker 构建每个工具一次,因此构造函数依赖会存活于 worker 生命周期。只注入无状态服务;在 handle() 内解析 scoped() 服务(ProductWriterService、VisionService)。所有请求状态放在 ChatContext 上。
- 可移植性。产品值是 JSON。使用 GrammarQueryManager::getGrammar()->jsonExtract() / jsonContains(),并像 SearchProducts 那样为原始表别名加上 DB::getTablePrefix() 前缀。packages/Webkul/AiAgent/tests/Unit/Tools/PgsqlCompatibilityTest.php 会 grep 仅 MySQL 的 JSON 函数——请把你的工具加入其中。
- Elasticsearch 是可选的。向量存储需要同时满足 ai-agent.vector_store.enabled 和 elasticsearch.enabled(ProductEmbeddingIndex::isEnabled());FindSimilarProducts 会回退到数据库池。任何使用嵌入的工具都需要同样的回退。
- 面向模型与面向用户的文本。name()、description()、schema 描述和 JSON 错误字符串由 LLM 读取,像所有核心工具一样保持英文。任何在管理 UI 中渲染或作为命令输出的内容,都要在全部 33 个语言区域中通过 trans()(unopim-standards localization.md)。
- 工具输出是发送给第三方模型的数据。返回最小字段;像 ManageUsers 那样对 PII 脱敏;绝不返回凭据或平台行。
验证
unopim-verify 的 gate 1–4 和 6 始终执行。Gate 5(Playwright)仅在聊天 widget 的 Blade 或其 JS 变更时执行——否则说明跳过。运行 --testsuite="AiAgent Unit Test"(CI 在 MySQL 和 PostgreSQL 上运行它)。MagicAI Unit Test / MagicAI Feature Test 在 MySQL 和 PostgreSQL 工作流的套件列表中缺失——只有 MariaDB 工作流运行它们——因此在改动 MagicAI 后请自行运行它们。