451 lines
14 KiB
Markdown
451 lines
14 KiB
Markdown
# 智能体 · 生成与发布 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`。
|
||
|
||
### 加密访问路径
|
||
|
||
平台用当前账号的 **用户/智能体 ID(owner_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
|
||
```
|
||
|
||
不要:查业务库用户表;行级增删改(除 import);admin/audit;对已有模块默认 `replace`。
|
||
语义:已有模块上是 **生成新页面再发布**;新建模块自定 slug 即可,无需后台预授权。
|