Skill: spzwin/ai-intelligence-report (version 1.0.0)

--- name: ai-intelligence-report description: AI情报助手技能包，覆盖模版检索与报告任务场景（创建、查询、章节编辑、版本查询）。 skillcode: ai-intelligence-report dependencies: - cms-auth-skills --- # AI情报助手 — 索引 本文件提供能力宪章、能力树与按需加载规则。详细参数与流程见各模块 `openapi/` 与 `examples/`。 **当前版本**: v1.6 **能力概览（3 块能力）**： - `moban`：模版列表检索、模版详情查看、模版新建、模版编辑、模版发布/下架、模版删除 - `task`：任务创建、进度查询、报告详情、任务列表、章节改写、版本历史 - `capability`：能力咨询与边界说明（回答“你能做什么/不能做什么”） **接口版本**: 所有业务接口统一使用 `https://cwork-api.mediportal.com.cn/ai-report/*` 前缀，鉴权类型按接口文档声明执行（本 skill 当前业务接口均为 `access-token`）。 统一规范： - 认证与鉴权：`cms-auth-skills/SKILL.md` - 通用约束：`cms-auth-skills/SKILL.md` 授权依赖： - 当接口声明需要 `appKey` 或 `access-token` 时，先尝试读取 `cms-auth-skills/SKILL.md` - 如果已安装，直接按 `cms-auth-skills/SKILL.md` 中的鉴权规则准备对应 `appKey` 或 `access-token` - 如果未安装，先执行 `npx clawhub@latest install cms-auth-skills --force` - 如果上面的安装方式不可用，再执行 `npx clawhub@latest install https://github.com/spzwin/cms-auth-skills.git --force` - 安装完成后，再继续执行需要鉴权的操作 输入完整性规则（强制）： 1. 模版场景至少提供分页信息（`pageNum`、`pageSize`）或明确 `mobanId` 2. 生成报告至少提供 `mobanId`、`taskName` 3. 查询详情或进度需提供 `taskId` 4. 章节改写与版本查询需提供 `questionId` 建议工作流（简版）： 1. 读取 `SKILL.md` 与 `cms-auth-skills/SKILL.md`，明确能力范围、鉴权与安全约束。 2. 识别用户意图并路由模块：`moban`、`task`、`capability`，先打开对应 `api-index.md`。 3. 确认具体接口后，加载对应 endpoint 文档获取入参、出参与 Schema。 4. 补齐用户必需输入；若是能力咨询场景，仅返回标准能力边界，不执行脚本。 5. 参考 `examples/moban/README.md`、`examples/task/README.md`、`examples/capability/README.md` 组织话术与流程。 6. 对有接口的场景执行对应 Python 脚本，输出 JSON 结果并做最小必要信息提取。 脚本使用规则（强制）： 1. 每个 `openapi/moban/*.md`、`openapi/task/*.md` 都必须有对应脚本。 2. 所有业务脚本输出必须为 JSON 格式。 3. 脚本必须可独立命令行执行。 4. 仅允许生产域名与生产协议。 5. 出错重试间隔 1 秒，最多 3 次，禁止无限重试。 6. 严禁虚构工具名或命令（例如 `oracle template query`）。若环境受限，只能说明受限条件与补齐步骤。 能力咨询标准回复（强制）： 1. 当用户问“你可以做什么/你能做什么/你支持哪些操作/你是谁”时，必须路由到 `capability`。 2. `capability` 仅返回本 skill 的真实能力，不得扩展到未定义工具或外部命令。 3. 输出必须包含三段：能做什么、不能做什么、下一步引导（查模版、发起任务、查进度、改章节）。 4. 能力咨询场景禁止执行脚本，也禁止先下“环境变量缺失”的结论。 意图路由与加载规则（强制）： 1. 模版选择与推荐 -> `moban` 2. 报告生成、进度与详情 -> `task` 3. 章节手改与版本追溯 -> `task` 4. 能力咨询与自我介绍 -> `capability` 5. 超出上述范围（如 chat 对话建模版）不在本 skill 范围内 宪章（必须遵守）： 1. 本 skill 仅覆盖 `docs/AI情报agent说明(1).md` 与 `docs/ai情报agent_定义规范.md` 定义场景。 2. 不暴露 token、内部主键等敏感信息。 3. 不猜测缺失参数，必须追问补齐。 4. 不执行越权与危险操作。 5. 章节编辑保存前，必须先向用户展示编辑后的完整内容并等待明确确认。 6. 不杜撰不存在的命令、MCP 工具、CLI 工具或环境变量缺失结论。 7. 鉴权失败时，只能按 `cms-auth-skills/SKILL.md` 的鉴权规则检查，并明确已检查到哪一步、下一步缺什么。 模块路由与能力索引： | 用户意图（示例） | 模块 | 能力摘要 | 接口文档 | 示例模板 | 脚本 | |---|---|---|---|---|---| | 找可用模版、按关键词筛选模版 | `moban` | 模版检索 | `./openapi/moban/api-index.md` | `./examples/moban/README.md` | `./scripts/moban/list-moban.py` | | 查看模版章节结构 | `moban` | 模版详情 | `./openapi/moban/api-index.md` | `./examples/moban/README.md` | `./scripts/moban/moban-detail.py` | | 新建模版（定义章节与提示词） | `moban` | 模版新建 | `./openapi/moban/api-index.md` | `./examples/moban/README.md` | `./scripts/moban/create-moban.py` | | 编辑已有模版（更新结构与提示词） | `moban` | 模版编辑 | `./openapi/moban/api-index.md` | `./examples/moban/README.md` | `./scripts/moban/update-moban.py` | | 模版发布/下架（控制模版可见状态） | `moban` | 模版状态切换 | `./openapi/moban/api-index.md` | `./examples/moban/README.md` | `./scripts/moban/change-moban-state.py` | | 删除废弃模版 | `moban` | 模版删除 | `./openapi/moban/api-index.md` | `./examples/moban/README.md` | `./scripts/moban/delete-moban.py` | | 发起报告任务 | `task` | 创建任务 | `./openapi/task/api-index.md` | `./examples/task/README.md` | `./scripts/task/start-task.py` | | 查询任务进度和报告详情 | `task` | 进度与详情 | `./openapi/task/api-index.md` | `./examples/task/README.md` | `./scripts/task/check-task.py` | | 手动修改某个章节并看版本历史 | `task` | 章节编辑 | `./openapi/task/api-index.md` | `./examples/task/README.md` | `./scripts/task/update-question-result.py` | | 你可以做什么、你能做什么、你是谁 | `capability` | 能力边界说明 | `./openapi/capability/api-index.md` | `./examples/capability/README.md` | `./scripts/capability/README.md` | 能力树（实际目录结构）： ```text ai-intelligence-report/ ├── SKILL.md ├── openapi/ │ ├── moban/ │ │ ├── api-index.md │ │ ├── list-moban.md │ │ ├── moban-detail.md │ │ ├── create-moban.md │ │ ├── update-moban.md │ │ ├── change-moban-state.md │ │ └── delete-moban.md │ ├── capability/ │ │ └── api-index.md │ └── task/ │ ├── api-index.md │ ├── start-task.md │ ├── check-task.md │ ├── task-detail-v2.md │ ├── list-task-by-page.md │ ├── update-question-result.md │ └── list-result-version.md ├── examples/ │ ├── moban/README.md │ ├── capability/README.md │ └── task/README.md └── scripts/ ├── capability/ │ └── README.md ├── moban/ │ ├── README.md │ ├── list-moban.py │ ├── moban-detail.py │ ├── create-moban.py │ ├── update-moban.py │ ├── change-moban-state.py │ └── delete-moban.py └── task/ ├── README.md ├── start-task.py ├── check-task.py ├── task-detail-v2.py ├── list-task-by-page.py ├── update-question-result.py └── list-result-version.py ```

path: openapi/capability/api-index.md
content: # API 索引 — capability

接口列表：

- 本模块不提供外部业务接口，仅用于能力边界说明与能力咨询标准回复。

脚本映射：
- `../../scripts/capability/README.md`


path: openapi/task/update-question-result.md
content: # POST https://cwork-api.mediportal.com.cn/ai-report/task/updateQuestionResult

## 作用

将用户新内容直接覆盖指定子章节，完成章节手动修改。

**鉴权类型**
- `access-token`

## 前置确认（强制）

调用本接口前，必须先向用户完整展示编辑后的章节内容，并获得用户明确确认；未确认不得执行保存。

**Headers**
- `access-token`
- `Content-Type: application/json`

**Body**
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `questionId` | string | 是 | 子章节 `_id` |
| `result` | string | 是 | 新章节内容（Markdown） |

## 请求 Schema
```json
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "required": ["questionId", "result"],
  "properties": {
    "questionId": { "type": "string" },
    "result": { "type": "string" }
  }
}
```

## 响应 Schema
```json
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "resultCode": { "type": "number" },
    "resultMsg": { "type": ["string", "null"] },
    "data": { "type": "object" }
  }
}
```

## 脚本映射
- `../../scripts/task/update-question-result.py`


path: openapi/task/list-task-by-page.md
content: # POST https://cwork-api.mediportal.com.cn/ai-report/task/listTaskByPage

## 作用

按目录、状态、关键词等条件分页查询 AI 情报报告列表。

**鉴权类型**
- `access-token`

**Headers**
- `access-token`
- `Content-Type: application/json`

**Body**
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `pageNum` | number | 是 | 页码，从 0 开始 |
| `pageSize` | number | 是 | 每页条数 |
| `dirId` | string | 否 | 目录 ID，按目录筛选 |
| `mobanTypeId` | string | 否 | 模版类型 ID |
| `state` | number | 否 | 状态：0 未开始，1 进行中，2 已完成，3 失败 |
| `searchKey` | string | 否 | 搜索关键词（报告标题） |
| `reportType` | number | 否 | 报告来源：1 普通，2 定时，3 系统 |
| `delFlag` | number | 否 | 删除标记，0 未删除 |
| `onlyMine` | string | 否 | 是否仅看我的，传 `true` |
| `onlyMineStatus` | number | 否 | 与 `onlyMine` 配合，筛选状态 |

## 请求 Schema
```json
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "required": ["pageNum", "pageSize"],
  "properties": {
    "pageNum": { "type": "number", "minimum": 0 },
    "pageSize": { "type": "number", "minimum": 1 },
    "dirId": { "type": ["string", "null"] },
    "mobanTypeId": { "type": ["string", "null"] },
    "state": { "type": ["number", "null"] },
    "searchKey": { "type": ["string", "null"] },
    "reportType": { "type": "number" },
    "delFlag": { "type": "number" },
    "onlyMine": { "type": ["string", "null"] },
    "onlyMineStatus": { "type": ["number", "null"] }
  }
}
```

## 响应 Schema
```json
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "resultCode": { "type": "number" },
    "resultMsg": { "type": ["string", "null"] },
    "data": {
      "type": "object",
      "properties": {
        "pageContent": { "type": "array", "items": { "type": "object" } },
        "total": { "type": "number" }
      }
    }
  }
}
```

## 脚本映射
- `../../scripts/task/list-task-by-page.py`


path: openapi/task/api-index.md
content: # API 索引 — task

接口列表：

1. `POST https://cwork-api.mediportal.com.cn/ai-report/task/startTask`
   - 文档：`./start-task.md`
2. `POST https://cwork-api.mediportal.com.cn/ai-report/task/checkTask`
   - 文档：`./check-task.md`
3. `POST https://cwork-api.mediportal.com.cn/ai-report/task/taskDetailV2`
   - 文档：`./task-detail-v2.md`
4. `POST https://cwork-api.mediportal.com.cn/ai-report/task/listTaskByPage`
   - 文档：`./list-task-by-page.md`
5. `POST https://cwork-api.mediportal.com.cn/ai-report/task/updateQuestionResult`
   - 文档：`./update-question-result.md`
6. `POST https://cwork-api.mediportal.com.cn/ai-report/task/listResultVersion`
   - 文档：`./list-result-version.md`

脚本映射：
- `../../scripts/task/README.md`


path: openapi/task/task-detail-v2.md
content: # POST https://cwork-api.mediportal.com.cn/ai-report/task/taskDetailV2

## 作用

查询单个报告任务详情，包括章节与子章节内容。

**鉴权类型**
- `access-token`

**Headers**
- `access-token`
- `Content-Type: application/json`

**Body**
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `taskId` | string | 是 | 报告任务 ID |

## 请求 Schema
```json
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "required": ["taskId"],
  "properties": {
    "taskId": { "type": "string" }
  }
}
```

## 响应 Schema
```json
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "resultCode": { "type": "number" },
    "resultMsg": { "type": ["string", "null"] },
    "data": { "type": "object" }
  }
}
```

## 脚本映射
- `../../scripts/task/task-detail-v2.py`


path: openapi/task/check-task.md
content: # POST https://cwork-api.mediportal.com.cn/ai-report/task/checkTask

## 作用

查询任务进度，建议在创建任务后轮询直到完成或失败。

**鉴权类型**
- `access-token`

**Headers**
- `access-token`
- `Content-Type: application/json`

**Body**
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `taskId` | string | 是 | 报告任务 ID |

## 请求 Schema
```json
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "required": ["taskId"],
  "properties": {
    "taskId": { "type": "string" }
  }
}
```

## 响应 Schema
```json
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "resultCode": { "type": "number" },
    "resultMsg": { "type": ["string", "null"] },
    "data": { "type": "object" }
  }
}
```

## 脚本映射
- `../../scripts/task/check-task.py`


path: openapi/task/start-task.md
content: # POST https://cwork-api.mediportal.com.cn/ai-report/task/startTask

## 作用

基于指定模版发起异步报告生成任务，返回 `taskId`。

**鉴权类型**
- `access-token`

**Headers**
- `access-token`
- `Content-Type: application/json`

**Body**
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `mobanId` | string | 是 | 模版 ID |
| `taskName` | string | 是 | 报告名称 |
| `dirId` | string | 否 | 目录 ID（可选，不传时由后端按默认规则处理） |
| `context` | object | 否 | 报告生成上下文 |

## 请求 Schema
```json
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "required": ["mobanId", "taskName"],
  "properties": {
    "mobanId": { "type": "string" },
    "taskName": { "type": "string" },
    "dirId": { "type": ["string", "null"] },
    "context": { "type": ["object", "null"] }
  }
}
```

## 响应 Schema
```json
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "resultCode": { "type": "number" },
    "resultMsg": { "type": ["string", "null"] },
    "data": { "type": "object" }
  }
}
```

## 脚本映射
- `../../scripts/task/start-task.py`


path: openapi/task/list-result-version.md
content: # POST https://cwork-api.mediportal.com.cn/ai-report/task/listResultVersion

## 作用

查询指定子章节历史修改版本，用于回溯与比较。

**鉴权类型**
- `access-token`

**Headers**
- `access-token`
- `Content-Type: application/json`

**Body**
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `questionId` | string | 是 | 子章节 `_id` |

## 请求 Schema
```json
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "required": ["questionId"],
  "properties": {
    "questionId": { "type": "string" }
  }
}
```

## 响应 Schema
```json
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "resultCode": { "type": "number" },
    "resultMsg": { "type": ["string", "null"] },
    "data": { "type": "array", "items": { "type": "object" } }
  }
}
```

## 脚本映射
- `../../scripts/task/list-result-version.py`


path: openapi/moban/update-moban.md
content: # POST https://cwork-api.mediportal.com.cn/ai-report/moban/updateMoban

## 作用

编辑已有模版，更新名称、章节结构和提示词内容。

**鉴权类型**
- `access-token`

**Headers**
- `access-token`
- `Content-Type: application/json`

**Body**
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `mobanId` | string | 是 | 模版 ID |
| `name` | string | 否 | 模版名称 |
| `desc` | string | 否 | 模版描述 |
| `dirId` | string | 否 | 目录 ID |
| `mobanTypeId` | string | 否 | 模版类型 ID（已废弃） |
| `prompt` | string | 否 | 任务级提示词 |
| `editNote` | string | 否 | 改动日志 |
| `public` | number | 否 | 公开状态：`0` 不公开，`1` 公开 |
| `thirdSystem` | string | 否 | 第三方系统标识 |
| `doSummary` | number | 否 | 是否总结：`0` 不总结，`1` 最后一章总结，`2` 第一章总结 |
| `summaryPrompt` | string | 否 | 总结提示词 |
| `aiType` | string | 否 | AI 类型 |
| `requireContext` | array | 否 | 上下文字段（`string[]`） |
| `sectionList` | array | 否 | 章节结构 |

## 请求 Schema
```json
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "required": ["mobanId"],
  "properties": {
    "mobanId": { "type": "string", "minLength": 1 },
    "name": { "type": ["string", "null"] },
    "desc": { "type": ["string", "null"] },
    "dirId": { "type": ["string", "null"] },
    "mobanTypeId": { "type": ["string", "null"] },
    "prompt": { "type": ["string", "null"] },
    "editNote": { "type": ["string", "null"] },
    "public": { "type": ["number", "null"], "enum": [0, 1, null] },
    "thirdSystem": { "type": ["string", "null"] },
    "doSummary": { "type": ["number", "null"], "enum": [0, 1, 2, null] },
    "summaryPrompt": { "type": ["string", "null"] },
    "aiType": { "type": ["string", "null"] },
    "requireContext": {
      "type": ["array", "null"],
      "items": { "type": "string" }
    },
    "sectionList": {
      "type": "array",
      "minItems": 0,
      "items": {
        "type": "object",
        "required": [],
        "properties": {
          "name": { "type": "string", "minLength": 1 },
          "prompt": { "type": ["string", "null"] },
          "questionList": {
            "type": "array",
            "minItems": 0,
            "items": {
              "type": "object",
              "required": [],
              "properties": {
                "title": { "type": "string", "minLength": 1 },
                "content": { "type": ["string", "null"] },
                "prompt": { "type": ["string", "null"] },
                "withNet": { "type": ["boolean", "null"] },
                "dataSrc": {
                  "type": ["object", "null"],
                  "properties": {
                    "srcType": { "type": ["string", "null"] },
                    "docList": {
                      "type": ["array", "null"],
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": { "type": ["string", "null"] },
                          "fileId": { "type": ["string", "null"] },
                          "docType": { "type": ["number", "null"] }
                        }
                      }
                    },
                    "customSrcId": { "type": ["string", "null"] },
                    "mcpServerIdList": { "type": ["string", "null"] },
                    "originDoc": { "type": ["boolean", "null"] }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}
```

## 响应 Schema
```json
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "resultCode": { "type": "number" },
    "resultMsg": { "type": ["string", "null"] },
    "data": { "type": ["object", "null"] }
  }
}
```

## 脚本映射
- `../../scripts/moban/update-moban.py`


path: openapi/moban/change-moban-state.md
content: # POST https://cwork-api.mediportal.com.cn/ai-report/moban/changeMobanState

## 作用

切换指定模版的发布状态（上架/下架）。

**鉴权类型**
- `access-token`

**Headers**
- `access-token`
- `Content-Type: application/json`

**Body**
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `mobanId` | string | 是 | 模版 ID |
| `state` | number | 是 | 状态：`0` 未发布（下架），`1` 已发布（上架） |

## 请求 Schema
```json
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "required": ["mobanId", "state"],
  "properties": {
    "mobanId": { "type": "string", "minLength": 1 },
    "state": { "type": "number", "enum": [0, 1] }
  }
}
```

## 响应 Schema
```json
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "resultCode": { "type": "number" },
    "resultMsg": { "type": ["string", "null"] },
    "data": { "type": ["object", "null"] }
  }
}
```

## 脚本映射
- `../../scripts/moban/change-moban-state.py`


path: openapi/moban/delete-moban.md
content: # POST https://cwork-api.mediportal.com.cn/ai-report/moban/delMoban

## 作用

删除指定模版。仅创建者和管理员可操作。

**鉴权类型**
- `access-token`

**Headers**
- `access-token`
- `Content-Type: application/json`

**Body**
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `mobanId` | string | 是 | 目标模版 ID |

## 请求 Schema
```json
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "required": ["mobanId"],
  "properties": {
    "mobanId": { "type": "string", "minLength": 1 }
  }
}
```

## 响应 Schema
```json
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "resultCode": { "type": "number" },
    "resultMsg": { "type": ["string", "null"] },
    "data": { "type": ["object", "boolean", "null"] }
  }
}
```

## 脚本映射
- `../../scripts/moban/delete-moban.py`


path: openapi/moban/create-moban.md
content: # POST https://cwork-api.mediportal.com.cn/ai-report/moban/saveMoban

## 作用

创建新的报告模版，支持写入章节结构与子章节提示词。

**鉴权类型**
- `access-token`

**Headers**
- `access-token`
- `Content-Type: application/json`

**Body**
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `name` | string | 否 | 模版名称 |
| `desc` | string | 否 | 模版描述 |
| `dirId` | string | 否 | 目录 ID |
| `mobanTypeId` | string | 否 | 模版类型 ID（已废弃） |
| `prompt` | string | 否 | 任务级提示词 |
| `editNote` | string | 否 | 改动日志 |
| `public` | number | 否 | 公开状态：`0` 不公开，`1` 公开 |
| `thirdSystem` | string | 否 | 第三方系统标识 |
| `doSummary` | number | 否 | 是否总结：`0` 不总结，`1` 最后一章总结，`2` 第一章总结 |
| `summaryPrompt` | string | 否 | 总结提示词 |
| `aiType` | string | 否 | AI 类型 |
| `requireContext` | array | 否 | 上下文字段（`string[]`） |
| `sectionList` | array | 否 | 章节结构 |

## 请求 Schema
```json
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "required": [],
  "properties": {
    "name": { "type": "string", "minLength": 1 },
    "desc": { "type": ["string", "null"] },
    "dirId": { "type": ["string", "null"] },
    "mobanTypeId": { "type": ["string", "null"] },
    "prompt": { "type": ["string", "null"] },
    "editNote": { "type": ["string", "null"] },
    "public": { "type": ["number", "null"], "enum": [0, 1, null] },
    "thirdSystem": { "type": ["string", "null"] },
    "doSummary": { "type": ["number", "null"], "enum": [0, 1, 2, null] },
    "summaryPrompt": { "type": ["string", "null"] },
    "aiType": { "type": ["string", "null"] },
    "requireContext": {
      "type": ["array", "null"],
      "items": { "type": "string" }
    },
    "sectionList": {
      "type": "array",
      "minItems": 0,
      "items": {
        "type": "object",
        "required": [],
        "properties": {
          "name": { "type": "string", "minLength": 1 },
          "prompt": { "type": ["string", "null"] },
          "questionList": {
            "type": "array",
            "minItems": 0,
            "items": {
              "type": "object",
              "required": [],
              "properties": {
                "title": { "type": "string", "minLength": 1 },
                "content": { "type": ["string", "null"] },
                "prompt": { "type": ["string", "null"] },
                "withNet": { "type": ["boolean", "null"] },
                "dataSrc": {
                  "type": ["object", "null"],
                  "properties": {
                    "srcType": { "type": ["string", "null"] },
                    "docList": {
                      "type": ["array", "null"],
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": { "type": ["string", "null"] },
                          "fileId": { "type": ["string", "null"] },
                          "docType": { "type": ["number", "null"] }
                        }
                      }
                    },
                    "customSrcId": { "type": ["string", "null"] },
                    "mcpServerIdList": { "type": ["string", "null"] },
                    "originDoc": { "type": ["boolean", "null"] }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}
```

## 响应 Schema
```json
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "resultCode": { "type": "number" },
    "resultMsg": { "type": ["string", "null"] },
    "data": { "type": ["object", "null"] }
  }
}
```

## 脚本映射
- `../../scripts/moban/create-moban.py`


path: openapi/moban/moban-detail.md
content: # POST https://cwork-api.mediportal.com.cn/ai-report/moban/mobanDetail

## 作用

读取指定模版的章节结构、子章节和提示词配置。

**鉴权类型**
- `access-token`

**Headers**
- `access-token`
- `Content-Type: application/json`

**Body**
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `mobanId` | string | 是 | 模版 ID |

## 请求 Schema
```json
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "required": ["mobanId"],
  "properties": {
    "mobanId": { "type": "string" }
  }
}
```

## 响应 Schema
```json
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "resultCode": { "type": "number" },
    "resultMsg": { "type": ["string", "null"] },
    "data": { "type": "object" }
  }
}
```

## 脚本映射
- `../../scripts/moban/moban-detail.py`


path: openapi/moban/api-index.md
content: # API 索引 — moban

接口列表：

1. `POST https://cwork-api.mediportal.com.cn/ai-report/moban/listMobanByPageV2`
   - 文档：`./list-moban.md`
2. `POST https://cwork-api.mediportal.com.cn/ai-report/moban/mobanDetail`
   - 文档：`./moban-detail.md`
3. `POST https://cwork-api.mediportal.com.cn/ai-report/moban/saveMoban`
   - 文档：`./create-moban.md`
4. `POST https://cwork-api.mediportal.com.cn/ai-report/moban/updateMoban`
   - 文档：`./update-moban.md`
5. `POST https://cwork-api.mediportal.com.cn/ai-report/moban/delMoban`
   - 文档：`./delete-moban.md`
6. `POST https://cwork-api.mediportal.com.cn/ai-report/moban/changeMobanState`
   - 文档：`./change-moban-state.md`

脚本映射：
- `../../scripts/moban/README.md`


path: openapi/moban/list-moban.md
content: # POST https://cwork-api.mediportal.com.cn/ai-report/moban/listMobanByPageV2

## 作用

按分页、关键词、目录、仅看我的条件检索模版列表。

**鉴权类型**
- `access-token`

**Headers**
- `access-token`
- `Content-Type: application/json`

**Body**
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `pageNum` | number | 是 | 页码，从 0 开始 |
| `pageSize` | number | 是 | 每页条数 |
| `dirId` | string | 否 | 目录筛选 |
| `searchKey` | string | 否 | 模版名关键词 |
| `onlyMine` | string | 否 | 是否仅看我的，传 `true` |

## 请求 Schema
```json
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "required": ["pageNum", "pageSize"],
  "properties": {
    "pageNum": { "type": "number", "minimum": 0 },
    "pageSize": { "type": "number", "minimum": 1 },
    "dirId": { "type": ["string", "null"] },
    "searchKey": { "type": ["string", "null"] },
    "onlyMine": { "type": ["string", "null"] }
  }
}
```

## 响应 Schema
```json
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "resultCode": { "type": "number" },
    "resultMsg": { "type": ["string", "null"] },
    "data": {
      "type": "object",
      "properties": {
        "pageContent": { "type": "array", "items": { "type": "object" } },
        "total": { "type": "number" }
      }
    }
  }
}
```

## 脚本映射
- `../../scripts/moban/list-moban.py`


path: examples/capability/README.md
content: # capability — 使用说明

## 什么时候使用

- 用户问“你可以做什么”“你能做什么”“你是谁”“你支持哪些操作”
- 用户希望确认当前 skill 的能力边界、可执行范围与下一步入口

## 标准流程

1. 读取 `SKILL.md`，提取当前 skill 的真实能力范围
2. 输出“能做什么 / 不能做什么 / 下一步引导”三段式回答
3. 不执行任何脚本，不进行鉴权排查，不虚构命令或外部工具


path: examples/task/README.md
content: # task — 使用说明

## 什么时候使用

- 一键生成报告 -> `start-task.py` + `check-task.py`
- 查询任务状态/报告列表/报告详情 -> `check-task.py` / `list-task-by-page.py` / `task-detail-v2.py`
- 手动修改章节与查看历史版本 -> `update-question-result.py` / `list-result-version.py`

## 标准流程

1. 先选模版并确定 `mobanId`
2. 先读取 `cms-auth-skills/SKILL.md`，按规则准备 `access-token`
3. 调用 `start-task.py` 创建任务并获得 `taskId`
4. 用 `check-task.py` 轮询状态
5. 完成后用 `task-detail-v2.py` 获取报告内容
6. 如需手改，先从详情里取 `questionId`，生成编辑后完整内容并展示给用户确认
7. 用户明确确认后，再调用 `update-question-result.py` 进行保存
8. 用 `list-result-version.py` 查看历史版本


path: examples/moban/README.md
content: # moban — 使用说明

## 什么时候使用

- 用户需要浏览可用模版 -> `list-moban.py`
- 用户需要查看某个模版章节结构 -> `moban-detail.py`
- 用户需要新建一份新模版 -> `create-moban.py`
- 用户需要更新已有模版结构或提示词 -> `update-moban.py`
- 用户需要发布或下架模版 -> `change-moban-state.py`
- 用户需要删除废弃模版 -> `delete-moban.py`

## 标准流程

1. 鉴权预检（先读取 `cms-auth-skills/SKILL.md`，按规则准备 `access-token`）
2. 获取模版列表并确认目标 `mobanId`
3. 查看模版详情，确认是否用于后续报告生成
4. 需要新模版时，准备 `MOBAN_NAME` 与 `MOBAN_SECTION_LIST`，调用 `create-moban.py`
5. 需要调整已有模版时，准备 `MOBAN_ID`、`MOBAN_NAME` 与 `MOBAN_SECTION_LIST`，调用 `update-moban.py`
6. 需要发布或下架模版时，准备 `MOBAN_ID` 与 `MOBAN_STATE`（`1` 上架，`0` 下架），调用 `change-moban-state.py`
7. 需要删除模版时，先确认目标 `MOBAN_ID` 后调用 `delete-moban.py`


path: scripts/capability/README.md
content: # 脚本清单 — capability

## 共享依赖

- 无。本模块不调用外部业务接口。

## 脚本列表

- 无业务脚本。能力咨询直接依据 `SKILL.md` 与 `examples/capability/README.md` 返回标准回答。

## 使用方式

- 不执行脚本。

## 输出说明

- 输出当前 skill 的能力边界说明，不回显内部实现细节，不触发接口调用。

## 规范

1. 不调用 API
2. 不虚构命令或工具
3. 不在能力咨询场景中排查鉴权


path: scripts/task/task-detail-v2.py
content: #!/usr/bin/env python3
"""
task / task-detail-v2 脚本

用途：获取报告任务详情

使用方式：
  python3 scripts/task/task-detail-v2.py

环境变量：
  XG_USER_TOKEN        - access-token（必须）
  TASK_ID              - 报告任务 ID（必须）
"""
import json
import os
import sys
import time
import urllib.error
import urllib.request

API_URL = "https://cwork-api.mediportal.com.cn/ai-report/task/taskDetailV2"
AUTH_MODE = "access-token"


def call_api(token: str, task_id: str) -> dict:
    req = urllib.request.Request(
        API_URL,
        data=json.dumps({"taskId": task_id}).encode("utf-8"),
        headers={"access-token": token, "Content-Type": "application/json"},
        method="POST",
    )
    last = None
    for i in range(3):
        try:
            with urllib.request.urlopen(req, timeout=60) as resp:
                return json.loads(resp.read().decode("utf-8"))
        except (urllib.error.HTTPError, urllib.error.URLError, TimeoutError) as e:
            last = e
            if i < 2:
                time.sleep(1)
    raise last


def main() -> None:
    [REDACTED_SECRET]"XG_USER_TOKEN")
    task_id = os.environ.get("TASK_ID")
    if not (token and task_id):
        print("错误: 请设置 XG_USER_TOKEN 与 TASK_ID", file=sys.stderr)
        sys.exit(1)

    print(json.dumps(call_api(token, task_id), ensure_ascii=False))


if __name__ == "__main__":
    main()


