Commit 70905178 authored by AI-甘富林's avatar AI-甘富林

Initial commit: qianjiangb2b - Vite + React + TypeScript + Supabase B2B platform

Frontend: React 18, TypeScript, Vite, shadcn/ui, Tailwind CSS
Backend: Supabase (Edge Functions, Migrations, Auth)
Features: Admin dashboard, AI agents, chat, orders, coupons, finance, marketing, after-sales
parents
VITE_SUPABASE_PROJECT_ID="your-project-id"
VITE_SUPABASE_PUBLISHABLE_KEY="your-publishable-key"
VITE_SUPABASE_URL="https://your-project.supabase.co"
SUPABASE_URL="https://your-project.supabase.co"
SUPABASE_SERVICE_ROLE_KEY="your-service-role-key"
SUPABASE_PROJECT_ID="your-project-id"
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
.env
.env.*
!.env.example
supabase/.temp
supabase/supabase-cli.exe
*.lockb
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
This diff is collapsed.
# Welcome to your Lovable project
## Project info
**URL**: https://lovable.dev/projects/38fd7eb5-c717-40c6-bf00-31f416321ded
## How can I edit this code?
There are several ways of editing your application.
**Use Lovable**
Simply visit the [Lovable Project](https://lovable.dev/projects/38fd7eb5-c717-40c6-bf00-31f416321ded) and start prompting.
Changes made via Lovable will be committed automatically to this repo.
**Use your preferred IDE**
If you want to work locally using your own IDE, you can clone this repo and push changes. Pushed changes will also be reflected in Lovable.
The only requirement is having Node.js & npm installed - [install with nvm](https://github.com/nvm-sh/nvm#installing-and-updating)
Follow these steps:
```sh
# Step 1: Clone the repository using the project's Git URL.
git clone <YOUR_GIT_URL>
# Step 2: Navigate to the project directory.
cd <YOUR_PROJECT_NAME>
# Step 3: Install the necessary dependencies.
npm i
# Step 4: Start the development server with auto-reloading and an instant preview.
npm run dev
```
**Edit a file directly in GitHub**
- Navigate to the desired file(s).
- Click the "Edit" button (pencil icon) at the top right of the file view.
- Make your changes and commit the changes.
**Use GitHub Codespaces**
- Navigate to the main page of your repository.
- Click on the "Code" button (green button) near the top right.
- Select the "Codespaces" tab.
- Click on "New codespace" to launch a new Codespace environment.
- Edit files directly within the Codespace and commit and push your changes once you're done.
## What technologies are used for this project?
This project is built with:
- Vite
- TypeScript
- React
- shadcn-ui
- Tailwind CSS
## How can I deploy this project?
Simply open [Lovable](https://lovable.dev/projects/38fd7eb5-c717-40c6-bf00-31f416321ded) and click on Share -> Publish.
## Can I connect a custom domain to my Lovable project?
Yes, you can!
To connect a domain, navigate to Project > Settings > Domains and click Connect Domain.
Read more here: [Setting up a custom domain](https://docs.lovable.dev/features/custom-domain#custom-domain)
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "default",
"rsc": false,
"tsx": true,
"tailwind": {
"config": "tailwind.config.ts",
"css": "src/index.css",
"baseColor": "slate",
"cssVariables": true,
"prefix": ""
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui",
"lib": "@/lib",
"hooks": "@/hooks"
}
}
# 项目知识库索引
> 智能电商管理系统(C 端消费者 + B 端管理后台)的完整文档索引。
> **最后更新**: 2026-04-23 · **当前真相源**: 标记为 ✅ 的文档为最新权威版本。
---
## 🎯 快速导航
| 我想… | 看这个 |
|---|---|
| 了解整个系统架构 | [project-overview.md](./project-overview.md) ✅ |
| 接入 Coze Agent | [coze-integration-guide.md](./coze-integration-guide.md) ✅ |
| 接入 Dify Agent | [dify-lovable-integration.md](./dify-lovable-integration.md) ✅ |
| 开发 GenUI 组件 | [genui-api-guide.md](./genui-api-guide.md) ✅ |
| 写管理端 AI 操作 | [admin-ai-operations-guide.md](./admin-ai-operations-guide.md) ✅ |
| 协同 Lovable + Coze | [lovable-coze-collaboration-guide.md](./lovable-coze-collaboration-guide.md) ✅ |
---
## 📚 文档分类
### 🏗 架构 & 总览
-[project-overview.md](./project-overview.md)**项目档案**:技术栈、模块、五大 Agent、关键数据流
-[system-architecture.md](./system-architecture.md) — 系统架构详解
- [coze-lovable-sync-status.md](./coze-lovable-sync-status.md) — Coze ↔ Lovable 同步现状
### 🤖 AI Agent 集成
-[coze-integration-guide.md](./coze-integration-guide.md) — Coze 接入主指南(B 端)
- [coze-consumer-agent-spec.md](./coze-consumer-agent-spec.md) — C 端 Coze Agent 规范
- [coze-issue-report-2026-02-06.md](./coze-issue-report-2026-02-06.md) — 已知问题报告
-[dify-lovable-integration.md](./dify-lovable-integration.md) — Dify 接入主指南(C 端)
- [dify-agent-config-guide.md](./dify-agent-config-guide.md) — Dify Agent 配置
- [dify-system-info-guide.md](./dify-system-info-guide.md) — Dify 系统信息接口
- [dify-page-control-guide.md](./dify-page-control-guide.md) — Dify 控制页面
- [dify-dashboard-control-guide.md](./dify-dashboard-control-guide.md) — Dify 控制仪表盘
- [langchain-agent-development-guide.md](./langchain-agent-development-guide.md) — LangChain 风格 Agent 开发
### 🎨 GenUI(动态 UI 生成)
-[genui-api-guide.md](./genui-api-guide.md) — GenUI API 与组件库
-[lovable-coze-collaboration-guide.md](./lovable-coze-collaboration-guide.md) — Lovable + Coze 协同协议
### 🛠 管理端能力
-[admin-ai-operations-guide.md](./admin-ai-operations-guide.md) — AI 自然语言操作(最新)
- [admin-operations-guide.md](./admin-operations-guide.md) — 传统管理操作 API
- [ai-audit-api.md](./ai-audit-api.md) — AI 审计接口
### 🧰 基础设施
- [e2b-sandbox-integration-guide.md](./e2b-sandbox-integration-guide.md) — E2B 沙盒集成
---
## 🧠 与 mem://(项目记忆)的关系
| 来源 | 用途 |
|---|---|
| **mem://** | 简洁规则 + 决策记录,**每次 AI 对话自动应用** |
| **docs/** | 详细技术文档,AI 按需查阅、新人入门 |
| **knowledge_base 表** | 向量化检索源,运行时 RAG 引用 |
**原则**
- 设计决策、约束、偏好 → 写 `mem://`
- 操作步骤、API 规范、架构图 → 写 `docs/`
- 需要 AI 在运行时检索的内容 → 同步到 `knowledge_base`
---
## 📝 维护规则
1. 新增文档时,必须在本索引列出并标记是否为权威版本(✅)
2. 文档过时时,标注 `> ⚠️ DEPRECATED · 见 xxx.md`
3. 重大架构变更需同步更新:本索引 + `mem://index.md` + `system_guide`
# Admin AI 自然语言操作指南
## 系统架构
```
┌─────────────────────────────────────────────────────────────────┐
│ 用户交互 │
│ 管理员输入: "显示价格最高的10个Apple商品" │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ AdminAIAssistant │
│ 1. 发送消息到 dify-chat-admin │
│ 2. 接收 Dify 返回的响应 │
│ 3. 解析响应中的动作标记块 │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ Dify 工作流 │
│ 1. 调用 system-info/system-actions 获取能力定义 │
│ 2. 理解用户意图 │
│ 3. 生成带有动作标记块的响应 │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ 统一动作系统 │
│ extractUnifiedActions() → executeUnifiedActions() │
│ - 页面动作: 导航、筛选、排序、搜索 │
│ - 数据动作: 创建、更新、删除 → admin-operations │
└─────────────────────────────────────────────────────────────────┘
```
## 动作类型
### 1. 页面动作 (PAGE_ACTION)
用于控制 Admin 页面的导航、筛选、排序和搜索。
#### 格式
```
[PAGE_ACTION]{"type":"...", "params":{...}}[/PAGE_ACTION]
```
#### 支持的类型
| type | 描述 | 必需参数 |
|------|------|----------|
| `navigate` | 导航到页面 | `tab` |
| `search` | 搜索 | `tab`, `keyword` |
| `sort` | 排序 | `tab`, `field`, `direction` |
| `filter` | 筛选 | `tab`, `filters` |
| `set_page_state` | 综合设置 | `tab`, 可选: `filters`, `sort`, `search` |
#### 有效的 tab 值
- `products` - 商品管理
- `orders` - 订单管理
- `users` - 用户管理
- `categories` - 分类管理
- `brands` - 品牌管理
- `banners` - 横幅管理
- `coupons` - 优惠券管理
- `aftersales` - 售后管理
#### 示例
**导航**
```json
[PAGE_ACTION]{"type":"navigate","params":{"tab":"orders"}}[/PAGE_ACTION]
```
**搜索**
```json
[PAGE_ACTION]{"type":"search","params":{"tab":"products","keyword":"iPhone"}}[/PAGE_ACTION]
```
**综合状态**
```json
[PAGE_ACTION]{"type":"set_page_state","params":{
"tab":"products",
"filters":{"brand":"Apple"},
"sort":{"field":"price","direction":"desc"}
}}[/PAGE_ACTION]
```
### 2. 数据动作 (DATA_ACTION)
用于执行数据库 CRUD 操作。
#### 格式
```
[DATA_ACTION]{"type":"...", "params":{...}}[/DATA_ACTION]
```
#### 支持的类型
| type | 描述 | 必需参数 |
|------|------|----------|
| `create_product` | 创建商品 | `name`, `price` |
| `update_product` | 更新商品 | `id` |
| `delete_product` | 删除商品 | `id` |
| `update_order` | 更新订单 | `id` |
| `cancel_order` | 取消订单 | `id` |
| `create_category` | 创建分类 | `name` |
| `create_brand` | 创建品牌 | `name` |
| `create_banner` | 创建横幅 | `title` |
| `approve_aftersales` | 批准售后 | `id` |
| `reject_aftersales` | 拒绝售后 | `id`, `reason` |
#### 示例
**创建商品**
```json
[DATA_ACTION]{"type":"create_product","params":{
"name":"iPhone 16 Pro",
"price":8999,
"brand":"Apple",
"category":"手机",
"stock_quantity":100
}}[/DATA_ACTION]
```
**更新订单状态**
```json
[DATA_ACTION]{"type":"update_order","params":{
"id":"order-uuid-here",
"status":"shipped"
}}[/DATA_ACTION]
```
## Dify 工作流配置
### 1. 添加 HTTP 请求节点
在 Dify 工作流中添加 HTTP 请求节点来获取系统能力:
**URL**: `https://tlsofopqzrzuduinsicm.supabase.co/functions/v1/system-actions`
**Method**: GET
**Headers**:
```
Authorization: Bearer <SUPABASE_ANON_KEY>
```
### 2. 系统提示词模板
```
你是一个智能管理后台助手,可以帮助管理员执行各种操作。
## 可用能力
### 页面操作
当用户想要查看数据、导航到页面、搜索或筛选时,使用 PAGE_ACTION:
{{system_actions_response.pageActions}}
### 数据操作
当用户想要创建、更新、删除数据时,使用 DATA_ACTION:
{{system_actions_response.dataActions}}
## 响应格式
在回复末尾添加动作标记块:
1. 页面操作:[PAGE_ACTION]{"type":"...", "params":{...}}[/PAGE_ACTION]
2. 数据操作:[DATA_ACTION]{"type":"...", "params":{...}}[/DATA_ACTION]
## 注意事项
- 确保 JSON 格式正确
- 必需参数必须提供
- 可以在一条回复中包含多个动作
- 先给用户自然语言回复,再附加动作标记块
```
### 3. 示例对话
**用户**: 打开商品管理页面
**AI响应**:
```
好的,我来帮您打开商品管理页面。
[PAGE_ACTION]{"type":"navigate","params":{"tab":"products"}}[/PAGE_ACTION]
```
**用户**: 显示所有Apple品牌的商品,按价格从高到低排序
**AI响应**:
```
好的,我来帮您筛选Apple品牌的商品并按价格排序。
[PAGE_ACTION]{"type":"set_page_state","params":{"tab":"products","filters":{"brand":"Apple"},"sort":{"field":"price","direction":"desc"}}}[/PAGE_ACTION]
```
**用户**: 创建一个新商品:华为Mate 60 Pro,价格6999元
**AI响应**:
```
好的,我来帮您创建这个商品。
[DATA_ACTION]{"type":"create_product","params":{"name":"华为Mate 60 Pro","price":6999,"brand":"Huawei","category":"手机"}}[/DATA_ACTION]
```
## 能力同步机制
1. **前端定义**: 能力定义在 `src/utils/capabilitiesSync.ts`
2. **自动同步**: Admin 页面加载时通过 `useCapabilitiesSync` 钩子同步到数据库
3. **Edge Function 读取**: `system-actions` 函数从 `system_capabilities` 表读取最新能力
### 添加新能力
1.`src/types/adminOperations.ts` 中添加新的操作类型
2.`src/ai/dataActions.ts` 中添加动作类型映射
3.`src/utils/adminOperationsClient.ts` 中添加客户端方法
4. 确保 `admin-operations` Edge Function 支持新操作
5. 刷新 Admin 页面触发同步
## 调试
### 查看解析的动作
在 AdminAIAssistant 中,解析到的动作会打印到控制台:
```
识别到统一动作: [{kind: "page_action", type: "navigate", params: {tab: "products"}}]
```
### 查看能力同步结果
同步完成后会在控制台打印:
```
Capabilities sync completed: 25 synced, 0 errors
```
### 手动测试 Edge Function
```bash
curl -X GET "https://tlsofopqzrzuduinsicm.supabase.co/functions/v1/system-actions" \
-H "Authorization: Bearer <ANON_KEY>"
```
This diff is collapsed.
# AI 审计 API 文档
## 概述
`system-audit` Edge Function 提供系统架构、代码结构、安全配置的完整文档输出,并支持调用外部 AI (GPT/Gemini) 进行自动化评估和审计。
## 端点
```
POST /functions/v1/system-audit
```
## 请求参数
| 参数 | 类型 | 必须 | 描述 |
|------|------|------|------|
| action | string | 是 | 操作类型: `export` \| `audit` |
| scope | string[] | 否 | 审计范围: `architecture`, `security`, `code`, `database`, `api` |
| model | string | 否 | AI模型: `gemini-3-flash-preview`(默认), `gemini-2.5-pro`, `gpt-5` |
| detailed | boolean | 否 | 是否返回详细报告 (默认: false) |
## 操作类型
### 1. 导出文档 (`action: "export"`)
返回完整的系统文档,不调用AI。
**请求示例**:
```json
{
"action": "export"
}
```
**响应结构**:
```json
{
"version": "2.0.0",
"exportedAt": "2026-01-28T10:00:00Z",
"documentation": {
"overview": { ... },
"architecture": { ... },
"agents": { ... },
"genui": { ... },
"database": { ... },
"api": { ... },
"security": { ... }
}
}
```
### 2. AI 审计 (`action: "audit"`)
调用 AI 对系统进行评估审计。
**请求示例**:
```json
{
"action": "audit",
"scope": ["architecture", "security"],
"model": "gemini-3-flash-preview",
"detailed": true
}
```
**响应结构**:
```json
{
"auditId": "uuid",
"model": "gemini-3-flash-preview",
"completedAt": "2026-01-28T10:00:00Z",
"summary": {
"overallScore": 85,
"categories": {
"architecture": { "score": 90, "findings": 3 },
"security": { "score": 80, "findings": 5 }
}
},
"findings": [
{
"id": "F001",
"category": "security",
"severity": "medium",
"title": "部分表缺少 RLS 策略",
"description": "...",
"recommendation": "...",
"affectedResources": ["table_name"]
}
],
"recommendations": [ ... ],
"rawAnalysis": "..." // AI 原始输出 (detailed=true时)
}
```
## 审计范围说明
| 范围 | 审计内容 |
|------|----------|
| architecture | 整体架构设计、模块划分、依赖关系 |
| security | RLS策略、认证授权、数据保护 |
| code | 代码结构、最佳实践、重复代码 |
| database | 表设计、索引、关系完整性 |
| api | Edge Functions设计、错误处理、性能 |
## 评分标准
| 分数范围 | 等级 | 说明 |
|----------|------|------|
| 90-100 | A | 优秀,符合最佳实践 |
| 80-89 | B | 良好,有小改进空间 |
| 70-79 | C | 合格,建议优化 |
| 60-69 | D | 需改进,存在明显问题 |
| <60 | F | 不合格,需重大改进 |
## 严重程度定义
| 级别 | 描述 |
|------|------|
| critical | 关键问题,必须立即修复 |
| high | 高优先级,应尽快处理 |
| medium | 中等优先级,计划修复 |
| low | 低优先级,可选优化 |
| info | 信息性建议 |
## 使用示例
### cURL 调用
```bash
# 导出文档
curl -X POST \
'https://tlsofopqzrzuduinsicm.supabase.co/functions/v1/system-audit' \
-H 'Content-Type: application/json' \
-d '{"action": "export"}'
# AI 审计
curl -X POST \
'https://tlsofopqzrzuduinsicm.supabase.co/functions/v1/system-audit' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer YOUR_TOKEN' \
-d '{
"action": "audit",
"scope": ["architecture", "security", "database"],
"model": "gemini-3-flash-preview"
}'
```
### JavaScript 调用
```typescript
import { supabase } from '@/integrations/supabase/client';
// 导出文档
const { data: docs } = await supabase.functions.invoke('system-audit', {
body: { action: 'export' }
});
// AI 审计
const { data: audit } = await supabase.functions.invoke('system-audit', {
body: {
action: 'audit',
scope: ['architecture', 'security'],
detailed: true
}
});
console.log('审计得分:', audit.summary.overallScore);
console.log('发现问题:', audit.findings.length);
```
## 限制
- 单次审计最大超时: 60秒
- 每日审计次数限制: 100次/项目
- 详细报告会增加 token 消耗
## 错误码
| 状态码 | 描述 |
|--------|------|
| 400 | 请求参数无效 |
| 401 | 未认证 (audit 操作需要认证) |
| 429 | 超出速率限制 |
| 500 | 服务器内部错误 |
| 503 | AI 服务暂时不可用 |
# Coze C端消费者聊天 Agent 开发规范
## 🔴🔴🔴 最高原则:数据库是唯一真相源 🔴🔴🔴
**DATABASE IS THE SINGLE SOURCE OF TRUTH**
所有业务数据(产品、价格、库存)必须来自系统提供的数据库数据。**AI 不得编造、猜测或生成任何数据。**
### 必须遵守
- ✅ 产品 ID 必须 100% 来自系统注入的产品目录 `[ID:xxx]`
- ✅ 产品价格必须以目录中的价格为准
- ✅ 如果目录中没有匹配的产品,返回 `picks: []`
- ✅ 宁可不推荐,也不推荐假数据
### 严格禁止
- ❌ 禁止生成/编造任何 UUID
- ❌ 禁止猜测产品 ID 格式
- ❌ 禁止使用示例中的占位符 ID
- ❌ 禁止截断或简化 UUID
### 快速获取此原则 API
```bash
curl https://tlsofopqzrzuduinsicm.supabase.co/functions/v1/consumer-agent-spec?format=ssot
```
---
## 1. 获取规范 API
Coze Agent 可以通过以下 API 自动读取最新规范:
### 基础 URL
```
https://tlsofopqzrzuduinsicm.supabase.co/functions/v1/consumer-agent-spec
```
### 请求参数
| 参数 | 说明 | 可选值 |
|------|------|--------|
| `format` | 返回格式 | `full`(默认)、`ssot`(唯一真相源原则)、`prompt``intents``formats``examples``issues``last_test` |
### 示例请求
```bash
# 🔴 获取唯一真相源原则(最重要!)
curl https://tlsofopqzrzuduinsicm.supabase.co/functions/v1/consumer-agent-spec?format=ssot
# 获取完整规范
curl https://tlsofopqzrzuduinsicm.supabase.co/functions/v1/consumer-agent-spec
# 仅获取系统提示词(含核心原则)
curl https://tlsofopqzrzuduinsicm.supabase.co/functions/v1/consumer-agent-spec?format=prompt
# 获取当前问题通报
curl https://tlsofopqzrzuduinsicm.supabase.co/functions/v1/consumer-agent-spec?format=issues
# 获取最近测试反馈
curl https://tlsofopqzrzuduinsicm.supabase.co/functions/v1/consumer-agent-spec?format=last_test
```
---
## 2. Coze 插件配置
在 Coze 平台创建一个 **API 插件**,配置如下:
### 插件信息
- **名称**: 获取开发规范
- **描述**: 获取 C端消费者聊天 Agent 的最新开发规范
### API 配置
```json
{
"openapi": "3.0.0",
"info": {
"title": "Consumer Agent Spec API",
"version": "1.1.0"
},
"servers": [
{
"url": "https://tlsofopqzrzuduinsicm.supabase.co/functions/v1"
}
],
"paths": {
"/consumer-agent-spec": {
"get": {
"operationId": "getAgentSpec",
"summary": "获取 C端消费者 Agent 开发规范",
"parameters": [
{
"name": "format",
"in": "query",
"schema": {
"type": "string",
"enum": ["full", "prompt", "intents", "formats", "examples"],
"default": "full"
},
"description": "返回格式: full=完整规范, prompt=系统提示词, intents=意图识别, formats=响应格式, examples=示例对话"
}
],
"responses": {
"200": {
"description": "成功返回规范"
}
}
}
}
}
}
```
---
## 3. API 响应格式
### 完整规范 (`format=full`)
```json
{
"version": "1.1.0",
"updated_at": "2026-02-04",
"agent_info": {
"name": "小智",
"role": "手机销售顾问助手",
"target_users": "C端消费者",
"language": "中文",
"personality": ["热情", "专业", "耐心"],
"speaking_style": "简洁友好,避免冗长"
},
"core_responsibilities": [...],
"response_formats": {...},
"intent_recognition": {...},
"product_matching_rules": {...},
"constraints": {...},
"context_injection": {...},
"example_dialogues": [...],
"system_prompt_template": "..."
}
```
### 系统提示词 (`format=prompt`)
```json
{
"system_prompt": "你是一个专业的手机销售顾问助手...",
"version": "1.1.0"
}
```
---
## 4. Coze Bot 使用方式
### 方式 A:启动时读取(推荐)
在 Coze Bot 的 **开场白****初始化流程** 中调用此 API,获取最新规范后注入到对话上下文。
### 方式 B:作为工具调用
将此 API 配置为 Coze 插件,Agent 可以在需要时主动调用获取规范。
### 方式 C:定时同步
Coze 工作流中设置定时任务,定期同步规范到知识库。
---
## 5. 环境变量配置
在 Supabase Secrets 中配置:
| 变量名 | 说明 | 必填 |
|--------|------|------|
| `COZE_API_KEY` | Coze API 密钥(Bearer Token) | ✅ |
| `COZE_CONSUMER_BOT_ID` | C端消费者 Bot ID | ✅ |
| `COZE_BASE_URL` | API 地址(默认 `https://api.coze.cn`) | ❌ |
---
## 6. 版本历史
| 版本 | 日期 | 变更 |
|------|------|------|
| 1.0.0 | 2026-02-03 | 初始规范 |
| 1.1.0 | 2026-02-04 | 改为 API 自动读取模式 |
---
**维护者**: Lovable AI
**最后更新**: 2026-02-04
This diff is collapsed.
# Coze C端消费者 Agent 问题报告
**报告日期**: 2026-02-06
**报告人**: Lovable 项目经理
**优先级**: 🔴 紧急 (P0)
**影响范围**: C端消费者聊天功能完全失效
---
## 📋 问题摘要
Coze Agent 在处理商品推荐请求时,存在两个严重问题:
1. **回复内容问题**:返回"我暂时无法回答您的问题"而非正常回复
2. **产品ID幻觉问题**:在 picks 中返回虚假的 UUID,而非使用提供的真实产品目录 ID
---
## 🔍 问题详情
### 问题 1: 无法回答问题
**现象**
用户发送正常的购物咨询(如"推荐一款手机"),Coze 返回:
```
"我暂时无法回答您的问题"
```
**期望**
Coze 应该正常回复商品推荐,并按照约定格式输出 picks。
---
### 问题 2: 产品ID幻觉(核心问题)
**现象**
当 Coze 尝试推荐产品时,返回的 `picks` 中包含**虚假的 UUID**
```json
{
"picks": [
{"product_id": "07a8b9c0-1234-5678-abcd-ef0123456789", "note": "小米手机"},
{"product_id": "e5f6a7b8-9999-aaaa-bbbb-ccccddddeeee", "note": "红米手机"}
]
}
```
**问题**
- 这些 ID 是 Coze 自己**编造/幻觉**出来的
- 它们**不存在**于我们提供的产品目录中
- 前端无法根据这些假 ID 渲染产品卡片
---
## 📤 我们提供给 Coze 的数据
### System Prompt 中包含完整产品目录
```
## ⚠️⚠️⚠️ 最重要的规则 - 产品推荐格式 ⚠️⚠️⚠️
当推荐产品时,你**必须且只能**使用下面产品目录中的真实 product_id!
**可用产品目录(共50个,请从这里选择):**
• ID="242a6f6e-3afd-4c0d-b8a2-aaaeee077157" | 红米Note 13 Pro | ¥1699
• ID="5e8f2a3b-7c4d-4e9f-8a1b-2c3d4e5f6a7b" | 小米14 Ultra | ¥5999
• ID="9a8b7c6d-5e4f-3a2b-1c0d-9e8f7a6b5c4d" | 华为Mate 60 | ¥6999
...
**输出格式(必须在回复末尾包含):**
\`\`\`json
{
"picks": [
{"product_id": "从上面目录复制的真实ID", "note": "推荐理由"}
]
}
\`\`\`
**⚠️ 严格规则:**
1. product_id **必须**从上面产品目录中复制,不要编造!
2. 如果目录中没有匹配的产品,返回空 picks: []
3. 错误示例:`"product_id": "e5f6a7b8-xxxx"` ❌(这是编造的)
4. 正确示例:`"product_id": "242a6f6e-3afd-4c0d-b8a2-aaaeee077157"` ✅(从目录复制)
```
### 数据注入位置
- System Prompt 中明确列出所有产品 ID 和名称
- Query 末尾附带可用产品列表(前20个)
---
## ✅ 修改要求
### 要求 1: 正确响应用户问题
Coze Agent 应该:
- 理解用户的购物咨询意图
- 给出专业、友好的回复
- **不要**返回"我暂时无法回答您的问题"
### 要求 2: 使用真实产品ID(必须)
Coze Agent 在生成 picks 时**必须**
| 规则 | 说明 |
|------|------|
| ✅ 复制真实ID | 从 System Prompt 中的产品目录复制完整 UUID |
| ✅ 精确匹配 | 用户说"小米手机" → 找到目录中包含"小米"的产品 → 复制其 ID |
| ❌ 禁止编造 | 永远不要生成/猜测/编造任何 UUID |
| ❌ 禁止截断 | 不要返回截断的 ID(如 `242a6f6e-...`) |
### 要求 3: 空 picks 优于假 picks
如果目录中没有匹配的产品:
```json
{
"picks": []
}
```
**不要**返回编造的 ID!空数组比假数据更安全。
---
## 🧪 测试用例
### 测试 1: 基础推荐
**输入**: "推荐一款手机"
**期望输出**:
```
为您推荐以下手机:
1. 红米Note 13 Pro - ¥1699
性价比之选,适合日常使用
\`\`\`json
{
"picks": [
{"product_id": "242a6f6e-3afd-4c0d-b8a2-aaaeee077157", "note": "性价比之选"}
]
}
\`\`\`
```
### 测试 2: 特定品牌推荐
**输入**: "有没有小米手机"
**期望**: 从目录中找到包含"小米"的产品,返回其**真实 ID**
### 测试 3: 无匹配产品
**输入**: "推荐一款折叠屏手机"
**期望**(如果目录中没有折叠屏):
```
抱歉,目前店铺暂无折叠屏手机,以下是其他热门推荐...
\`\`\`json
{
"picks": []
}
\`\`\`
```
---
## 📊 验收标准
| # | 标准 | 验证方式 |
|---|------|----------|
| 1 | Coze 正常回复用户问题,不再返回"无法回答" | 发送"推荐手机",收到正常回复 |
| 2 | picks 中的 product_id 100% 存在于提供的目录 | 前端能成功渲染产品卡片 |
| 3 | 无幻觉 ID | 日志中不再出现 "产品ID不在目录中" 警告 |
| 4 | 格式正确 | picks 格式符合 JSON 规范 |
---
## 📎 附件
- 相关代码: `supabase/functions/coze-chat/index.ts`
- Agent 规范: `docs/coze-consumer-agent-spec.md`
- API 端点: `https://tlsofopqzrzuduinsicm.supabase.co/functions/v1/consumer-agent-spec`
---
## ⏰ 期望修复时间
由于此问题导致**C端消费者聊天功能完全失效**,请尽快修复:
- **临时修复**: 2026-02-06(今天)
- **完整修复**: 2026-02-07
---
**联系方式**: 如有疑问请回复此文档或在项目群中沟通。
# Coze-Lovable 函数调用规范
**版本**: 2.0.0
**更新时间**: 2026-02-03
---
## 🎯 核心要求
**Coze AI 必须返回以下 JSON 格式,前端会自动解析并路由到工作台:**
```json
{
"answer": "简洁的文字回答(显示在聊天框)",
"ui_schema": {
"layout": "vertical",
"gap": "md",
"components": [
{ "type": "组件类型", "props": { ... } }
]
},
"agent_type": "manager|product|marketing|finance|service",
"suggested_actions": ["建议操作1", "建议操作2"]
}
```
---
## 📋 组件类型速查表
| 组件类型 | 用途 | props 必填字段 |
|---------|------|---------------|
| `stats_row` | 统计指标行 | `items: [{label, value, trend?, icon?}]` |
| `data_table` | 数据表格 | `title, columns: [{key, label}], rows: [{...}]` |
| `chart` | 图表 | `chartType: "pie"|"bar"|"line"|"area", data: [{name, value}]` |
| `alert` | 警告提示 | `type: "info"|"warning"|"error"|"success", message` |
| `insight_card` | 洞察卡片 | `title, description, type?, action?` |
| `progress_bar` | 进度条 | `label, value (0-100), color?` |
| `text` | 文本块 | `content, variant?: "default"|"muted"|"heading"` |
| `approval_list` | 审批列表 | `items: [{id, title, description, status, created_at}]` |
---
## ✅ 正确示例
### 查询客户列表
```json
{
"answer": "已为您查询到客户信息列表。",
"agent_type": "manager",
"ui_schema": {
"layout": "vertical",
"gap": "md",
"components": [
{
"type": "stats_row",
"props": {
"items": [
{ "label": "总客户数", "value": "156", "trend": "+12%" },
{ "label": "活跃客户", "value": "89", "trend": "+5%" },
{ "label": "新增本月", "value": "23", "trend": "+8%" }
]
}
},
{
"type": "data_table",
"props": {
"title": "客户信息列表",
"columns": [
{ "key": "name", "label": "客户名称" },
{ "key": "email", "label": "邮箱" },
{ "key": "phone", "label": "电话" },
{ "key": "status", "label": "状态" }
],
"rows": [
{ "name": "张三", "email": "zhang@example.com", "phone": "138****1234", "status": "活跃" },
{ "name": "李四", "email": "li@example.com", "phone": "139****5678", "status": "活跃" }
]
}
}
]
},
"suggested_actions": ["导出客户列表", "查看客户详情", "添加新客户"]
}
```
---
## ❌ 错误示例
```json
// 错误 - 缺少 props 包装
{ "type": "stats_row", "items": [...] }
// 错误 - title 在顶层而非 props
{ "type": "data_table", "title": "标题", "props": { "columns": [...] } }
// 错误 - 将整个 JSON 作为文本返回
"```json\n{\"answer\": \"...\", \"ui_schema\": {...}}\n```"
```
---
## 🔄 意图到 Agent 映射
| 用户意图关键词 | agent_type | 前端自动导航 Tab |
|--------------|------------|-----------------|
| 客户、用户、审批、团队、KPI、全局 | `manager` | home |
| 商品、库存、上架、热销、品牌 | `product` | products |
| 营销、促销、优惠券、秒杀、拼团 | `marketing` | marketing |
| 财务、收入、利润、退款、会员 | `finance` | finance |
| 售后、客服、工单、投诉、物流 | `service` | aftersales |
---
## 📡 API 端点
Coze Agent 可调用以下 Edge Function 获取实时数据:
```
POST https://tlsofopqzrzuduinsicm.supabase.co/functions/v1/coze-langchain
Content-Type: application/json
{
"text": "用户输入的自然语言",
"agent_type": "manager", // 可选,不传则自动识别
"session_id": "会话ID" // 可选,用于上下文关联
}
```
**响应处理**:
- `answer` → 显示在聊天框
- `ui_schema` → 推送到工作台渲染
- `agent_type` → 决定导航到哪个 Tab
---
## 🧪 调试方法
访问 `/genui-debug` 页面可直接粘贴 `ui_schema` JSON 测试渲染效果。
---
*此文档供 Coze AI 读取以正确生成 GenUI Schema*
# Dify Agent 配置控制指南
## 概述
本文档指导如何配置 Dify 工作流,使 AI 能够通过自然语言查询和配置 Agent 设置。
## 系统架构
```
用户输入 → Dify Workflow → 生成 DATA_ACTION → 前端执行 → 配置更新
生成 UI_SCHEMA → 渲染 AgentSettingsCard
```
---
## 数据动作类型
### 1. query_agent - 查询 Agent 配置
```json
[DATA_ACTION]
{
"kind": "data_action",
"type": "query_agent",
"params": {
"agentType": "service"
}
}
[/DATA_ACTION]
```
### 2. update_agent - 更新 Agent 配置
```json
[DATA_ACTION]
{
"kind": "data_action",
"type": "update_agent",
"params": {
"agentType": "service",
"isActive": true,
"autoExecuteEnabled": true,
"maxAutoAmount": 500,
"responseStyle": "professional",
"tone": "calm"
}
}
[/DATA_ACTION]
```
### 3. set_agent_auto_execute - 设置自动执行
```json
[DATA_ACTION]
{
"kind": "data_action",
"type": "set_agent_auto_execute",
"params": {
"agentType": "service",
"enabled": true
}
}
[/DATA_ACTION]
```
### 4. set_agent_max_amount - 设置自动执行额度
```json
[DATA_ACTION]
{
"kind": "data_action",
"type": "set_agent_max_amount",
"params": {
"agentType": "service",
"maxAmount": 1000
}
}
[/DATA_ACTION]
```
### 5. set_agent_notifications - 设置通知
```json
[DATA_ACTION]
{
"kind": "data_action",
"type": "set_agent_notifications",
"params": {
"agentType": "service",
"notifyOnInsights": true,
"notifyOnApprovals": true,
"notifyOnErrors": false
}
}
[/DATA_ACTION]
```
### 6. set_agent_approval_types - 设置需审批操作
```json
[DATA_ACTION]
{
"kind": "data_action",
"type": "set_agent_approval_types",
"params": {
"agentType": "service",
"approvalTypes": ["refund", "aftersales_approve"]
}
}
[/DATA_ACTION]
```
---
## GenUI 组件
### agent_settings_card - Agent 配置卡片
```json
{
"type": "agent_settings_card",
"props": {
"data": {
"agentType": "service",
"isActive": true,
"autoExecuteEnabled": true,
"maxAutoAmount": 500,
"responseStyle": "professional",
"tone": "calm",
"requiresApprovalTypes": ["refund", "aftersales_approve"],
"notifyOnInsights": true,
"notifyOnApprovals": true,
"notifyOnErrors": false
},
"showActions": true,
"compact": false
}
}
```
### agent_settings_list - Agent 配置列表
```json
{
"type": "agent_settings_list",
"props": {
"title": "所有 Agent 配置",
"agents": [
{ "agentType": "manager", "isActive": true, ... },
{ "agentType": "service", "isActive": true, ... },
{ "agentType": "marketing", "isActive": false, ... }
]
}
}
```
---
## Agent 类型
| agentType | 中文名称 | 说明 |
|-----------|----------|------|
| `manager` | 店长经理 · 小管 | 全局协调 |
| `product` | 商品经理 · 小品 | 商品管理 |
| `marketing` | 营销经理 · 小营 | 营销活动 |
| `service` | 客服经理 · 小服 | 售后服务 |
| `finance` | 财务经理 · 小财 | 财务管理 |
## 审批类型
| 类型 | 中文名称 |
|------|----------|
| `refund` | 退款审批 |
| `price_change` | 价格调整 |
| `campaign_create` | 活动创建 |
| `campaign_update` | 活动修改 |
| `product_delete` | 商品删除 |
| `order_cancel` | 订单取消 |
| `user_block` | 用户封禁 |
| `aftersales_approve` | 售后审批 |
| `goal_create` | 目标创建 |
## 响应风格
| 值 | 中文 |
|----|------|
| `professional` | 专业正式 |
| `friendly` | 亲切友好 |
| `concise` | 简洁高效 |
| `detailed` | 详细全面 |
## 语气
| 值 | 中文 |
|----|------|
| `formal` | 正式 |
| `casual` | 随和 |
| `enthusiastic` | 热情 |
| `calm` | 沉稳 |
---
## Dify System Prompt 示例
```markdown
# 你是商城管理助手
你可以帮助用户查询和配置各个 AI Agent 的设置。
## Agent 配置动作
当需要操作 Agent 配置时,生成对应的 DATA_ACTION:
### 查询配置示例
用户: "看看客服Agent的配置"
好的,我来查询客服Agent的当前配置。
[DATA_ACTION]
{"kind":"data_action","type":"query_agent","params":{"agentType":"service"}}
[/DATA_ACTION]
### 开启自动执行示例
用户: "让营销Agent可以自动执行500元以下的操作"
好的,我来配置营销Agent的自动执行设置。
[DATA_ACTION]
{"kind":"data_action","type":"set_agent_auto_execute","params":{"agentType":"marketing","enabled":true}}
[/DATA_ACTION]
[DATA_ACTION]
{"kind":"data_action","type":"set_agent_max_amount","params":{"agentType":"marketing","maxAmount":500}}
[/DATA_ACTION]
已将营销Agent设置为自动执行模式,额度限制为500元。
### 配置通知示例
用户: "关闭客服Agent的洞察通知"
好的,我来调整通知设置。
[DATA_ACTION]
{"kind":"data_action","type":"set_agent_notifications","params":{"agentType":"service","notifyOnInsights":false}}
[/DATA_ACTION]
已关闭客服Agent的洞察通知。
### 配置审批权限示例
用户: "让客服Agent可以自动处理售后,但退款还是要人工审批"
好的,我来调整审批配置。
[DATA_ACTION]
{"kind":"data_action","type":"set_agent_approval_types","params":{"agentType":"service","approvalTypes":["refund"]}}
[/DATA_ACTION]
已配置:客服Agent可自动处理一般售后,退款操作仍需人工审批。
```
---
## 自然语言映射示例
| 用户输入 | 动作类型 | 参数 |
|----------|----------|------|
| "查看客服Agent配置" | query_agent | agentType: service |
| "开启营销Agent自动执行" | set_agent_auto_execute | agentType: marketing, enabled: true |
| "把自动执行额度设为1000" | set_agent_max_amount | maxAmount: 1000 |
| "关闭洞察通知" | set_agent_notifications | notifyOnInsights: false |
| "退款需要人工审批" | set_agent_approval_types | approvalTypes: ["refund"] |
| "暂停商品Agent" | update_agent | agentType: product, isActive: false |
| "把客服Agent风格改成亲切友好" | update_agent | agentType: service, responseStyle: friendly |
# Dify 仪表板控制工作流配置指南
## 概述
本文档指导如何配置 Dify 工作流,使 AI 能够通过自然语言控制店长视窗的组件显示、布局切换。
## 系统架构
```
用户输入 → Dify Workflow → 生成 DASHBOARD_ACTION → 前端解析执行 → UI 更新
```
---
## 仪表板动作类型
### 1. configure_widgets - 配置组件显示
```json
[DASHBOARD_ACTION]
{
"kind": "dashboard_action",
"type": "configure_widgets",
"params": {
"show": ["sales_trend", "stats_cards"],
"hide": ["category_stats"]
}
}
[/DASHBOARD_ACTION]
```
### 2. focus_widget - 聚焦单个组件
```json
[DASHBOARD_ACTION]
{
"kind": "dashboard_action",
"type": "focus_widget",
"params": { "widget": "pending_approvals" }
}
[/DASHBOARD_ACTION]
```
### 3. set_layout - 切换布局模式
```json
[DASHBOARD_ACTION]
{
"kind": "dashboard_action",
"type": "set_layout",
"params": { "layout": "analytics" }
}
[/DASHBOARD_ACTION]
```
### 4. refresh_widget - 刷新组件数据
```json
[DASHBOARD_ACTION]
{
"kind": "dashboard_action",
"type": "refresh_widget",
"params": { "widgets": ["insight_feed", "stats_cards"] }
}
[/DASHBOARD_ACTION]
```
### 5. set_time_range - 设置数据时间范围
```json
[DASHBOARD_ACTION]
{
"kind": "dashboard_action",
"type": "set_time_range",
"params": { "timeRange": "month" }
}
[/DASHBOARD_ACTION]
```
---
## 可用组件 ID
| ID | 中文名称 | 类型 |
|----|----------|------|
| `agent_status` | Agent状态栏 | status |
| `store_goal` | 经营目标卡片 | goal |
| `quick_actions` | 快捷操作 | actions |
| `pending_approvals` | 待审批列表 | list |
| `sales_trend` | 销售趋势图 | chart |
| `order_status` | 订单状态分布 | chart |
| `category_stats` | 类目统计 | chart |
| `user_growth` | 用户增长 | chart |
| `insight_feed` | AI洞察流 | feed |
| `stats_cards` | 统计卡片 | stats |
## 预设布局
| layout | 名称 | 包含组件 |
|--------|------|----------|
| `default` | 默认布局 | 全部10个组件 |
| `compact` | 紧凑布局 | agent_status, stats_cards, pending_approvals, insight_feed |
| `analytics` | 数据分析 | stats_cards, sales_trend, order_status, category_stats, user_growth |
| `approvals` | 审批视图 | agent_status, store_goal, pending_approvals, insight_feed |
## 时间范围
| timeRange | 中文 |
|-----------|------|
| `today` | 今日 |
| `week` | 本周 |
| `month` | 本月 |
| `quarter` | 本季度 |
| `year` | 本年 |
---
## Dify System Prompt 示例
```markdown
# 你是商城管理助手
你可以通过生成结构化动作来控制店长工作台界面。
## 仪表板控制动作格式
当需要调整界面显示时,在回复中包含:
[DASHBOARD_ACTION]
{
"kind": "dashboard_action",
"type": "动作类型",
"params": { 参数 }
}
[/DASHBOARD_ACTION]
## 示例
### 用户说"只显示销售数据"
好的,我来为您调整显示内容。
[DASHBOARD_ACTION]
{"kind":"dashboard_action","type":"configure_widgets","params":{"show":["sales_trend","stats_cards","order_status"]}}
[/DASHBOARD_ACTION]
已为您显示销售相关组件。
### 用户说"切换到数据分析视图"
好的,正在切换布局。
[DASHBOARD_ACTION]
{"kind":"dashboard_action","type":"set_layout","params":{"layout":"analytics"}}
[/DASHBOARD_ACTION]
已切换到数据分析视图。
### 用户说"看一下待审批"
好的,我来聚焦待审批列表。
[DASHBOARD_ACTION]
{"kind":"dashboard_action","type":"focus_widget","params":{"widget":"pending_approvals"}}
[/DASHBOARD_ACTION]
已聚焦到待审批列表。
```
---
## 自然语言映射示例
| 用户输入 | 生成的动作 |
|----------|-----------|
| "只显示图表" | `configure_widgets` → show: charts |
| "隐藏洞察流" | `configure_widgets` → hide: insight_feed |
| "切换紧凑视图" | `set_layout` → compact |
| "看本月数据" | `set_time_range` → month |
| "刷新洞察" | `refresh_widget` → insight_feed |
| "聚焦销售趋势" | `focus_widget` → sales_trend |
# Dify & Lovable 协同工作架构设计
## 系统架构概述
本系统采用分层架构,将AI能力和前端展示分离:
- **Dify**: 负责AI工作流、意图识别、智能对话等核心AI能力
- **Lovable**: 负责前端界面、用户交互、数据展示和业务逻辑
## 分工职责
### Dify 职责范围
1. **意图识别与分类**
- 识别用户消息的意图类型(产品咨询、订单查询、售后服务等)
- 提供意图置信度评分
- 提取关键实体信息
2. **工作流管理**
- 设计和执行复杂的对话工作流
- 处理多轮对话上下文
- 管理对话状态转换
3. **智能对话生成**
- 生成自然、准确的AI回复
- 根据上下文提供个性化回复
- 支持多种对话场景
4. **知识库管理**
- 产品信息检索
- FAQ自动回答
- 政策规则查询
### Lovable 职责范围
1. **用户界面展示**
- 聊天界面渲染
- 产品卡片展示
- 订单状态显示
2. **业务数据管理**
- 用户信息管理
- 订单数据操作
- 产品信息展示
3. **系统集成**
- 调用Dify API
- 数据格式转换
- 错误处理和重试
4. **用户体验优化**
- 加载状态管理
- 交互反馈
- 响应式设计
## 交互接口设计
### 1. 意图识别接口
```typescript
// Lovable -> Dify
interface IntentRequest {
message: string;
user_id: string;
conversation_id?: string;
context?: {
current_agent?: string;
conversation_history?: Array<{
role: 'user' | 'assistant';
content: string;
timestamp: string;
}>;
user_profile?: {
name?: string;
preferences?: Record<string, any>;
};
};
}
// Dify -> Lovable
interface IntentResponse {
intent: string;
confidence: number;
entities?: Record<string, any>;
suggested_agent?: string;
suggested_actions?: Array<{
type: 'show_products' | 'show_orders' | 'show_contact';
data?: any;
}>;
response_text: string;
conversation_id: string;
message_id: string;
}
```
### 2. 对话接口
```typescript
// Lovable -> Dify
interface ChatRequest {
message: string;
user_id: string;
conversation_id?: string;
intent_context?: {
detected_intent?: string;
confidence?: number;
entities?: Record<string, any>;
};
business_context?: {
current_products?: Array<any>;
current_orders?: Array<any>;
user_preferences?: Record<string, any>;
};
}
// Dify -> Lovable
interface ChatResponse {
content: string;
conversation_id: string;
message_id: string;
metadata: {
intent: string;
confidence: number;
source: 'dify';
created_at: string;
suggested_actions?: Array<{
type: 'show_products' | 'show_orders' | 'show_contact' | 'agent_switch';
data?: any;
priority?: number;
}>;
context_update?: {
conversation_state?: string;
user_preferences?: Record<string, any>;
};
};
}
```
## 工作流程
### 1. 用户消息处理流程
```mermaid
sequenceDiagram
participant User
participant Lovable
participant Dify
participant Database
User->>Lovable: 发送消息
Lovable->>Dify: 调用意图识别
Dify-->>Lovable: 返回意图和初步回复
Lovable->>Database: 查询相关业务数据
Lovable->>Dify: 发送带业务上下文的对话请求
Dify-->>Lovable: 返回最终AI回复
Lovable->>User: 展示AI回复 + 业务数据
```
### 2. 智能推荐流程
```mermaid
sequenceDiagram
participant User
participant Lovable
participant Dify
participant ProductDB
User->>Lovable: "我想买手机"
Lovable->>Dify: 意图识别请求
Dify-->>Lovable: 识别为产品咨询
Lovable->>ProductDB: 查询手机产品
Lovable->>Dify: 带产品数据的对话请求
Dify-->>Lovable: 生成推荐话术
Lovable->>User: 展示推荐话术 + 产品卡片
```
## 数据格式规范
### 1. 意图类型定义
```typescript
enum IntentType {
PRODUCT_INQUIRY = 'product_inquiry',
ORDER_QUERY = 'order_query',
LOGISTICS_INQUIRY = 'logistics_inquiry',
AFTER_SALES = 'after_sales',
PAYMENT_ISSUE = 'payment_issue',
ACCOUNT_MANAGEMENT = 'account_management',
GENERAL_INQUIRY = 'general_inquiry',
AGENT_SWITCH = 'agent_switch',
UNKNOWN = 'unknown'
}
```
### 2. 实体提取格式
```typescript
interface ExtractedEntities {
product_name?: string;
product_category?: string;
order_number?: string;
price_range?: {
min?: number;
max?: number;
};
quantity?: number;
brand?: string;
color?: string;
size?: string;
delivery_address?: string;
phone_number?: string;
email?: string;
}
```
## 错误处理策略
### 1. Dify 服务异常
- Lovable端实现自动重试机制(最多3次)
- 超时设置:30秒
- 降级策略:使用本地意图识别算法
### 2. 数据格式异常
- 严格校验Dify返回的数据格式
- 提供默认回复文案
- 记录错误日志供后续分析
## 性能优化
### 1. 缓存策略
- 对话上下文缓存(Redis)
- 意图识别结果缓存(5分钟)
- 产品信息缓存(1小时)
### 2. 并发处理
- 意图识别和数据查询并行执行
- 使用连接池管理Dify API调用
- 实现请求去重机制
## 配置管理
### 环境变量
```bash
# Dify 配置
DIFY_API_KEY=your_dify_api_key
DIFY_BASE_URL=https://api.dify.ai
DIFY_TIMEOUT=30000
# 功能开关
ENABLE_INTENT_RECOGNITION=true
ENABLE_CONTEXT_CACHE=true
ENABLE_FALLBACK_INTENT=true
```
### 运行时配置
```typescript
interface SystemConfig {
intentRecognition: {
enabled: boolean;
confidenceThreshold: number;
fallbackEnabled: boolean;
};
cache: {
enabled: boolean;
ttl: {
intent: number;
context: number;
products: number;
};
};
retry: {
maxAttempts: number;
backoffMs: number;
};
}
```
## 监控与日志
### 1. 关键指标
- Dify API调用成功率
- 意图识别准确率
- 对话完成率
- 用户满意度
### 2. 日志记录
- 所有Dify API调用记录
- 意图识别结果记录
- 错误和异常记录
- 用户行为轨迹记录
## 部署说明
### 1. Dify工作流部署
- 在Dify平台创建应用
- 配置知识库和工作流
- 获取API密钥和接口地址
### 2. Lovable集成部署
- 配置环境变量
- 部署Supabase Edge Functions
- 更新前端组件
## 版本管理
### API版本兼容性
- 使用语义化版本管理
- 维护向后兼容性
- 提供版本迁移指南
### 更新流程
1. Dify工作流更新
2. 接口格式确认
3. Lovable代码适配
4. 测试验证
5. 生产环境发布
\ No newline at end of file
# Dify 页面控制工作流配置指南
## 概述
本文档指导如何配置 Dify 工作流,使 AI 能够通过自然语言控制 Admin 后台页面。
## 系统架构
```
用户输入 → Dify Workflow → 生成 PAGE_ACTION → 前端解析执行 → UI 更新
```
---
## 第一步:调用 system-actions 获取能力定义
### HTTP 节点配置
```yaml
节点类型: HTTP Request
请求方法: GET
URL: {{SUPABASE_URL}}/functions/v1/system-actions
Headers:
Authorization: Bearer {{SUPABASE_ANON_KEY}}
Content-Type: application/json
```
### 返回数据结构
```json
{
"pageActions": {
"navigate": { "description": "导航到指定页面", "params": ["tab"] },
"search": { "description": "搜索", "params": ["tab", "keyword"] },
"filter": { "description": "筛选", "params": ["tab", "filters"] },
"sort": { "description": "排序", "params": ["tab", "field", "direction"] },
"set_page_state": { "description": "组合操作", "params": ["tab", "keyword", "filters", "sort"] }
},
"metadata": {
"validTabs": ["products", "orders", "users", "categories", "brands", "banners", "coupons", "aftersales"]
}
}
```
---
## 第二步:配置 System Prompt
将以下内容添加到 Dify 工作流的 System Prompt 中:
```markdown
# 你是一个智能后台管理助手
你可以通过生成结构化的页面动作来控制后台 UI。
## 页面动作格式
当需要操作页面时,在回复中包含以下格式的动作块:
[PAGE_ACTION]
{
"kind": "page_action",
"type": "动作类型",
"params": { 参数对象 }
}
[/PAGE_ACTION]
## 支持的动作类型
### 1. navigate - 导航到页面
```json
{
"kind": "page_action",
"type": "navigate",
"params": { "tab": "products" }
}
```
### 2. search - 搜索
```json
{
"kind": "page_action",
"type": "search",
"params": { "tab": "products", "keyword": "iPhone" }
}
```
### 3. filter - 筛选
```json
{
"kind": "page_action",
"type": "filter",
"params": {
"tab": "orders",
"filters": { "status": "pending" }
}
}
```
### 4. sort - 排序
```json
{
"kind": "page_action",
"type": "sort",
"params": {
"tab": "products",
"field": "price",
"direction": "desc"
}
}
```
### 5. set_page_state - 组合操作(推荐)
```json
{
"kind": "page_action",
"type": "set_page_state",
"params": {
"tab": "orders",
"keyword": "张三",
"filters": { "status": "shipped" },
"sort": { "field": "created_at", "direction": "desc" }
}
}
```
## 有效的 tab 值
| Tab 值 | 中文名称 | 可搜索字段 | 可筛选字段 | 可排序字段 |
|--------|----------|------------|------------|------------|
| products | 商品管理 | name, brand | category, brand, is_active | price, created_at, stock |
| orders | 订单管理 | order_number, user | status | created_at, total_amount |
| users | 用户管理 | name, email, phone | role, status | created_at, last_login |
| categories | 分类管理 | name | is_active | display_order |
| brands | 品牌管理 | name | is_active | display_order |
| banners | 轮播图管理 | title | is_active | display_order |
| coupons | 优惠券管理 | code, name | status, type | created_at, end_date |
| aftersales | 售后管理 | order_number | status, type | created_at |
## 回复示例
### 示例1:用户说"查看所有待发货订单"
好的,我来帮您查看待发货的订单。
[PAGE_ACTION]
{
"kind": "page_action",
"type": "set_page_state",
"params": {
"tab": "orders",
"filters": { "status": "pending" }
}
}
[/PAGE_ACTION]
已为您筛选出所有待发货订单。
### 示例2:用户说"搜索价格最高的iPhone手机"
好的,我来搜索iPhone手机并按价格排序。
[PAGE_ACTION]
{
"kind": "page_action",
"type": "set_page_state",
"params": {
"tab": "products",
"keyword": "iPhone",
"sort": { "field": "price", "direction": "desc" }
}
}
[/PAGE_ACTION]
已为您搜索iPhone相关商品,并按价格从高到低排序。
### 示例3:用户说"去优惠券页面"
好的,正在为您跳转到优惠券管理页面。
[PAGE_ACTION]
{
"kind": "page_action",
"type": "navigate",
"params": { "tab": "coupons" }
}
[/PAGE_ACTION]
## 重要规则
1. **始终使用有效的 tab 值** - 只能使用上表中列出的 tab 值
2. **kind 字段必填** - 始终设置 `"kind": "page_action"`
3. **参数完整性** - 确保必需参数都已提供
4. **自然回复** - 在动作块前后添加自然语言说明
5. **单次回复单动作** - 每次回复最多包含一个 PAGE_ACTION 块
```
---
## 第三步:Dify 工作流节点配置
### 推荐工作流结构
```
开始 → LLM节点(含System Prompt) → 结束
```
### LLM 节点配置
| 配置项 | 值 |
|--------|-----|
| 模型 | gpt-4 或同等能力模型 |
| Temperature | 0.3 (降低随机性) |
| System Prompt | 使用上述完整模板 |
---
## 第四步:测试用例
配置完成后,测试以下用户输入:
| 用户输入 | 预期动作 |
|----------|----------|
| "去商品页面" | `navigate` → products |
| "搜索华为手机" | `search` → products, keyword: 华为 |
| "显示今天的订单" | `filter` → orders, filters: today |
| "按价格排序" | `sort` → products, field: price |
| "查看待处理的售后" | `set_page_state` → aftersales, filters: pending |
---
## 调试技巧
1. **检查动作格式** - 确保 `[PAGE_ACTION]...[/PAGE_ACTION]` 格式正确
2. **验证 JSON** - 确保内部 JSON 语法正确
3. **查看控制台** - 前端会输出解析和执行日志
4. **测试单一动作** - 先测试简单的 navigate,再测试复杂组合
---
## 常见问题
### Q: 动作没有执行?
检查 `[PAGE_ACTION]` 标签是否完整闭合,JSON 格式是否正确。
### Q: Tab 无法识别?
确保使用英文小写的 tab 值,如 `products` 而非 `商品``Products`
### Q: 中文别名支持?
系统支持中文别名如"商品"、"订单",但建议在 Dify 配置中统一使用英文 tab 值以确保一致性。
# Dify 系统功能查询指南
## 概述
为了让 Dify 智能体能够动态了解系统的功能清单和当前状态,我们提供了一个专用的 API 端点:`system-info`
## API 端点
```
GET https://tlsofopqzrzuduinsicm.supabase.co/functions/v1/system-info
```
**特点:**
- 无需身份验证(公开端点)
- 返回完整的系统架构和功能清单
- 包含实时统计数据和示例数据
## 返回数据结构
```json
{
"version": "1.0.0",
"description": "智能电商管理系统 - AI助手可以帮助管理产品、订单、用户、售后等各项业务",
"statistics": {
"products": { "total": 150, "active": 120 },
"orders": { "total": 500 },
"users": { "total": 1000 },
"afterSales": { "total": 50 }
},
"database": {
"tables": [
{
"name": "products",
"description": "商品信息表",
"columns": ["id", "name", "price", "stock_quantity", ...]
}
]
},
"operations": {
"product": {
"query": {
"name": "查询产品",
"description": "根据条件查询产品列表",
"params": ["keyword", "category", "brand", ...]
},
"create": { ... },
"update": { ... }
},
"order": { ... },
"user": { ... },
"afterSales": { ... },
"category": { ... },
"brand": { ... },
"banner": { ... },
"analytics": { ... }
},
"sampleData": {
"products": [...],
"orders": [...],
"categories": [...],
"brands": [...]
},
"apiInfo": {
"endpoint": "https://tlsofopqzrzuduinsicm.supabase.co/functions/v1/admin-operations",
"method": "POST",
"authentication": "Bearer Token (JWT)",
"requestFormat": {
"operation": "string",
"params": "object"
}
},
"businessRules": {
"orderWorkflow": [...],
"productManagement": [...],
"afterSales": [...]
}
}
```
## 在 Dify 中配置
### 方法 1: 工作流启动时获取(推荐)
在 Dify 工作流的开始节点添加 HTTP 请求:
1. **添加 HTTP 请求节点**
- 节点名称: `获取系统信息`
- URL: `https://tlsofopqzrzuduinsicm.supabase.co/functions/v1/system-info`
- Method: `GET`
- 无需认证
2. **将返回结果传递给 LLM**
- 在 LLM 节点的上下文中引用 `{{获取系统信息.body}}`
- 或者提取特定字段如 `{{获取系统信息.body.operations}}`
### 方法 2: 配置为 Dify 工具
1. **创建自定义工具**
```yaml
name: get_system_info
description: 获取系统完整的功能清单和架构信息
parameters: []
api:
url: https://tlsofopqzrzuduinsicm.supabase.co/functions/v1/system-info
method: GET
```
2. **在 Agent 中启用此工具**
- Agent 可以在需要时调用此工具获取最新系统信息
### 方法 3: 系统提示词中包含
如果系统功能相对稳定,也可以在系统提示词中直接包含:
```
你是一个智能电商管理助手。系统功能包括:
产品管理:
- product.query: 查询产品
- product.create: 创建产品
- product.update: 更新产品
- product.updateStock: 更新库存
...
订单管理:
- order.query: 查询订单
- order.update: 更新订单
...
当用户询问系统能做什么时,基于以上功能列表回答。
当需要执行具体操作时,使用 admin-operations 工具。
```
## 使用场景
### 场景 1: 用户询问系统能力
**用户:** "这个系统能做什么?"
**Dify 流程:**
1. 调用 `system-info` 获取功能清单
2. 基于 `operations` 字段生成易懂的功能说明
3. 回复用户系统的主要功能模块
### 场景 2: 智能推荐操作
**用户:** "帮我看看现在有什么问题"
**Dify 流程:**
1. 调用 `system-info` 获取统计数据
2. 分析 `statistics` 发现异常(如库存低、待处理售后多)
3. 推荐相应的管理操作
### 场景 3: 动态参数提示
**用户:** "我想更新产品"
**Dify 流程:**
1. 从 `operations.product.update` 获取参数列表
2. 提示用户需要提供哪些信息
3. 收集完参数后调用 `admin-operations` 执行
## 测试命令
```bash
# 获取系统信息
curl https://tlsofopqzrzuduinsicm.supabase.co/functions/v1/system-info
# 格式化输出
curl https://tlsofopqzrzuduinsicm.supabase.co/functions/v1/system-info | jq .
# 只看操作列表
curl https://tlsofopqzrzuduinsicm.supabase.co/functions/v1/system-info | jq .operations
# 只看统计数据
curl https://tlsofopqzrzuduinsicm.supabase.co/functions/v1/system-info | jq .statistics
```
## 与 admin-operations 的配合
```mermaid
graph LR
A[Dify Agent] -->|1. 获取功能清单| B[system-info]
B -->|2. 返回系统信息| A
A -->|3. 理解用户意图| A
A -->|4. 执行管理操作| C[admin-operations]
C -->|5. 返回操作结果| A
A -->|6. 反馈给用户| D[用户]
```
**工作流程:**
1. Dify 启动时或定期调用 `system-info` 了解系统能力
2. 用户提出需求时,基于功能清单理解意图
3. 确定需要执行的操作后,调用 `admin-operations` 执行
4. 将执行结果以自然语言反馈给用户
## 最佳实践
1. **首次对话时获取系统信息**
- 在会话开始时调用一次 `system-info`
- 缓存结果避免重复调用
2. **动态更新统计数据**
- 每次执行操作后可以重新获取 `statistics`
- 保持 Agent 对系统状态的感知
3. **构建操作映射**
- 将自然语言需求映射到具体的 operation type
- 使用 `operations` 中的 `description` 帮助理解
4. **参数验证**
- 参考 `operations.[category].[action].params` 验证用户输入
- 提前提示缺失的必填参数
5. **示例数据辅助理解**
- 使用 `sampleData` 让 Agent 理解数据结构
- 在回答时可以引用真实数据作为示例
## 注意事项
- `system-info` 是公开端点,任何人都可以访问
- 不包含敏感数据,只返回系统架构和功能描述
- 示例数据只返回前5条,不会泄露完整数据
- 执行实际操作仍需要通过 `admin-operations` 进行身份验证
## 故障排查
**问题: 无法访问 system-info**
- 检查 URL 是否正确
- 确认网络连接正常
- 查看 Edge Function 部署状态
**问题: 返回数据不完整**
- 检查数据库连接
- 查看 Edge Function 日志
- 确认表权限配置正确
**问题: 统计数据不准确**
- 检查 RLS 策略是否影响了查询
- 确认 ANON_KEY 权限足够读取统计
## 扩展建议
1. **添加版本控制**
-`version` ���段标记 API 版本
- 支持多版本兼容
2. **缓存优化**
- 使用 Redis 缓存系统信息
- 设置合理的过期时间
3. **监控告警**
- 统计 API 调用频率
- 监控响应时间和错误率
4. **权限细分**
- 考虑为不同角色返回不同的功能列表
- 添加可选的认证支持
# E2B 沙盒集成指南
本文档说明如何在前端接收和展示 E2B 沙盒执行结果。
## 1. 类型定义
### SandboxExecutionResult
```typescript
interface SandboxExecutionResult {
executionId: string; // 执行ID
status: 'running' | 'success' | 'error' | 'timeout' | 'cancelled';
agentType: 'manager' | 'marketing' | 'product' | 'service' | 'finance';
taskDescription: string; // 任务描述
codeType?: 'python' | 'javascript' | 'shell';
code?: string; // 执行的代码
stdout?: string; // 标准输出
stderr?: string; // 错误输出
data?: Record<string, any>; // 结构化数据
files?: SandboxFile[]; // 生成的文件
charts?: SandboxChart[]; // 生成的图表
stats?: { // 执行统计
startTime: string;
endTime?: string;
durationMs?: number;
memoryUsedMb?: number;
cpuTimeMs?: number;
};
error?: { // 错误信息
type: string;
message: string;
traceback?: string;
};
}
```
## 2. API 客户端
位置: `src/utils/sandboxClient.ts`
### 主要函数
```typescript
// 执行沙盒任务
await executeSandbox({
agentType: 'finance',
taskDescription: '分析本月销售数据',
code: 'import pandas as pd\n...',
codeType: 'python',
timeout: 60000
});
// 获取执行结果
await getSandboxResult(executionId);
// 取消执行
await cancelSandboxExecution(executionId);
// 下载文件
await downloadSandboxFile(executionId, fileId);
// 订阅状态更新
const unsubscribe = subscribeSandboxStatus(executionId, (event) => {
console.log('状态更新:', event);
});
// 获取执行历史
await getSandboxHistory('finance', 20);
```
## 3. GenUI 组件
### SandboxResultCard
展示沙盒执行结果的卡片组件。
```typescript
// 在 AI 返回的 UI Schema 中使用
{
type: 'sandbox_result',
props: {
result: sandboxExecutionResult,
showRerun: true,
showCancel: false
}
}
```
### 功能特性
- 显示执行状态(运行中/成功/失败/超时/取消)
- 显示 Agent 类型和代码语言
- 标签页切换:输出/文件/图表
- 代码折叠展示
- 文件下载
- 执行统计(耗时、内存、CPU)
- 重新执行/取消按钮
## 4. 后端 Edge Function 规范
### 请求格式
POST `/functions/v1/sandbox-execute`
```json
{
"agentType": "finance",
"taskDescription": "分析销售数据",
"code": "import pandas as pd...",
"codeType": "python",
"timeout": 60000,
"env": {
"API_KEY": "xxx"
}
}
```
### 响应格式
```json
{
"executionId": "exec_123",
"status": "success",
"agentType": "finance",
"taskDescription": "分析销售数据",
"stdout": "处理完成...",
"data": {
"totalSales": 150000,
"topProducts": [...]
},
"files": [
{
"id": "file_1",
"name": "report.pdf",
"type": "pdf",
"size": 102400,
"mimeType": "application/pdf"
}
],
"stats": {
"startTime": "2024-01-01T10:00:00Z",
"endTime": "2024-01-01T10:00:05Z",
"durationMs": 5000
}
}
```
### 状态更新广播
通过 Supabase Realtime 广播:
```typescript
// 频道: sandbox:{executionId}
// 事件: status
{
executionId: "exec_123",
status: "running",
progress: 50,
message: "正在处理数据...",
partialOutput: "已处理 500/1000 条记录"
}
```
## 5. 使用示例
### 在 Agent 工作台中使用
```tsx
import { SandboxResultCard } from '@/ai/genui/components';
import { subscribeSandboxStatus } from '@/utils/sandboxClient';
function AgentWorkbench() {
const [result, setResult] = useState<SandboxExecutionResult | null>(null);
useEffect(() => {
if (result?.executionId && result.status === 'running') {
return subscribeSandboxStatus(result.executionId, (event) => {
setResult(prev => prev ? { ...prev, ...event } : null);
});
}
}, [result?.executionId]);
return (
<div>
{result && (
<SandboxResultCard
result={result}
onRerun={() => handleRerun(result)}
onCancel={() => handleCancel(result.executionId)}
/>
)}
</div>
);
}
```
### 在 GenUI 聊天中使用
AI 返回的消息可以包含 `sandbox_result` 组件:
```json
{
"answer": "分析完成,以下是结果:",
"ui_schema": {
"components": [
{
"type": "sandbox_result",
"props": {
"result": {
"executionId": "exec_123",
"status": "success",
"agentType": "finance",
"taskDescription": "分析本月销售数据",
"stdout": "分析完成...",
"files": [
{
"id": "file_1",
"name": "sales_report.pdf",
"type": "pdf",
"size": 51200
}
]
}
}
}
]
}
}
```
## 6. Action 处理
组件会触发以下 action:
- `sandbox.rerun` - 重新执行,参数: `{ executionId }`
- `sandbox.cancel` - 取消执行,参数: `{ executionId }`
`RenderContext.onAction` 中处理这些 action。
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
import js from "@eslint/js";
import globals from "globals";
import reactHooks from "eslint-plugin-react-hooks";
import reactRefresh from "eslint-plugin-react-refresh";
import tseslint from "typescript-eslint";
export default tseslint.config(
{ ignores: ["dist"] },
{
extends: [js.configs.recommended, ...tseslint.configs.recommended],
files: ["**/*.{ts,tsx}"],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
},
plugins: {
"react-hooks": reactHooks,
"react-refresh": reactRefresh,
},
rules: {
...reactHooks.configs.recommended.rules,
"react-refresh/only-export-components": ["warn", { allowConstantExport: true }],
"@typescript-eslint/no-unused-vars": "off",
},
},
);
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};
This diff is collapsed.
<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="1200" fill="none"><rect width="1200" height="1200" fill="#EAEAEA" rx="3"/><g opacity=".5"><g opacity=".5"><path fill="#FAFAFA" d="M600.709 736.5c-75.454 0-136.621-61.167-136.621-136.62 0-75.454 61.167-136.621 136.621-136.621 75.453 0 136.62 61.167 136.62 136.621 0 75.453-61.167 136.62-136.62 136.62Z"/><path stroke="#C9C9C9" stroke-width="2.418" d="M600.709 736.5c-75.454 0-136.621-61.167-136.621-136.62 0-75.454 61.167-136.621 136.621-136.621 75.453 0 136.62 61.167 136.62 136.621 0 75.453-61.167 136.62-136.62 136.62Z"/></g><path stroke="url(#a)" stroke-width="2.418" d="M0-1.209h553.581" transform="scale(1 -1) rotate(45 1163.11 91.165)"/><path stroke="url(#b)" stroke-width="2.418" d="M404.846 598.671h391.726"/><path stroke="url(#c)" stroke-width="2.418" d="M599.5 795.742V404.017"/><path stroke="url(#d)" stroke-width="2.418" d="m795.717 796.597-391.441-391.44"/><path fill="#fff" d="M600.709 656.704c-31.384 0-56.825-25.441-56.825-56.824 0-31.384 25.441-56.825 56.825-56.825 31.383 0 56.824 25.441 56.824 56.825 0 31.383-25.441 56.824-56.824 56.824Z"/><g clip-path="url(#e)"><path fill="#666" fill-rule="evenodd" d="M616.426 586.58h-31.434v16.176l3.553-3.554.531-.531h9.068l.074-.074 8.463-8.463h2.565l7.18 7.181V586.58Zm-15.715 14.654 3.698 3.699 1.283 1.282-2.565 2.565-1.282-1.283-5.2-5.199h-6.066l-5.514 5.514-.073.073v2.876a2.418 2.418 0 0 0 2.418 2.418h26.598a2.418 2.418 0 0 0 2.418-2.418v-8.317l-8.463-8.463-7.181 7.181-.071.072Zm-19.347 5.442v4.085a6.045 6.045 0 0 0 6.046 6.045h26.598a6.044 6.044 0 0 0 6.045-6.045v-7.108l1.356-1.355-1.282-1.283-.074-.073v-17.989h-38.689v23.43l-.146.146.146.147Z" clip-rule="evenodd"/></g><path stroke="#C9C9C9" stroke-width="2.418" d="M600.709 656.704c-31.384 0-56.825-25.441-56.825-56.824 0-31.384 25.441-56.825 56.825-56.825 31.383 0 56.824 25.441 56.824 56.825 0 31.383-25.441 56.824-56.824 56.824Z"/></g><defs><linearGradient id="a" x1="554.061" x2="-.48" y1=".083" y2=".087" gradientUnits="userSpaceOnUse"><stop stop-color="#C9C9C9" stop-opacity="0"/><stop offset=".208" stop-color="#C9C9C9"/><stop offset=".792" stop-color="#C9C9C9"/><stop offset="1" stop-color="#C9C9C9" stop-opacity="0"/></linearGradient><linearGradient id="b" x1="796.912" x2="404.507" y1="599.963" y2="599.965" gradientUnits="userSpaceOnUse"><stop stop-color="#C9C9C9" stop-opacity="0"/><stop offset=".208" stop-color="#C9C9C9"/><stop offset=".792" stop-color="#C9C9C9"/><stop offset="1" stop-color="#C9C9C9" stop-opacity="0"/></linearGradient><linearGradient id="c" x1="600.792" x2="600.794" y1="403.677" y2="796.082" gradientUnits="userSpaceOnUse"><stop stop-color="#C9C9C9" stop-opacity="0"/><stop offset=".208" stop-color="#C9C9C9"/><stop offset=".792" stop-color="#C9C9C9"/><stop offset="1" stop-color="#C9C9C9" stop-opacity="0"/></linearGradient><linearGradient id="d" x1="404.85" x2="796.972" y1="403.903" y2="796.02" gradientUnits="userSpaceOnUse"><stop stop-color="#C9C9C9" stop-opacity="0"/><stop offset=".208" stop-color="#C9C9C9"/><stop offset=".792" stop-color="#C9C9C9"/><stop offset="1" stop-color="#C9C9C9" stop-opacity="0"/></linearGradient><clipPath id="e"><path fill="#fff" d="M581.364 580.535h38.689v38.689h-38.689z"/></clipPath></defs></svg>
\ No newline at end of file
User-agent: Googlebot
Allow: /
User-agent: Bingbot
Allow: /
User-agent: Twitterbot
Allow: /
User-agent: facebookexternalhit
Allow: /
User-agent: *
Allow: /
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment