Teleop(超视距遥操)API · JS / 浏览器
Teleop(超视距遥操)API · JS / 浏览器
⚠️ 尚未上线:本能力为 v1.5.0-SNAPSHOT 开发中特性,接口与协议可能调整,正式发布前请勿用于生产环境。
v1.5.0。本页列出 JS SDK 的公开 TypeScript API。wire 协议、事件类型、错误码与 Java v1.5.0 · Teleop API 一致;差异集中在回调模型(无回调类,走
message事件)与浏览器鉴权 / 心跳(服务端代理)。
与原生 SDK 的差异
| 差异点 | Java / Android / iOS | JS(浏览器) |
|---|---|---|
| 推音频 | appendAudioDelta(eventId, base64[, gain]) | sendAudio(base64, eventId?, gain?),eventId 缺省用 startAudio 返回值 |
| 结束音频 | doneAudio(eventId) | finishAudio(eventId?) |
| 探活 | keepalive(cb, timeout) | keepAlive()(无回调、无 timeout 参数) |
| ACK | TeleopEnterCallback / TeleopExitCallback 等回调类 | 无;sdk.on('message') 里按 type === "*_ack" 判读 |
| 鉴权 | SDK 直接带 X-App-* 头 | authProvider 回调向同源服务端换签名代理 URL |
| 心跳 | 协议级 Ping | JSON {type:"ping"},服务端代理转协议级 Ping |
| ID 生成 | IdGenerator.generateTeleopId() | 构造 TeleopSession 时自动生成 teleop_<hex>;sdk.newEventId() 生成 eventId |
导入
ts
import {
createAgentSdk,
AgentSdk,
AgentConnection,
KeepAliveController,
TeleopSession,
AgentEventType,
AgentPolicy,
systemInfoSnapshot,
systemInfoDescription,
sendSdkMetaReport,
} from 'linksoul-agentsdk';
import type {
AgentSdkOptions,
AuthProvider,
ConnectionEvents,
ConnectionOptions,
KeepAliveOptions,
SocketFactory,
SocketLike,
TeleopOptions,
TeleopAck,
SystemInfoSnapshot,
} from 'linksoul-agentsdk';
类图
text
createAgentSdk(appId, options) → AgentSdk
AgentSdk
├── static create(appId, options) → AgentSdk // 按 appId 单例
├── static get(appId) → AgentSdk | undefined
├── static listAppIds() → string[]
├── on(event, listener) → () => void // 返回取消订阅函数
├── connect() → Promise<void>
├── close() → void
├── release() → void // close + 移出单例表
├── createTeleopSession(options) → TeleopSession
├── send(message) → void
└── newEventId() → string // event_<base36>_<seq>_<hex>
TeleopSession
├── constructor(sdk, { agentId, teleopId? })
├── enter() → string(eventId)
├── startAudio(param?) → string(eventId)
├── sendAudio(base64, eventId?, gain?) → void
├── finishAudio(eventId?) → void
├── keepAlive() → string(eventId)
└── exit() → string(eventId)
createAgentSdk / AgentSdk
ts
export function createAgentSdk(appId: string, options: AgentSdkOptions): AgentSdk;
export type AgentSdkOptions = ConnectionOptions;
export class AgentSdk {
readonly connection: AgentConnection;
readonly appId: string;
readonly options: AgentSdkOptions;
static create(appId: string, options: AgentSdkOptions): AgentSdk; // 同 appId 复用实例
static get(appId: string): AgentSdk | undefined;
static listAppIds(): string[];
on<K extends keyof ConnectionEvents>(event: K, listener: (value: ConnectionEvents[K]) => void): () => void;
connect(): Promise<void>;
close(): void;
release(): void;
createTeleopSession(options: TeleopOptions): TeleopSession;
send(message: Record<string, unknown>): void;
newEventId(): string;
}
ConnectionOptions / AuthProvider
ts
export type ConnectionOptions = {
authProvider: AuthProvider;
socketFactory?: SocketFactory; // 可注入自定义 WebSocket(如 Node 侧 ws,测试用)
reconnect?: boolean | { delayMs?: number }; // 默认开启,固定 3000ms
keepAlive?: KeepAliveOptions;
};
export type AuthProvider = () => Promise<{ url: string; protocols?: string | string[] }>;
authProvider 在每次 connect() 与每次自动重连时被调用,需返回一个已鉴权的(通常指向同源代理的)WebSocket URL。
TeleopSession
ts
export type TeleopOptions = { agentId: string; teleopId?: string };
export type TeleopAck = { teleopId: string; eventId: string; code: number; message?: string };
export class TeleopSession {
readonly agentId: string;
readonly teleopId: string; // 未传时自动生成 teleop_<hex>
constructor(sdk: AgentSdk, options: TeleopOptions);
enter(): string; // 发 teleop.enter,返回 eventId
startAudio(param?: Record<string, unknown>): string; // 发 teleop_audio.start,返回并记住 eventId
sendAudio(audioBase64: string, eventId?: string, gain?: number): void; // 发 teleop_audio.delta(含 audio + audioLen + gain);未 startAudio 先调会抛错
finishAudio(eventId?: string): void; // 发 teleop_audio.done,清空内部 audioEventId;未 startAudio 先调会抛错
keepAlive(): string; // 发 teleop.keepalive,返回 eventId
exit(): string; // 发 teleop.exit,返回 eventId
}
- 所有方法同步执行(内部
sdk.send()立即经开着的 WebSocket 发出),返回string(eventId)或void,不返回 Promise; sendAudio会就地解码 base64 计算audioLen(解码后字节数)一并发出;可选gain为音频增益倍数,默认1.0,有效范围(0, 10](<=0归一为1.0,>10截断为10.0),随消息gain字段下发;- 无 per-session 事件回调;
TeleopAck类型仅用于描述下行 ACK 的字段形状(teleopId/eventId/code/message),实际从sdk.on('message')解析。
下行 ACK 判读
JS SDK 不提供回调类。在 sdk.on('message') 里按 type 判读:
ts
sdk.on('message', ({ data }) => {
let msg: { type: string; code?: number; teleopId?: string; eventId?: string; msg?: string };
try { msg = JSON.parse(typeof data === 'string' ? data : ''); } catch { return; }
switch (msg.type) {
case AgentEventType.TeleopEnterAck: /* msg.code === 0 成功 */ break;
case AgentEventType.TeleopKeepaliveAck: /* msg.code !== 0 视为离线 */ break;
case AgentEventType.TeleopExitAck: /* 清理 */ break;
}
});
code 语义与原生一致:0 成功;-1 服务端拒绝 / 机器人离线。
ConnectionEvents
ts
export type ConnectionEvents = {
connected: void;
disconnected: { willReconnect: boolean };
reconnecting: { attempt: number };
message: { data: unknown };
sent: { data: Record<string, unknown> };
error: Error;
keepalive: { state: 'idle' | 'probing' | 'healthy' | 'timeout'; probes: number };
};
KeepAliveOptions(连接层心跳,非遥操 keepAlive)
ts
export type KeepAliveOptions = {
readIdleMs?: number; // 默认 20000:无下行超过此时长进入探测
probeIntervalMs?: number; // 默认 1000:探测 ping 间隔
maxProbes?: number; // 默认 3:连续探测次数
createPing?: (sequence: number) => string; // 默认 JSON.stringify({type:'ping', sequence})
};
注意区分:这里的连接层 keep-alive 是保活 WebSocket;而
TeleopSession.keepAlive()是探测机器人是否在线,两者不同。
事件类型与策略
ts
export const AgentEventType = {
TeleopEnter: 'agentsdk.teleop.enter',
TeleopEnterAck: 'agentsdk.teleop.enter_ack',
TeleopAudioStart: 'agentsdk.teleop_audio.start',
TeleopAudioDelta: 'agentsdk.teleop_audio.delta',
TeleopAudioDone: 'agentsdk.teleop_audio.done',
TeleopKeepalive: 'agentsdk.teleop.keepalive',
TeleopKeepaliveAck: 'agentsdk.teleop.keepalive_ack',
TeleopExit: 'agentsdk.teleop.exit',
TeleopExitAck: 'agentsdk.teleop.exit_ack',
SdkMetaReport: 'agentsdk.sdk_meta.report',
Error: 'agentsdk.error',
} as const;
export const AgentPolicy = {
Active: 'active',
Passive: 'passive',
Teleop: 'teleop',
} as const;
wire 结构
上行 enter / keepalive / exit:
json
{
"type": "agentsdk.teleop.enter",
"agentId": "<agentId>",
"teleopId": "teleop_xxxxxxxxxxxxxxxxxxxxx",
"eventId": "event_xxxxxxxxxxxxxxxxxxxxx",
"agentMode": "teleop"
}
startAudio(param 扁平放入):
json
{
"type": "agentsdk.teleop_audio.start",
"agentId": "<agentId>",
"teleopId": "teleop_xxxxxxxxxxxxxxxxxxxxx",
"eventId": "event_xxxxxxxxxxxxxxxxxxxxx",
"agentMode": "teleop",
"param": { "role": "male", "threshold": 0 }
}
sendAudio(delta,含 audioLen / gain):
json
{
"type": "agentsdk.teleop_audio.delta",
"agentId": "<agentId>",
"teleopId": "teleop_xxxxxxxxxxxxxxxxxxxxx",
"eventId": "event_xxxxxxxxxxxxxxxxxxxxx",
"agentMode": "teleop",
"audio": "<base64 chunk>",
"audioLen": 1920,
"gain": 1.0
}
audioLen 是解码后的字节数,供服务端做完整性 / QoS 校验;业务侧无需理会。
SDK meta 上报
ts
export function sendSdkMetaReport(sdk: AgentSdk, appId: string): void;
export function systemInfoSnapshot(): SystemInfoSnapshot;
export function systemInfoDescription(): string;
export interface SystemInfoSnapshot {
readonly os: string;
readonly osVersion: string;
readonly arch: string; // 浏览器恒为 "browser"
readonly macAddress: string; // 无真实 MAC,用 localStorage 持久化的 client_<hex>
readonly username: string; // 浏览器恒为空串
}
每次 connected(含重连)SDK 自动调用 sendSdkMetaReport,发送 agentsdk.sdk_meta.report(sdkLanguage: "js")。上报失败被静默吞掉,不影响主流程。