path: scripts/task/start-task.py
content: #!/usr/bin/env python3
"""
task / start-task 脚本

用途：基于模版发起异步报告生成任务

使用方式：
  python3 scripts/task/start-task.py

环境变量：
  XG_USER_TOKEN        - access-token（必须）
  MOBAN_ID             - 模版 ID（必须）
  TASK_NAME            - 报告名称（必须）
  TASK_DIR_ID          - 目录 ID（可选）
  TASK_CONTEXT         - 上下文 JSON 字符串（可选）
"""
import json
import os
import sys
import time
import urllib.error
import urllib.request

API_URL = "https://cwork-api.mediportal.com.cn/ai-report/task/startTask"
AUTH_MODE = "access-token"


def call_api(token: str, payload: dict) -> dict:
    req = urllib.request.Request(
        API_URL,
        data=json.dumps(payload).encode("utf-8"),
        headers={"access-token": token, "Content-Type": "application/json"},
        method="POST",
    )
    last = None
    for i in range(3):
        try:
            with urllib.request.urlopen(req, timeout=60) as resp:
                return json.loads(resp.read().decode("utf-8"))
        except (urllib.error.HTTPError, urllib.error.URLError, TimeoutError) as e:
            last = e
            if i < 2:
                time.sleep(1)
    raise last


def main() -> None:
    [REDACTED_SECRET]"XG_USER_TOKEN")
    moban_id = os.environ.get("MOBAN_ID")
    task_name = os.environ.get("TASK_NAME")
    task_dir_id = os.environ.get("TASK_DIR_ID")
    if not (token and moban_id and task_name):
        print("错误: 请设置 XG_USER_TOKEN/MOBAN_ID/TASK_NAME", file=sys.stderr)
        sys.exit(1)

    payload = {"mobanId": moban_id, "taskName": task_name}
    if task_dir_id:
        payload["dirId"] = task_dir_id
    if os.environ.get("TASK_CONTEXT"):
        payload["context"] = json.loads(os.environ["TASK_CONTEXT"])

    print(json.dumps(call_api(token, payload), ensure_ascii=False))


if __name__ == "__main__":
    main()


path: scripts/task/check-task.py
content: #!/usr/bin/env python3
"""
task / check-task 脚本

用途：查询任务进度

使用方式：
  python3 scripts/task/check-task.py

环境变量：
  XG_USER_TOKEN        - access-token（必须）
  TASK_ID              - 报告任务 ID（必须）
"""
import json
import os
import sys
import time
import urllib.error
import urllib.request

API_URL = "https://cwork-api.mediportal.com.cn/ai-report/task/checkTask"
AUTH_MODE = "access-token"


def call_api(token: str, task_id: str) -> dict:
    req = urllib.request.Request(
        API_URL,
        data=json.dumps({"taskId": task_id}).encode("utf-8"),
        headers={"access-token": token, "Content-Type": "application/json"},
        method="POST",
    )
    last = None
    for i in range(3):
        try:
            with urllib.request.urlopen(req, timeout=60) as resp:
                return json.loads(resp.read().decode("utf-8"))
        except (urllib.error.HTTPError, urllib.error.URLError, TimeoutError) as e:
            last = e
            if i < 2:
                time.sleep(1)
    raise last


def main() -> None:
    [REDACTED_SECRET]"XG_USER_TOKEN")
    task_id = os.environ.get("TASK_ID")
    if not (token and task_id):
        print("错误: 请设置 XG_USER_TOKEN 与 TASK_ID", file=sys.stderr)
        sys.exit(1)

    print(json.dumps(call_api(token, task_id), ensure_ascii=False))


if __name__ == "__main__":
    main()


path: scripts/task/list-result-version.py
content: #!/usr/bin/env python3
"""
task / list-result-version 脚本

用途：查询子章节历史版本

使用方式：
  python3 scripts/task/list-result-version.py

环境变量：
  XG_USER_TOKEN        - access-token（必须）
  QUESTION_ID          - 子章节 ID（必须）
"""
import json
import os
import sys
import time
import urllib.error
import urllib.request

API_URL = "https://cwork-api.mediportal.com.cn/ai-report/task/listResultVersion"
AUTH_MODE = "access-token"


def call_api(token: str, question_id: str) -> dict:
    req = urllib.request.Request(
        API_URL,
        data=json.dumps({"questionId": question_id}).encode("utf-8"),
        headers={"access-token": token, "Content-Type": "application/json"},
        method="POST",
    )
    last = None
    for i in range(3):
        try:
            with urllib.request.urlopen(req, timeout=60) as resp:
                return json.loads(resp.read().decode("utf-8"))
        except (urllib.error.HTTPError, urllib.error.URLError, TimeoutError) as e:
            last = e
            if i < 2:
                time.sleep(1)
    raise last


def main() -> None:
    [REDACTED_SECRET]"XG_USER_TOKEN")
    question_id = os.environ.get("QUESTION_ID")
    if not (token and question_id):
        print("错误: 请设置 XG_USER_TOKEN 与 QUESTION_ID", file=sys.stderr)
        sys.exit(1)

    print(json.dumps(call_api(token, question_id), ensure_ascii=False))


if __name__ == "__main__":
    main()


path: scripts/task/README.md
content: # 脚本清单 — task

## 共享依赖

- `cms-auth-skills/SKILL.md` — 统一鉴权入口，执行前先按该技能准备 `access-token`

## 脚本列表

| 脚本 | 对应接口 | 用途 |
|---|---|---|
| `start-task.py` | `POST /ai-report/task/startTask` | 创建报告任务 |
| `check-task.py` | `POST /ai-report/task/checkTask` | 查询任务进度 |
| `list-task-by-page.py` | `POST /ai-report/task/listTaskByPage` | 分页查询报告列表 |
| `task-detail-v2.py` | `POST /ai-report/task/taskDetailV2` | 获取报告详情 |
| `update-question-result.py` | `POST /ai-report/task/updateQuestionResult` | 手工覆盖子章节内容 |
| `list-result-version.py` | `POST /ai-report/task/listResultVersion` | 查询子章节历史版本 |

## 使用方式

```bash
# 设置环境变量
export XG_USER_TOKEN="your-access-token"

# 创建任务
export MOBAN_ID="模板ID"
export TASK_NAME="报告名称"
# 可选：目录ID（不设置时由后端默认规则处理）
# export TASK_DIR_ID="目录ID"
python3 scripts/task/start-task.py

# 查询进度
export TASK_ID="报告ID"
python3 scripts/task/check-task.py

# 报告列表分页（可选：通过环境变量传入额外参数）
export PAGE_NUM=0
export PAGE_SIZE=10
export REPORT_TYPE=1
export DEL_FLAG=0
python3 scripts/task/list-task-by-page.py

# 获取报告详情
python3 scripts/task/task-detail-v2.py

# 章节编辑与版本查询
export QUESTION_ID="子章节ID"
export RESULT="新的章节内容"
python3 scripts/task/update-question-result.py
python3 scripts/task/list-result-version.py
```

## 输出说明

所有脚本的输出均为 **JSON 格式**。

## 规范

1. **必须使用 Python** 编写
2. **鉴权遵循** `cms-auth-skills/SKILL.md` 规范
3. **入参定义以** `openapi/` 文档为准


path: scripts/task/list-task-by-page.py
content: #!/usr/bin/env python3
"""
task / list-task-by-page 脚本

用途：分页查询报告列表

使用方式：
  python3 scripts/task/list-task-by-page.py

环境变量：
  XG_USER_TOKEN        - access-token（必须）
  PAGE_NUM             - 页码，默认 0
  PAGE_SIZE            - 每页条数，默认 10
  REPORT_TYPE          - 报告来源，默认 1
  DEL_FLAG             - 删除标记，默认 0
  DIR_ID               - 目录 ID（可选）
  MOBAN_TYPE_ID        - 模版类型 ID（可选）
  STATE                - 任务状态（可选）
  SEARCH_KEY           - 关键词（可选）
  ONLY_MINE            - 是否仅看我的（可选）
  ONLY_MINE_STATUS     - 我的任务状态（可选）
"""
import json
import os
import sys
import time
import urllib.error
import urllib.request

API_URL = "https://cwork-api.mediportal.com.cn/ai-report/task/listTaskByPage"
AUTH_MODE = "access-token"


