架构概述 · JS / 浏览器
架构概述 · JS / 浏览器
JS SDK(linksoul-agentsdk)是面向浏览器的 TypeScript SDK(ESM),与 Java v1.5.0 共享同一套 wire 协议。与原生 SDK 最大的结构性差异是:浏览器 WebSocket 无法设置自定义请求头,因此鉴权与心跳都前置到同源服务端代理完成。
系统架构
┌─────────────────────────────────────────────────────────────────────────────┐
│ 灵心平台 (LinkSoul) │
│ ┌───────────────────────┐ ┌───────────────────────┐ │
│ │ LinkskyGateway │ ◄──────► │ 交互网关 (Gateway) │ │
│ │ (二开接入网关) │ Bridge │ 连接机器人终端 │ │
│ └───────────▲───────────┘ └───────────▲───────────┘ │
└──────────────┼───────────────────────────────────┼───────────────────────────┘
│ wss(带 HMAC 五头签名) │
│ │
┌──────┴──────┐ ┌──────┴──────┐
│ 你的服务端代理 │ │ 机器人终端 │
│ (计算签名) │ │ 音频/视频/动作│
└──────▲──────┘ └──────────────┘
│ 本地代理 URL(无签名要求)
│
┌──────┴──────┐
│ 浏览器 (JS SDK)│ TeleopSession / ExtSkillSession
└──────────────┘
模块结构
linksoul-agentsdk/src/
├── agent-sdk.ts # AgentSdk(按 appId 单例)+ createAgentSdk 工厂
├── connection/
│ ├── agent-connection.ts # 连接编排(connect/重连/消息分发)
│ ├── keep-alive.ts # KeepAliveController(应用层保活)
│ └── types.ts # ConnectionOptions / AuthProvider / SocketLike ...
├── teleop/teleop-session.ts # TeleopSession(遥操六方法)
├── ext-skill/ext-skill-session.ts # ExtSkillSession(query / invoke)
├── protocol/events.ts # AgentEventType / AgentPolicy / ArbiterDecision 常量
├── sdk-meta-report.ts # 连接后自动上报 sdk_meta.report
├── system-info.ts # systemInfoSnapshot(无真实 MAC/用户名)
└── random-id.ts # randomHex
连接与鉴权
浏览器 WebSocket 构造器不支持自定义请求头,无法在握手时带 X-App-Id / X-Signature。JS SDK 通过 authProvider 回调把鉴权外包给同源服务端:
const sdk = createAgentSdk(appId, {
authProvider: async () => {
const res = await fetch('/api/ws-auth', { method: 'POST' }); // 服务端用 appSecret 签名
const { url } = await res.json(); // 返回已鉴权的(本地代理)URL
return { url };
},
});
await sdk.connect();
authProvider在每次connect()与每次自动重连时都会被调用;- 返回
{ url, protocols? },url通常指向你服务端的本地代理; appSecret绝不出现在前端代码里。
保活(keepalive)
浏览器无法发协议级 PingFrame,JS SDK 的 KeepAliveController 发的是 JSON 文本 {"type":"ping"},由服务端代理转换成协议级 PingFrame 发给网关,再把 Pong 合成 JSON 回浏览器——这条转换是接入契约必须由代理完成(否则连接握手成功但心跳永远超时)。
重连机制
- 连接失败/断开后自动重连,默认固定
3s(reconnect.delayMs可调); reconnect?: boolean | { delayMs?: number },传false关闭;- 保活探测超时(空闲 20s → 探测 3 次无响应)会主动
close(4000)触发重连。
事件模型
JS SDK 采用 sdk.on(event, listener) 订阅连接级事件,返回取消订阅函数:
| 事件 | 负载 | 说明 |
|---|---|---|
connected | void | 连接成功(自动上报 sdk_meta.report) |
disconnected | { willReconnect } | 连接断开 |
reconnecting | { attempt } | 第 N 次重连 |
message | { data } | 所有下行消息(业务侧 JSON.parse 后按 type 分派) |
sent | { data } | 上行消息 |
error | Error | 连接错误 |
keepalive | { state, probes } | 保活状态机 |
v1.5.0 范围:JS SDK 只内置 Teleop + ExtSkill 两条交互路径。被动(8 种回调)、主动(任务流)尚无公开实现——
agent-sdk.ts不含任何被动回调类或TaskFlowRequest。相关 wire 常量(FunctionCallExpose/FunctionCallArbiter/HistoriesExpose/ArbiterDecision)在protocol/events.ts中预留但未接入分发。详见 被动交互指南 与 主动交互指南。
线程 / 并发模型
浏览器单线程事件循环,无多线程概念:sdk.send() 逻辑同步执行(立即写 WebSocket),异步只体现在 authProvider 与网络 I/O 上。