@heybox/hb-sdk API Reference - v0.9.5
    正在准备搜索索引...

    接口 CompanionSession

    受 Host 监管的 Companion 活动进程 Session。

    Session 只暴露审核版本 Manifest 声明的能力,不暴露 PID、原生句柄、路径、命令行或环境变量。 页面 reload 不会结束进程;可通过 getActiveSession() 重新取得当前 controller。

    interface CompanionSession {
        alias: string;
        attachments?: CompanionAttachments;
        capabilities: readonly CompanionCapability[];
        id: string;
        notifications?: CompanionNotifications;
        state: CompanionState;
        stdio?: CompanionStdio;
        target: CompanionTarget;
        onExit(handler: CompanionExitHandler): () => void;
        onOwnershipLost(handler: CompanionOwnershipLostHandler): () => void;
        onStateChange(handler: CompanionStateChangeHandler): () => void;
        terminate(): Promise<void>;
        waitForExit(): Promise<CompanionExit>;
    }
    索引

    属性

    alias: string

    package.json#heybox.companions 中声明的 alias。

    attachments?: CompanionAttachments

    声明并获 Host 支持 attachments 时存在。

    capabilities: readonly CompanionCapability[]

    当前审核版本实际开放给 Session 的能力集合。

    id: string

    Host 为当前活动进程分配的 opaque Session id。

    notifications?: CompanionNotifications

    声明并获 Host 支持 notifications 时存在。

    当前状态;退出后固定为 exited。

    声明并获 Host 支持 stdio 时存在。

    当前 Session 使用的目标平台。

    方法

    • 订阅当前 Companion Session 的一次性退出结果。

      参数

      返回 () => void

      取消该函数引用的订阅函数。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()
      }
      }
    • 订阅当前 Runtime 丢失 Companion Session controller 的事件。

      参数

      返回 () => void

      同步返回取消订阅函数。调用后仅移除当前 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()
      }
      }

      0.8.1

      windows

      macos

      windows none

      macos none

    • 订阅当前 Session 的生命周期状态变化。

      参数

      • handler: CompanionStateChangeHandler

        收到新状态时同步调用的函数。当前唯一的回调参数是 'exited';不会在注册时 立即收到当前的 'running',也不会收到 ownership 转移或 stdin 关闭通知。

      返回 () => void

      取消当前 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 的完整受管进程树。

      返回 Promise<void>

      当前 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
      }
      }
      }

      0.8.1

      windows

      macos

      windows none

      macos none

    • 等待 Host 确认当前 Companion Session 的进程终态。

      返回 Promise<CompanionExit>

      当前 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()
      }
      }