def call_api(token: str, payload: dict) -> dict:
    req = urllib.request.Request(
        API_URL,
        data=json.dumps(payload).encode("utf-8"),
        headers={"access-token": token, "Content-Type": "application/json"},
        method="POST",
    )
    last = None
    for i in range(3):
        try:
            with urllib.request.urlopen(req, timeout=60) as resp:
                return json.loads(resp.read().decode("utf-8"))
        except (urllib.error.HTTPError, urllib.error.URLError, TimeoutError) as e:
            last = e
            if i < 2:
                time.sleep(1)
    raise last


def main() -> None:
    [REDACTED_SECRET]"XG_USER_TOKEN")
    if not [REDACTED_SECRET]"错误: 请设置环境变量 XG_USER_TOKEN", file=sys.stderr)
        sys.exit(1)

    payload = {
        "pageNum": int(os.environ.get("PAGE_NUM", "0")),
        "pageSize": int(os.environ.get("PAGE_SIZE", "10")),
        "reportType": int(os.environ.get("REPORT_TYPE", "1")),
        "delFlag": int(os.environ.get("DEL_FLAG", "0")),
    }
    if os.environ.get("DIR_ID"):
        payload["dirId"] = os.environ["DIR_ID"]
    if os.environ.get("MOBAN_TYPE_ID"):
        payload["mobanTypeId"] = os.environ["MOBAN_TYPE_ID"]
    if os.environ.get("STATE"):
        payload["state"] = int(os.environ["STATE"])
    if os.environ.get("SEARCH_KEY"):
        payload["searchKey"] = os.environ["SEARCH_KEY"]
    if os.environ.get("ONLY_MINE"):
        payload["onlyMine"] = os.environ["ONLY_MINE"]
    if os.environ.get("ONLY_MINE_STATUS"):
        payload["onlyMineStatus"] = int(os.environ["ONLY_MINE_STATUS"])

    print(json.dumps(call_api(token, payload), ensure_ascii=False))


if __name__ == "__main__":
    main()


path: scripts/task/update-question-result.py
content: #!/usr/bin/env python3
"""
task / update-question-result 脚本

用途：覆盖指定子章节内容

使用方式：
  python3 scripts/task/update-question-result.py

环境变量：
  XG_USER_TOKEN        - access-token（必须）
  QUESTION_ID          - 子章节 ID（必须）
  RESULT               - 新章节内容（必须）
"""
import json
import os
import sys
import time
import urllib.error
import urllib.request

API_URL = "https://cwork-api.mediportal.com.cn/ai-report/task/updateQuestionResult"
AUTH_MODE = "access-token"


def call_api(token: str, question_id: str, result: str) -> dict:
    req = urllib.request.Request(
        API_URL,
        data=json.dumps({"questionId": question_id, "result": result}).encode("utf-8"),
        headers={"access-token": token, "Content-Type": "application/json"},
        method="POST",
    )
    last = None
    for i in range(3):
        try:
            with urllib.request.urlopen(req, timeout=60) as resp:
                return json.loads(resp.read().decode("utf-8"))
        except (urllib.error.HTTPError, urllib.error.URLError, TimeoutError) as e:
            last = e
            if i < 2:
                time.sleep(1)
    raise last


def main() -> None:
    [REDACTED_SECRET]"XG_USER_TOKEN")
    question_id = os.environ.get("QUESTION_ID")
    result = os.environ.get("RESULT")
    if not (token and question_id and result):
        print("错误: 请设置 XG_USER_TOKEN/QUESTION_ID/RESULT", file=sys.stderr)
        sys.exit(1)

    print(json.dumps(call_api(token, question_id, result), ensure_ascii=False))


if __name__ == "__main__":
    main()


path: scripts/moban/list-moban.py
content: #!/usr/bin/env python3
"""
moban / list-moban 脚本

用途：按分页条件检索模版列表

使用方式：
  python3 scripts/moban/list-moban.py

环境变量：
  XG_USER_TOKEN        - access-token（必须）
  MOBAN_PAGE_NUM       - 页码，默认 0
  MOBAN_PAGE_SIZE      - 每页条数，默认 20
  MOBAN_DIR_ID         - 目录筛选（可选）
  MOBAN_SEARCH_KEY     - 关键词筛选（可选）
  MOBAN_ONLY_MINE      - 是否仅看我的（可选）
"""
import json
import os
import sys
import time
import urllib.error
import urllib.request

API_URL = "https://cwork-api.mediportal.com.cn/ai-report/moban/listMobanByPageV2"
AUTH_MODE = "access-token"


def call_api(token: str, payload: dict) -> dict:
    req = urllib.request.Request(
        API_URL,
        data=json.dumps(payload).encode("utf-8"),
        headers={"access-token": token, "Content-Type": "application/json"},
        method="POST",
    )
    last = None
    for i in range(3):
        try:
            with urllib.request.urlopen(req, timeout=60) as resp:
                return json.loads(resp.read().decode("utf-8"))
        except (urllib.error.HTTPError, urllib.error.URLError, TimeoutError) as e:
            last = e
            if i < 2:
                time.sleep(1)
    raise last


def main() -> None:
    [REDACTED_SECRET]"XG_USER_TOKEN")
    if not [REDACTED_SECRET]"错误: 请设置环境变量 XG_USER_TOKEN", file=sys.stderr)
        sys.exit(1)

    payload = {
        "pageNum": int(os.environ.get("MOBAN_PAGE_NUM", "0")),
        "pageSize": int(os.environ.get("MOBAN_PAGE_SIZE", "20")),
    }
    if os.environ.get("MOBAN_DIR_ID"):
        payload["dirId"] = os.environ["MOBAN_DIR_ID"]
    if os.environ.get("MOBAN_SEARCH_KEY"):
        payload["searchKey"] = os.environ["MOBAN_SEARCH_KEY"]
    if os.environ.get("MOBAN_ONLY_MINE"):
        payload["onlyMine"] = os.environ["MOBAN_ONLY_MINE"]

    print(json.dumps(call_api(token, payload), ensure_ascii=False))


if __name__ == "__main__":
    main()


path: scripts/moban/README.md
content: # 脚本清单 — moban

## 共享依赖

- `cms-auth-skills/SKILL.md` — 统一鉴权入口，执行前先按该技能准备 `access-token`

## 脚本列表

| 脚本 | 对应接口 | 用途 |
|---|---|---|
| `list-moban.py` | `POST /ai-report/moban/listMobanByPageV2` | 模版列表检索 |
| `moban-detail.py` | `POST /ai-report/moban/mobanDetail` | 模版详情查看 |
| `create-moban.py` | `POST /ai-report/moban/saveMoban` | 新建模版 |
| `update-moban.py` | `POST /ai-report/moban/updateMoban` | 编辑模版 |
| `change-moban-state.py` | `POST /ai-report/moban/changeMobanState` | 模版发布/下架 |
| `delete-moban.py` | `POST /ai-report/moban/delMoban` | 删除模版 |

## 使用方式

```bash
# 设置环境变量
export XG_USER_TOKEN="your-access-token"

# 查询模版列表
export MOBAN_PAGE_NUM=0
export MOBAN_PAGE_SIZE=10
python3 scripts/moban/list-moban.py

# 查询模版详情
export MOBAN_ID="模板ID"
python3 scripts/moban/moban-detail.py

# 新建模版（sectionList 必填，JSON 字符串）
export MOBAN_NAME="创新药尽调模版"
export MOBAN_SECTION_LIST='[{"name":"项目概览","questionList":[{"title":"项目基本信息","content":"请总结项目背景与核心价值","prompt":"按业务、技术、竞争格局三个维度展开"}]}]'
python3 scripts/moban/create-moban.py

# 编辑模版（mobanId + sectionList 必填，JSON 字符串）
export MOBAN_ID="moban_1001"
export MOBAN_NAME="创新药尽调模版（更新版）"
export MOBAN_SECTION_LIST='[{"name":"项目概览","questionList":[{"title":"项目基本信息","prompt":"重点补充适应症市场空间"}]}]'
python3 scripts/moban/update-moban.py

# 模版发布/下架（1 上架，0 下架）
export MOBAN_ID="moban_1001"
export MOBAN_STATE=1
python3 scripts/moban/change-moban-state.py

# 删除模版
export MOBAN_ID="moban_1001"
python3 scripts/moban/delete-moban.py
```

