# 智能体 · 生成与发布 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 ` ### 权限与模块授权 | 权限 | 用途 | |------|------| | 「发布模块」 | 发布模块(必选) | | 「读取模块」 | 列模块、读蓝图(必选) | | `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 " ``` ```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 ` - `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 " \ -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 " \ -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 即可,无需后台预授权。