只读aliaspackage.json#heybox.companions 中声明的 alias。
可选 只读attachments声明并获 Host 支持 attachments 时存在。
只读capabilities当前审核版本实际开放给 Session 的能力集合。
只读idHost 为当前活动进程分配的 opaque Session id。
可选 只读notifications声明并获 Host 支持 notifications 时存在。
只读state当前状态;退出后固定为 exited。
可选 只读stdio声明并获 Host 支持 stdio 时存在。
只读target当前 Session 使用的目标平台。
订阅当前 Companion Session 的一次性退出结果。
接收 CompanionExit 的同步函数。必须是 function;传入其他值会在请求前
同步抛出 INVALID_PARAMS。
取消该函数引用的订阅函数。Session 尚未退出时,调用后不再收到未来退出事件;同一 函数引用重复注册只保留一个订阅,取消函数可重复调用。Session 已退出时,handler 会在本次注册 调用中同步收到已保存的退出结果,并返回一个无操作取消函数。
HbMiniProgramSDKError 仅当 handler 不是函数时同步返回 INVALID_PARAMS;该方法
不发送 bridge 请求,不检查权限、Host capability、controller ownership,也不会因 Session 退出、
事件源缺失或 Host 错误返回 Promise rejection。
未来事件由当前 proxy 的本地 Set 监听集合派发,退出处理完成后集合会清空;每个 proxy 对同一
Session 只派发一次退出。退出 handler 与 onStateChange('exited') 在 SDK 已将 state 置为
'exited'、并 resolve 同一个 waitForExit() Promise 后同步
执行。handler 抛出的同步异常不会被 SDK 捕获,可能阻断同次退出事件中尚未执行的其他 handler;
它不会撤销已经确定的 waitForExit() 结果。
onExit() 的同步回放只适用于 SDK 已经收到并保存退出事件的 proxy。若 Host 没有接入可选的
Session event source,或 SDK / 页面在退出事件到达前被销毁,注册不会轮询或主动查询,handler
可能永远不会调用;页面应在组件销毁时调用仍有效的取消函数。controller ownership 丢失只触发
onOwnershipLost(),不触发 onExit(),因为进程可能仍在运行。
已退出时的同步回放发生在注册调用栈内:如果 handler 本身抛错,该异常会直接从 onExit() 调用
冒出,调用方应在注册外层捕获。若需要等待风格且不需要取消订阅,使用
waitForExit();它与 onExit() 观察同一个退出结果。
V1 真实 Session 仅支持新 PC Host 的 Windows x64 与 macOS arm64;Browser Dev Host Fake 提供 确定性退出事件。其他平台或缺少事件源的集成不会提供回调重放或事件轮询 fallback。
import hbSDK from '@heybox/hb-sdk'
const session = await hbSDK.companion.getActiveSession('runner')
if (session) {
const stop = session.onExit(exit => {
if (exit.reason === 'exited') {
renderExitCode(exit.exitCode)
} else {
renderTermination(exit.reason, exit.exitCode)
}
})
// ownership 丢失不代表退出;它只应停止新的控制调用。
const stopOwnership = session.onOwnershipLost(() => disableCompanionControls())
try {
await doPageWork()
} finally {
stop()
stopOwnership()
}
}
running 到 exited。订阅当前 Runtime 丢失 Companion Session controller 的事件。
控制权从当前 Runtime 转移给其他 Runtime / 页面时调用的无参同步 CompanionOwnershipLostHandler。它不接收新 generation、Session ID、退出原因或错误对象。
同步返回取消订阅函数。调用后仅移除当前 SDK proxy 的本地 handler,不释放 controller、 不停止进程、不关闭 stdio,也不向 Host 发送 unsubscribe;重复调用取消函数安全且不会抛错。 相同函数引用重复注册按 Set 语义只保留一项,任一对应取消函数都会移除该项。
HbMiniProgramSDKError handler 不是函数时同步抛出 INVALID_PARAMS。注册本身
不发送 bridge 请求,因此不会因权限、Session 已退出、当前已失去 ownership 或 Host event source
缺失而拒绝。
ownership lost 不是进程退出:Session 的 state 仍可能是 'running',
waitForExit() 继续等待同一进程,onExit() 不会因本事件
触发。收到通知后,旧 proxy 的 write()、closeStdin()、terminate()、Attachment 和
Notification 控制操作都会在本地以 COMPANION_SESSION_OWNERSHIP_LOST 拒绝;Host 仍会用私有
controller generation 做最终校验。输出、退出和 ownership 事件的先后由 Host 决定,不能用本
回调判断进程何时终止。
Runtime 只接受 Session ID 匹配且 controllerGeneration 为非负 safe integer 的合法
companion.session.ownershipLost 事件。SDK 只在事件 generation 等于当前 proxy generation 且
proxy 仍标记为拥有 controller 时调用 handler;旧 generation、重复事件或已退出/已丢失控制权的
proxy 会被静默丢弃。该事件触发时 SDK 先把本地 ownership 标记为 false,再同步遍历当前 handlers。
SDK 不捕获 handler 的同步异常,也不会 await handler 返回的 Promise;业务应自行隔离异常。
通过 companion.getActiveSession 取得同一 Session 的更高 generation 时,SDK 会复用同一个 proxy、将 ownership 恢复为 true、重置 output sequence 水位,并保留已注册的 handler;之后新的 ownership-lost 事件仍可再次触发同一订阅。 页面 reload 会创建新的 SDK/proxy,旧订阅不会跨页面保留。
自定义 Host 若未提供 Session 事件源,本方法仍可注册,但不会收到 ownership、输出或退出
事件,也没有轮询 fallback;控制请求仍可能以 COMPANION_SESSION_OWNERSHIP_LOST 失败。
业务不能把“尚未收到通知”当作仍拥有控制权。
不要求新的可信用户手势,也不改变权限或 Session 生命周期。它适用于在 ownership 丢失后立即 禁用按钮、停止发送新命令并显示恢复入口;不要在回调中自动抢占 controller 或无条件重发可能已 提交的 stdin/terminate 请求。
import hbSDK from '@heybox/hb-sdk'
const session = await hbSDK.companion.getActiveSession('runner')
if (session) {
const stopOwnership = session.onOwnershipLost(() => {
// 这不是退出通知;先停止新控制调用,进程仍可能运行。
disableCompanionControls()
showReacquireButton()
})
const stopExit = session.onExit(exit => renderExit(exit))
try {
await runPageLifetime()
} finally {
stopOwnership()
stopExit()
}
}
订阅当前 Session 的生命周期状态变化。
收到新状态时同步调用的函数。当前唯一的回调参数是 'exited';不会在注册时
立即收到当前的 'running',也不会收到 ownership 转移或 stdin 关闭通知。
取消当前 handler 的同步函数。可调用一次或多次;取消后不再接收未来状态变化,不会
终止 Session、关闭 stdio 或取消其他 handler。相同函数引用重复注册按 Set 语义只保留一项,
任一对应取消函数都会移除该项。
HbMiniProgramSDKError handler 不是函数时同步抛出 INVALID_PARAMS。订阅本身
不发送 bridge 请求,因此不会因为权限、Host operation、Session 已退出或 controller 状态异步拒绝。
注册只是本地订阅,不会查询或回放 session.state。要初始化 UI,应立即读取
session.state,再注册 handler;对于已经是 'exited' 的 proxy,注册本方法不会回放,若需要
退出结果应改用 onExit()(它会在已收到退出后同步回放)或
waitForExit()(已退出时会 resolve 保存的结果)。
实际状态迁移只有 Host/Runtime 收到当前 Session ID 的合法 companion.session.exit 事件时才会发生:
proxy 的 state 从 'running' 变为 'exited',等待 Promise resolve,然后依次派发本 handler
与 onExit handler,最后清理状态和输出订阅。若 Host 没有提供可选的 Session event source,
本方法仍可注册成功,但不会主动收到变化;state 可能继续显示 'running',
waitForExit() 也可能一直 pending。SDK 没有轮询或 WebSocket fallback。
handler 的同步异常不会被 SDK 捕获或转换:由于状态 handler 按 Set 顺序同步遍历,异常可能阻止
后续状态 handler、onExit handler 和退出后的订阅清理。请在 handler 内捕获业务异常,或使用
不会抛出的薄回调把错误交给自己的异步日志通道。handler 返回的 Promise 同样不会被等待;rejected
Promise 需由业务自行处理。
Session ownership 丢失不会改变 state,进程仍可能是 'running';收到
onOwnershipLost() 后应停止控制调用,需要恢复时由
companion.getActiveSession 取得新 controller。
新 generation 复用同一 proxy 时,本地状态 handler 保持注册,但只有后续真实退出事件才会派发 'exited'。
组件销毁时应显式调用返回的取消函数,避免把页面闭包留在活动 Session 上。
import hbSDK from '@heybox/hb-sdk'
const session = await hbSDK.companion.getActiveSession('runner')
if (session) {
// 先读取当前值,再订阅未来的 running -> exited 迁移。
console.log(session.state)
const stopState = session.onStateChange(state => {
console.log(state)
})
const stopExit = session.onExit(exit => {
console.log(exit)
stopState()
})
window.addEventListener('pagehide', () => {
stopState()
stopExit()
}, { once: true })
}
请求 Host 强制结束当前 Session 的完整受管进程树。
当前 controller 对应的 Host terminate 请求成功后以 undefined resolve。返回值不包含
CompanionExit、退出码或已结束的进程数量,也不等待 SDK 收到独立的 Session exit 事件;
terminate 响应与 exit 事件可能以任意顺序到达。需要确认最终退出原因时应同时使用
waitForExit() 或 onExit()。
HbMiniProgramSDKError 当前 proxy 已知 Session 已退出时以
COMPANION_SESSION_EXITED 拒绝;当前 Runtime 已失去 controller 时以
COMPANION_SESSION_OWNERSHIP_LOST 拒绝。本地检查与 Host 执行之间仍存在竞态,Host 会根据私有
Session ID 与 controller generation 再次拒绝已退出进程或过期 controller。
HbMiniProgramSDKError Host 无法终止完整进程树时以
COMPANION_TERMINATE_FAILED 拒绝;进程已异常退出、因输出上限结束或 Session 状态已变化时还
可能返回 COMPANION_PROCESS_CRASHED、COMPANION_OUTPUT_LIMIT、
COMPANION_SESSION_EXITED 等对应稳定 Companion 错误码。
HbMiniProgramSDKError 当前运行快照缺少或未启用 companion 权限时返回
PERMISSION_NOT_IN_SNAPSHOT / PERMISSION_DENIED;Host 未开放
companion.session.terminate 时返回 METHOD_FORBIDDEN,旧 Runtime 也可能返回
METHOD_NOT_FOUND。未知 Host 失败会脱敏为 COMPANION_HOST_FAILED;SDK / Runtime 已终止、
不可用或请求超时时还可能返回 SDK_DESTROYED、RUNTIME_UNAVAILABLE、REQUEST_TIMEOUT。
这是强制、非优雅终止,不会先发送业务 shutdown 消息,不会隐式调用 closeStdin(),也不保证 Companion 有机会刷新业务数据、清空 stdout/stderr、完成附件写入或运行自己的退出清理。Host 负责终止由该 Session 监管的完整进程树, Mini-program 不能选择 PID、只杀子进程、发送自定义 signal 或取得原生进程句柄。
正常业务退出应优先使用 Companion 自己定义的 stdio 协议:通过
write() 发送带幂等 ID 的 shutdown frame,按协议决定是否
closeStdin(),再用 waitForExit() 等待进程自行退出。terminate() 适合用户明确执行“强制停止”、
进程无响应、业务协议不可用或 Host 风险处置;不要把它当作 graceful close、页面卸载清理或
closeStdin() 的同义词。页面 hide、reload 本身不会自动调用本方法。
terminate() 是每个 CompanionSession 都有的核心 controller 操作,不依赖可选的
'stdio'、'attachments' 或 'notifications' capability;没有 session.stdio 的 Session 仍可
强制结束。它属于已声明并经平台批准的 companion 高风险能力,但调用本身不要求新的可信用户
手势,也不展示 prepare / launch 授权弹窗。
只有当前 controller 可以终止进程。session.state === 'running' 不证明当前 Runtime 仍持有
controller;其他 Runtime 通过
companion.getActiveSession 取得控制后,旧
proxy 的本方法会以 COMPANION_SESSION_OWNERSHIP_LOST 失败。失去 controller 不影响同一 proxy 的
waitForExit():它仍可观察进程由新 controller、权限撤销或 Host shutdown 导致的最终退出。
SDK 不维护“termination requested”状态,也不会合并、缓存或短路重复调用。在 exit 事件到达前
重复调用会再次向 Host 发送 terminate;不保证幂等,Host 可以再次确认,也可以返回
COMPANION_SESSION_EXITED / COMPANION_TERMINATE_FAILED。请求超时或连接中断时无法从错误判断
Host 是否已经执行终止,因此不要无条件自动重试;应等待 exit 事件或通过明确的恢复流程重新取得
Session 状态。
terminate() resolve 不会直接把本地 session.state 改成 'exited'。SDK 只在收到合法的
companion.session.exit 事件后更新状态、resolve waitForExit() 并调用 onExit();Host 通常会把
强制终止报告为 { reason: 'terminated' },但调用方应以实际 CompanionExit 为准。若 Host
没有提供 Session 事件源,terminate 请求仍可能成功,而 state 不更新、waitForExit() 一直
pending;Mini-program 没有轮询 fallback。
V1 真实 Companion Session 仅支持新 PC Host 的 Windows x64 与 macOS arm64;Browser Dev Host
Fake 会立即发出 reason: 'terminated' 的确定性 exit 事件,仅用于 UI 与状态机联调,不代表真实
操作系统的终止时序。其他平台、旧 Host 或未开放 operation 的环境 fail closed。
import hbSDK, { HbMiniProgramSDKError } from '@heybox/hb-sdk'
const session = await hbSDK.companion.getActiveSession('runner')
if (session) {
// 先取得持久的退出 Promise,避免假设 terminate response 与 exit event 的先后顺序。
const exitPromise = session.waitForExit()
try {
await session.terminate()
const exit = await exitPromise
console.log(exit.reason, exit.exitCode)
} catch (error) {
if (
error instanceof HbMiniProgramSDKError &&
(error.code === 'COMPANION_SESSION_EXITED' ||
error.code === 'COMPANION_SESSION_OWNERSHIP_LOST')
) {
console.warn('Session 已退出或控制权已转移')
} else {
throw error
}
}
}
等待 Host 确认当前 Companion Session 的进程终态。
当前 Session proxy 持有的同一个 Promise<CompanionExit>。同一 proxy 每次调用都严格
返回同一个 Promise 实例;第一个有效退出事件到达时以冻结的 CompanionExit resolve
一次。若 Session 已退出,后续调用仍返回该已 fulfilled Promise,并取得同一个退出对象引用。
该方法不接收参数、不执行校验、不发 bridge 请求,调用本身不会同步抛出
HbMiniProgramSDKError,返回的 Promise 也不会因权限、controller ownership、SDK / Runtime
终止或 Host 操作错误而 reject。异常终止通过 CompanionExit 的 reason 作为成功结果表达。
waitForExit() 是纯本地一次性观察器。Session proxy 构造时即创建退出 Promise,不会因每次调用
新建请求、listener、timer 或轮询,也不要求新的可信用户手势。取得该 Session 的 launch() /
getActiveSession() 仍要求已声明并经平台批准的 companion 权限,但等待本身不重新检查权限。
permission-revoked 是可能 resolve 的退出 reason,不是该 Promise 的 rejection。
SDK 只接受与当前 Session ID 匹配、由 Runtime 校验过的 companion.session.exit 事件。Runtime 会
丢弃未知 reason、缺失 exited.exitCode 或包含非 safe-integer exit code 的非法 Host 事件;SDK
对同一 Session 只处理第一条有效 exit,之后重复事件不会改变结果或再次触发生命周期迁移。退出
对象由 Runtime 与 SDK 分别复制/冻结,不包含 PID、路径、原生句柄、controller generation 或
Host 私有诊断。
Promise resolve 发生在 SDK 把 session.state 置为 exited 后,并且早于同步派发
onStateChange('exited') 与 onExit() handler。任一本地 handler
抛错都不会把已经确定的退出 Promise 改为 rejected。onExit() 适合需要取消订阅或在已退出时
同步回放的回调风格;waitForExit() 适合一次性 await,不需要也不提供 unsubscribe。
Host 的 onSessionEvent 是可选集成 Port。当前支持的新 PC Host 与 Browser Dev Host Fake 会提供
退出事件;自定义/兼容 Host 如果返回 Session 却没有 event source,或者 Runtime/页面在退出事件
到达前被销毁,本 Promise 可能永久 pending。它没有 timeout、AbortSignal、取消方法或主动状态查询
fallback;调用方不能通过取消 await 停止 Host 进程,也不能把 Promise pending 当作进程仍存活。
controller ownership 转移与进程退出是独立状态。收到
onOwnershipLost() 后,控制类 API 会以
COMPANION_SESSION_OWNERSHIP_LOST 失败,但此 Promise 不 resolve/reject,仍等待同一 Host 进程的
exit 事件;通过 companion.getActiveSession
重新取得同一 Session 的新 controller generation 时,同一 proxy 和退出 Promise 继续复用。
页面 reload 会创建新的 SDK/proxy,需要重新取得活动 Session 后重新等待。
terminate() 只请求 Host 强制终止进程,其 Promise 完成不等于
exit 事件已经抵达,也不保证最终 CompanionExit 的 reason。为避免 terminate response 与 exit event 的先后竞态,
先保存 const exitPromise = session.waitForExit(),再调用 terminate(),最后 await 该 Promise。
waitForExit() 本身不能终止、关闭 stdin 或取消 Session;正常退出应优先使用 Companion 自己的
stdio 协议。
V1 真实 Session 仅支持新 PC Host 的 Windows x64 与 macOS arm64。Browser Dev Host 的确定性
Fake 会产生 exited、crashed、output-limit 和 terminated 等测试终态,但不执行真实进程,
不能替代目标系统对 exit code、崩溃和 Host shutdown 的验收。
import hbSDK from '@heybox/hb-sdk'
const session = await hbSDK.companion.getActiveSession('runner')
if (session) {
const exitPromise = session.waitForExit()
console.assert(exitPromise === session.waitForExit())
const stopOwnership = session.onOwnershipLost(() => {
disableCompanionControls()
// ownership 丢失不代表进程退出;继续等待同一个 exitPromise。
})
try {
const exit = await exitPromise
if (exit.reason === 'exited') {
renderProcessExitCode(exit.exitCode)
} else {
renderHostTermination(exit.reason, exit.exitCode)
}
} finally {
stopOwnership()
}
}
受 Host 监管的 Companion 活动进程 Session。
Session 只暴露审核版本 Manifest 声明的能力,不暴露 PID、原生句柄、路径、命令行或环境变量。 页面 reload 不会结束进程;可通过
getActiveSession()重新取得当前 controller。