## 输出说明

所有脚本的输出均为 **JSON 格式**。

## 规范

1. **必须使用 Python** 编写
2. **鉴权遵循** `cms-auth-skills/SKILL.md` 规范
3. **入参定义以** `openapi/` 文档为准


path: scripts/moban/change-moban-state.py
content: #!/usr/bin/env python3
"""
moban / change-moban-state 脚本

用途：模版发布/下架

使用方式：
  python3 scripts/moban/change-moban-state.py

环境变量：
  XG_USER_TOKEN                - access-token（必须）
  MOBAN_ID                     - 模版 ID（必须）
  MOBAN_STATE                  - 模版状态（必须，0 下架 / 1 上架）
"""
import json
import os
import sys
import time
import urllib.error
import urllib.request

API_URL = "https://cwork-api.mediportal.com.cn/ai-report/moban/changeMobanState"
AUTH_MODE = "access-token"


def call_api(token: str, payload: dict) -> dict:
    req = urllib.request.Request(
        API_URL,
        data=json.dumps(payload).encode("utf-8"),
        headers={"access-token": token, "Content-Type": "application/json"},
        method="POST",
    )
    last = None
    for i in range(3):
        try:
            with urllib.request.urlopen(req, timeout=60) as resp:
                return json.loads(resp.read().decode("utf-8"))
        except (urllib.error.HTTPError, urllib.error.URLError, TimeoutError) as e:
            last = e
            if i < 2:
                time.sleep(1)
    raise last


def main() -> None:
    [REDACTED_SECRET]"XG_USER_TOKEN")
    moban_id = os.environ.get("MOBAN_ID")
    state_raw = os.environ.get("MOBAN_STATE")

    if not [REDACTED_SECRET]"错误: 请设置环境变量 XG_USER_TOKEN", file=sys.stderr)
        sys.exit(1)
    if not moban_id:
        print("错误: 请设置环境变量 MOBAN_ID", file=sys.stderr)
        sys.exit(1)
    if state_raw is None:
        print("错误: 请设置环境变量 MOBAN_STATE（0/1）", file=sys.stderr)
        sys.exit(1)

    try:
        state = int(state_raw)
    except ValueError:
        print("错误: MOBAN_STATE 必须是 0 或 1", file=sys.stderr)
        sys.exit(1)

    if state not in (0, 1):
        print("错误: MOBAN_STATE 只能是 0 或 1", file=sys.stderr)
        sys.exit(1)

    payload = {"mobanId": moban_id, "state": state}
    print(json.dumps(call_api(token, payload), ensure_ascii=False))


if __name__ == "__main__":
    main()


path: scripts/moban/update-moban.py
content: #!/usr/bin/env python3
"""
moban / update-moban 脚本

用途：编辑已有模版

使用方式：
  python3 scripts/moban/update-moban.py

环境变量：
  XG_USER_TOKEN                - access-token（必须）
  MOBAN_ID                     - 模版 ID（必须）
  MOBAN_NAME                   - 模版名称（必须）
  MOBAN_SECTION_LIST           - 章节结构 JSON 字符串（必须）
  MOBAN_DESC                   - 模版描述（可选）
  MOBAN_DIR_ID                 - 目录 ID（可选）
  MOBAN_TYPE_ID                - 模版类型 ID（可选）
  MOBAN_PROMPT                 - 任务级提示词（可选）
  MOBAN_EDIT_NOTE              - 改动日志（可选）
  MOBAN_PUBLIC                 - 公开状态（可选，0/1）
  MOBAN_THIRD_SYSTEM           - 第三方系统标识（可选）
  MOBAN_DO_SUMMARY             - 是否总结（可选，0/1/2）
  MOBAN_SUMMARY_PROMPT         - 总结提示词（可选）
  MOBAN_AI_TYPE                - AI 类型（可选）
  MOBAN_REQUIRE_CONTEXT        - 上下文字段 JSON 字符串（可选，string[]）
"""
import json
import os
import sys
import time
import urllib.error
import urllib.request

API_URL = "https://cwork-api.mediportal.com.cn/ai-report/moban/updateMoban"
AUTH_MODE = "access-token"


def call_api(token: str, payload: dict) -> dict:
    req = urllib.request.Request(
        API_URL,
        data=json.dumps(payload).encode("utf-8"),
        headers={"access-token": token, "Content-Type": "application/json"},
        method="POST",
    )
    last = None
    for i in range(3):
        try:
            with urllib.request.urlopen(req, timeout=60) as resp:
                return json.loads(resp.read().decode("utf-8"))
        except (urllib.error.HTTPError, urllib.error.URLError, TimeoutError) as e:
            last = e
            if i < 2:
                time.sleep(1)
    raise last


def parse_json_env(env_name: str, default):
    raw = os.environ.get(env_name)
    if not raw:
        return default
    return json.loads(raw)


def main() -> None:
    [REDACTED_SECRET]"XG_USER_TOKEN")
    moban_id = os.environ.get("MOBAN_ID")
    name = os.environ.get("MOBAN_NAME")
    if not [REDACTED_SECRET]"错误: 请设置环境变量 XG_USER_TOKEN", file=sys.stderr)
        sys.exit(1)
    if not moban_id:
        print("错误: 请设置环境变量 MOBAN_ID", file=sys.stderr)
        sys.exit(1)
    if not name:
        print("错误: 请设置环境变量 MOBAN_NAME", file=sys.stderr)
        sys.exit(1)

    try:
        section_list = parse_json_env("MOBAN_SECTION_LIST", None)
        if not isinstance(section_list, list) or len(section_list) == 0:
            print("错误: MOBAN_SECTION_LIST 必须是非空 JSON 数组", file=sys.stderr)
            sys.exit(1)
        require_context = parse_json_env("MOBAN_REQUIRE_CONTEXT", None)
    except json.JSONDecodeError as exc:
        print(f"错误: JSON 环境变量解析失败: {exc}", file=sys.stderr)
        sys.exit(1)

    payload = {
        "mobanId": moban_id,
        "name": name,
        "sectionList": section_list,
    }
    if os.environ.get("MOBAN_DESC"):
        payload["desc"] = os.environ["MOBAN_DESC"]
    if os.environ.get("MOBAN_DIR_ID"):
        payload["dirId"] = os.environ["MOBAN_DIR_ID"]
    if os.environ.get("MOBAN_TYPE_ID"):
        payload["mobanTypeId"] = os.environ["MOBAN_TYPE_ID"]
    if os.environ.get("MOBAN_PROMPT"):
        payload["prompt"] = os.environ["MOBAN_PROMPT"]
    if os.environ.get("MOBAN_EDIT_NOTE"):
        payload["editNote"] = os.environ["MOBAN_EDIT_NOTE"]
    if os.environ.get("MOBAN_PUBLIC"):
        payload["public"] = int(os.environ["MOBAN_PUBLIC"])
    if os.environ.get("MOBAN_THIRD_SYSTEM"):
        payload["thirdSystem"] = os.environ["MOBAN_THIRD_SYSTEM"]
    if os.environ.get("MOBAN_DO_SUMMARY"):
        payload["doSummary"] = int(os.environ["MOBAN_DO_SUMMARY"])
    if os.environ.get("MOBAN_SUMMARY_PROMPT"):
        payload["summaryPrompt"] = os.environ["MOBAN_SUMMARY_PROMPT"]
    if os.environ.get("MOBAN_AI_TYPE"):
        payload["aiType"] = os.environ["MOBAN_AI_TYPE"]
    if require_context is not None:
        payload["requireContext"] = require_context

    print(json.dumps(call_api(token, payload), ensure_ascii=False))


if __name__ == "__main__":
    main()


