npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

medix-agent-sdk

v2.1.1

Published

医疗智能体集成SDK — 基于 postMessage 的 Host/Agent 双端通信解决方案

Readme

MedixAgentSDK

Version License TypeScript Node

医疗智能体集成 SDK — 基于 postMessage 的 Host/Agent 双端通信解决方案。

将 AI 智能体以 iframe 方式嵌入 HIS、EMR、护理系统等医疗平台,双端通过标准化消息协议完成握手、上下文同步、动作调用、内容读取与 @提及 交互。


目录


特性

  • 双端架构 — Host(宿主)与 Agent(智能体)职责分离,通过 postMessage 安全通信
  • 提及系统 — 支持 @ 提及内容、动作、表单等多种类型,带分页与关键词搜索
  • 动作执行 — XML 格式动作定义,便于大模型解析与调用
  • 上下文管理 — Host 主动推送,Agent 实时获取页面上下文
  • 结构化错误SDKError + SDKErrorCode 枚举,告别中文字符串判断
  • 调试日志debug 开关控制,生产环境零噪音
  • 类型完备 — 完整 TypeScript 类型定义,IDE 自动补全
  • 安全通信agentOrigin 配置确保 postMessage 不使用通配符 *

安装

npm install medix-agent-sdk

业务项目中建议使用范围版本,不要长期写死精确版本。示例:

{
  "dependencies": {
    "medix-agent-sdk": "^2.1.0"
  }
}

这样在同一主版本内发布 patch / minor 后,业务项目可直接执行 npm update medix-agent-sdk 升级。


架构概览

┌──────────────────────────────────────────────────────┐
│                   宿主页面(Host)                     │
│                                                        │
│   HostManager                                          │
│   ├── 创建并管理 iframe                                │
│   ├── 注册 Action / Content / Mention 处理器           │
│   └── 权限控制(按 Permission 枚举校验每条请求)         │
│                        │  postMessage(targetOrigin)    │
│                        ▼                              │
│           ┌──────────────────────┐                    │
│           │       iframe          │                    │
│           │   智能体页面(Agent) │                    │
│           │                      │                    │
│           │   AgentManager        │                    │
│           │   ├── 握手 & 就绪     │                    │
│           │   ├── 获取上下文      │                    │
│           │   ├── 调用 Action     │                    │
│           │   ├── 读取 Content    │                    │
│           │   └── @ 提及项解析   │                    │
│           └──────────────────────┘                    │
└──────────────────────────────────────────────────────┘

通信流程

  1. Agent 加载后自动发起 HANDSHAKE
  2. Host 响应并返回权限列表、可用资源
  3. 双方触发 READY 事件,业务逻辑开始执行
  4. 每条请求携带唯一 id,响应回传同一 id 完成匹配,默认超时 10 秒

快速开始

Host 端(宿主应用)

import MedixAgentSDK, { Permission, MentionableType, SDKEventType } from 'medix-agent-sdk';

const host = MedixAgentSDK.Host.init({
  // ── 必填 ──────────────────────────────────────
  agentUrl: 'https://your-agent-app.com',
  permissions: [
    Permission.READ_CONTENT,
    Permission.EXECUTE_ACTIONS,
    Permission.ACCESS_CONTEXT,
    Permission.EMIT_EVENTS,
    Permission.USE_MENTIONS,
  ],

  // ── 安全(生产环境务必填写) ───────────────────
  agentOrigin: 'https://your-agent-app.com',

  // ── 调试(生产环境设为 false 或不传) ──────────
  debug: false,

  // ── 容器 ──────────────────────────────────────
  containerId: 'agent-container',

  // ── 初始上下文 ────────────────────────────────
  context: {
    patientId: 'P001',
    department: '内科',
  },

  // ── 提及项声明(处理器需单独注册) ───────────
  mentions: [
    {
      id: 'patient-info',
      type: MentionableType.CONTENT,
      name: '患者信息',
      category: '临床数据',
      description: '获取当前就诊患者的完整信息',
    },
  ],

  // ── 动作声明(处理器需单独注册) ─────────────
  actions: [
    {
      id: 'create-record',
      name: 'create_nursing_record',
      description: '创建护理记录,记录患者当前状态与护理措施',
      xmlDefinition: `
        <action>
          <name>create_nursing_record</name>
          <parameters>
            <parameter name="content" type="string" required="true">
              <description>记录内容</description>
            </parameter>
            <parameter name="type" type="string" required="false">
              <description>记录类型:观察记录 | 护理措施 | 用药记录</description>
            </parameter>
          </parameters>
        </action>
      `,
    },
  ],

  // ── iframe 样式 ───────────────────────────────
  styles: {
    width: '100%',
    height: '600px',
    borderRadius: '8px',
    boxShadow: '0 2px 12px rgba(0,0,0,0.1)',
  },
});

// 注册提及项解析器
host.onMentionResolved('patient-info', async (mentionData) => {
  return await patientService.getFullInfo(mentionData.metadata?.patientId);
});

// 注册动作处理器
host.registerAction('create-record', async (params) => {
  const result = await nursingService.createRecord(params);
  return { success: true, recordId: result.id };
});

// 注册内容处理器
host.registerContent('lab-report', async (params) => {
  return await labService.getReport(params.reportId);
});

// 监听 SDK 就绪
host.addEventListener(SDKEventType.READY, () => {
  console.log('Agent 已就绪');
});

// 监听 Agent 自定义事件
host.onAgentEvent('diagnosis-submitted', (data) => {
  console.log('诊断已提交:', data);
});

// 患者切换时更新上下文
function onPatientChange(patient) {
  host.updateContext({ patientId: patient.id, patientName: patient.name });
}

Agent 端(智能体应用)

import MedixAgentSDK, { SDKEventType, SDKError, SDKErrorCode } from 'medix-agent-sdk';

const agent = MedixAgentSDK.Agent.init({
  autoConnect: true,
  debug: false,
});

// 等待握手完成(建议所有业务逻辑在此之后执行)
await agent.waitForReady();

// 获取宿主注入的上下文
const context = await agent.getContext();
console.log('当前患者:', context.patientId);

// 读取宿主注册的内容
const report = await agent.getContent('lab-report', { reportId: 'R001' });

// 获取 @ 提及项列表(支持筛选)
const mentions = await agent.getMentions({ category: '临床数据' });

// 解析用户选择的提及项
const patientData = await agent.resolveMention({
  id: 'patient-info',
  name: '患者信息',
  type: 'content',
  // position 为可选字段,非输入框场景可不传
});

// 一次性获取所有动作定义(单次请求,无性能问题)
const actions = await agent.getActions();

// 执行动作
const result = await agent.executeAction('create-record', {
  content: '患者体温 37.2°C,精神状态良好',
  type: '观察记录',
});

// 监听宿主直接发送的消息
agent.onMessage(({ message, metadata }) => {
  console.log('收到宿主消息:', message);
});

// 监听宿主插入输入框的内容
agent.onInsertMessage(({ message }) => {
  insertIntoInputBox(message);
});

// 监听宿主自定义事件
agent.onHostEvent('patient-changed', (data) => {
  console.log('患者已切换:', data);
});

调试模式

SDK 默认静默,生产环境控制台零输出。开发时有两种开启方式:

方式一:初始化时配置(推荐)

// Host 端
MedixAgentSDK.Host.init({ debug: true, ... });

// Agent 端
MedixAgentSDK.Agent.init({ debug: true, ... });

方式二:运行时动态开关

import { enableDebug, disableDebug } from 'medix-agent-sdk';

enableDebug();   // 开启
disableDebug();  // 关闭

warnerror 级别的日志无论是否开启 debug 都会输出,不会被静默。


错误处理

所有异步方法均通过 Promise 抛出结构化的 SDKError,通过 error.code 精准判断:

import { SDKError, SDKErrorCode } from 'medix-agent-sdk';

try {
  const result = await agent.executeAction('create-record', params);
} catch (error) {
  if (error instanceof SDKError) {
    switch (error.code) {
      case SDKErrorCode.UNAUTHORIZED:
        console.error('权限不足,请检查 Host 初始化时的 permissions 配置');
        break;
      case SDKErrorCode.NOT_FOUND:
        console.error('动作不存在,请检查 actionId 是否已在 Host 端注册');
        break;
      case SDKErrorCode.REQUEST_TIMEOUT:
        console.error('请求超时,Handler 执行时间过长');
        break;
      case SDKErrorCode.NOT_READY:
        console.error('SDK 尚未就绪,请先 await waitForReady()');
        break;
      default:
        console.error('未知错误:', error.message, error.details);
    }
  }
}

SDKErrorCode 速查

