@eka-care/medassistance-widget-embed (英语)
使用Web组件的可嵌入式部件加载器。 添加脚本和脚本 <eka-medassist-widget> 用于框架不可知、懒惰的聊天部件的自定义元素.
概览
- 自定义网络组件 – 说吧 –
<eka-medassist-widget>易于嵌入 - 懒惰装入 - 当用户打开部件时部件资产加载
- 框架不可知论 - 不需要反应或构建步骤
- 孤立的造型 - 阴影 DOM 避免与主机样式相冲突
- 简单整合 —脚本标记+自定义元素
安装
npm install @eka-care/medassist-widget-embed
或者从CDN装入(根据需要替换版本):
<script
src="https://cdn.jsdelivr.net/npm/@eka-care/medassist-widget-embed@latest/dist/index.js"
async></script>
对于自我托管,确保已建部件资产(medassist-widget.js, (中文(简体) ), medassist-widget.css(一) 随身服务 index.js,或将软件包默认的 CDN 用于部件资产(参见 如何运作) (中文(简体) ).
使用量
<!DOCTYPE html>
<html>
<head>
<title>My Website</title>
</head>
<body>
<h1>Welcome</h1>
<eka-medassist-widget agent-id="your-agent-id-here"></eka-medassist-widget>
<script src="https://cdn.jsdelivr.net/npm/@eka-care/medassist-widget-embed@latest/dist/index.js" async></script>
</body>
</html>
部件以浮动按钮的形式出现; 单击它加载并打开聊天.
配置
必需属性
agent-id- 你的医疗辅助剂识别器
可选属性
icon-url— 自定义启动按钮的图标 URL. 省略时,发射装置使用代理人所配置的图标(theme.icon_img从代理配置( agent config) 开始, 并且仅在配置已装入时显示 —— 没有内置默认图标title- 部件标题base-url— API/代理配置的基础 URLdisplay-mode– 说吧 –"widget"(浮动按钮),"full"(正线全视图)或"side_panel"(被遮住的面板,见 侧面板模式(中文(简体) )side-panel-mode– 说吧 –"push"(违约)或"overlay";仅用于display-mode="side_panel"side-panel-width– 面板宽度为px,被夹到320–560 (默认400);仅侧面板side– 说吧 –"right"(违约)或"left"; 默认为"left"在RTL 文档上; 仅侧面板override-widget-width编号 :override-widget-height– px 中浮动窗口的大小( 正数; 其他的都忽略了) 。 仅在桌面上浮动模式:全页,侧面板和移动布局保持自己的缩放. 被挤到320-800宽和480-900高处,从不比两侧的取景口减20px大. 他们控制了特工的配置theme.widget_width编号 :theme.widget_height;每个维数优先是主机覆盖 → 代理配置 → 默认 384x600context- JSON 上下文键值对
程序配置为 EkaMedAssist.init()
脚本加载后,您可以在用户打开部件前设置或覆盖配置 :
window.EkaMedAssist.init({
agentId: "your-agent-id",
title: "MedAssist",
iconUrl: "https://example.com/icon.svg",
baseUrl: "https://api.example.com",
context: { key: "value" },
theme: {
background: "#1a1738",
primary: "#09FBD3",
textColor: "white",
overrideWidgetWidth: 480, // floating window size in px (same as the override-widget-* attributes)
overrideWidgetHeight: 720,
},
});
自定义图标示例
<eka-medassist-widget
agent-id="your-agent-id"
icon-url="https://example.com/custom-icon.svg"></eka-medassist-widget>
自定义发射器样式
如果您需要重新定位浮动启动器按钮( 不同的断点, 自定义 z- index等) , 请通过 CSS customLauncherStyles 内 init() 或直接与 custom-launcher-styles 属性。 CSS被注入到发射台的"影子"DOM中,这样你就可以使用媒体查询,徘徊状态,以及CSS允许的任何东西.
两个选择者作为稳定合同得到支持:
:host——发射器包装. 使用它来覆盖position, (中文(简体) ),bottom, (中文(简体) ),right, (中文(简体) ),left, (中文(简体) ),top, (中文(简体) ),transform, (中文(简体) ),z-index等 (中文(简体) ).#medassist-open-btn按钮元素本身。 用于大小,背景,框影,边框线等.
window.EkaMedAssist.init({
agentId: "your-agent-id",
customLauncherStyles: `
@media (max-width: 991px) {
:host {
right: auto;
left: 50%;
bottom: 47px;
transform: translateX(-50%);
}
}
@media (max-width: 767px) {
:host { bottom: 34px; }
}
`,
});
这只会影响发射机按钮——点击打开的聊天面板不受影响.
侧面板模式
display-mode="side_panel" 将聊天停靠在固定宽度而不是浮动的取景口边缘上。 在移动宽的取景口上,部件会像其他模式一样回到其移动布局.
<eka-medassist-widget
agent-id="your-agent-id"
display-mode="side_panel"
side-panel-mode="push"
side-panel-width="400"
side="right"></eka-medassist-widget>
side-panel-mode 选择面板与您页面的关系 :
overlay– 面板浮出页面上. 页面上没有任何动作.push(默认) — 页面被移到一边, 这样面板就不会覆盖它 。 打开加载器时将样式表注入文档<head>添加eka-medassist-pushed类改为<body>;关闭时,两者再次被取出,使页面保持原样.
被注入的样式表有两件事:
body.eka-medassist-pushed { margin-right: 400px; transition: margin 300ms ease; } /* margin-left when side="left" */
body.eka-medassist-pushed > * { max-width: 100%; }
比值会回流出正常的入流内容. 这个 max-width cap 使视图大小的应用程序根(width: 100vw尾风 w-screen)为: 直接子女 <body> 缩放 <body> 而不是在面板下滑动。 它不会触摸 position: fixed 要素和a min-width 你还是能赢.
如果您的取景口大小的根坐落在一个包件元素内,则盖无法到达. 相对于其父母的大小(w-full 改为 w-screen),或明确减去面板宽度:
/* An app shell that must stay 100vw when the panel is closed */
.app-shell {
width: calc(100vw - var(--eka-medassist-panel-width, 0px));
transition: width 300ms ease;
}
主办分析活动
部件从不与 GTM / gtag 说话 / dataLayer 自己来 主机页面通过定义全局选择 window.trackWidgetEvent(name, detail); 部件称它,主机向自己的分析堆栈转发任何它想要的东西。 没有这个功能, 部件就一无所获 . detail 实值 { sessionId, ...extra } 并且只携带非敏感识别符——从不发短信、用户数据或电话号码. sessionId 仅当一个全新的会话仍在创建中时被省略.
定义加载器脚本运行前的函数:在它存在前已发射的事件被丢弃,而不是排队.
启动
name | 额外 detail | 何时 |
|---|---|---|
session_error | { reason, status?, closeCode? } | 某事使用户无法聊天. 失败者. reason 实值 "<category>:<code>",比如说. connection_failed:network_error 参见以下类别. |
connection_established | { resumed } | 会话已经建立并连接了——用户可以发送消息. 每次打开每个会话的部件 ID . resumed 实值 true 当一个已有会话再次被取出(重新装入,或从历史开始的过去聊天)时, false 为新创造出的人. |
session_error 类别( reason 在结肠之前:
| 类别 | 结肠后代码 | 何时 |
|---|---|---|
auth_failed | SDK恢复原因(AUTH_EXPIRED, (中文(简体) ), SESSION_FORBIDDEN)或服务器的错误代码. status 为401/403. | 证书被拒绝: 令牌交换或刷新失败, 或者服务器回答 401/403. |
session_failed | 服务器错误代码, 恢复原因( E)SESSION_NOT_FOUND, (中文(简体) ), RETRY_LATER),是一个波段编码(session_not_found或SDK分类. | 会议无法创建、恢复或保留. |
connection_failed | NETWORK_ERROR (牵引失败), timeout (请求超时), CONNECTION_ERROR,或套接字/流断开原因(network_error, (中文(简体) ), server_closed, (中文(简体) ), authentication_error, (中文(简体) ), timeout, (中文(简体) ), max_reconnect_attempts与 closeCode。 。 。 . | 运输无法到达或下降. |
SDK错误仅在聊天未连接时被报告;之后的错误(feedback, history, recording)并不是启动失败.
参与
这些回答是"访客在这次访问中是否与机器人互动". 喜欢 connection_established,每个值就像一个页面视图:每次打开每个会话代码的部件,所以关闭机器人并再次打开它们。 他们再次为复会开火——一个继续老式聊天的回归用户算作一种互动——而且每个用户都携带 resumed (意思是说) connection_established),因此两者可以在漏斗中分出. 没有发送后续消息的事件 .
name | 额外 detail | 何时 |
|---|---|---|
first_message_sent | { resumed } | 部件打开后发送的第一封信件( Enter, 发送按钮, 或问候建议), 即使恢复的笔录已经保存了更早的信息 . |
first_bot_reply | { resumed, messageId } | 第一个在部件打开后开始渲染的助手回复 。 静地问候不算数. |
开始一个新的聊天会创建一个新的会话 ID,所以所有三个里程碑都再次为它起火 resumed: false。 。 。 .
漏斗 : connection_established → first_message_sent → first_bot_reply 每次访问,不论会议是否恢复 resumed 比较新来客和回客.
事件名称为蛇 case;主机在转发时会添加自己的前缀(例如. eka_session_error) (中文(简体) ).
window.trackWidgetEvent = (name, detail) => {
window.dataLayer?.push({ event: `eka_${name}`, ...detail });
};
是什么推力不能移动, 和钩处理它
position: fixed 元素(粘接头,横幅, inset: 0 overlays)被定位在取景口上,因此没有外出样式表可以移动. 当面板打开时,加载器会公布它所做的一切,以便你自己的CSS或JS能够遵循:
body.eka-medassist-pushed-上课<body>被推倒的时候.--eka-medassist-panel-width- 自定义财产<html>,比如说.400px关闭删除 .--eka-medassist-panel-side- 自定义财产<html>, (中文(简体) ),right或者说left关闭删除 .eka-medassist:side-panel-push– 说吧 –window事件,detail: { pushed: boolean, width: number, side: "left" | "right" }. 公开开火(pushed: true)和关闭(pushed: false) (中文(简体) ).window.EkaMedAssist.onSidePanelPushChange(pushed, widthPx, side)- 和召回的信号一样EkaMedAssist.onClose。 。 。 .
给自定义属性 a 0px 倒置后, 当面板关闭时, 同一规则是正确的 :
/* A fixed header that should stop at the panel edge instead of running under it */
.site-header {
position: fixed;
top: 0;
left: 0;
right: var(--eka-medassist-panel-width, 0px);
transition: right 300ms ease;
}
window.addEventListener("eka-medassist:side-panel-push", (e) => {
const { pushed, width, side } = e.detail;
// e.g. store in app state and offset fixed chrome / recompute a canvas
});
客户工具
赋予运行的代理函数 在您的页面中 (读取或编辑您的应用程序状态). 页面宣布它们; 后端告诉 LLM 它们存在; 当 LLM 调用一个时, SDK 运行您 run 然后把结果发回来 声明遵循MCP Tool 形状; 仅 name / description / inputSchema / outputSchema / annotations 离开页面 run 从来没有.
EkaMedAssist.init({
agentId: "<agent-id>",
tools: [
{
name: "read_note",
description: "Read the note the user has open.",
inputSchema: { type: "object", properties: { section_keys: { type: "array", items: { type: "string" } } } },
annotations: { title: "Reading the note", readOnlyHint: true },
run: async (input, ctx) => {
ctx.progress({ message: "Collecting sections…" });
return { sections: getSections(input.section_keys) }; // plain object → structured result
},
},
],
});
// Replace the list at any time (before or after the widget opens):
EkaMedAssist.registerTools([...]);
规则:
run必须在呼叫时读取活页状态——工具注册一次并重新使用.- 返回普通对象( 变成)
structuredContent)或完整的MCPCallToolResult。 。 。 . - 报告故障时,模型应投出
Error与code(字符串)和可选data(对象);变成{ isError: true, structuredContent: { code, message, ...data } }。 。 。 . annotations.title工具运行时在回复泡上显示的标签;ctx.progress({ message })更新它现场.ctx.signal超时中止( e)timeoutMs,默认 30 s),服务器取消,或会话结束.- Iframe 嵌入式中不支持( 函数不能跨帧) .
- 需要部件
0.2.x(React-SDK架构). 遗产0.1.x部件忽略tools。 。 。 .
议定书细节: docs/client-tools-plan.md 在回购。 发音: test-client-tools.html。 。 。 .
环境
SDK舰只拥有生产后端. 这个 environment 属性 / init({ environment }) 用于保存
向后兼容但除此以外的任何值 production 被忽略; 指向另一个后端 base-url 编号 :
init({ baseUrl })。 。 。 .
如何运作
- 初始负载 - 脚本注册自定义元素
<eka-medassist-widget>。 。 。 . - 按钮 - 元素显示一个浮动按钮(或全视图,如果
display-mode="full") (中文(简体) ). - 懒惰负载 - 在第一个打开时,脚本取取部件JS和CSS(来自同一来源或来自
https://cdn.jsdelivr.net/npm/@eka-care/medassist-widget@latest/dist/(默认情况下). - 隔离 – 部件运行在Shadow DOM内部,以避免风格和脚本冲突.
使用您自己的部件资产( 例如, 建起后) @eka-care/medassistance-widget (英语)),主机 medassist-widget.js 财务报告和审定财务报表 medassist-widget.css 并通过 data-widget-assets 属性 :
<script
src="/path/to/widget-embed/index.js"
data-widget-assets="/path/to/widget-assets/"
async></script>
文件结构
widget-embed/
├── dist/
│ ├── index.js # Loader and custom element
│ ├── iframe.js # Optional iframe helper
│ └── iframe.html # Optional iframe template
├── assets/
│ └── bot-icon.svg # Sample icon for the test pages (not a runtime default)
└── README.md
浏览器支持
- 克罗姆、火狐、萨法里、边缘(最晚)
- 需要自定义元素、阴影 DOM 和 ES6+
发展
构建软件包 :
npm run build
要在本地建立和捆绑部件资产 :
npm run build:with-widget
(需要先建部件包 。)
整合实例
反应
import { useEffect } from "react";
function App() {
useEffect(() => {
const script = document.createElement("script");
script.src = "https://cdn.jsdelivr.net/npm/@eka-care/medassist-widget-embed@latest/dist/index.js";
script.async = true;
document.body.appendChild(script);
}, []);
return (
<div>
<h1>My App</h1>
<eka-medassist-widget agent-id="your-agent-id" />
</div>
);
}
阴道
<template>
<div>
<eka-medassist-widget :agent-id="agentId" />
</div>
</template>
<script>
export default {
data: () => ({ agentId: "your-agent-id" }),
mounted() {
const script = document.createElement("script");
script.src = "https://cdn.jsdelivr.net/npm/@eka-care/medassist-widget-embed@latest/dist/index.js";
script.async = true;
document.body.appendChild(script);
},
};
</script>
解决问题
- 未显示部件 - 检查
agent-id,确保加载器脚本加载(Network tab),并检查控制台是否出错. - 资产 404 - 如果使用自营资产,确保
medassist-widget.js财务报告和审定财务报表medassist-widget.css在给出的路径中服务data-widget-assets(或使用默认的CDN).
许可证
麻省理工学院