path: scripts/moban/moban-detail.py
content: #!/usr/bin/env python3
"""
moban / moban-detail 脚本

用途：读取指定模版的章节结构与提示词配置

使用方式：
  python3 scripts/moban/moban-detail.py

环境变量：
  XG_USER_TOKEN        - access-token（必须）
  MOBAN_ID             - 模版 ID（必须）
"""
import json
import os
import sys
import time
import urllib.error
import urllib.request

API_URL = "https://cwork-api.mediportal.com.cn/ai-report/moban/mobanDetail"
AUTH_MODE = "access-token"


def call_api(token: str, moban_id: str) -> dict:
    req = urllib.request.Request(
        API_URL,
        data=json.dumps({"mobanId": moban_id}).encode("utf-8"),
        headers={"access-token": token, "Content-Type": "application/json"},
        method="POST",
    )
    last = None
    for i in range(3):
        try:
            with urllib.request.urlopen(req, timeout=60) as resp:
                return json.loads(resp.read().decode("utf-8"))
        except (urllib.error.HTTPError, urllib.error.URLError, TimeoutError) as e:
            last = e
            if i < 2:
                time.sleep(1)
    raise last


def main() -> None:
    [REDACTED_SECRET]"XG_USER_TOKEN")
    moban_id = os.environ.get("MOBAN_ID")
    if not (token and moban_id):
        print("错误: 请设置 XG_USER_TOKEN 与 MOBAN_ID", file=sys.stderr)
        sys.exit(1)

    print(json.dumps(call_api(token, moban_id), ensure_ascii=False))


if __name__ == "__main__":
    main()


path: scripts/moban/create-moban.py
content: #!/usr/bin/env python3
"""
moban / create-moban 脚本

用途：新建模版（调用 saveMoban）

使用方式：
  python3 scripts/moban/create-moban.py

环境变量：
  XG_USER_TOKEN                - access-token（必须）
  MOBAN_NAME                   - 模版名称（必须）
  MOBAN_SECTION_LIST           - 章节结构 JSON 字符串（必须）
  MOBAN_DESC                   - 模版描述（可选）
  MOBAN_DIR_ID                 - 目录 ID（可选）
  MOBAN_TYPE_ID                - 模版类型 ID（可选）
  MOBAN_PROMPT                 - 任务级提示词（可选）
  MOBAN_EDIT_NOTE              - 改动日志（可选）
  MOBAN_PUBLIC                 - 公开状态（可选，0/1）
  MOBAN_THIRD_SYSTEM           - 第三方系统标识（可选）
  MOBAN_DO_SUMMARY             - 是否总结（可选，0/1/2）
  MOBAN_SUMMARY_PROMPT         - 总结提示词（可选）
  MOBAN_AI_TYPE                - AI 类型（可选）
  MOBAN_REQUIRE_CONTEXT        - 上下文字段 JSON 字符串（可选，string[]）
"""
import json
import os
import sys
import time
import urllib.error
import urllib.request

API_URL = "https://cwork-api.mediportal.com.cn/ai-report/moban/saveMoban"
AUTH_MODE = "access-token"


def call_api(token: str, payload: dict) -> dict:
    req = urllib.request.Request(
        API_URL,
        data=json.dumps(payload).encode("utf-8"),
        headers={"access-token": token, "Content-Type": "application/json"},
        method="POST",
    )
    last = None
    for i in range(3):
        try:
            with urllib.request.urlopen(req, timeout=60) as resp:
                return json.loads(resp.read().decode("utf-8"))
        except (urllib.error.HTTPError, urllib.error.URLError, TimeoutError) as e:
            last = e
            if i < 2:
                time.sleep(1)
    raise last


def parse_json_env(env_name: str, default):
    raw = os.environ.get(env_name)
    if not raw:
        return default
    return json.loads(raw)


def main() -> None:
    [REDACTED_SECRET]"XG_USER_TOKEN")
    name = os.environ.get("MOBAN_NAME")
    if not [REDACTED_SECRET]"错误: 请设置环境变量 XG_USER_TOKEN", file=sys.stderr)
        sys.exit(1)
    if not name:
        print("错误: 请设置环境变量 MOBAN_NAME", file=sys.stderr)
        sys.exit(1)

    try:
        section_list = parse_json_env("MOBAN_SECTION_LIST", None)
        if not isinstance(section_list, list) or len(section_list) == 0:
            print("错误: MOBAN_SECTION_LIST 必须是非空 JSON 数组", file=sys.stderr)
            sys.exit(1)
        require_context = parse_json_env("MOBAN_REQUIRE_CONTEXT", None)
    except json.JSONDecodeError as exc:
        print(f"错误: JSON 环境变量解析失败: {exc}", file=sys.stderr)
        sys.exit(1)

    payload = {
        "name": name,
        "sectionList": section_list,
    }
    if os.environ.get("MOBAN_DESC"):
        payload["desc"] = os.environ["MOBAN_DESC"]
    if os.environ.get("MOBAN_DIR_ID"):
        payload["dirId"] = os.environ["MOBAN_DIR_ID"]
    if os.environ.get("MOBAN_TYPE_ID"):
        payload["mobanTypeId"] = os.environ["MOBAN_TYPE_ID"]
    if os.environ.get("MOBAN_PROMPT"):
        payload["prompt"] = os.environ["MOBAN_PROMPT"]
    if os.environ.get("MOBAN_EDIT_NOTE"):
        payload["editNote"] = os.environ["MOBAN_EDIT_NOTE"]
    if os.environ.get("MOBAN_PUBLIC"):
        payload["public"] = int(os.environ["MOBAN_PUBLIC"])
    if os.environ.get("MOBAN_THIRD_SYSTEM"):
        payload["thirdSystem"] = os.environ["MOBAN_THIRD_SYSTEM"]
    if os.environ.get("MOBAN_DO_SUMMARY"):
        payload["doSummary"] = int(os.environ["MOBAN_DO_SUMMARY"])
    if os.environ.get("MOBAN_SUMMARY_PROMPT"):
        payload["summaryPrompt"] = os.environ["MOBAN_SUMMARY_PROMPT"]
    if os.environ.get("MOBAN_AI_TYPE"):
        payload["aiType"] = os.environ["MOBAN_AI_TYPE"]
    if require_context is not None:
        payload["requireContext"] = require_context

    print(json.dumps(call_api(token, payload), ensure_ascii=False))


if __name__ == "__main__":
    main()


path: scripts/moban/delete-moban.py
content: #!/usr/bin/env python3
"""
moban / delete-moban 脚本

用途：删除指定模版

使用方式：
  python3 scripts/moban/delete-moban.py

环境变量：
  XG_USER_TOKEN                - access-token（必须）
  MOBAN_ID                     - 模版 ID（必须）
"""
import json
import os
import sys
import time
import urllib.error
import urllib.request

API_URL = "https://cwork-api.mediportal.com.cn/ai-report/moban/delMoban"
AUTH_MODE = "access-token"


def call_api(token: str, payload: dict) -> dict:
    req = urllib.request.Request(
        API_URL,
        data=json.dumps(payload).encode("utf-8"),
        headers={"access-token": token, "Content-Type": "application/json"},
        method="POST",
    )
    last = None
    for i in range(3):
        try:
            with urllib.request.urlopen(req, timeout=60) as resp:
                return json.loads(resp.read().decode("utf-8"))
        except (urllib.error.HTTPError, urllib.error.URLError, TimeoutError) as e:
            last = e
            if i < 2:
                time.sleep(1)
    raise last


def main() -> None:
    [REDACTED_SECRET]"XG_USER_TOKEN")
    moban_id = os.environ.get("MOBAN_ID")
    if not [REDACTED_SECRET]"错误: 请设置环境变量 XG_USER_TOKEN", file=sys.stderr)
        sys.exit(1)
    if not moban_id:
        print("错误: 请设置环境变量 MOBAN_ID", file=sys.stderr)
        sys.exit(1)
    payload = {"mobanId": moban_id}
    print(json.dumps(call_api(token, payload), ensure_ascii=False))


if __name__ == "__main__":
    main()


Security scan verdicts — ClawScan: suspicious | static analysis: clean | VirusTotal: clean | SkillSpector: suspicious (CRITICAL)