| 错误码 | 说明 | |---|---| | UNAUTHORIZED | 权限不足(对应 HTTP 401) | | NOT_FOUND | Action / Content / Mention 不存在(404) | | INVALID_REQUEST | 请求参数格式错误(400) | | INTERNAL_ERROR | Handler 内部执行异常(500) | | REQUEST_TIMEOUT | 请求超时(默认 10s) | | NOT_READY | waitForReady 超时(默认 15s) | | SDK_DESTROYED | 实例已销毁,pending 请求被取消 | | NOT_INITIALIZED | SDK 未初始化 |


配置项参考

HostConfig

interface HostConfig {
  // ── 必填 ──────────────────────────────────────────────
  agentUrl: string;          // 智能体页面 URL
  permissions: Permission[]; // 授予智能体的权限列表

  // ── 安全(生产环境必填) ───────────────────────────────
  agentOrigin?: string;      // Agent 页面的 origin,不填则使用 '*' 并打警告
                             // 示例:'https://agent.your-domain.com'

  // ── 调试 ──────────────────────────────────────────────
  debug?: boolean;           // 是否开启调试日志,默认 false

  // ── 容器 ──────────────────────────────────────────────
  containerId?: string;      // 挂载容器的 DOM id,不填则自动生成
  autoCreate?: boolean;      // 是否自动创建 iframe,默认 true

  // ── 数据预声明(处理器需单独注册) ────────────────────
  context?: any;
  contents?: ContentDefinition[];
  actions?: ActionDefinition[];
  mentions?: Mentionable[];

  // ── iframe 样式 ────────────────────────────────────────
  styles?: {
    width?: string; height?: string; border?: string;
    borderRadius?: string; boxShadow?: string; zIndex?: string;
    position?: 'fixed' | 'relative' | 'absolute';
    top?: string; right?: string; bottom?: string; left?: string;
  };

  // ── 回调(向后兼容) ───────────────────────────────────
  onReady?: () => void;
  onError?: (error: any) => void;
}

AgentConfig

interface AgentConfig {
  autoConnect?: boolean; // 是否自动发起握手,默认 true
  debug?: boolean;       // 是否开启调试日志,默认 false

  // ── 回调(向后兼容) ───────────────────────────────────
  onReady?: () => void;
  onError?: (error: any) => void;
}

⚠️ 注意:旧版 AgentConfig 中的 registerContents / registerActions / registerMentions 已在 v2.1.0 中移除。如需在全局缓存中注册,请直接调用 SDKManager.register*() 方法。


API 参考

Host SDK

| 方法 | 说明 | |---|---| | Host.init(config) | 初始化并返回 HostManager 实例 | | host.updateContext(data) | 更新上下文并推送给 Agent | | host.registerContent(id, handler) | 注册内容处理器 | | host.registerAction(id, handler) | 注册动作处理器 | | host.registerMention(mention, resolver) | 注册单个提及项及其解析器 | | host.registerMentions(mentions, resolvers) | 批量注册提及项 | | host.onMentionResolved(id, resolver) | 仅注册解析器(提及项不存在时自动创建) | | host.removeMention(id) | 移除提及项 | | host.registerActionDefinition(def) | 注册动作 XML 定义 | | host.registerActionDefinitions(defs) | 批量注册动作 XML 定义 | | host.registerPlugin(name, plugin) | 注册插件 | | host.sendMessageToAgent(msg, meta?) | 直接发送消息给 Agent | | host.insertMessageToAgent(msg, meta?) | 插入消息到 Agent 输入框 | | host.emitToAgent(eventName, data) | 向 Agent 发送自定义事件 | | host.onAgentEvent(eventName, cb) | 监听 Agent 发来的自定义事件 | | host.addEventListener(event, handler) | 监听 SDK 内置事件 | | host.show() | 显示 iframe 容器 | | host.hide() | 隐藏 iframe 容器 | | host.destroy() | 销毁实例,移除 DOM,清理监听器 |

Agent SDK

| 方法 | 说明 | |---|---| | Agent.init(config) | 初始化并返回 AgentManager 实例 | | agent.waitForReady(timeout?) | 等待握手完成,默认超时 15s | | agent.connect() | 手动发起握手(autoConnect: false 时使用) | | agent.getContext() | 获取宿主注入的上下文 | | agent.getContent(id, params?) | 读取宿主注册的内容 | | agent.executeAction(id, params) | 调用宿主注册的动作 | | agent.getMentions(query?) | 获取提及项列表(支持筛选与分页) | | agent.resolveMention(mentionData) | 解析提及项获取具体数据 | | agent.getActions() | 一次性获取所有动作定义(单次请求) | | agent.onMessage(cb) | 监听宿主直接发送的消息 | | agent.onInsertMessage(cb) | 监听宿主插入输入框的消息 | | agent.onHostEvent(eventName, cb) | 监听宿主自定义事件 | | agent.addEventListener(event, handler) | 监听 SDK 内置事件 | | agent.destroy() | 销毁实例,清理所有处理器 |


提及系统

提及项类型

enum MentionableType {
  CONTENT = 'content',  // 内容型:患者信息、检查结果、病历等
  ACTION  = 'action',   // 动作型:查询、下单、创建记录等
  FORM    = 'form',     // 表单型:问诊表单、康复计划等
  CUSTOM  = 'custom',   // 自定义类型
}

注册与解析

// Host 端注册
host.registerMention(
  {
    id: 'diagnosis-result',
    type: MentionableType.CONTENT,
    name: '诊断结果',
    category: '临床数据',
    description: '获取当前患者的最新诊断结果',
  },
  async (mentionData) => {
    return await clinicService.getDiagnosis(mentionData.metadata?.patientId);
  }
);

// Agent 端使用
const mentions = await agent.getMentions({
  query: '诊断',          // 关键词搜索
  category: '临床数据',   // 按分类筛选
  type: 'content',        // 按类型筛选
  limit: 20,              // 分页大小
  offset: 0,              // 偏移量
});

// 用户选择提及项后解析
const result = await agent.resolveMention({
  id: 'diagnosis-result',
  name: '诊断结果',
  type: MentionableType.CONTENT,
  // position 为可选,输入框场景传实际位置,其他场景可省略
  position: { start: 5, end: 10 },
});

动作系统

XML 格式定义

// Host 端注册动作定义(供 Agent 端 getActions() 获取)
host.registerActionDefinition({
  id: 'create-record',
  name: 'create_nursing_record',
  description: '创建护理记录,记录患者当前状态与护理措施',
  displayName: '创建护理记录',
  category: '护理操作',
  xmlDefinition: `
    <action>
      <name>create_nursing_record</name>
      <description>创建护理记录</description>
      <parameters>
        <parameter name="content" type="string" required="true">
          <description>记录内容</description>
        </parameter>
        <parameter name="type" type="string" required="false">
          <description>记录类型</description>
          <options>
            <option>观察记录</option>
            <option>护理措施</option>
            <option>用药记录</option>
          </options>
        </parameter>
      </parameters>
    </action>
  `,
});

// Host 端注册执行处理器
host.registerAction('create-record', async (params) => {
  const { content, type } = params;
  const record = await nursingService.create({ content, type });
  return { success: true, recordId: record.id };
});

// Agent 端获取所有动作(一次请求)
const actions = await agent.getActions();

// Agent 端执行动作
const result = await agent.executeAction('create-record', {
  content: '患者体温 37.2°C,精神状态良好',
  type: '观察记录',
});

权限管理

Host 初始化时声明权限,Agent 的每条请求都会在 Host 侧校验,未授权返回 UNAUTHORIZED 错误。

import { Permission } from 'medix-agent-sdk';

MedixAgentSDK.Host.init({
  permissions: [
    Permission.READ_CONTENT,    // 允许 Agent 读取内容(getContent)
    Permission.EXECUTE_ACTIONS, // 允许 Agent 执行动作(executeAction / getActions)
    Permission.ACCESS_CONTEXT,  // 允许 Agent 访问上下文(getContext)
    Permission.EMIT_EVENTS,     // 允许 Agent 向 Host 发送自定义事件
    Permission.USE_MENTIONS,    // 允许 Agent 使用 @ 提及功能
  ],
  ...
});

Vue 集成示例

<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue';
import MedixAgentSDK, { SDKEventType, type Mentionable } from 'medix-agent-sdk';

const isReady = ref(false);
const mentions = ref<Mentionable[]>([]);
let agent: ReturnType<typeof MedixAgentSDK.Agent.init>;

onMounted(async () => {
  agent = MedixAgentSDK.Agent.init({ autoConnect: true, debug: false });

  await agent.waitForReady();
  isReady.value = true;

  mentions.value = await agent.getMentions();

  agent.onInsertMessage(({ message }) => {
    insertTextAtCursor(message);
  });

  agent.addEventListener(SDKEventType.CONTEXT_UPDATED, (ctx) => {
    console.log('上下文已更新:', ctx);
  });
});

onUnmounted(() => {
  agent?.destroy();
});
</script>

React 集成示例

