@_daniel_jiang/host-sdk
v1.1.3
Published
Agent 平台宿主嵌入 SDK(iframe Hub/Widget,框架无关)
Readme
@_daniel_jiang/host-sdk
Agent 平台宿主嵌入 SDK(iframe 模式)。UI 由 Agent /host/hub、/host/widget 渲染;宿主只需 init + registerPage。
表单提交与附件上传均在 Agent Widget iframe 内完成:用户点「开始」后,Widget 以 multipart 一次调用 POST /api/v1/host/scenarios/{workflow}/run(表单 JSON 字段 + 可选 attachment_files)。不再使用独立的 POST /sessions/{id}/files。
本文档随 npm 包发布,面向接入方(安装与用法)。本仓库维护者改 SDK / 发版说明见仓库根目录
README.md§4。
安装
npm install @_daniel_jiang/host-sdk
# 或 yarn add @_daniel_jiang/host-sdk{
"dependencies": {
"@_daniel_jiang/host-sdk": "^1.1.3"
}
}官方源:https://www.npmjs.com/package/@_daniel_jiang/host-sdk
国内阿里云等私库一般可代理拉取。
用法
import { AgentHost } from '@_daniel_jiang/host-sdk'
await AgentHost.init({
host: 'edc',
// 推荐:BFF bootstrap 返回 agent_token + agent_web_origin,无需前端环境变量
bootstrap: () => fetch('/boot-admin/agent/bootstrap?hosts=edc', { credentials: 'include' }).then((r) => r.json()),
// 可选:打开需 establish 的 Widget 前强制刷新会话
// prepareOpenWidget: () => bootstrapAgentSession(true),
// 按需:Hub 场景弹窗打开时现取系统 / 名称 / 描述 / 菜单(不必全局 watch 路由)
// getHostContext: () => ({ system: '我的项目', name: projectName, description, menu }),
})
AgentHost.registerPage(
'edc_patient_list',
[{
id: 'form_fill',
workflow: 'edc_form_fill',
label: 'AI 填表',
host: 'edc',
prefilled: () => ({
sub_project_id: currentSubProjectId,
project_id: currentProjectId,
target: buildTargetFromEdcSelection(selectedForm),
}),
enabled: () => Boolean(currentSubProjectId && selectedForm),
hostContext: { refresh: 'patient_list' },
}],
{
// 任务 success 且 hostContext.refresh 匹配时调用;unregisterPage 后自动失效
refreshKey: 'patient_list',
onRefresh: () => refreshPatientList(),
},
)
// 表单列表页:AI 设计 CRF(上传 Word/PDF)
AgentHost.registerPage(
'edc_form_list',
[{
id: 'crf_design',
workflow: 'edc_crf_design',
label: 'AI 设计 CRF',
host: 'edc',
prefilled: () => ({
sub_project_id: currentSubProjectId,
sort_start: nextFormSort,
}),
enabled: () => Boolean(currentSubProjectId),
hostContext: { refresh: 'form_list' },
}],
{ refreshKey: 'form_list', onRefresh: () => refreshFormList() },
)
AgentHost.openAction('edc_patient_list', 'form_fill')
// 离开页时务必 unregister(keep-alive 切走 / destroy),避免后台误刷
AgentHost.unregisterPage('edc_patient_list')EDC / 专病库可用 createAgentPageMixin 自动处理进出页 register/unregister。
宿主上下文在 init({ getHostContext }) 提供:Hub 场景弹窗打开时 request-host-context 现取系统 / 名称 / 描述 / 菜单,不必对路由或专病做全局 watch。system 建议用:专病数据库系统 / 我的项目 / 数据探索(后两者为科研平台子系统)。手册 / 建设探讨是 Hub 全局场景,业务页只需 registerPage 本页 AI 能力。
无弹窗直跑(kind: 'direct')
缺省仍打开 Widget。kind: 'direct' 时点「立即开始」不弹 Widget:
- 有
skill:Hub 创建会话并发送 Chat 消息(selected_skill_slugs),不走POST /host/scenarios - 仅有
workflow:Hub 创建会话后静默POST /host/scenarios(物化/推沙盒),仍不弹 Widget - 执行策略(
no_tools/skip_post_summary)写在 Agenthost_ui_registry,不写 Skill、也不由宿主 action 定死。Hub 直跑 skill 时拉GET /host/workflows/{name}/ui;Chat@同一技能不读 host_ui,仍是完整 Agent。 - 可选
noTools: true:仅作覆盖(旧宿主);新场景请只在 host_ui 声明no_tools。 直跑不必填workflow(纯 skill)或不必填skill(纯 workflow)。hintPlacement: 'anchor'+anchor把横幅贴到控件旁,仅当该控件聚焦时显示;不设则仍贴在右下角 FAB 上方。完成时onRefresh可收到apply(如{ remark }或{ form_values })。旧宿主不升级、不传这些字段,行为与 1.0 相同。
能否启动由宿主自己的 enabled() 决定,SDK 不按场景 slug 拦截。canOpen() 仅兼容旧调用,恒为 true。
Widget 内提交流程(iframe,宿主无需处理文件)
- SDK 打开
/host/widget?workflow=...iframe - Widget 拉取
GET /host/workflows/{name}/ui渲染表单(勾选填表场景 Widget 仅上传文书/文本) - Widget 创建会话
POST /sessions - 用户提交 →
POST /host/scenarios/{name}/run(multipart,一次完成) - Hub iframe 展示任务进度;成功 / 失败 / 取消完成后 SDK 对仍注册页触发
onRefresh(失败时通常无apply,宿主可据此关 loading)
complete / success 来自 Agent 任务协议(Hub/Widget postMessage),与宿主业务 API 返回结构无关。
带附件的工作流(如 Excel 批量填表)无需宿主先上传文件;附件在 Widget 内选好后随 scenario run 一并提交。
Bootstrap 契约(宿主 BFF)
GET /agent/bootstrap?hosts=edc 建议返回:
{
"agent_token": "...",
"refresh_token": "...",
"agent_web_origin": "https://agent.example.com"
}agent_web_origin:Agent 前端地址(iframe、Hub)- Token 换取走 boot-admin → Agent API(
agent-host-api-base-url),与agent_web_origin分离
可选:init({ agentOrigin: '...' }) 显式覆盖 BFF 下发的地址。
Scenario API(Headless / 自绘表单时)
iframe SDK 一般不需要宿主直调;若宿主自画表单、绕过 Widget,可按下列契约提交:
POST /api/v1/host/scenarios/{workflow_name}/run
Authorization: Bearer <token>
Content-Type: multipart/form-data| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| session_id | string | 是 | 已创建的 Agent 会话 UUID |
| host | string | 否 | 宿主标识,默认 research_portal |
| host_context | string (JSON) | 否 | 页面上下文、刷新回调等 |
| prefilled | string (JSON) | 否 | 宿主勾选带入的只读参数 |
| form_values | string (JSON) | 否 | 用户在表单中的选择 |
| prompt_extra | string | 否 | 附加 prompt |
| attachment_files | file[] | 否 | 附件,可多文件 |
响应示例:
{
"success": true,
"data": {
"task_id": "uuid",
"session_id": "uuid",
"status": "queued",
"stream_url": "/api/v1/tasks/{task_id}/stream"
}
}与 Chat 对比:
| 场景 | 接口 |
|------|------|
| Chat 发消息 + 附件 | POST /sessions/{id}/messages-with-files |
| Host Widget / Scenario | POST /host/scenarios/{name}/run(multipart) |
完整契约见仓库 PRD/11_host_widget_integration.md §6。
