Files
ai_site/docs/智能体-生成发布-API.md
2026-07-31 10:31:17 +08:00

451 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 智能体 · 生成与发布 API
Base URL`http://127.0.0.1:8180`(网关)
需求 / 能力说明见:[智能体-生成发布-能力说明.md](./智能体-生成发布-能力说明.md)
> 业务用语:**模块**。API 路径仍为 `/api/v1/apps/...`。
> **智能体默认无需配置 `app_slugs`**:启用「生成发布」后可自由发布自建模块;`app_slugs` 仅在需要白名单限制时填写。
> **禁止**在已发布模块的业务库查用户 / 权限。账号绑定只走「首次登记」。
---
## 总览
| 步骤 | 方法 | 路径 | 鉴权 |
|------|------|------|------|
| 首次登记 | POST | `/api/v1/auth/agent/register` | 公开 + `register_secret` |
| 换票 | POST | `/api/v1/auth/token` | 公开client_credentials |
| 列模块 | GET | `/api/v1/apps` | Bearer + 「读取模块」(管理=全部;智能体默认不限制) |
| 登记在建 | PUT | `/api/v1/apps/{slug}/draft` | Bearer + 「发布模块」 |
| 读蓝图 | GET | `/api/v1/apps/{slug}/blueprint` | Bearer + 「读取模块」 |
| 列模型 | GET | `/ai/api/v1/llm/providers` | 公开 |
| 生成 | POST | `/api/v1/apps/generate` | 网关可公开 |
| 发布 | POST | `/api/v1/apps/{slug}/publish` | Bearer + 「发布模块」 |
| 公开读(加密路径) | GET | `/api/v1/public/m/{token}/blueprint` | 公开 |
| 导入 | POST | `/api/v1/apps/{slug}/{resource}/import` | Bearer + `row.import` |
| 抽查 | GET | `/api/v1/apps/{slug}/{resource}` | Bearer + `row.read` |
决策树:
```text
GET /apps本账号可见模块
├─ 选中已有模块 slug
│ → GET blueprint避开已有 page id/route
│ → generate生成新页面
│ → publish mode=add_pages|auto
│ → import
└─ 无合适模块
→ generate完整多页蓝图
→ publish mode=create|auto自定新 slug无需预授权
→ import
```
---
## 0. 首次登记
`POST /api/v1/auth/agent/register`(公开)
宿主第一次接入时调用。必须上传:
| 宿主侧 | API 字段 | 必填 | 说明 |
|--------|----------|------|------|
| 宇恒 ID | `host_key` | 是 | 稳定唯一标识,幂等绑定 |
| 名称 | `name` | 是 | 控制台显示名 |
| — | `tenant_id` | 否 | 默认 `1` |
| — | `register_secret` | 是 | 与平台注册密钥一致 |
```json
{
"name": "宇恒节点显示名",
"host_key": "<宇恒ID>",
"tenant_id": 1,
"register_secret": "dev-only-change-me"
}
```
响应含 `client_id` / `client_secret`(只返回一次),`status``pending`
管理员在控制台选角色「生成发布」并启用后即可换票。**可访问模块可留空**(留空=可自由发布自建模块)。
同一 `host_key`pending 重连会轮换 secret已 active 再 register → 409。
---
## 1. 换票
`POST /api/v1/auth/token`(公开)
```json
{
"grant_type": "client_credentials",
"client_id": "agt_xxx",
"client_secret": "明文密钥"
}
```
`access_token`。后续列模块 / 读蓝图 / 发布 / 导入须:
`Authorization: Bearer <access_token>`
### 权限与模块授权
| 权限 | 用途 |
|------|------|
| 「发布模块」 | 发布模块(必选) |
| 「读取模块」 | 列模块、读蓝图(必选) |
| `row.import` | 灌数(必选) |
| `row.read` | 抽查(建议) |
| `storage.write` / `storage.read` | 素材(建议) |
推荐角色:**生成发布(`publisher`**。
`app_slugs`**可选白名单**。
- **留空(推荐默认)**:不限制,智能体可自定 slug 生成/发布
- 填写若干 slug 或 `*`:仅允许列表内(`*`=全部)
生成接口经网关可公开;发布与导入须鉴权(角色权限),**不强制**后台预授权模块。
---
## 2. 列出模块(先选目标)
`GET /api/v1/apps`
需 Bearer + 「读取模块」。
| 调用方 | 可见范围(`scope` |
|--------|---------------------|
| 管理账号(非 agent | `all`:本租户全部(含在建) |
| 智能体(`app_slugs` 空或含 `*` | `open`:不限制 |
| 智能体(配置了白名单) | `granted`:仅白名单 |
```bash
curl -s http://127.0.0.1:8180/api/v1/apps \
-H "Authorization: Bearer <access_token>"
```
```json
{
"scope": "all",
"items": [
{
"app_id": "...",
"slug": "settlement",
"name": "沉降观测",
"status": "draft",
"status_label": "在建",
"building": true,
"page_count": 4,
"entity_count": 2,
"updated_at": "2026-07-24T08:00:00Z",
"created_at": "2026-07-24T08:00:00Z"
}
]
}
```
| 情况 | 下一步 |
|------|--------|
| 有目标模块(含在建) | 记下 `slug` → 读蓝图 / 继续生成 → `publish` |
| 没有 | 选定新 `slug` → generate → `PUT .../draft` 登记在建 → `publish` 上线 |
### 2.1 登记在建模块
生成蓝图后、正式发布前:
`PUT /api/v1/apps/{slug}/draft`
Body`{ "blueprint": { ... } }`
需 「发布模块」。不跑 DDL状态为 `draft`(在建)。已发布模块不可用本接口覆盖。
---
## 3. 读取已发布/在建蓝图
`GET /api/v1/apps/{slug}/blueprint`
需 Bearer + 「读取模块」 + 该模块已授权。
用途:
- 生成新页面前,收集已有 `pages[].id` / `route`,避免冲突
- 发布后自检
---
## 4. 列出大模型(可选)
`GET /ai/api/v1/llm/providers`(公开)
兼容:`http://127.0.0.1:8180/ai/api/v1/llm/providers`
```json
{
"default": "deepseek",
"providers": [
{
"id": "deepseek",
"label": "DeepSeek",
"configured": true,
"default_model": "deepseek-chat",
"models": [{ "id": "deepseek-chat", "label": "deepseek-chat" }]
}
]
}
```
---
## 5. 生成蓝图 / 生成新页面
`POST /api/v1/apps/generate`
(网关转发 AI兼容 `POST /ai/api/v1/apps/generate`
`Content-Type: multipart/form-data`
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `prompt` | string | 建议 | 需求描述。**已有模块**时写清:目标 slug、要新增哪些页面、勿复用已有 id/route |
| `storage_mode` | string | 否 | `schema_per_app`(默认)或 `database_per_app` |
| `llm_provider` | string | 否 | 默认 `deepseek` |
| `llm_model` | string | 否 | 空则用厂商默认 |
| `excel` | file | 否 | xlsx / csv / json |
| `data_file` | file | 否 | 同 excel |
| `images` | file[] | 否 | 界面截图 |
| `layout_files` | file[] | 否 | 页面 HTML/MHTML |
```bash
# 示例:为已有模块生成新页面
curl -s http://127.0.0.1:8180/api/v1/apps/generate \
-F "prompt=目标模块 settlement。已有 page id: dash_main, list_records。请新生成「测点筛选」列表+新建表单id/route 勿冲突。" \
-F "storage_mode=schema_per_app" \
-F "llm_provider=deepseek" \
-F "llm_model=deepseek-chat" \
-F "excel=@./settlement.xlsx" \
-F "images=@./board_a.png"
```
成功响应要点:
```json
{
"draft": {
"version": "1.0",
"meta": { "slug": "settlement", "name": "..." },
"entities": [],
"apis": {},
"pages": [],
"storage": {},
"security": {}
},
"warnings": [],
"confidence": 0.86,
"require_confirm": true,
"llm_provider": "deepseek",
"llm_model": "deepseek-chat",
"fidelity": { "skipped": false, "target": 95, "final_score": 96, "passed": true },
"generate_log": { "run_id": "...", "lines": [] }
}
```
| 字段 | 说明 |
|------|------|
| `draft` | 蓝图;发布时提交(可微调) |
| `draft.meta.slug` | 新建模块时用此 slug已有模块发布时以路径 `{slug}` 为准 |
| `draft.pages` | **禁止只生成 1 个 page**;数量不设上限 |
| `draft == null` | 生成失败,看 `warnings` / `generate_log` |
### 页面约定
| type | 用途 |
|------|------|
| `list` | 列表(建议 `actions``import` |
| `form_create` | 新建表单 |
| `form_edit` | 编辑表单 |
| `dashboard` | 看板 |
| `detail` | 详情 |
每个 page 必须有独立 `id` / `title` / `route` / `entity`
```json
"layout": {
"columns": ["sku", "qty", "status"],
"actions": ["create", "edit", "delete", "export", "import", "refresh"]
}
```
**已有模块**`draft` 应主要是**新生成的 pages**(及对应 entities / apis不要把旧页面再写一遍。
**新建模块**`draft` 为完整多页蓝图。
---
## 6. 发布(宿主 → 建站平台)
宿主(宇恒)侧「发布」应把建站蓝图与展示元数据 **POST 到本建站平台**;平台落库建站,并**按用户/智能体 ID 加密出文件路径**,回执给宿主表格展示。
`POST /api/v1/apps/{slug}/publish`
Headers
- `Authorization: Bearer <access_token>`
- `Content-Type: application/json`
Path `{slug}` = 选定的目标**模块**(新建时为新 slug`blueprint.meta.slug` 会对齐到路径 slug。
默认无需预授权;仅当账号配置了 `app_slugs` 白名单时才校验。
```json
{
"mode": "auto",
"blueprint": { },
"host_meta": {
"module_name": "whm123",
"publish_style": "immediate",
"host_base_url": "https://whm123.yuheng.com"
}
}
```
| 字段 | 说明 |
|------|------|
| `mode` | 见下表 |
| `blueprint` | 建站蓝图(必填) |
| `host_meta.module_name` | 宿主表格「模块名称」 |
| `host_meta.publish_style` | `immediate` → 立即发布上线 |
| `host_meta.host_base_url` | 宿主访问域名;有则作为回执 `access_url` |
| `mode` | 含义 |
|--------|------|
| `auto`(默认) | 模块已存在 → 发布新生成的页面;不存在 → 新建模块 |
| `add_pages` | 必须已存在;发布草稿中的**新页面** |
| `create` | 必须不存在;新建模块 |
| `replace` | 整份覆盖(慎用) |
日常用 `auto` 或显式 `add_pages` / `create`
### 加密访问路径
平台用当前账号的 **用户/智能体 IDowner_id** + 租户 + 模块 slug加密生成逻辑文件路径
- `access_path`:如 `m/ajzm1_...`(路径中**无明文 slug / 用户 id**
- `access_url`:优先宿主 `host_base_url`;否则 `{PublicBaseURL}/api/v1/public/{access_path}/blueprint`
公开读取蓝图(无需登录):
`GET /api/v1/public/m/{token}/blueprint`
其中 `{token}``access_path` 去掉前缀 `m/` 的段。
### 宿主「AI 表格数据」字段映射
| 宿主表格 | 取自发布响应 |
|----------|----------------|
| 模块名称 | `module_name` |
| 发布方式 | `publish_style``immediate` → 立即发布上线) |
| 访问地址 | `access_url`(或宿主自拼域名 + `access_path` |
| 发布时间 | `published_at` |
| 状态 | `status` = `published` → 已发布 |
下一步仍是:**灌数 → 打开模块**。
### 已有模块(`auto` / `add_pages`
- 保留该模块已有 pages / entities / apis
- 发布草稿中**新生成**的 page`id``route` 不可冲突)
- 新 entity / resource 一并加入;已有 entity 只追加新字段
- 若没有任何新 page / entity / resource → 400
### 新建模块时 blueprint 至少含
- `meta.slug` / `meta.name`
- `version`(如 `"1.0"`
- `storage``{ "mode": "schema_per_app", "engine": "postgres" }`
- `security``{ "visibility": "private", "roles": [], "row_policies": [] }`
- `apis.base_path` = `/api/v1/apps/{slug}`
- `entities` / `apis` / `pages`
```bash
curl -s http://127.0.0.1:8180/api/v1/apps/settlement/publish \
-H "Authorization: Bearer <access_token>" \
-H "Content-Type: application/json" \
-d '{"mode":"create","host_meta":{"module_name":"whm123","publish_style":"immediate","host_base_url":"https://whm123.yuheng.com"},"blueprint":{...}}'
```
响应示例:
```json
{
"app_id": "...",
"slug": "settlement",
"schema_name": "app_t1_settlement",
"status": "published",
"publish_mode": "created",
"module_name": "whm123",
"publish_style": "immediate",
"access_path": "m/ajzm1_...",
"access_url": "https://whm123.yuheng.com",
"published_at": "2026-07-24T02:00:00Z",
"owner_id": 3,
"endpoints": ["GET /api/v1/apps/settlement/blueprint", "..."],
"ddl": [],
"memory_mode": false
}
```
| `publish_mode` | 含义 |
|----------------|------|
| `created` | 新建了模块 |
| `pages_added` | 向已有模块发布了新页面 |
| `replaced` | 整份覆盖 |
| HTTP | 原因 |
|------|------|
| 401 | token 无效 |
| 403 | 缺 「发布模块」;或配置了白名单但不含该 slug |
| 400 | 蓝图非法 / page id 冲突 / mode 与是否存在不一致 |
---
## 7. 导入业务数据(发布后必做)
发布只建表,**不自动灌数**。
`POST /api/v1/apps/{slug}/{resource}/import`
`Content-Type: multipart/form-data`
需 Bearer + `row.import` + 模块授权。
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `file` | file | 是 | xlsx / csv / json |
`resource` = `apis.resources[].path`(无前导 `/`),如 `records`
```bash
curl -s "http://127.0.0.1:8180/api/v1/apps/settlement/records/import" \
-H "Authorization: Bearer <access_token>" \
-F "file=@./settlement.xlsx"
```
```json
{ "inserted": 120, "skipped": 0, "errors": [] }
```
抽查:
`GET /api/v1/apps/{slug}/{resource}?page=1&page_size=5`(需 `row.read`
确认 `total > 0`,否则任务未完成。
---
## 8. 推荐调用顺序
```text
0. POST /api/v1/auth/agent/register 宇恒ID(host_key) + 名称(name)
1. (管理员)启用 + 角色 publisher模块白名单可选默认留空
2. POST /api/v1/auth/token
3. GET /api/v1/apps 先选模块(仅本账号可见)
4. GET /api/v1/apps/{slug}/blueprint 仅已有模块:避让已有 page
5. POST /api/v1/apps/generate 生成新页面 或 完整蓝图
6. POST /api/v1/apps/{slug}/publish mode=auto | add_pages | create
7. POST /api/v1/apps/{slug}/{resource}/import
8. GET /api/v1/apps/{slug}/{resource}?page=1&page_size=5
```
不要:查业务库用户表;行级增删改(除 importadmin/audit对已有模块默认 `replace`
语义:已有模块上是 **生成新页面再发布**;新建模块自定 slug 即可,无需后台预授权。