import { useEffect, useRef, useState } from 'react';
import MedixAgentSDK, { SDKEventType, type Mentionable } from 'medix-agent-sdk';

export function AgentPanel() {
  const hostRef = useRef<ReturnType<typeof MedixAgentSDK.Host.init> | null>(null);
  const [agentReady, setAgentReady] = useState(false);

  useEffect(() => {
    hostRef.current = MedixAgentSDK.Host.init({
      agentUrl: 'https://your-agent-app.com',
      agentOrigin: 'https://your-agent-app.com',
      containerId: 'agent-panel',
      permissions: [/* ... */],
      debug: process.env.NODE_ENV === 'development',
    });

    hostRef.current.addEventListener(SDKEventType.READY, () => {
      setAgentReady(true);
    });

    hostRef.current.registerAction('create-record', async (params) => {
      return await nursingService.create(params);
    });

    return () => {
      hostRef.current?.destroy();
    };
  }, []);

  return (
    <div>
      {agentReady && <span>Agent 已就绪</span>}
      <div id="agent-panel" style={{ height: 600 }} />
    </div>
  );
}

开发指南

环境要求

  • Node.js >= 16
  • TypeScript >= 5.0
  • 现代浏览器(支持 postMessage API)

本地开发

# 克隆项目
git clone https://github.com/your-org/medix-agent-sdk.git
cd medix-agent-sdk

# 安装依赖
npm install

# 开发模式(监听文件变化,自动重新构建)
npm run dev

# 类型检查
npm run typecheck

# 构建生产产物
npm run build

发布到 npm

SDK 修改后发布步骤

1. 完成代码修改

  • 完成 SDK 功能、类型或构建相关修改
  • 如果对外 API、接入方式、示例代码有变化,同步更新 README.md
  • 如果有版本变更说明,同步更新 CHANGELOG.md

2. 安装依赖并登录 npm

npm install
npm login

3. 发布前校验

npm run typecheck
npm run clean
npm run build
npm pack --dry-run

4. 执行发布命令

# patch:修复问题、兼容性调整
bash publish.sh patch

# minor:新增向后兼容功能
bash publish.sh minor

# major:存在破坏性变更
bash publish.sh major

5. Windows 环境执行说明

  • 如果本机安装了 Git Bash,优先在 Git Bash 中执行 bash publish.sh patch
  • 如果使用的是 PowerShell 且不能直接跑 bash publish.sh,可以手动按下面步骤执行
# 以 patch 发布为例
npm version patch --no-git-tag-version
npm run typecheck
npm run clean
npm run build
npm pack --dry-run
npm publish --access public

6. 业务项目升级 SDK

# 安装最新版本
npm install medix-agent-sdk@latest

# 或更新到当前 package.json 范围内允许的最新版本
npm update medix-agent-sdk

如果业务项目依赖写成 "medix-agent-sdk": "^2.1.0",通常执行 npm update medix-agent-sdk 即可。


一键发布命令

# 发 patch 版本(默认):2.1.0 → 2.1.1
bash publish.sh

# 发 minor 版本:2.1.0 → 2.2.0
bash publish.sh minor

# 发 major 版本:2.1.0 → 3.0.0
bash publish.sh major

# 演习模式(不实际发布,仅预览流程)
bash publish.sh --dry-run

脚本会自动完成:环境检查 → Git 状态校验 → 类型检查 → 构建 → 版本升级 → 发布 → Git Tag。


更新日志

详细变更记录见 CHANGELOG.md

v2.1.0 主要变更

新增

  • HostConfig.agentOrigin — postMessage 安全目标 origin,生产环境必填
  • HostConfig.debug / AgentConfig.debug — 日志开关,默认 false
  • enableDebug() / disableDebug() — 运行时动态切换日志
  • SDKError + SDKErrorCode — 结构化错误,替代裸字符串
  • agent.getActions() 改用批量接口,从 N 次串行请求降为 1 次
  • MessageType.GET_ACTION_DEFINITIONS — 新增批量获取动作定义协议

修复

  • Host + Agent 同页时消息被重复处理的 Bug
  • plugin.initialize() 未传 sdk 实例参数
  • destroy() 时未拒绝 pending 请求导致的内存泄漏

破坏性变更

  • AgentConfig 移除 registerContents / registerActions / registerMentions(原本无效)
  • MentionData.position 改为可选字段
  • 错误判断需改用 error instanceof SDKError && error.code === SDKErrorCode.xxx

许可证

ISC License © your-org