@heybox/hb-sdk 0.8.1 → 0.8.2-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/README.md +2 -2
  3. package/dist/cli-chunks/{build-DPe1Ycjd.cjs → build-bVThH3Z5.cjs} +4 -4
  4. package/dist/cli-chunks/{context-BSUhAv3Z.cjs → context-DpKqGnjp.cjs} +2 -2
  5. package/dist/cli-chunks/{create-CaiKrGnb.cjs → create-BWC2343y.cjs} +1 -1
  6. package/dist/cli-chunks/{dev-BG1o8Q-0.cjs → dev-t14YpHHY.cjs} +9 -9
  7. package/dist/cli-chunks/{doctor-DutO2P5H.cjs → doctor-BWkrE0Hj.cjs} +1 -1
  8. package/dist/cli-chunks/{index-CKIyipP9.cjs → index-CDtcZVWv.cjs} +15 -15
  9. package/dist/cli-chunks/{index-Bur0U2z1.cjs → index-D3FMcOZq.cjs} +2 -2
  10. package/dist/cli-chunks/{index.esm-BPlpP-O0.cjs → index.esm-BrJBaJWS.cjs} +7 -7
  11. package/dist/cli-chunks/{login-C1JlLEza.cjs → login-DRMl7nFH.cjs} +2 -2
  12. package/dist/cli-chunks/{project-vite-Bd0WzAqQ.cjs → project-vite-CXgdzIYw.cjs} +1 -1
  13. package/dist/cli-chunks/{remote-DTFEf3Dj.cjs → remote-ibQybNiM.cjs} +6 -6
  14. package/dist/cli-chunks/{runtime-permission-env-C2S34ldj.cjs → runtime-permission-env-DiTeD75Q.cjs} +576 -20
  15. package/dist/cli-chunks/{session-zXVkHuhY.cjs → session-CIoBspg-.cjs} +1 -1
  16. package/dist/cli-chunks/{skill-CCB3DyXk.cjs → skill-5labzuWk.cjs} +2 -2
  17. package/dist/cli-chunks/{version-0qwlEyZC.cjs → version-QiVEs76a.cjs} +1 -1
  18. package/dist/cli.cjs +1 -1
  19. package/dist/devtools/browser-dev-host/assets/browser-dev-host-DxzOkljJ.js +101 -0
  20. package/dist/devtools/browser-dev-host/assets/{desktop-app-launch-DOfl5YvO.js → desktop-app-launch-B4KsgItx.js} +1 -1
  21. package/dist/devtools/browser-dev-host/assets/{index-CFr28-0O.js → index-9Nb3XhtI.js} +3 -3
  22. package/dist/devtools/browser-dev-host/index.html +2 -2
  23. package/dist/index.cjs.js +948 -44
  24. package/dist/index.esm.js +948 -44
  25. package/dist/miniapp-publish.cjs.js +536 -30
  26. package/dist/miniapp-publish.esm.js +536 -30
  27. package/dist/protocol.cjs.js +807 -2
  28. package/dist/protocol.esm.js +807 -2
  29. package/dist/vite.cjs.js +184 -1
  30. package/dist/vite.esm.js +184 -1
  31. package/package.json +7 -7
  32. package/skill/references/api-root.md +192 -8
  33. package/skill/references/recipes.md +45 -7
  34. package/skill/skill.json +5 -5
  35. package/types/core/errors.d.ts +33 -9
  36. package/types/core/handshake-state.d.ts +32 -2
  37. package/types/core/singleton.d.ts +265 -6
  38. package/types/miniapp-manifest/bindings.d.ts +65 -0
  39. package/types/miniapp-manifest/schema.d.ts +136 -19
  40. package/types/miniapp-publish/index.d.ts +425 -29
  41. package/types/modules/auth/index.d.ts +159 -5
  42. package/types/modules/cloud/index.d.ts +514 -40
  43. package/types/modules/companion/index.d.ts +1518 -17
  44. package/types/modules/device/index.d.ts +140 -9
  45. package/types/modules/environment/index.d.ts +172 -4
  46. package/types/modules/files/types.d.ts +1396 -21
  47. package/types/modules/navigation/app-pages/types.d.ts +81 -24
  48. package/types/modules/navigation/index.d.ts +230 -7
  49. package/types/modules/network/index.d.ts +297 -26
  50. package/types/modules/share/copy-link.d.ts +35 -5
  51. package/types/modules/share/index.d.ts +210 -0
  52. package/types/modules/share/screenshot.d.ts +23 -5
  53. package/types/modules/share/show-share-menu.d.ts +18 -5
  54. package/types/modules/share/types.d.ts +148 -23
  55. package/types/modules/storage/index.d.ts +139 -9
  56. package/types/modules/ui/index.d.ts +249 -18
  57. package/types/modules/user/get-info.d.ts +29 -8
  58. package/types/modules/user/index.d.ts +157 -0
  59. package/types/modules/user/revoke-authorization.d.ts +26 -2
  60. package/types/modules/user/steam-game-list.d.ts +96 -15
  61. package/types/modules/viewport/index.d.ts +158 -22
  62. package/types/protocol/types.d.ts +19 -1
  63. package/types/vite/index.d.ts +159 -1
  64. package/dist/devtools/browser-dev-host/assets/browser-dev-host-pUcws1MK.js +0 -101
@@ -5,51 +5,1196 @@ import type { FileHandle } from '../files';
5
5
  interface CompanionRequester extends MiniProgramOperationRequester {
6
6
  on<T extends MiniProgramEventName>(eventName: T, handler: MiniProgramEventHandler<T>): () => void;
7
7
  }
8
+ /**
9
+ * `companion.prepare` 的进度与取消配置。
10
+ *
11
+ * @remarks
12
+ * 所有字段均可省略。SDK 会在发送请求前校验 options 必须是非 `null` 且非数组的对象、
13
+ * `signal` 必须符合 `AbortSignal` 接口、`onProgress` 必须是函数;不合法时以
14
+ * `INVALID_PARAMS` 拒绝。
15
+ *
16
+ * @see {@link MiniProgramCompanionModule.prepare | companion.prepare}
17
+ */
8
18
  export interface CompanionPrepareOptions {
19
+ /**
20
+ * 用于向 Host 发送准备取消意图的信号。
21
+ *
22
+ * @remarks
23
+ * 调用前已经 aborted 时,SDK 在发起 prepare 前以 `COMPANION_PREPARATION_CANCELLED`
24
+ * 拒绝。操作在途时触发 signal,SDK 会另发 `cancelPreparation(alias)`,但不会使用普通
25
+ * bridge cancel,也不会仅在页面本地立即 settle;最终结果仍由 Host 的取消与原子提交
26
+ * 竞态决定。
27
+ *
28
+ * 同 alias 的准备由 Host 共享,因此该取消意图针对整项在途准备,不只是移除当前页面的
29
+ * progress observer,其他 joiner 也可能收到取消结果。页面 reload 本身不会触发这个
30
+ * signal,也不会自动取消 Host 操作。需要观察取消请求本身是否失败时,显式 await
31
+ * {@link MiniProgramCompanionModule.cancelPreparation | companion.cancelPreparation}。
32
+ */
9
33
  signal?: AbortSignal;
34
+ /**
35
+ * 准备阶段进度回调。
36
+ *
37
+ * @remarks
38
+ * 回调接收经过 Runtime 校验的 {@link CompanionPrepareProgress}:Host 可能报告
39
+ * `downloading`、`verifying`、`extracting`;下载 `total` 可以省略,其他阶段同时提供
40
+ * `processed` 与 `total`。加入既有操作时,Host 可以先回放最近进度;不保证页面收到每个
41
+ * 中间值。回调抛错会被 SDK 隔离,不会取消 Host 操作或改变 prepare 的最终结果。
42
+ */
10
43
  onProgress?: (progress: CompanionPrepareProgress) => void;
11
44
  }
45
+ /**
46
+ * Companion stdout/stderr 单个原始输出 chunk 的同步回调。
47
+ *
48
+ * @param data - 当前 handler 独占的新 `Uint8Array` 副本。修改它不会改变 Host 事件、其他 handler
49
+ * 收到的数据或后续 chunk;数组只表示本次 transport chunk,不携带 stream、sequence、文本编码或
50
+ * 消息边界。
51
+ * @returns 返回值会被 SDK 忽略。回调应同步消费或复制所需数据;SDK 不会 await 返回的 Promise。
52
+ *
53
+ * @remarks
54
+ * SDK 不执行文本解码、换行处理、JSON 解析或业务 framing。一个字符或业务消息可能跨多个 chunk,
55
+ * 多个消息也可能粘在同一 chunk;只有业务协议明确规定 UTF-8 时才应使用 streaming
56
+ * `TextDecoder`,并仍需自行处理消息边界与跨 controller generation 的重放。
57
+ *
58
+ * 同步抛出的异常会被 SDK 隔离,不会阻止同一 chunk 的其他 handler,也不会阻止内部 output ack;
59
+ * 因为返回值不被 await,异步 handler 的 rejected Promise 不属于该隔离范围,应在回调内部自行捕获。
60
+ *
61
+ * @see {@link CompanionStdio.onStdout}
62
+ * @see {@link CompanionStdio.onStderr}
63
+ */
12
64
  export type CompanionOutputHandler = (data: Uint8Array) => void;
65
+ /**
66
+ * Companion Session 退出时调用的同步回调。
67
+ *
68
+ * @param exit - Runtime 校验并冻结的 {@link CompanionExit} 一次性退出结果。`reason: 'exited'` 时
69
+ * 必有 safe-integer `exitCode`;其他 reason 的 `exitCode` 可能缺省,调用方不应自行补 `0`。
70
+ * @returns 返回值会被 SDK 忽略;回调不会被 await。
71
+ *
72
+ * @remarks
73
+ * 同一 Session 只接受第一条有效退出事件。退出结果不是 controller ownership 转移、stdin 关闭或
74
+ * `terminate()` 请求的返回值;它表示 Host 确认的真实进程终态。回调可能在事件到达时同步执行,
75
+ * 也可能在 Session 已退出后通过 {@link CompanionSession.onExit | onExit()} 注册时同步重放。
76
+ *
77
+ * SDK 不会捕获该回调的同步异常;需要隔离异常时应在 handler 内自行 `try/catch`。因为回调返回值
78
+ * 不会被 await,async handler 的 rejected Promise 也不会由 SDK 接管。
79
+ *
80
+ * @see {@link CompanionExit}
81
+ * @see {@link CompanionSession.onExit}
82
+ * @see {@link CompanionSession.waitForExit}
83
+ */
13
84
  export type CompanionExitHandler = (exit: CompanionExit) => void;
85
+ /** 当前 Runtime 失去 Session controller 时调用的回调。 */
86
+ /**
87
+ * Companion Session controller 转移时调用的无参同步回调。
88
+ *
89
+ * @returns 返回值会被 SDK 忽略;回调不会被 await。同步异常不会由 SDK 隔离,业务应在 handler
90
+ * 内自行捕获;async handler 的 rejected Promise 也不会由 SDK 接管。
91
+ *
92
+ * @remarks
93
+ * 该回调只表示当前 Runtime 不再拥有控制权,不提供新旧 generation、Session ID 或退出原因。
94
+ * 需要恢复控制时调用 {@link MiniProgramCompanionModule.getActiveSession | companion.getActiveSession};
95
+ * 需要知道进程是否退出时使用 {@link CompanionSession.onExit | onExit()} 或
96
+ * {@link CompanionSession.waitForExit | waitForExit()}。
97
+ *
98
+ * @see {@link CompanionSession.onOwnershipLost}
99
+ * @see {@link CompanionSession.onExit}
100
+ * @see {@link CompanionSession.waitForExit}
101
+ */
14
102
  export type CompanionOwnershipLostHandler = () => void;
103
+ /** Session 的生命周期状态;退出后不会回到 `running`。 */
15
104
  export type CompanionState = 'running' | 'exited';
105
+ /**
106
+ * Companion Session 状态变化回调。
107
+ *
108
+ * @param state - 新状态。当前 SDK 只在收到首次合法退出事件时调用 handler 一次,值为 `'exited'`;
109
+ * 初始 `'running'` 不会在注册时回放。
110
+ * @returns 返回值会被 SDK 忽略;回调同步执行,返回的 Promise 不会被等待。
111
+ *
112
+ * @remarks
113
+ * controller ownership 转移、stdin 关闭、输出重放和权限变化都不是状态变化,不会调用本 handler。
114
+ * 需要知道控制权是否仍归当前 Runtime 时使用
115
+ * {@link CompanionSession.onOwnershipLost | CompanionSession.onOwnershipLost()};需要退出原因、
116
+ * exit code 或在退出后注册时的即时回放时使用 {@link CompanionSession.onExit | onExit()}。
117
+ */
16
118
  export type CompanionStateChangeHandler = (state: CompanionState) => void;
119
+ /**
120
+ * 请求 Host 展示的固定类别通知。
121
+ *
122
+ * @remarks
123
+ * 页面只选择语义类别,通知标题、正文、图标、按钮、声音和其他系统展示细节均由 Host 根据当前
124
+ * Mini-program、Companion 与平台规则生成。该对象不是原生 Notification options,也不允许页面
125
+ * 注入任意通知文本。
126
+ */
17
127
  export interface CompanionNotification {
128
+ /**
129
+ * 固定通知类别:`completed` 表示任务完成,`failed` 表示失败,`stopped` 表示已停止,
130
+ * `attention` 表示需要用户关注。Host 负责把类别转换成最终本地化通知内容。
131
+ */
18
132
  category: CompanionNotificationCategory;
19
133
  }
134
+ /**
135
+ * Companion 的标准输入输出能力。
136
+ *
137
+ * 仅当 Manifest 声明 `stdio` 且当前 Host 返回该能力时存在。传输的是原始字节,
138
+ * 不保证一次 write 对应一次 stdout/stderr 回调;业务协议必须自行处理 framing、拆包和重复。
139
+ */
20
140
  export interface CompanionStdio {
141
+ /**
142
+ * 向当前 Companion Session 的 stdin 写入原始字节。
143
+ *
144
+ * @param data - 要写入的 `Uint8Array`。SDK 只复制当前 view 覆盖的字节区间;`byteOffset` 之外的
145
+ * backing buffer 内容不会发送。空 `Uint8Array` 合法并会交给 Host,但不应把空写入当作 flush、
146
+ * EOF 或消息分隔符。
147
+ * @returns Host 确认本次 stdin 写入请求完成后以 `undefined` resolve。该时点不返回写入字节数,
148
+ * 也不表示 Companion 已读取、解析或处理数据,更不保证会产生 stdout/stderr。
149
+ * @throws {@link HbMiniProgramSDKError} `data` 不是当前 realm 的 ArrayBuffer-backed `Uint8Array`,
150
+ * 或使用 `SharedArrayBuffer` backing 时,在发送 bridge 请求前返回 `INVALID_PARAMS`。普通数组、
151
+ * `ArrayBuffer`、`DataView`、其他 typed array 也不会被隐式转换。
152
+ * @throws {@link HbMiniProgramSDKError} 当前 proxy 已知 Session 已退出时返回
153
+ * `COMPANION_SESSION_EXITED`;controller 已转移给其他 Runtime generation 时返回
154
+ * `COMPANION_SESSION_OWNERSHIP_LOST`。检查与 Host 写入之间仍存在竞态,Host 会用私有
155
+ * controller generation 再次拒绝过期调用。
156
+ * @throws {@link HbMiniProgramSDKError} stdin 已由 {@link CompanionStdio.closeStdin | closeStdin()}
157
+ * 关闭、Session 不再提供 `stdio` 或通信管道不可用时返回 `COMPANION_PIPE_CLOSED`;进程异常退出
158
+ * 或因输出上限结束时还可能返回 `COMPANION_PROCESS_CRASHED` / `COMPANION_OUTPUT_LIMIT`。
159
+ * @throws {@link HbMiniProgramSDKError} 未声明或未获批 `companion` 权限时返回
160
+ * `PERMISSION_NOT_DECLARED` / `PERMISSION_DENIED`;Host 未开放 `companion.session.write` 时返回
161
+ * `METHOD_FORBIDDEN`,旧 Runtime 可返回 `METHOD_NOT_FOUND`。未知 Host 失败会脱敏并返回
162
+ * `COMPANION_HOST_FAILED`;SDK/Runtime 终止或请求超时还可能返回 `SDK_DESTROYED`、
163
+ * `RUNTIME_UNAVAILABLE`、`REQUEST_TIMEOUT`。
164
+ *
165
+ * @remarks
166
+ * `stdio` 只在 Session 快照的 capability 集合包含 `'stdio'` 时存在;调用前必须按
167
+ * `session.stdio` 是否存在分支。它是已声明并经平台批准的 `companion` 高风险能力的一部分,
168
+ * 不要求新的可信用户手势;但持有 `CompanionStdio` 对象不代表 controller、进程或管道之后一直有效。
169
+ * `session.state === 'running'` 也不能证明当前 Runtime 仍持有 controller,因为 ownership 转移不会
170
+ * 结束进程。
171
+ *
172
+ * SDK 在调用时同步复制 `data` 的可见字节,Runtime 在调用 Host 前再制作一份副本;调用返回后修改
173
+ * 原数组或 backing buffer 不会改变本次 payload。两层都只接受普通 `ArrayBuffer` backing,拒绝
174
+ * `SharedArrayBuffer`,因此该 API 不建立跨 bridge 共享内存。SDK 没有公开 stdin 单次写入大小上限,
175
+ * 也不会自动分块;实际可接受大小仍受 Host、IPC 和操作系统管道限制,不能据此假定无限写入。
176
+ *
177
+ * 字节不会经过 UTF-8 解码、换行处理、JSON 序列化或其他内容转换。stdin 是 byte stream,不保留
178
+ * JavaScript `write()` 调用边界:一次写入可被 Companion 分段读取,多次写入也可被合并。业务必须
179
+ * 自己定义长度前缀、转义或其他 framing,并在需要确定顺序时逐次 `await`,不要并发写入后依赖完成顺序。
180
+ *
181
+ * {@link CompanionStdio.onStdout | onStdout()} 和 {@link CompanionStdio.onStderr | onStderr()} 是独立的
182
+ * 异步输出流;单次写入可能对应零个、一个或多个输出 chunk,输出也可能在本 Promise settle 前后到达。
183
+ * 应在写入前订阅,并让业务 framing 自带关联 ID。Host 输出采用 at-least-once 投递;SDK 会在同一
184
+ * controller generation 内按 stream sequence 抑制已见 replay 并确认它,但 controller 转移、页面 reload
185
+ * 或业务重连后仍应自行处理重放和去重。
186
+ *
187
+ * `closeStdin()` 是不可逆的输入半关闭,不等于终止 Session;关闭后 stdout/stderr 和退出事件仍可继续。
188
+ * 应先依次 await 所有业务帧写入,再关闭 stdin;不要让 `write()` 与 `closeStdin()` 并发竞态。失去
189
+ * controller 后不要自动重试不确定是否已提交的写入,否则可能向进程重复发送业务命令。需要明确恢复控制时,
190
+ * 由业务调用 {@link MiniProgramCompanionModule.getActiveSession | companion.getActiveSession},再按自己的
191
+ * 幂等协议决定是否重发。
192
+ *
193
+ * V1 真实 Companion stdio 仅支持新 PC Host 的 Windows x64 与 macOS arm64;Browser Dev Host
194
+ * 提供确定性 Fake 用于验证 framing、输出和错误 UI,不执行真实程序。其他平台、旧 Host 或缺少
195
+ * `companion.session.write` operation 时 fail closed,不提供 WebSocket、worker 或 shell fallback。
196
+ *
197
+ * @example
198
+ * ```ts
199
+ * import hbSDK, { HbMiniProgramSDKError } from '@heybox/hb-sdk'
200
+ *
201
+ * const session = await hbSDK.companion.getActiveSession('runner')
202
+ * const stdio = session?.stdio
203
+ * if (session && stdio) {
204
+ * const stopStdout = stdio.onStdout(chunk => consumeBusinessFrames(chunk))
205
+ * const stopStderr = stdio.onStderr(chunk => appendDiagnosticBytes(chunk))
206
+ * const stopOwnership = session.onOwnershipLost(() => disableCompanionControls())
207
+ *
208
+ * try {
209
+ * // encodeBusinessFrame 自行添加长度、消息 ID 等业务 framing。
210
+ * await stdio.write(encodeBusinessFrame({ id: 'status-1', type: 'status' }))
211
+ * await stdio.closeStdin()
212
+ * await session.waitForExit() // 保留输出订阅,直到进程结束。
213
+ * } catch (error) {
214
+ * if (
215
+ * error instanceof HbMiniProgramSDKError &&
216
+ * (error.code === 'COMPANION_PIPE_CLOSED' || error.code === 'COMPANION_SESSION_OWNERSHIP_LOST')
217
+ * ) {
218
+ * disableCompanionControls()
219
+ * } else {
220
+ * throw error
221
+ * }
222
+ * } finally {
223
+ * stopStdout()
224
+ * stopStderr()
225
+ * stopOwnership()
226
+ * }
227
+ * }
228
+ * ```
229
+ *
230
+ * @see {@link CompanionStdio.closeStdin}
231
+ * @see {@link CompanionStdio.onStdout}
232
+ * @see {@link CompanionStdio.onStderr}
233
+ * @see {@link CompanionOutputHandler}
234
+ * @see {@link CompanionSession.onOwnershipLost}
235
+ * @see {@link CompanionSession.waitForExit}
236
+ * @see {@link MiniProgramCompanionModule.getActiveSession | companion.getActiveSession}
237
+ * @see {@link https://docs.xiaoheihe.cn/hb_sdk/guide/companion | 受管桌面程序}
238
+ * @see {@link https://docs.xiaoheihe.cn/hb_sdk/guide/error-handling | 错误处理}
239
+ * @see {@link https://docs.xiaoheihe.cn/hb_sdk/guide/permissions | 权限声明}
240
+ *
241
+ * @since 0.8.1-alpha.4
242
+ * @hbPlatform windows
243
+ * @hbPlatform macos
244
+ * @hbClient windows none
245
+ * @hbClient macos none
246
+ */
21
247
  write(data: Uint8Array): Promise<void>;
248
+ /**
249
+ * 不可逆地关闭当前 Companion Session 的 stdin 写入端。
250
+ *
251
+ * @returns 当前 controller 对应的 Host 确认 stdin close 请求完成后以 `undefined` resolve。该时点只
252
+ * 表示输入半关闭已由 Host 接受,不返回退出码,不等待 Companion 消费完先前输入、stdout/stderr
253
+ * 排空或进程退出;使用 {@link CompanionSession.waitForExit | waitForExit()} 等待进程终态。
254
+ * @throws {@link HbMiniProgramSDKError} 当前 proxy 已知 Session 已退出时返回
255
+ * `COMPANION_SESSION_EXITED`;controller 已转移给其他 Runtime generation 时返回
256
+ * `COMPANION_SESSION_OWNERSHIP_LOST`。本地检查与 Host 执行之间仍存在竞态,Host 会用私有
257
+ * controller generation 再次拒绝过期调用。
258
+ * @throws {@link HbMiniProgramSDKError} stdin 已关闭、Session 不再提供 `stdio` 或通信管道不可用时
259
+ * 可返回 `COMPANION_PIPE_CLOSED`;进程异常退出或因输出上限结束时还可能返回
260
+ * `COMPANION_PROCESS_CRASHED` / `COMPANION_OUTPUT_LIMIT`。
261
+ * @throws {@link HbMiniProgramSDKError} 未声明或未获批 `companion` 权限时返回
262
+ * `PERMISSION_NOT_DECLARED` / `PERMISSION_DENIED`;Host 未开放
263
+ * `companion.session.closeStdin` 时返回 `METHOD_FORBIDDEN`,旧 Runtime 可返回 `METHOD_NOT_FOUND`。
264
+ * 未识别的 Host 失败会脱敏为 `COMPANION_HOST_FAILED`;SDK / Runtime 终止、不可用或请求超时还
265
+ * 可能返回 `SDK_DESTROYED`、`RUNTIME_UNAVAILABLE`、`REQUEST_TIMEOUT`。
266
+ *
267
+ * @remarks
268
+ * `closeStdin()` 是一次性的输入半关闭,不是 flush、取消、{@link CompanionSession.terminate | terminate()}
269
+ * 或“请求进程退出”的别名。成功后不能重新打开 stdin,后续 {@link CompanionStdio.write | write()}
270
+ * 会失败;但 Companion 仍可继续运行、处理已经收到的字节并产生 stdout/stderr,Session 的
271
+ * `state` 也会保持 `'running'`,直到 Host 发送独立退出事件。
272
+ *
273
+ * SDK 不维护公开的 `stdinClosed` 状态,也不会合并或短路重复调用;每次调用都会携带当前私有
274
+ * controller generation 发往 Host。重复关闭不属于公共幂等保证:不同 Host 可能重复确认,也可能
275
+ * 返回 `COMPANION_PIPE_CLOSED`。业务应只关闭一次;若请求失败或超时,Host 是否已经完成关闭可能
276
+ * 无法从该错误判断,不要无条件自动重试。
277
+ *
278
+ * SDK 不会在 {@link CompanionStdio.write | write()} 与 `closeStdin()` 之间建立队列。要发送最后一帧,
279
+ * 应先逐次 `await` 所有 write,再调用一次 close;并发调用会产生由实际请求到达顺序决定的竞态,
280
+ * 最后的 write 可能因管道已关闭而失败。空 `Uint8Array` 写入也不是 EOF,只有本方法表达 stdin EOF。
281
+ *
282
+ * 该调用要求 Session 快照包含 `'stdio'`(否则 `session.stdio` 为 `undefined`)、进程尚未退出,且当前
283
+ * Runtime generation 仍持有 controller。`session.state === 'running'` 本身不能证明仍有控制权;应监听
284
+ * {@link CompanionSession.onOwnershipLost | onOwnershipLost()} 并立即停止新的 write/close 操作。失去
285
+ * controller 或关闭 stdin 都不会让 {@link CompanionSession.waitForExit | waitForExit()} 提前完成;
286
+ * 后者仍绑定同一个进程的真实退出事件。
287
+ *
288
+ * 该方法属于已声明并经平台批准的 `companion` 高风险能力,不要求新的可信用户手势。V1 真实
289
+ * Companion stdio 仅支持新 PC Host 的 Windows x64 与 macOS arm64;Browser Dev Host 提供确定性
290
+ * Fake,其他平台、旧 Host 或 operation 缺失时 fail closed,不提供 WebSocket、worker 或 shell
291
+ * fallback。
292
+ *
293
+ * @example
294
+ * ```ts
295
+ * import hbSDK from '@heybox/hb-sdk'
296
+ *
297
+ * const session = await hbSDK.companion.getActiveSession('runner')
298
+ * const stdio = session?.stdio
299
+ * if (session && stdio) {
300
+ * const stopStdout = stdio.onStdout(chunk => consumeBusinessFrames(chunk))
301
+ * const stopStderr = stdio.onStderr(chunk => appendDiagnosticBytes(chunk))
302
+ *
303
+ * try {
304
+ * await stdio.write(encodeBusinessFrame({ type: 'finish' }))
305
+ * await stdio.closeStdin() // 只调用一次,并且在最后一次 write 完成之后。
306
+ *
307
+ * // stdin 已关闭后输出仍可能继续;进程终态以 waitForExit() 为准。
308
+ * const exit = await session.waitForExit()
309
+ * console.log(exit)
310
+ * } finally {
311
+ * stopStdout()
312
+ * stopStderr()
313
+ * }
314
+ * }
315
+ * ```
316
+ *
317
+ * @see {@link CompanionStdio.write | CompanionStdio.write()} 在关闭前写入原始字节。
318
+ * @see {@link CompanionStdio.onStdout | CompanionStdio.onStdout()} 订阅关闭后仍可能到达的标准输出。
319
+ * @see {@link CompanionStdio.onStderr | CompanionStdio.onStderr()} 订阅关闭后仍可能到达的标准错误。
320
+ * @see {@link CompanionSession.waitForExit | CompanionSession.waitForExit()} 等待独立的进程退出终态。
321
+ * @see {@link CompanionSession.onOwnershipLost | CompanionSession.onOwnershipLost()} 监听 controller 转移。
322
+ * @see {@link CompanionSession.terminate | CompanionSession.terminate()} 显式请求终止进程。
323
+ * @see {@link https://docs.xiaoheihe.cn/hb_sdk/guide/companion | 受管桌面程序}
324
+ * @see {@link https://docs.xiaoheihe.cn/hb_sdk/guide/error-handling | 错误处理}
325
+ */
22
326
  closeStdin(): Promise<void>;
327
+ /**
328
+ * 订阅当前 Companion Session 的 stdout 原始字节 chunk。
329
+ *
330
+ * @param handler - 每个新 stdout chunk 的同步 {@link CompanionOutputHandler}。必须是函数;SDK
331
+ * 不会向它传入 sequence、controller generation、文本、错误或退出状态。
332
+ * @returns 同步返回取消订阅函数。调用后只移除当前 SDK proxy 上的本地 handler,不关闭 stdout、
333
+ * 不发送 Host unsubscribe、不关闭 stdin,也不终止 Session。重复调用取消函数安全且不会抛错。
334
+ * @throws {@link HbMiniProgramSDKError} `handler` 不是函数时同步抛出 `INVALID_PARAMS`。订阅本身
335
+ * 不发 bridge 请求,因此不会因权限、ownership、Session 已退出或 Host event source 缺失而拒绝。
336
+ *
337
+ * @remarks
338
+ * 该方法只在 `session.stdio` 存在时可调用;`stdio` 是否存在由 Session 快照的
339
+ * `capabilities` 是否包含 `'stdio'` 决定。没有该 capability 时整个 `session.stdio` 为
340
+ * `undefined`,调用方必须先分支。注册不要求新的可信用户手势,也不额外请求权限;Session 后续
341
+ * 仍可能因权限撤销、进程退出或 controller 转移而停止投递。
342
+ *
343
+ * stdout 是原始 byte stream,不是一次 {@link CompanionStdio.write | write()} 对应一次回调的消息
344
+ * 通道。SDK 不定义字符编码,也不保证 chunk 与换行、JSON、RPC frame 或业务消息对齐;业务必须
345
+ * 自行处理拆包、粘包和 framing。handler 每次收到独立的新 `Uint8Array` 副本,同一事件的其他
346
+ * handler 也收到各自副本,因此一个 handler 修改 bytes 不会污染另一个 handler。
347
+ *
348
+ * Host 输出按 at-least-once 语义投递。Runtime 先拒绝非法 Session ID、stream、generation、
349
+ * sequence 或 bytes;SDK 再在当前 controller generation 内分别为 stdout/stderr 记录最后一个
350
+ * sequence。已见或倒退的 stdout sequence 不会再次调用 handler,但有效 replay 仍会 best-effort
351
+ * 发送内部 `companion.session.ackOutput`;ack 失败不会转交给业务,也不会让本方法抛错。controller
352
+ * 转移、重新取得控制、页面 reload 或业务重连会形成新的去重边界,业务 frame 仍应携带自己的
353
+ * 幂等 ID,不能把 SDK 的 generation 内去重当作端到端 exactly-once 保证。
354
+ *
355
+ * handler 的同步异常会被隔离:其他 stdout handler 仍会收到同一 chunk,内部 ack 也仍会尝试。
356
+ * SDK 忽略 handler 返回值且不会 await Promise;若传入 async 函数,需在函数内部处理 rejected
357
+ * Promise。取消函数仅影响未来本地分发,已经开始执行的回调不会被中断。
358
+ *
359
+ * 订阅没有历史回放或本地缓冲。事件到达时即使没有 handler,SDK 仍可确认并丢弃该 chunk,之后
360
+ * 注册不会补发;应在调用 `write()` 或触发 Companion 输出之前订阅。Session exit 会清除当前已
361
+ * 注册的 stdout/stderr handlers,退出后不会再投递。调用取消函数后 Host 仍可继续产生输出并由
362
+ * SDK 内部确认,取消订阅不能用于流控或阻止 Companion 达到输出上限。
363
+ *
364
+ * ownership 丢失时,旧 proxy 不再分发旧 controller generation 的 output。调用
365
+ * {@link MiniProgramCompanionModule.getActiveSession | companion.getActiveSession} 取得同一 Session
366
+ * 的更新 controller 后,SDK 会复用同一 proxy,保留已注册 handler,并为新 generation 重置
367
+ * stdout/stderr sequence 去重状态;业务仍需处理 Host 重放。若不希望恢复后继续接收,应在
368
+ * `onOwnershipLost()` 中调用本方法返回的取消函数。
369
+ *
370
+ * Host 集成还必须提供 `HostCompanionPort.onSessionEvent()` 事件源。当前该 Host Port 成员是可选的:
371
+ * 若 Host 返回含 `stdio` 的 Session,却没有接入事件源,本方法仍会成功注册,但 stdout、exit 与
372
+ * ownership 事件都不会到达 SDK,且没有轮询或 WebSocket fallback。Mini-program 无法通过本方法
373
+ * 检测该集成缺口;Host/Runtime 集成方应把 Session event source 作为可用 stdio 输出的必要条件。
374
+ *
375
+ * V1 真实 Companion stdio 仅支持新 PC Host 的 Windows x64 与 macOS arm64;Browser Dev Host
376
+ * 提供确定性 Fake 以验证 bytes、ack、framing 和错误 UI,不执行真实程序。其他平台、旧 Host 或
377
+ * 未开放 Companion 的环境不会提供可用 Session stdio。
378
+ *
379
+ * @example
380
+ * ```ts
381
+ * import hbSDK from '@heybox/hb-sdk'
382
+ *
383
+ * const session = await hbSDK.companion.getActiveSession('runner')
384
+ * const stdio = session?.stdio
385
+ *
386
+ * if (session && stdio) {
387
+ * // 仅当 Companion 业务协议规定 stdout 是 UTF-8 行文本时这样解码。
388
+ * const decoder = new TextDecoder()
389
+ * let pending = ''
390
+ *
391
+ * const stopStdout = stdio.onStdout(bytes => {
392
+ * pending += decoder.decode(bytes, { stream: true })
393
+ * const lines = pending.split('\n')
394
+ * pending = lines.pop() ?? ''
395
+ * for (const line of lines) console.log(line)
396
+ * })
397
+ * const stopOwnership = session.onOwnershipLost(stopStdout)
398
+ *
399
+ * session.onExit(() => {
400
+ * pending += decoder.decode()
401
+ * if (pending) console.log(pending)
402
+ * stopStdout()
403
+ * stopOwnership()
404
+ * })
405
+ * }
406
+ * ```
407
+ *
408
+ * @see {@link CompanionOutputHandler}
409
+ * @see {@link CompanionStdio.onStderr | CompanionStdio.onStderr()} 订阅独立的 stderr stream。
410
+ * @see {@link CompanionStdio.write | CompanionStdio.write()} 向 stdin 写入原始字节。
411
+ * @see {@link CompanionSession.onOwnershipLost | CompanionSession.onOwnershipLost()} 观察 controller 转移。
412
+ * @see {@link CompanionSession.onExit | CompanionSession.onExit()} 在进程退出时完成 decoder 并清理订阅。
413
+ * @see {@link MiniProgramCompanionModule.getActiveSession | companion.getActiveSession} 恢复活动 Session controller。
414
+ * @see [受管桌面程序](/guide/companion) 查看 stdio framing、重放与恢复流程。
415
+ *
416
+ * @since 0.8.1-alpha.4
417
+ * @hbPlatform windows
418
+ * @hbPlatform macos
419
+ * @hbClient windows none
420
+ * @hbClient macos none
421
+ */
23
422
  onStdout(handler: CompanionOutputHandler): () => void;
423
+ /**
424
+ * 订阅当前 Companion Session 的 stderr 原始字节流。
425
+ *
426
+ * @param handler - 每个新 stderr chunk 到达时同步调用的处理函数。参数是 SDK 为当前 handler
427
+ * 单独复制的 `Uint8Array`;修改它不会改变 Host payload,也不会影响同一事件的其他 handler。
428
+ * @returns 取消当前 handler 的同步函数。可调用一次或多次;取消后不再接收未来 chunk,不会关闭
429
+ * stderr、stdin 或 Session,也不会取消其他 handler。相同函数引用重复订阅按 Set 语义只保留一项,
430
+ * 任一对应取消函数都会移除该项。
431
+ * @throws {@link HbMiniProgramSDKError} `handler` 不是函数时同步抛出 `INVALID_PARAMS`。订阅本身不发送
432
+ * bridge 请求,因此不会因权限、Host operation、Session 退出或 controller ownership 状态异步拒绝。
433
+ *
434
+ * @remarks
435
+ * `session.stdio` 只在 Session capability 集合包含 `'stdio'` 时存在;调用前必须先判空。取得
436
+ * Session 仍受已声明并经平台批准的 `companion` 权限、当前版本产物和 Host 支持约束,但本地注册
437
+ * handler 不要求新的可信用户手势,也不重新校验权限。Host 没有 Session event source 的兼容集成
438
+ * 即使返回了 `stdio`,订阅也只是成功注册本地 handler,之后不会收到输出事件;它不会轮询、报错或
439
+ * 从 `write()` 响应中推导 stderr。
440
+ *
441
+ * stderr 与 {@link CompanionStdio.onStdout | onStdout()} 使用相同的原始字节、sequence、去重和确认
442
+ * 合同,但两条流相互独立:各自维护最近 sequence 和 handler 集合,相同 sequence 数字可以分别在
443
+ * stdout 与 stderr 出现。字节不会自动按 UTF-8、换行、JSON 或消息边界解码;一个逻辑诊断可能被
444
+ * 拆到多个 chunk,一个 chunk 也可能含多条诊断。stderr 只是 Companion 进程选择的第二输出流,
445
+ * 收到数据不等于进程失败,退出结果应通过 {@link CompanionSession.waitForExit} 或
446
+ * {@link CompanionSession.onExit} 判断。
447
+ *
448
+ * 对当前 controller generation,每条格式合法且 sequence 大于本流已见水位的事件最多向业务
449
+ * handler 投递一次。较旧或重复的 sequence 不会再次投递,但 SDK 仍会发送 best-effort
450
+ * `companion.session.ackOutput`;即使没有 stderr handler 或某个 handler 抛错,也会继续确认。
451
+ * ack 是 SDK 内部 fire-and-forget 请求,失败会被吞掉,不会回调 handler,也不表示 Host 一定停止
452
+ * 重放。因此 Host 输出是 at-least-once,业务跨 controller 转移、页面 reload 或重连仍应按自己的
453
+ * framing / 消息 ID 处理重放和去重。
454
+ *
455
+ * handler 按注册集合顺序同步执行,返回值会被忽略,Promise 不会被等待。每个 handler 的同步异常
456
+ * 都被 SDK 单独捕获,不会阻断同一 chunk 的其他 handler 或 ack;异步 handler 的 rejected Promise
457
+ * 不会被 SDK 捕获,应在 handler 内显式处理。订阅不会重放注册前的 stderr,也不能读取历史缓冲区。
458
+ *
459
+ * Session 退出后,SDK 会清空 stdout/stderr handler;已有取消函数仍可安全调用。controller ownership
460
+ * 丢失后,旧 generation 的输出被忽略且不会确认,已有订阅不会因此收到错误或自动取消;调用方应同时
461
+ * 监听 {@link CompanionSession.onOwnershipLost} 并停止依赖旧 controller。之后通过
462
+ * {@link MiniProgramCompanionModule.getActiveSession | companion.getActiveSession} 取得同一 Session 的
463
+ * 新 controller generation 时,SDK 会重置两条流的 sequence 水位,当前 proxy 上尚未取消的 handler
464
+ * 可以继续接收新 generation 输出。其他 Session ID、非法字节、非法 sequence、generation 不匹配以及
465
+ * 已退出 Session 的事件都会被丢弃。
466
+ *
467
+ * {@link CompanionStdio.write | write()} 只向 stdin 写入原始字节,不保证产生 stderr,也不保证一次
468
+ * write 对应一次回调。需要捕获启动后的早期诊断时,应在 write 前订阅,并在 Session 退出或页面销毁
469
+ * 时调用取消函数。V1 真实 Companion stdio 仅支持新 PC Host 的 Windows x64 与 macOS arm64;
470
+ * Browser Dev Host 的确定性 Fake 只用于联调,不能替代真实进程验收。
471
+ *
472
+ * @example
473
+ * ```ts
474
+ * import hbSDK from '@heybox/hb-sdk'
475
+ *
476
+ * const session = await hbSDK.companion.getActiveSession('runner')
477
+ * if (session?.stdio) {
478
+ * const decoder = new TextDecoder()
479
+ * const stopStderr = session.stdio.onStderr(bytes => {
480
+ * // stream: true 保留跨 chunk 的 UTF-8 解码状态;协议 framing 仍需业务自行处理。
481
+ * appendDiagnosticText(decoder.decode(bytes, { stream: true }))
482
+ * })
483
+ * const stopOwnership = session.onOwnershipLost(() => {
484
+ * disableCompanionControls()
485
+ * })
486
+ *
487
+ * try {
488
+ * await session.stdio.write(encodeBusinessFrame({ type: 'status' }))
489
+ * await session.waitForExit()
490
+ * appendDiagnosticText(decoder.decode())
491
+ * } finally {
492
+ * stopStderr()
493
+ * stopOwnership()
494
+ * }
495
+ * }
496
+ * ```
497
+ *
498
+ * @see {@link CompanionOutputHandler}
499
+ * @see {@link CompanionStdio.onStdout}
500
+ * @see {@link CompanionStdio.write}
501
+ * @see {@link CompanionStdio.closeStdin}
502
+ * @see {@link CompanionSession.onOwnershipLost}
503
+ * @see {@link CompanionSession.onExit}
504
+ * @see {@link CompanionSession.waitForExit}
505
+ * @see {@link MiniProgramCompanionModule.getActiveSession | companion.getActiveSession}
506
+ * @see {@link https://docs.xiaoheihe.cn/hb_sdk/guide/companion | 受管桌面程序}
507
+ * @see {@link https://docs.xiaoheihe.cn/hb_sdk/guide/error-handling | 错误处理}
508
+ * @see {@link https://docs.xiaoheihe.cn/hb_sdk/guide/permissions | 权限声明}
509
+ */
24
510
  onStderr(handler: CompanionOutputHandler): () => void;
25
511
  }
512
+ /**
513
+ * Companion 产生的受控附件访问能力。
514
+ *
515
+ * `id` 是 Companion 业务协议中的不透明标识,不是路径、URL 或文件句柄;返回的文件只能按
516
+ * 当前 `FileHandle` 权限读取。
517
+ */
26
518
  export interface CompanionAttachments {
519
+ /**
520
+ * 按 Companion 业务协议中的 opaque ID 打开一个受控附件。
521
+ *
522
+ * @param id - Companion 自己产生并通过业务协议交给页面的附件 ID。SDK 只要求它是长度大于 `0` 的
523
+ * string,不 trim、不限制格式或长度;空字符串和非字符串在发送请求前返回 `INVALID_PARAMS`。
524
+ * 空白字符串虽通过本地结构校验,通常仍会由 Host 按未知 ID 拒绝。
525
+ * @returns 当前 Runtime session 中新注册的冻结 {@link FileHandle} direct proxy。`kind` 固定为
526
+ * `'file'`,`mode` 固定衰减为 `'read'`,`name` 是 Host 提供并经校验的 basename;不返回物理路径、
527
+ * 原生句柄、URL、controller generation 或可持久化的 wire ref。
528
+ * @throws {@link HbMiniProgramSDKError} `id` 为空或不是 string 时返回 `INVALID_PARAMS`;Host 找不到
529
+ * 当前 Session 对应的 ID、该 ID 已失效或 Session 没有 attachments capability 时通常返回
530
+ * `COMPANION_ATTACHMENT_NOT_FOUND`。
531
+ * @throws {@link HbMiniProgramSDKError} 当前 proxy 已知 Session 已退出时返回
532
+ * `COMPANION_SESSION_EXITED`;controller 已转移给其他 Runtime generation 时返回
533
+ * `COMPANION_SESSION_OWNERSHIP_LOST`。本地检查与 Host 打开之间存在竞态,Host 会用未公开的
534
+ * controller generation 再次校验当前调用。
535
+ * @throws {@link HbMiniProgramSDKError} 未声明或未获批 `companion` 权限时返回
536
+ * `PERMISSION_NOT_DECLARED` / `PERMISSION_DENIED`;Host 未开放 `companion.openAttachment` 时返回
537
+ * `METHOD_FORBIDDEN`,旧 Runtime 可返回 `METHOD_NOT_FOUND`。Host 不支持 Companion 或附件描述符
538
+ * 暂不可用时还可能返回 `COMPANION_UNSUPPORTED` / `COMPANION_DESCRIPTOR_UNAVAILABLE`。
539
+ * @throws {@link HbMiniProgramSDKError} 当前 Runtime session 的 direct handles 已达到 1024 上限时
540
+ * 返回 `FILE_QUOTA_EXCEEDED`。Host 返回的对象不是完整 File capability、名称/mode/ref 非法、不是
541
+ * 精确 direct File,或 Runtime 无法注册安全 opaque handle 时返回 `FILE_IO_FAILED`;其他未知 Host
542
+ * 失败会脱敏为 `COMPANION_HOST_FAILED`。SDK/Runtime 终止或请求超时还可能返回
543
+ * `SDK_DESTROYED`、`RUNTIME_UNAVAILABLE`、`REQUEST_TIMEOUT`。
544
+ *
545
+ * @remarks
546
+ * `id` 是当前 Companion 业务协议的不透明标识,不是路径、文件名、URL、下载地址或系统 bookmark。
547
+ * 页面不能用 `../`、绝对路径或自己拼接的字符串访问任意文件,也不应解析 ID 推断物理位置。Host
548
+ * 将 ID 解析为当前 Session 明确暴露的一个附件,并只把对应 File capability 交给 Runtime。
549
+ * `open()` 本身不读取内容,也不根据扩展名推断格式。
550
+ *
551
+ * `session.attachments` 仅在 Session 快照的 capability 集合包含 `'attachments'` 时存在;调用前应按
552
+ * 属性是否存在分支。打开动作需要当前 Runtime 持有 Session controller,但不要求新的可信用户手势。
553
+ * `session.state === 'running'` 不能证明仍有控制权;有 Session event source 时应监听
554
+ * {@link CompanionSession.onOwnershipLost | onOwnershipLost()} 并停止新的 `open()`。自定义 Host 缺少
555
+ * event source 时本地状态可能不会主动更新,但 Host 仍必须拒绝旧 generation,不能把事件监听当作授权边界。
556
+ *
557
+ * 成功后附件 provenance 保存在 Runtime 文件 registry 中,不进入公开 proxy。返回句柄是独立的当前
558
+ * Runtime session 能力:SDK 不会仅因随后收到 ownership-lost 或 exit 事件就在本地删除它,但 Host 可随
559
+ * Session、授权或底层附件生命周期撤销访问,后续读取会以 `FILE_ACCESS_REVOKED` 等错误失败。因此不能
560
+ * 序列化、跨页面保存或假定它在 controller 转移/进程退出后仍可读;需要新句柄时先明确取得当前 controller
561
+ * 并重新按业务 ID 打开。
562
+ *
563
+ * 每次成功 `open()` 都注册一个新的 direct handle,即使 ID 相同也不缓存或复用 proxy,并与
564
+ * `files.pickFiles()`、`files.pickDirectory()`、`files.saveFile()` 共享当前 Runtime session 的 1024
565
+ * handle 上限。页面应复用已经返回的 FileHandle,避免循环重复打开同一 ID;Runtime session 结束时
566
+ * registry 会统一失效。
567
+ *
568
+ * 返回句柄始终只读,即使底层 Host File 原本可写:`create()`、`writeText()`、`writeBytes()` 和
569
+ * `remove()` 都会以 `FILE_ACCESS_DENIED` 拒绝,也不能从中派生父目录或兄弟文件。已启用的
570
+ * `companion` 权限只为 registry 证明 provenance 的附件开放 {@link FileHandle.readText | readText()}、
571
+ * {@link FileHandle.readBytes | readBytes()} 和 {@link FileHandle.stat | stat()};这三项不要求另行声明
572
+ * `filesystem`。其他 FileHandle operation 不因 attachment provenance 获得通用 filesystem 权限。
573
+ *
574
+ * `readText()` / `readBytes()` 都会把完整附件载入内存,没有公开 stream、range read 或自动分段 API。
575
+ * `open()` 不受文件内容大小影响,但后续读取仍受实际 PC Host 的单次 I/O 与内存限制,可能返回
576
+ * `FILE_TOO_LARGE`;新 PC Host 没有公开沿用 Android/iOS 的固定 8 MiB 上限。可先用 `stat()` 做业务
577
+ * 大小门槛,但附件可能在两次异步调用之间变化,stat 与 read 不是原子操作。
578
+ *
579
+ * V1 真实 attachments 仅支持实现该 capability 的新 PC Host(Windows x64 / macOS arm64);
580
+ * Browser Dev Host 只提供 ID 为 `'report'` 的确定性 Fake 文件,用于验证 UI 与读取流程,不访问本机
581
+ * 任意路径。其他平台、旧 Host 或 operation 缺失时 fail closed,不提供浏览器 File / Blob、URL fetch
582
+ * 或内存 fallback。
583
+ *
584
+ * @example
585
+ * ```ts
586
+ * import hbSDK, { HbMiniProgramSDKError } from '@heybox/hb-sdk'
587
+ *
588
+ * const session = await hbSDK.companion.getActiveSession('runner')
589
+ * const attachments = session?.attachments
590
+ * if (session && attachments) {
591
+ * let ownsController = true
592
+ * const stopOwnership = session.onOwnershipLost(() => {
593
+ * ownsController = false
594
+ * })
595
+ *
596
+ * try {
597
+ * const attachmentId = readAttachmentIdFromBusinessFrame()
598
+ * if (!ownsController) return
599
+ *
600
+ * const file = await attachments.open(attachmentId)
601
+ * const stat = await file.stat()
602
+ * if (stat.size > 4 * 1024 * 1024) throw new Error('附件超过业务读取上限')
603
+ *
604
+ * const bytes = await file.readBytes()
605
+ * consumeAttachment(file.name, bytes)
606
+ * } catch (error) {
607
+ * if (
608
+ * error instanceof HbMiniProgramSDKError &&
609
+ * (error.code === 'COMPANION_ATTACHMENT_NOT_FOUND' ||
610
+ * error.code === 'COMPANION_SESSION_OWNERSHIP_LOST')
611
+ * ) {
612
+ * showAttachmentUnavailable()
613
+ * } else {
614
+ * throw error
615
+ * }
616
+ * } finally {
617
+ * stopOwnership()
618
+ * }
619
+ * }
620
+ * ```
621
+ *
622
+ * @see {@link FileHandle}
623
+ * @see {@link FileHandle.readText}
624
+ * @see {@link FileHandle.readBytes}
625
+ * @see {@link FileHandle.stat}
626
+ * @see {@link CompanionSession.onOwnershipLost}
627
+ * @see {@link MiniProgramCompanionModule.getActiveSession | companion.getActiveSession}
628
+ * @see {@link https://docs.xiaoheihe.cn/hb_sdk/guide/companion | 受管桌面程序}
629
+ * @see {@link https://docs.xiaoheihe.cn/hb_sdk/guide/error-handling | 错误处理}
630
+ * @see {@link https://docs.xiaoheihe.cn/hb_sdk/guide/permissions | 权限声明}
631
+ *
632
+ * @since 0.8.1-alpha.4
633
+ * @hbPlatform windows
634
+ * @hbPlatform macos
635
+ * @hbClient windows none
636
+ * @hbClient macos none
637
+ */
27
638
  open(id: string): Promise<FileHandle>;
28
639
  }
640
+ /** Companion 请求 Host 展示固定类别系统通知的能力。 */
29
641
  export interface CompanionNotifications {
642
+ /**
643
+ * 请求 Host 为当前 Companion Session 展示固定类别的系统通知。
644
+ *
645
+ * @param input - 必须是包含合法 `category` 的非数组对象,详见 {@link CompanionNotification}。
646
+ * 支持 `completed`、`failed`、`stopped`、`attention` 四类。缺失或其他值返回 `INVALID_PARAMS`。
647
+ * JavaScript 传入的额外字段会被忽略并从 bridge payload 移除,不会作为自定义标题、正文、按钮、
648
+ * URL 或原生通知参数传给 Host。
649
+ * @returns Host 确认本次通知请求已处理后以 `undefined` resolve。不返回通知 ID,也不保证操作系统
650
+ * 最终展示、用户看见或点击通知;系统通知权限、免打扰和平台投递策略仍由 Host / 操作系统决定。
651
+ * @throws {@link HbMiniProgramSDKError} input 缺失、不是对象、是数组,或 `category` 不在四个固定值中
652
+ * 时,在发送 bridge 请求前返回 `INVALID_PARAMS`。
653
+ * @throws {@link HbMiniProgramSDKError} 当前 proxy 已知 Session 已退出时返回
654
+ * `COMPANION_SESSION_EXITED`;controller 已转移给其他 Runtime generation 时返回
655
+ * `COMPANION_SESSION_OWNERSHIP_LOST`。本地检查与 Host 展示之间存在竞态,Host 会用私有
656
+ * controller generation 再次拒绝过期调用。
657
+ * @throws {@link HbMiniProgramSDKError} 当前 Host、操作系统或 Session 无法展示通知时返回
658
+ * `COMPANION_NOTIFICATION_UNAVAILABLE`;Companion 不受支持、进程已异常退出或因输出上限结束时
659
+ * 还可能返回 `COMPANION_UNSUPPORTED`、`COMPANION_PROCESS_CRASHED`、`COMPANION_OUTPUT_LIMIT`。
660
+ * @throws {@link HbMiniProgramSDKError} 未声明或未获批 `companion` 权限时返回
661
+ * `PERMISSION_NOT_DECLARED` / `PERMISSION_DENIED`;Host 未开放 `companion.showNotification` 时返回
662
+ * `METHOD_FORBIDDEN`,旧 Runtime 可返回 `METHOD_NOT_FOUND`。未知 Host 失败会脱敏为
663
+ * `COMPANION_HOST_FAILED`;SDK / Runtime 终止、不可用或请求超时还可能返回 `SDK_DESTROYED`、
664
+ * `RUNTIME_UNAVAILABLE`、`REQUEST_TIMEOUT`。
665
+ *
666
+ * @remarks
667
+ * `notifications` 只在 Session 快照的 capability 集合包含 `'notifications'` 时存在;调用前必须按
668
+ * `session.notifications` 是否存在分支。该 capability 与 `stdio`、`attachments` 相互独立:Session
669
+ * 可以只提供其中一项;显示通知不要求 stdio framing,也不会创建附件、返回 `FileHandle`、消耗
670
+ * direct-handle 配额或要求 `filesystem` / `network` 权限。
671
+ *
672
+ * SDK 先校验 input 和当前 controller,再只发送私有 Session ID、controller generation 与固定
673
+ * `category`;Runtime 重复校验并裁剪 payload。页面无法传入标题、正文或任意系统通知配置,Host
674
+ * 根据 category 生成安全、平台一致的固定文案。需要展示业务详情时,应在 Mini-program UI 内呈现,
675
+ * 不要把未知字段附加到 input 期待 Host 透传。
676
+ *
677
+ * 调用不要求新的可信用户手势,但要求当前进程仍在运行且当前 Runtime generation 持有 controller。
678
+ * `session.state === 'running'` 不能证明 controller 未转移;应监听
679
+ * {@link CompanionSession.onOwnershipLost | onOwnershipLost()} 并停止后续通知请求。页面完全断开后
680
+ * 不承诺继续发送业务通知;该 API 不是 Host 后台定时通知、推送订阅或持久通知队列。
681
+ *
682
+ * V1 真实 Companion notifications 仅支持新 PC Host 的 Windows x64 与 macOS arm64;Browser Dev
683
+ * Host 只记录确定性 Fake diagnostic,不展示真实系统通知。其他平台、旧 Host、Session 未声明
684
+ * capability 或 operation 缺失时 fail closed,不回退为浏览器 Notification API、toast 或 stdio 消息。
685
+ *
686
+ * @example
687
+ * ```ts
688
+ * import hbSDK, { HbMiniProgramSDKError } from '@heybox/hb-sdk'
689
+ *
690
+ * const session = await hbSDK.companion.getActiveSession('runner')
691
+ * const notifications = session?.notifications
692
+ * if (notifications) {
693
+ * try {
694
+ * await notifications.show({ category: 'completed' })
695
+ * } catch (error) {
696
+ * if (
697
+ * error instanceof HbMiniProgramSDKError &&
698
+ * error.code === 'COMPANION_NOTIFICATION_UNAVAILABLE'
699
+ * ) {
700
+ * showCompletionInPage()
701
+ * } else {
702
+ * throw error
703
+ * }
704
+ * }
705
+ * }
706
+ * ```
707
+ *
708
+ * @see {@link CompanionNotification}
709
+ * @see {@link CompanionSession.onOwnershipLost | CompanionSession.onOwnershipLost()} 监听 controller 转移。
710
+ * @see {@link CompanionAttachments.open | CompanionAttachments.open()} 通过 opaque ID 打开受控只读附件。
711
+ * @see {@link CompanionStdio.write | CompanionStdio.write()} 向 Companion 的原始字节流写入业务协议。
712
+ * @see {@link MiniProgramCompanionModule.getActiveSession | companion.getActiveSession} 取得活动 Session controller。
713
+ * @see {@link https://docs.xiaoheihe.cn/hb_sdk/guide/companion | 受管桌面程序}
714
+ * @see {@link https://docs.xiaoheihe.cn/hb_sdk/guide/error-handling | 错误处理}
715
+ * @see {@link https://docs.xiaoheihe.cn/hb_sdk/guide/permissions | 权限声明}
716
+ */
30
717
  show(input: CompanionNotification): Promise<void>;
31
718
  }
719
+ /**
720
+ * 受 Host 监管的 Companion 活动进程 Session。
721
+ *
722
+ * Session 只暴露审核版本 Manifest 声明的能力,不暴露 PID、原生句柄、路径、命令行或环境变量。
723
+ * 页面 reload 不会结束进程;可通过 `getActiveSession()` 重新取得当前 controller。
724
+ */
32
725
  export interface CompanionSession {
726
+ /** Host 为当前活动进程分配的 opaque Session id。 */
33
727
  readonly id: string;
728
+ /** `package.json#heybox.companions` 中声明的 alias。 */
34
729
  readonly alias: string;
730
+ /** 当前 Session 使用的目标平台。 */
35
731
  readonly target: CompanionTarget;
732
+ /** 当前审核版本实际开放给 Session 的能力集合。 */
36
733
  readonly capabilities: readonly CompanionCapability[];
734
+ /** 当前状态;退出后固定为 `exited`。 */
37
735
  readonly state: CompanionState;
736
+ /** 声明并获 Host 支持 `stdio` 时存在。 */
38
737
  readonly stdio?: CompanionStdio;
738
+ /** 声明并获 Host 支持 `attachments` 时存在。 */
39
739
  readonly attachments?: CompanionAttachments;
740
+ /** 声明并获 Host 支持 `notifications` 时存在。 */
40
741
  readonly notifications?: CompanionNotifications;
742
+ /**
743
+ * 请求 Host 强制结束当前 Session 的完整受管进程树。
744
+ *
745
+ * @returns 当前 controller 对应的 Host terminate 请求成功后以 `undefined` resolve。返回值不包含
746
+ * {@link CompanionExit}、退出码或已结束的进程数量,也不等待 SDK 收到独立的 Session exit 事件;
747
+ * terminate 响应与 exit 事件可能以任意顺序到达。需要确认最终退出原因时应同时使用
748
+ * {@link CompanionSession.waitForExit | waitForExit()} 或 {@link CompanionSession.onExit | onExit()}。
749
+ * @throws {@link HbMiniProgramSDKError} 当前 proxy 已知 Session 已退出时以
750
+ * `COMPANION_SESSION_EXITED` 拒绝;当前 Runtime 已失去 controller 时以
751
+ * `COMPANION_SESSION_OWNERSHIP_LOST` 拒绝。本地检查与 Host 执行之间仍存在竞态,Host 会根据私有
752
+ * Session ID 与 controller generation 再次拒绝已退出进程或过期 controller。
753
+ * @throws {@link HbMiniProgramSDKError} Host 无法终止完整进程树时以
754
+ * `COMPANION_TERMINATE_FAILED` 拒绝;进程已异常退出、因输出上限结束或 Session 状态已变化时还
755
+ * 可能返回 `COMPANION_PROCESS_CRASHED`、`COMPANION_OUTPUT_LIMIT`、
756
+ * `COMPANION_SESSION_EXITED` 等对应稳定 Companion 错误码。
757
+ * @throws {@link HbMiniProgramSDKError} 未声明或未获批 `companion` 权限时返回
758
+ * `PERMISSION_NOT_DECLARED` / `PERMISSION_DENIED`;Host 未开放
759
+ * `companion.session.terminate` 时返回 `METHOD_FORBIDDEN`,旧 Runtime 也可能返回
760
+ * `METHOD_NOT_FOUND`。未知 Host 失败会脱敏为 `COMPANION_HOST_FAILED`;SDK / Runtime 已终止、
761
+ * 不可用或请求超时时还可能返回 `SDK_DESTROYED`、`RUNTIME_UNAVAILABLE`、`REQUEST_TIMEOUT`。
762
+ *
763
+ * @remarks
764
+ * 这是强制、非优雅终止,不会先发送业务 shutdown 消息,不会隐式调用
765
+ * {@link CompanionStdio.closeStdin | closeStdin()},也不保证 Companion 有机会刷新业务数据、清空
766
+ * stdout/stderr、完成附件写入或运行自己的退出清理。Host 负责终止由该 Session 监管的完整进程树,
767
+ * Mini-program 不能选择 PID、只杀子进程、发送自定义 signal 或取得原生进程句柄。
768
+ *
769
+ * 正常业务退出应优先使用 Companion 自己定义的 stdio 协议:通过
770
+ * {@link CompanionStdio.write | write()} 发送带幂等 ID 的 shutdown frame,按协议决定是否
771
+ * `closeStdin()`,再用 `waitForExit()` 等待进程自行退出。`terminate()` 适合用户明确执行“强制停止”、
772
+ * 进程无响应、业务协议不可用或 Host 风险处置;不要把它当作 graceful close、页面卸载清理或
773
+ * `closeStdin()` 的同义词。页面 hide、reload 本身不会自动调用本方法。
774
+ *
775
+ * `terminate()` 是每个 {@link CompanionSession} 都有的核心 controller 操作,不依赖可选的
776
+ * `'stdio'`、`'attachments'` 或 `'notifications'` capability;没有 `session.stdio` 的 Session 仍可
777
+ * 强制结束。它属于已声明并经平台批准的 `companion` 高风险能力,但调用本身不要求新的可信用户
778
+ * 手势,也不展示 prepare / launch 授权弹窗。
779
+ *
780
+ * 只有当前 controller 可以终止进程。`session.state === 'running'` 不证明当前 Runtime 仍持有
781
+ * controller;其他 Runtime 通过
782
+ * {@link MiniProgramCompanionModule.getActiveSession | companion.getActiveSession} 取得控制后,旧
783
+ * proxy 的本方法会以 `COMPANION_SESSION_OWNERSHIP_LOST` 失败。失去 controller 不影响同一 proxy 的
784
+ * `waitForExit()`:它仍可观察进程由新 controller、权限撤销或 Host shutdown 导致的最终退出。
785
+ *
786
+ * SDK 不维护“termination requested”状态,也不会合并、缓存或短路重复调用。在 exit 事件到达前
787
+ * 重复调用会再次向 Host 发送 terminate;不保证幂等,Host 可以再次确认,也可以返回
788
+ * `COMPANION_SESSION_EXITED` / `COMPANION_TERMINATE_FAILED`。请求超时或连接中断时无法从错误判断
789
+ * Host 是否已经执行终止,因此不要无条件自动重试;应等待 exit 事件或通过明确的恢复流程重新取得
790
+ * Session 状态。
791
+ *
792
+ * `terminate()` resolve 不会直接把本地 `session.state` 改成 `'exited'`。SDK 只在收到合法的
793
+ * `companion.session.exit` 事件后更新状态、resolve `waitForExit()` 并调用 `onExit()`;Host 通常会把
794
+ * 强制终止报告为 `{ reason: 'terminated' }`,但调用方应以实际 {@link CompanionExit} 为准。若 Host
795
+ * 没有接入 `HostCompanionPort.onSessionEvent()`,terminate 请求仍可能成功,而 `state` 不更新、
796
+ * `waitForExit()` 一直 pending;Mini-program 没有轮询 fallback,Host/Runtime 集成方必须提供事件源。
797
+ *
798
+ * V1 真实 Companion Session 仅支持新 PC Host 的 Windows x64 与 macOS arm64;Browser Dev Host
799
+ * Fake 会立即发出 `reason: 'terminated'` 的确定性 exit 事件,仅用于 UI 与状态机联调,不代表真实
800
+ * 操作系统的终止时序。其他平台、旧 Host 或未开放 operation 的环境 fail closed。
801
+ *
802
+ * @example
803
+ * ```ts
804
+ * import hbSDK, { HbMiniProgramSDKError } from '@heybox/hb-sdk'
805
+ *
806
+ * const session = await hbSDK.companion.getActiveSession('runner')
807
+ * if (session) {
808
+ * // 先取得持久的退出 Promise,避免假设 terminate response 与 exit event 的先后顺序。
809
+ * const exitPromise = session.waitForExit()
810
+ *
811
+ * try {
812
+ * await session.terminate()
813
+ * const exit = await exitPromise
814
+ * console.log(exit.reason, exit.exitCode)
815
+ * } catch (error) {
816
+ * if (
817
+ * error instanceof HbMiniProgramSDKError &&
818
+ * (error.code === 'COMPANION_SESSION_EXITED' ||
819
+ * error.code === 'COMPANION_SESSION_OWNERSHIP_LOST')
820
+ * ) {
821
+ * console.warn('Session 已退出或控制权已转移')
822
+ * } else {
823
+ * throw error
824
+ * }
825
+ * }
826
+ * }
827
+ * ```
828
+ *
829
+ * @see {@link CompanionSession.waitForExit | CompanionSession.waitForExit()} 等待独立的进程退出事件。
830
+ * @see {@link CompanionSession.onExit | CompanionSession.onExit()} 订阅并同步回放已收到的退出结果。
831
+ * @see {@link CompanionSession.onOwnershipLost | CompanionSession.onOwnershipLost()} 监听 controller 转移。
832
+ * @see {@link CompanionStdio.write | CompanionStdio.write()} 优先发送业务定义的优雅退出 frame。
833
+ * @see {@link CompanionStdio.closeStdin | CompanionStdio.closeStdin()} 执行输入半关闭而不终止进程。
834
+ * @see {@link MiniProgramCompanionModule.getActiveSession | companion.getActiveSession} 恢复活动 Session controller。
835
+ * @see [受管桌面程序](/guide/companion) 查看 Session、stdio 与进程树生命周期。
836
+ *
837
+ * @since 0.8.1-alpha.4
838
+ * @hbPlatform windows
839
+ * @hbPlatform macos
840
+ * @hbClient windows none
841
+ * @hbClient macos none
842
+ */
41
843
  terminate(): Promise<void>;
844
+ /**
845
+ * 等待 Host 确认当前 Companion Session 的进程终态。
846
+ *
847
+ * @returns 当前 Session proxy 持有的同一个 `Promise<CompanionExit>`。同一 proxy 每次调用都严格
848
+ * 返回同一个 Promise 实例;第一个有效退出事件到达时以冻结的 {@link CompanionExit} resolve
849
+ * 一次。若 Session 已退出,后续调用仍返回该已 fulfilled Promise,并取得同一个退出对象引用。
850
+ * @throws 该方法不接收参数、不执行校验、不发 bridge 请求,调用本身不会同步抛出
851
+ * {@link HbMiniProgramSDKError},返回的 Promise 也不会因权限、controller ownership、SDK / Runtime
852
+ * 终止或 Host 操作错误而 reject。异常终止通过 {@link CompanionExit} 的 `reason` 作为成功结果表达。
853
+ *
854
+ * @remarks
855
+ * `waitForExit()` 是纯本地一次性观察器。Session proxy 构造时即创建退出 Promise,不会因每次调用
856
+ * 新建请求、listener、timer 或轮询,也不要求新的可信用户手势。取得该 Session 的 `launch()` /
857
+ * `getActiveSession()` 仍要求已声明并经平台批准的 `companion` 权限,但等待本身不重新检查权限。
858
+ * `permission-revoked` 是可能 resolve 的退出 reason,不是该 Promise 的 rejection。
859
+ *
860
+ * SDK 只接受与当前 Session ID 匹配、由 Runtime 校验过的 `companion.session.exit` 事件。Runtime 会
861
+ * 丢弃未知 reason、缺失 `exited.exitCode` 或包含非 safe-integer exit code 的非法 Host 事件;SDK
862
+ * 对同一 Session 只处理第一条有效 exit,之后重复事件不会改变结果或再次触发生命周期迁移。退出
863
+ * 对象由 Runtime 与 SDK 分别复制/冻结,不包含 PID、路径、原生句柄、controller generation 或
864
+ * Host 私有诊断。
865
+ *
866
+ * Promise resolve 发生在 SDK 把 `session.state` 置为 `exited` 后,并且早于同步派发
867
+ * `onStateChange('exited')` 与 {@link CompanionSession.onExit | onExit()} handler。任一本地 handler
868
+ * 抛错都不会把已经确定的退出 Promise 改为 rejected。`onExit()` 适合需要取消订阅或在已退出时
869
+ * 同步回放的回调风格;`waitForExit()` 适合一次性 `await`,不需要也不提供 unsubscribe。
870
+ *
871
+ * Host 的 `onSessionEvent` 是可选集成 Port。当前支持的新 PC Host 与 Browser Dev Host Fake 会提供
872
+ * 退出事件;自定义/兼容 Host 如果返回 Session 却没有 event source,或者 Runtime/页面在退出事件
873
+ * 到达前被销毁,本 Promise 可能永久 pending。它没有 timeout、AbortSignal、取消方法或主动状态查询
874
+ * fallback;调用方不能通过取消 `await` 停止 Host 进程,也不能把 Promise pending 当作进程仍存活。
875
+ *
876
+ * controller ownership 转移与进程退出是独立状态。收到
877
+ * {@link CompanionSession.onOwnershipLost | onOwnershipLost()} 后,控制类 API 会以
878
+ * `COMPANION_SESSION_OWNERSHIP_LOST` 失败,但此 Promise 不 resolve/reject,仍等待同一 Host 进程的
879
+ * exit 事件;通过 {@link MiniProgramCompanionModule.getActiveSession | companion.getActiveSession}
880
+ * 重新取得同一 Session 的新 controller generation 时,同一 proxy 和退出 Promise 继续复用。
881
+ * 页面 reload 会创建新的 SDK/proxy,需要重新取得活动 Session 后重新等待。
882
+ *
883
+ * {@link CompanionSession.terminate | terminate()} 只请求 Host 强制终止进程,其 Promise 完成不等于
884
+ * exit 事件已经抵达,也不保证最终 {@link CompanionExit} 的 `reason`。为避免 terminate response 与 exit event 的先后竞态,
885
+ * 先保存 `const exitPromise = session.waitForExit()`,再调用 `terminate()`,最后 await 该 Promise。
886
+ * `waitForExit()` 本身不能终止、关闭 stdin 或取消 Session;正常退出应优先使用 Companion 自己的
887
+ * stdio 协议。
888
+ *
889
+ * V1 真实 Session 仅支持新 PC Host 的 Windows x64 与 macOS arm64。Browser Dev Host 的确定性
890
+ * Fake 会产生 `exited`、`crashed`、`output-limit` 和 `terminated` 等测试终态,但不执行真实进程,
891
+ * 不能替代目标系统对 exit code、崩溃和 Host shutdown 的验收。
892
+ *
893
+ * @example
894
+ * ```ts
895
+ * import hbSDK from '@heybox/hb-sdk'
896
+ *
897
+ * const session = await hbSDK.companion.getActiveSession('runner')
898
+ * if (session) {
899
+ * const exitPromise = session.waitForExit()
900
+ * console.assert(exitPromise === session.waitForExit())
901
+ *
902
+ * const stopOwnership = session.onOwnershipLost(() => {
903
+ * disableCompanionControls()
904
+ * // ownership 丢失不代表进程退出;继续等待同一个 exitPromise。
905
+ * })
906
+ *
907
+ * try {
908
+ * const exit = await exitPromise
909
+ * if (exit.reason === 'exited') {
910
+ * renderProcessExitCode(exit.exitCode)
911
+ * } else {
912
+ * renderHostTermination(exit.reason, exit.exitCode)
913
+ * }
914
+ * } finally {
915
+ * stopOwnership()
916
+ * }
917
+ * }
918
+ * ```
919
+ *
920
+ * @see {@link CompanionExit}
921
+ * @see {@link CompanionSession.onExit}
922
+ * @see {@link CompanionSession.onStateChange}
923
+ * @see {@link CompanionSession.onOwnershipLost}
924
+ * @see {@link CompanionSession.terminate}
925
+ * @see {@link MiniProgramCompanionModule.getActiveSession | companion.getActiveSession}
926
+ * @see {@link CompanionStdio.closeStdin}
927
+ * @see {@link https://docs.xiaoheihe.cn/hb_sdk/guide/companion | 受管桌面程序}
928
+ * @see {@link https://docs.xiaoheihe.cn/hb_sdk/guide/error-handling | 错误处理}
929
+ * @see {@link https://docs.xiaoheihe.cn/hb_sdk/guide/permissions | 权限声明}
930
+ */
42
931
  waitForExit(): Promise<CompanionExit>;
932
+ /**
933
+ * 订阅当前 Session 的生命周期状态变化。
934
+ *
935
+ * @param handler - 收到新状态时同步调用的函数。当前唯一的回调参数是 `'exited'`;不会在注册时
936
+ * 立即收到当前的 `'running'`,也不会收到 ownership 转移或 stdin 关闭通知。
937
+ * @returns 取消当前 handler 的同步函数。可调用一次或多次;取消后不再接收未来状态变化,不会
938
+ * 终止 Session、关闭 stdio 或取消其他 handler。相同函数引用重复注册按 `Set` 语义只保留一项,
939
+ * 任一对应取消函数都会移除该项。
940
+ * @throws {@link HbMiniProgramSDKError} `handler` 不是函数时同步抛出 `INVALID_PARAMS`。订阅本身
941
+ * 不发送 bridge 请求,因此不会因为权限、Host operation、Session 已退出或 controller 状态异步拒绝。
942
+ *
943
+ * @remarks
944
+ * 注册只是本地订阅,不会查询或回放 `session.state`。要初始化 UI,应立即读取
945
+ * `session.state`,再注册 handler;对于已经是 `'exited'` 的 proxy,注册本方法不会回放,若需要
946
+ * 退出结果应改用 {@link CompanionSession.onExit | onExit()}(它会在已收到退出后同步回放)或
947
+ * {@link CompanionSession.waitForExit | waitForExit()}(已退出时会 resolve 保存的结果)。
948
+ *
949
+ * 实际状态迁移只有 Host/Runtime 收到当前 Session ID 的合法 `companion.session.exit` 事件时才会发生:
950
+ * proxy 的 `state` 从 `'running'` 变为 `'exited'`,等待 Promise resolve,然后依次派发本 handler
951
+ * 与 `onExit` handler,最后清理状态和输出订阅。若 Host 没有提供可选的 Session event source,
952
+ * 本方法仍可注册成功,但不会主动收到变化;`state` 可能继续显示 `'running'`,
953
+ * `waitForExit()` 也可能一直 pending。SDK 没有轮询或 WebSocket fallback。
954
+ *
955
+ * handler 的同步异常不会被 SDK 捕获或转换:由于状态 handler 按 `Set` 顺序同步遍历,异常可能阻止
956
+ * 后续状态 handler、`onExit` handler 和退出后的订阅清理。请在 handler 内捕获业务异常,或使用
957
+ * 不会抛出的薄回调把错误交给自己的异步日志通道。handler 返回的 Promise 同样不会被等待;rejected
958
+ * Promise 需由业务自行处理。
959
+ *
960
+ * Session ownership 丢失不会改变 `state`,进程仍可能是 `'running'`;收到
961
+ * {@link CompanionSession.onOwnershipLost | onOwnershipLost()} 后应停止控制调用,需要恢复时由
962
+ * {@link MiniProgramCompanionModule.getActiveSession | companion.getActiveSession} 取得新 controller。
963
+ * 新 generation 复用同一 proxy 时,本地状态 handler 保持注册,但只有后续真实退出事件才会派发 `'exited'`。
964
+ * 组件销毁时应显式调用返回的取消函数,避免把页面闭包留在活动 Session 上。
965
+ *
966
+ * @example
967
+ * ```ts
968
+ * import hbSDK from '@heybox/hb-sdk'
969
+ *
970
+ * const session = await hbSDK.companion.getActiveSession('runner')
971
+ * if (session) {
972
+ * // 先读取当前值,再订阅未来的 running -> exited 迁移。
973
+ * renderState(session.state)
974
+ *
975
+ * const stopState = session.onStateChange(state => {
976
+ * renderState(state)
977
+ * })
978
+ * const stopExit = session.onExit(exit => {
979
+ * renderExit(exit)
980
+ * stopState()
981
+ * stopExit()
982
+ * })
983
+ * }
984
+ * ```
985
+ *
986
+ * @see {@link CompanionStateChangeHandler}
987
+ * @see {@link CompanionSession.state}
988
+ * @see {@link CompanionSession.onExit | CompanionSession.onExit()} 退出结果与已退出 proxy 的即时回放。
989
+ * @see {@link CompanionSession.waitForExit | CompanionSession.waitForExit()} 等待同一进程的退出结果。
990
+ * @see {@link CompanionSession.onOwnershipLost | CompanionSession.onOwnershipLost()} 观察 controller 转移。
991
+ * @see {@link MiniProgramCompanionModule.getActiveSession | companion.getActiveSession} 恢复活动 Session。
992
+ * @see {@link https://docs.xiaoheihe.cn/hb_sdk/guide/companion | 受管桌面程序}
993
+ * @see {@link https://docs.xiaoheihe.cn/hb_sdk/guide/error-handling | 错误处理}
994
+ */
43
995
  onStateChange(handler: CompanionStateChangeHandler): () => void;
996
+ /**
997
+ * 订阅当前 Companion Session 的一次性退出结果。
998
+ *
999
+ * @param handler - 接收 {@link CompanionExit} 的同步函数。必须是 function;传入其他值会在请求前
1000
+ * 同步抛出 `INVALID_PARAMS`。
1001
+ * @returns 取消该函数引用的订阅函数。Session 尚未退出时,调用后不再收到未来退出事件;同一
1002
+ * 函数引用重复注册只保留一个订阅,取消函数可重复调用。Session 已退出时,handler 会在本次注册
1003
+ * 调用中同步收到已保存的退出结果,并返回一个无操作取消函数。
1004
+ * @throws {@link HbMiniProgramSDKError} 仅当 `handler` 不是函数时同步返回 `INVALID_PARAMS`;该方法
1005
+ * 不发送 bridge 请求,不检查权限、Host capability、controller ownership,也不会因 Session 退出、
1006
+ * 事件源缺失或 Host 错误返回 Promise rejection。
1007
+ *
1008
+ * @remarks
1009
+ * 未来事件由当前 proxy 的本地 `Set` 监听集合派发,退出处理完成后集合会清空;每个 proxy 对同一
1010
+ * Session 只派发一次退出。退出 handler 与 `onStateChange('exited')` 在 SDK 已将 `state` 置为
1011
+ * `'exited'`、并 resolve 同一个 {@link CompanionSession.waitForExit | waitForExit()} Promise 后同步
1012
+ * 执行。handler 抛出的同步异常不会被 SDK 捕获,可能阻断同次退出事件中尚未执行的其他 handler;
1013
+ * 它不会撤销已经确定的 `waitForExit()` 结果。
1014
+ *
1015
+ * `onExit()` 的同步回放只适用于 SDK 已经收到并保存退出事件的 proxy。若 Host 没有接入可选的
1016
+ * Session event source,或 SDK / 页面在退出事件到达前被销毁,注册不会轮询或主动查询,handler
1017
+ * 可能永远不会调用;页面应在组件销毁时调用仍有效的取消函数。controller ownership 丢失只触发
1018
+ * {@link CompanionSession.onOwnershipLost | onOwnershipLost()},不触发 `onExit()`,因为进程可能仍在运行。
1019
+ *
1020
+ * 已退出时的同步回放发生在注册调用栈内:如果 handler 本身抛错,该异常会直接从 `onExit()` 调用
1021
+ * 冒出,调用方应在注册外层捕获。若需要等待风格且不需要取消订阅,使用
1022
+ * {@link CompanionSession.waitForExit | waitForExit()};它与 `onExit()` 观察同一个退出结果。
1023
+ *
1024
+ * V1 真实 Session 仅支持新 PC Host 的 Windows x64 与 macOS arm64;Browser Dev Host Fake 提供
1025
+ * 确定性退出事件。其他平台或缺少事件源的集成不会提供回调重放或事件轮询 fallback。
1026
+ *
1027
+ * @example
1028
+ * ```ts
1029
+ * import hbSDK from '@heybox/hb-sdk'
1030
+ *
1031
+ * const session = await hbSDK.companion.getActiveSession('runner')
1032
+ * if (session) {
1033
+ * const stop = session.onExit(exit => {
1034
+ * if (exit.reason === 'exited') {
1035
+ * renderExitCode(exit.exitCode)
1036
+ * } else {
1037
+ * renderTermination(exit.reason, exit.exitCode)
1038
+ * }
1039
+ * })
1040
+ *
1041
+ * // ownership 丢失不代表退出;它只应停止新的控制调用。
1042
+ * const stopOwnership = session.onOwnershipLost(() => disableCompanionControls())
1043
+ * try {
1044
+ * await doPageWork()
1045
+ * } finally {
1046
+ * stop()
1047
+ * stopOwnership()
1048
+ * }
1049
+ * }
1050
+ * ```
1051
+ *
1052
+ * @see {@link CompanionExitHandler}
1053
+ * @see {@link CompanionExit}
1054
+ * @see {@link CompanionSession.waitForExit | CompanionSession.waitForExit()} 等待同一退出结果。
1055
+ * @see {@link CompanionSession.onStateChange | CompanionSession.onStateChange()} 观察 `running` 到 `exited`。
1056
+ * @see {@link CompanionSession.onOwnershipLost | CompanionSession.onOwnershipLost()} 区分 controller 转移。
1057
+ * @see {@link MiniProgramCompanionModule.getActiveSession | companion.getActiveSession} 取得活动 Session。
1058
+ * @see {@link https://docs.xiaoheihe.cn/hb_sdk/guide/companion | 受管桌面程序}
1059
+ */
44
1060
  onExit(handler: CompanionExitHandler): () => void;
1061
+ /**
1062
+ * 订阅当前 Runtime 丢失 Companion Session controller 的事件。
1063
+ *
1064
+ * @param handler - 控制权从当前 Runtime 转移给其他 Runtime / 页面时调用的无参同步
1065
+ * {@link CompanionOwnershipLostHandler}。它不接收新 generation、Session ID、退出原因或错误对象。
1066
+ * @returns 同步返回取消订阅函数。调用后仅移除当前 SDK proxy 的本地 handler,不释放 controller、
1067
+ * 不停止进程、不关闭 stdio,也不向 Host 发送 unsubscribe;重复调用取消函数安全且不会抛错。
1068
+ * 相同函数引用重复注册按 Set 语义只保留一项,任一对应取消函数都会移除该项。
1069
+ * @throws {@link HbMiniProgramSDKError} `handler` 不是函数时同步抛出 `INVALID_PARAMS`。注册本身
1070
+ * 不发送 bridge 请求,因此不会因权限、Session 已退出、当前已失去 ownership 或 Host event source
1071
+ * 缺失而拒绝。
1072
+ *
1073
+ * @remarks
1074
+ * ownership lost 不是进程退出:Session 的 `state` 仍可能是 `'running'`,
1075
+ * {@link CompanionSession.waitForExit | waitForExit()} 继续等待同一进程,`onExit()` 不会因本事件
1076
+ * 触发。收到通知后,旧 proxy 的 `write()`、`closeStdin()`、`terminate()`、Attachment 和
1077
+ * Notification 控制操作都会在本地以 `COMPANION_SESSION_OWNERSHIP_LOST` 拒绝;Host 仍会用私有
1078
+ * controller generation 做最终校验。输出、退出和 ownership 事件的先后由 Host 决定,不能用本
1079
+ * 回调判断进程何时终止。
1080
+ *
1081
+ * Runtime 只接受 Session ID 匹配且 `controllerGeneration` 为非负 safe integer 的合法
1082
+ * `companion.session.ownershipLost` 事件。SDK 只在事件 generation 等于当前 proxy generation 且
1083
+ * proxy 仍标记为拥有 controller 时调用 handler;旧 generation、重复事件或已退出/已丢失控制权的
1084
+ * proxy 会被静默丢弃。该事件触发时 SDK 先把本地 ownership 标记为 false,再同步遍历当前 handlers。
1085
+ * SDK 不捕获 handler 的同步异常,也不会 await handler 返回的 Promise;业务应自行隔离异常。
1086
+ *
1087
+ * 通过 {@link MiniProgramCompanionModule.getActiveSession | companion.getActiveSession} 取得同一
1088
+ * Session 的更高 generation 时,SDK 会复用同一个 proxy、将 ownership 恢复为 true、重置 output
1089
+ * sequence 水位,并保留已注册的 handler;之后新的 ownership-lost 事件仍可再次触发同一订阅。
1090
+ * 页面 reload 会创建新的 SDK/proxy,旧订阅不会跨页面保留。
1091
+ *
1092
+ * Host 的 `HostCompanionPort.onSessionEvent()` 是可选集成 Port。若 Host 返回活动 Session 却不提供
1093
+ * event source,本方法仍会成功注册,但不会收到 ownership-lost、output 或 exit 事件,且没有轮询或
1094
+ * WebSocket fallback;控制请求仍可能直接失败为 `COMPANION_SESSION_OWNERSHIP_LOST`。Host/Runtime
1095
+ * 集成方必须提供事件源,业务不能把“尚未收到通知”当作仍拥有控制权。
1096
+ *
1097
+ * 不要求新的可信用户手势,也不改变权限或 Session 生命周期。它适用于在 ownership 丢失后立即
1098
+ * 禁用按钮、停止发送新命令并显示恢复入口;不要在回调中自动抢占 controller 或无条件重发可能已
1099
+ * 提交的 stdin/terminate 请求。
1100
+ *
1101
+ * @example
1102
+ * ```ts
1103
+ * import hbSDK from '@heybox/hb-sdk'
1104
+ *
1105
+ * const session = await hbSDK.companion.getActiveSession('runner')
1106
+ * if (session) {
1107
+ * const stopOwnership = session.onOwnershipLost(() => {
1108
+ * // 这不是退出通知;先停止新控制调用,进程仍可能运行。
1109
+ * disableCompanionControls()
1110
+ * showReacquireButton()
1111
+ * })
1112
+ * const stopExit = session.onExit(exit => renderExit(exit))
1113
+ *
1114
+ * try {
1115
+ * await runPageLifetime()
1116
+ * } finally {
1117
+ * stopOwnership()
1118
+ * stopExit()
1119
+ * }
1120
+ * }
1121
+ * ```
1122
+ *
1123
+ * @see {@link CompanionOwnershipLostHandler}
1124
+ * @see {@link CompanionSession.onExit | CompanionSession.onExit()} 监听真实进程退出。
1125
+ * @see {@link CompanionSession.waitForExit | CompanionSession.waitForExit()} 等待真实退出结果。
1126
+ * @see {@link MiniProgramCompanionModule.getActiveSession | companion.getActiveSession} 恢复 controller。
1127
+ * @see {@link CompanionSession.terminate | CompanionSession.terminate()} 强制终止进程树。
1128
+ * @see {@link CompanionStdio.write | CompanionStdio.write()} 发送业务协议命令。
1129
+ * @see [受管桌面程序](/guide/companion) 查看 ownership、Session 与恢复流程。
1130
+ *
1131
+ * @since 0.8.1-alpha.4
1132
+ * @hbPlatform windows
1133
+ * @hbPlatform macos
1134
+ * @hbClient windows none
1135
+ * @hbClient macos none
1136
+ */
45
1137
  onOwnershipLost(handler: CompanionOwnershipLostHandler): () => void;
46
1138
  }
47
1139
  export interface MiniProgramCompanionModule {
48
1140
  /**
49
- * 读取指定 alias 的 Companion 信息与就绪状态。
1141
+ * 读取指定 alias 在当前版本与当前平台上的 Companion 描述快照。
1142
+ *
1143
+ * @param alias - `package.json#heybox.companions` 中声明的 Companion alias。必须完整匹配
1144
+ * `[a-z][a-z0-9-]{0,31}`:长度为 1 至 32,第一个字符是小写 ASCII 字母,其余字符
1145
+ * 只能是小写字母、数字或连字符;SDK 不会 trim 或改变大小写。
1146
+ * @returns Host 绑定的当前审核版本、精确预览版本或本地开发快照对应的冻结
1147
+ * {@link CompanionInfo}。返回只描述当前平台选中的制品,不包含准备状态或活动 Session。
1148
+ * @throws {@link HbMiniProgramSDKError} alias 不符合格式时在请求前以 `INVALID_PARAMS`
1149
+ * 拒绝;当前版本未声明 alias、当前平台没有匹配 target、预览 Host 不支持 Companion、
1150
+ * 描述符暂不可用或当前 Host 不支持能力时,可能以 `COMPANION_NOT_DECLARED`、
1151
+ * `COMPANION_TARGET_UNSUPPORTED`、`COMPANION_PREVIEW_UNSUPPORTED`、
1152
+ * `COMPANION_DESCRIPTOR_UNAVAILABLE`、`COMPANION_UNSUPPORTED` 或 `METHOD_FORBIDDEN` 拒绝。
1153
+ * 未声明或未获批 `companion` 权限时分别以 `PERMISSION_NOT_DECLARED`、
1154
+ * `PERMISSION_DENIED` 拒绝;Host 返回 alias 不匹配、未知 target/capability/source、非法大小
1155
+ * 或签名状态时以 `COMPANION_HOST_FAILED` 拒绝。握手失败、SDK/Runtime 已销毁、bridge
1156
+ * 超时及其他 Host 失败会保留对应 SDK 错误码。
1157
+ *
1158
+ * @remarks
1159
+ * 该方法是只读查询:不会下载、校验、解压、准备或启动程序,也不会创建或取得 Session
1160
+ * controller。它不要求可信用户手势,不展示 prepare/launch 的 Host 授权弹窗,但仍需要
1161
+ * Manifest 声明且平台批准 `companion` 权限。V1 真实能力仅支持新 PC Host 的
1162
+ * `windows-x64` 与 `macos-arm64`;Browser Dev Host 返回固定 Fake 描述,仅用于状态联调。
1163
+ *
1164
+ * SDK 不缓存该结果,每次调用都会重新向 Host 查询当前绑定上下文。返回字段包括请求的
1165
+ * `alias`、展示名 `displayName`、当前平台选中的 `target`、去重后的 `capabilities`、压缩
1166
+ * 归档字节数 `archiveBytes`、签名检查状态 `signatureStatus` 和可选来源 `source`。Runtime
1167
+ * 会丢弃 Host 提供的路径、下载 URL、SHA-256、entrypoint 等敏感或非公开字段。
1168
+ *
1169
+ * {@link CompanionInfo} 没有 `state` 或版本字段。使用
1170
+ * {@link MiniProgramCompanionModule.getPreparationStatus | companion.getPreparationStatus}
1171
+ * 区分 `not-prepared`、`preparing`、`ready`、`failed`;需要开始准备时,必须在新的可信
1172
+ * 用户操作中显式调用 {@link MiniProgramCompanionModule.prepare | companion.prepare}。
1173
+ * `getInfo()` 成功不表示制品已经下载、签名有效、可以启动或存在活动 Session。
1174
+ *
1175
+ * @example
1176
+ * ```ts
1177
+ * import hbSDK from '@heybox/hb-sdk'
1178
+ *
1179
+ * const info = await hbSDK.companion.getInfo('runner')
1180
+ * const status = await hbSDK.companion.getPreparationStatus('runner')
1181
+ *
1182
+ * renderCompanionSummary({
1183
+ * name: info.displayName,
1184
+ * target: info.target,
1185
+ * archiveBytes: info.archiveBytes,
1186
+ * source: info.source ?? 'unknown',
1187
+ * capabilities: info.capabilities,
1188
+ * preparationState: status.state,
1189
+ * })
1190
+ * ```
1191
+ *
1192
+ * @see {@link CompanionInfo}
1193
+ * @see {@link MiniProgramCompanionModule.getPreparationStatus | companion.getPreparationStatus}
1194
+ * @see {@link MiniProgramCompanionModule.prepare | companion.prepare}
1195
+ * @see {@link https://docs.xiaoheihe.cn/hb_sdk/guide/companion | 受管桌面程序}
1196
+ * @see {@link https://docs.xiaoheihe.cn/hb_sdk/guide/permissions | 权限声明}
50
1197
  *
51
- * @param alias - `package.json#heybox.companions` 中声明的 Companion alias。
52
- * @returns 当前审核版本对应的 Companion 信息。
53
1198
  * @since 0.8.1-alpha.4
54
1199
  * @hbPlatform windows
55
1200
  * @hbPlatform macos
@@ -60,8 +1205,74 @@ export interface MiniProgramCompanionModule {
60
1205
  /**
61
1206
  * 查询指定 alias 的准备状态;页面 reload 后可据此重新加入在途准备。
62
1207
  *
63
- * @param alias - `package.json#heybox.companions` 中声明的 Companion alias。
64
- * @returns 当前准备状态。
1208
+ * @param alias - `package.json#heybox.companions` 中声明的 Companion alias。必须完整匹配
1209
+ * `[a-z][a-z0-9-]{0,31}`:长度为 1 至 32,第一个字符是小写 ASCII 字母,其余字符
1210
+ * 只能是小写字母、数字或连字符;SDK 不会 trim 或改变大小写。
1211
+ * @returns Host 当前保存的冻结 {@link CompanionPreparationStatus} 快照,以 `state` 区分
1212
+ * `not-prepared`、`preparing`、`ready` 与 `failed`。
1213
+ * @throws {@link HbMiniProgramSDKError} alias 不符合格式时在请求前以 `INVALID_PARAMS`
1214
+ * 拒绝;当前版本未声明 alias、当前平台没有匹配 target、预览 Host 不支持 Companion、
1215
+ * 描述符暂不可用或 Host 不支持该能力时,可能以 `COMPANION_NOT_DECLARED`、
1216
+ * `COMPANION_TARGET_UNSUPPORTED`、`COMPANION_PREVIEW_UNSUPPORTED`、
1217
+ * `COMPANION_DESCRIPTOR_UNAVAILABLE`、`COMPANION_UNSUPPORTED` 或 `METHOD_FORBIDDEN` 拒绝。
1218
+ * 未声明或未获批 `companion` 权限时分别以 `PERMISSION_NOT_DECLARED`、
1219
+ * `PERMISSION_DENIED` 拒绝;Host 返回未知 state、非法进度、非法 `preparedAt` 或失败摘要
1220
+ * 时以 `COMPANION_HOST_FAILED` 拒绝。握手失败、SDK/Runtime 已销毁、bridge 超时及其他
1221
+ * Host 失败会保留对应 SDK 错误码。
1222
+ *
1223
+ * @remarks
1224
+ * 该方法是只读查询:不会开始、加入或取消准备,不会下载、校验、解压或启动程序。
1225
+ * 它不要求可信用户手势,也不展示 prepare/launch 的 Host 授权弹窗,但仍需要 Manifest
1226
+ * 声明且平台批准 `companion` 权限。V1 真实能力仅支持新 PC Host 的 `windows-x64` 与
1227
+ * `macos-arm64`;Browser Dev Host 的固定 Fake 状态只用于恢复流程联调。
1228
+ *
1229
+ * - `not-prepared`:当前版本与 target 没有已提交产物,也没有在途操作。需要由新的可信
1230
+ * 用户操作调用 {@link MiniProgramCompanionModule.prepare | companion.prepare}。
1231
+ * - `preparing`:Host 持有在途操作,`progress` 是查询时的最近快照。页面 reload、最小化
1232
+ * 或进入后台不会取消它;需要持续进度时可再次调用 `prepare()` 加入同一操作并传
1233
+ * `onProgress`,而不是轮询本方法模拟事件流。
1234
+ * - `ready`:产物已完成原子提交;`preparedAt` 是 Host 时间戳,不是过期时间或版本号。
1235
+ * 启动仍需新的可信用户手势和独立 Host 授权。
1236
+ * - `failed`:`error.code` 是稳定分支字段,`message` 是 Runtime 规范化文案;
1237
+ * `retryable` 只建议一次新的 prepare 是否可能成功,不会自动重试或绕过门禁。
1238
+ *
1239
+ * 状态由 Host 按当前小程序 identity、版本、target 与 alias 持有,页面 reload 后可以重新
1240
+ * 查询恢复 UI。快照不随状态变化自动更新:调用 `prepare()`、
1241
+ * {@link MiniProgramCompanionModule.cancelPreparation | companion.cancelPreparation} 或发生
1242
+ * 原子提交竞态后,应再次查询对账。取消意图不保证赢得提交竞态,因此取消后仍可能得到
1243
+ * `ready`,不能直接在页面本地假设 `not-prepared`。
1244
+ *
1245
+ * {@link MiniProgramCompanionModule.getInfo | companion.getInfo} 读取当前产物的名称、target、
1246
+ * capability、大小、签名与来源,但不包含准备 state;两者不能互相替代。
1247
+ *
1248
+ * @example
1249
+ * ```ts
1250
+ * import hbSDK from '@heybox/hb-sdk'
1251
+ *
1252
+ * const status = await hbSDK.companion.getPreparationStatus('runner')
1253
+ * switch (status.state) {
1254
+ * case 'not-prepared':
1255
+ * showPrepareButton()
1256
+ * break
1257
+ * case 'preparing':
1258
+ * renderProgress(status.progress)
1259
+ * break
1260
+ * case 'ready':
1261
+ * showLaunchButton(status.preparedAt)
1262
+ * break
1263
+ * case 'failed':
1264
+ * renderPreparationError(status.error.code, status.error.retryable)
1265
+ * }
1266
+ * ```
1267
+ *
1268
+ * @see {@link CompanionPreparationStatus}
1269
+ * @see {@link CompanionPrepareProgress}
1270
+ * @see {@link MiniProgramCompanionModule.getInfo | companion.getInfo}
1271
+ * @see {@link MiniProgramCompanionModule.prepare | companion.prepare}
1272
+ * @see {@link MiniProgramCompanionModule.cancelPreparation | companion.cancelPreparation}
1273
+ * @see {@link https://docs.xiaoheihe.cn/hb_sdk/guide/companion | 受管桌面程序}
1274
+ * @see {@link https://docs.xiaoheihe.cn/hb_sdk/guide/permissions | 权限声明}
1275
+ *
65
1276
  * @since 0.8.1-alpha.4
66
1277
  * @hbPlatform windows
67
1278
  * @hbPlatform macos
@@ -70,12 +1281,98 @@ export interface MiniProgramCompanionModule {
70
1281
  */
71
1282
  getPreparationStatus(alias: string): Promise<CompanionPreparationStatus>;
72
1283
  /**
73
- * 在可信用户手势下准备指定 alias 的 Companion 产物,并可观察进度或通过 `AbortSignal` 取消。
1284
+ * 准备指定 alias 的 Companion 产物,并可观察进度或请求取消。
1285
+ *
1286
+ * @param alias - `package.json#heybox.companions` 中声明的 Companion alias。必须完整匹配
1287
+ * `[a-z][a-z0-9-]{0,31}`:长度为 1 至 32,第一个字符是小写 ASCII 字母,其余字符
1288
+ * 只能是小写字母、数字或连字符;SDK 不会 trim 或改变大小写。
1289
+ * @param options - 可选取消信号与进度回调;字段合同见 {@link CompanionPrepareOptions}。
1290
+ * @returns Host 完成原子提交后返回当前产物的冻结 {@link CompanionInfo}。如果产物已经
1291
+ * `ready`,Host 可直接返回;如果加入同 alias 在途操作,则与该共享操作一同 settle。
1292
+ * 返回值没有 `state` 或 `preparedAt`,需要这些字段时调用
1293
+ * {@link MiniProgramCompanionModule.getPreparationStatus | companion.getPreparationStatus}。
1294
+ * @throws {@link HbMiniProgramSDKError} alias、options、`signal` 或 `onProgress` 不合法时在
1295
+ * 请求前以 `INVALID_PARAMS` 拒绝。真正开始新准备时,缺少新的可信用户手势以
1296
+ * `USER_GESTURE_REQUIRED` 拒绝,用户取消 Host 授权以 `COMPANION_USER_CANCELLED` 拒绝;
1297
+ * 下载、归档、完整性或入口失败,以及准备被取消时,分别可能以 `COMPANION_DOWNLOAD_FAILED`、
1298
+ * `COMPANION_ARCHIVE_INVALID`、`COMPANION_INTEGRITY_FAILED`、
1299
+ * `COMPANION_ENTRYPOINT_INVALID`、`COMPANION_PREPARATION_CANCELLED` 拒绝。
1300
+ *
1301
+ * 当前版本未声明 alias、当前平台没有匹配 target、预览 Host 不支持 Companion、描述符
1302
+ * 暂不可用或当前 Host 未开放能力时,可能以 `COMPANION_NOT_DECLARED`、
1303
+ * `COMPANION_TARGET_UNSUPPORTED`、`COMPANION_PREVIEW_UNSUPPORTED`、
1304
+ * `COMPANION_DESCRIPTOR_UNAVAILABLE`、`COMPANION_UNSUPPORTED` 或 `METHOD_FORBIDDEN` 拒绝。
1305
+ * 未声明或未获批 `companion` 权限时分别以 `PERMISSION_NOT_DECLARED`、
1306
+ * `PERMISSION_DENIED` 拒绝;Host 返回非法状态、进度或产物描述时以
1307
+ * `COMPANION_HOST_FAILED` 拒绝。握手失败、SDK/Runtime 已销毁及其他 bridge 或 Host 失败
1308
+ * 会保留对应 SDK 错误码。
1309
+ *
1310
+ * @remarks
1311
+ * 准备由 Host 持有,包含下载、SHA-256/归档校验、受控解压和原子提交。真正开始一项新
1312
+ * 准备前,Runtime 要求新的可信用户手势,并展示一次 Host 授权;调用应直接发生在准备
1313
+ * 按钮回调中,作为该回调的第一个异步操作,不要预先等待握手或其他 Promise。
1314
+ *
1315
+ * 同一小程序 identity、版本、target 与 alias 同时只运行一项准备。状态已经
1316
+ * `preparing` 时,再次调用会加入同一操作、复用下载并接收进度,不重复授权;状态已经
1317
+ * `ready` 时也不重复授权或下载。因而 join/ready 快路径可以在没有新手势时完成,但业务
1318
+ * 不应依赖它绕过真正新准备的手势要求。
1319
+ *
1320
+ * 页面 reload、最小化或进入后台只断开当前 observer,不会取消 Host 操作。新页面先调用
1321
+ * `getPreparationStatus()` 恢复 UI;若为 `preparing`,可再次调用 `prepare()` 加入并继续
1322
+ * 观察。该长操作不使用普通 SDK 请求的固定总时长 timeout,仍可能因 Host、网络、权限
1323
+ * 撤销或 Runtime 终止失败。
1324
+ *
1325
+ * `onProgress` 只用于展示,完整阶段为 `downloading`、`verifying`、`extracting`。业务不能
1326
+ * 根据进度值自行判断 ready;Promise resolve 或重新查询到 `ready` 才表示 Host 已完成
1327
+ * 原子提交。
1328
+ *
1329
+ * 在途 `signal` 触发或显式调用
1330
+ * {@link MiniProgramCompanionModule.cancelPreparation | companion.cancelPreparation} 都只发送
1331
+ * best-effort 取消意图。取消先于提交生效时,prepare 通常以
1332
+ * `COMPANION_PREPARATION_CANCELLED` 拒绝;原子提交已开始时提交结果优先,本 Promise 仍
1333
+ * 可能成功并返回 {@link CompanionInfo}。取消后应重新查询状态,不能直接假设
1334
+ * `not-prepared`。
1335
+ *
1336
+ * `prepare()` 只使产物 ready,不会启动进程。真正新启动必须由另一场可信用户操作调用
1337
+ * {@link MiniProgramCompanionModule.launch | companion.launch},不能在同一个点击中
1338
+ * `await prepare()` 后串联。只需要名称、target、能力、大小、签名或来源时,使用
1339
+ * {@link MiniProgramCompanionModule.getInfo | companion.getInfo},避免触发准备工作流。
1340
+ *
1341
+ * 该调用需要 Manifest 声明且平台批准 `companion` 权限。V1 真实准备仅支持新 PC Host 的
1342
+ * `windows-x64` 与 `macos-arm64`;Browser Dev Host 只模拟固定进度和状态,不下载、校验或
1343
+ * 解压真实归档,不能替代目标系统验收。
1344
+ *
1345
+ * @example
1346
+ * ```ts
1347
+ * import hbSDK from '@heybox/hb-sdk'
1348
+ *
1349
+ * prepareButton.addEventListener('click', () => {
1350
+ * const controller = new AbortController()
1351
+ * cancelButton.onclick = () => controller.abort()
1352
+ *
1353
+ * // prepare() 是本次点击中的第一个异步操作。
1354
+ * void hbSDK.companion.prepare('runner', {
1355
+ * signal: controller.signal,
1356
+ * onProgress(progress) {
1357
+ * renderProgress(progress)
1358
+ * },
1359
+ * }).then(info => {
1360
+ * renderPreparedArtifact(info.displayName, info.source)
1361
+ * showLaunchButton() // launch 由之后另一场点击触发。
1362
+ * }).catch(showPreparationError)
1363
+ * })
1364
+ * ```
1365
+ *
1366
+ * @see {@link CompanionPrepareOptions}
1367
+ * @see {@link CompanionPrepareProgress}
1368
+ * @see {@link CompanionInfo}
1369
+ * @see {@link MiniProgramCompanionModule.getInfo | companion.getInfo}
1370
+ * @see {@link MiniProgramCompanionModule.getPreparationStatus | companion.getPreparationStatus}
1371
+ * @see {@link MiniProgramCompanionModule.cancelPreparation | companion.cancelPreparation}
1372
+ * @see {@link MiniProgramCompanionModule.launch | companion.launch}
1373
+ * @see {@link https://docs.xiaoheihe.cn/hb_sdk/guide/companion | 受管桌面程序}
1374
+ * @see {@link https://docs.xiaoheihe.cn/hb_sdk/guide/permissions | 权限声明}
74
1375
  *
75
- * @param alias - `package.json#heybox.companions` 中声明的 Companion alias。
76
- * @param options - 进度回调与取消信号。
77
- * @returns 准备完成后的 Companion 信息。
78
- * @remarks 准备操作由 Host 持有,页面 reload 只断开观察者;同一 alias 可加入同一在途准备。
79
1376
  * @since 0.8.1-alpha.4
80
1377
  * @hbPlatform windows
81
1378
  * @hbPlatform macos
@@ -86,7 +1383,56 @@ export interface MiniProgramCompanionModule {
86
1383
  /**
87
1384
  * 取消指定 alias 的在途准备;已进入原子提交时最终提交结果优先于取消意图。
88
1385
  *
89
- * @param alias - `package.json#heybox.companions` 中声明的 Companion alias。
1386
+ * @param alias - `package.json#heybox.companions` 中声明的 Companion alias。必须完整匹配
1387
+ * `[a-z][a-z0-9-]{0,31}`:长度为 1 至 32,第一个字符是小写 ASCII 字母,其余字符
1388
+ * 只能是小写字母、数字或连字符;SDK 不会 trim 或改变大小写。
1389
+ * @returns Host 处理本次取消意图后以 `undefined` resolve。该时点不表示关联的
1390
+ * `prepare()` Promise 已经 settle,也不返回是否找到在途操作或取消是否赢得竞态。
1391
+ * @throws {@link HbMiniProgramSDKError} alias 不符合格式时在请求前以 `INVALID_PARAMS`
1392
+ * 拒绝;当前审核版本未声明该 alias、目标平台不匹配或 Host 不支持 Companion 时可能以
1393
+ * `COMPANION_NOT_DECLARED`、`COMPANION_TARGET_UNSUPPORTED`、`COMPANION_UNSUPPORTED` 或
1394
+ * `METHOD_FORBIDDEN` 拒绝。未声明或未获批 `companion` 权限时分别以
1395
+ * `PERMISSION_NOT_DECLARED`、`PERMISSION_DENIED` 拒绝;握手失败、SDK/Runtime 已销毁、
1396
+ * bridge 超时及其他 Host 失败会保留对应 SDK 错误码。
1397
+ *
1398
+ * @remarks
1399
+ * 这是幂等、best-effort 的 Host 取消请求。没有在途准备时调用会成功 no-op;alias 已经
1400
+ * `ready` 时也会成功,但不会删除、回滚或使已提交产物变回 `not-prepared`。重复调用不会
1401
+ * 叠加取消次数,也不会停止已启动的 Companion Session。
1402
+ *
1403
+ * 取消只在 Host 原子提交开始前保证有机会终止下载、校验或解压。取消和提交并发时,
1404
+ * 原子提交结果优先:本方法可能已经 resolve,而受影响的 `prepare()` 仍成功返回,随后
1405
+ * {@link MiniProgramCompanionModule.getPreparationStatus | companion.getPreparationStatus}
1406
+ * 也可能是 `ready`。取消抢先生效时,在途 `prepare()` 通常以
1407
+ * `COMPANION_PREPARATION_CANCELLED` 拒绝;该错误属于准备调用,不是本方法成功 resolve 的
1408
+ * 返回值。调用后应重新查询 Host 状态,不能直接把 UI 固定为 `not-prepared`。
1409
+ *
1410
+ * 本方法需要已声明并经平台批准的 `companion` 权限,但不需要可信用户手势,也不会显示
1411
+ * prepare/launch 的 Host 授权弹窗。显式取消按钮或新页面取消旧的 Host 操作时应 await
1412
+ * 本方法;若取消只与当前 `prepare()` 调用的生命周期绑定,可传入 `AbortSignal`,在途
1413
+ * 调用的 signal 触发时 SDK 会向 Host 发送同类取消意图,但页面 reload 本身不会自动取消
1414
+ * Host 操作。
1415
+ *
1416
+ * @example
1417
+ * ```ts
1418
+ * import hbSDK from '@heybox/hb-sdk'
1419
+ *
1420
+ * await hbSDK.companion.cancelPreparation('runner')
1421
+ *
1422
+ * const status = await hbSDK.companion.getPreparationStatus('runner')
1423
+ * if (status.state === 'ready') {
1424
+ * // 原子提交赢得竞态,产物仍然可以由新的用户操作启动。
1425
+ * showReadyState()
1426
+ * } else {
1427
+ * renderPreparationStatus(status)
1428
+ * }
1429
+ * ```
1430
+ *
1431
+ * @see {@link MiniProgramCompanionModule.prepare | companion.prepare}
1432
+ * @see {@link MiniProgramCompanionModule.getPreparationStatus | companion.getPreparationStatus}
1433
+ * @see {@link https://docs.xiaoheihe.cn/hb_sdk/guide/companion | 受管桌面程序}
1434
+ * @see {@link https://docs.xiaoheihe.cn/hb_sdk/guide/permissions | 权限声明}
1435
+ *
90
1436
  * @since 0.8.1-alpha.4
91
1437
  * @hbPlatform windows
92
1438
  * @hbPlatform macos
@@ -95,11 +1441,97 @@ export interface MiniProgramCompanionModule {
95
1441
  */
96
1442
  cancelPreparation(alias: string): Promise<void>;
97
1443
  /**
98
- * 在独立的可信用户手势与 Host 授权下启动指定 alias 的 Companion,并返回当前 Session。
1444
+ * 启动指定 alias 的 Companion,或取得已经活动的同 alias Session。
1445
+ *
1446
+ * @param alias - `package.json#heybox.companions` 中声明的 Companion alias。必须完整匹配
1447
+ * `[a-z][a-z0-9-]{0,31}`:长度为 1 至 32,第一个字符是小写 ASCII 字母,其余字符
1448
+ * 只能是小写字母、数字或连字符;SDK 不会 trim 或改变大小写。
1449
+ * @returns Host 确认进程处于 `running` 并把当前 controller 交给本 Runtime 后返回
1450
+ * {@link CompanionSession} proxy。如果同 alias 已有活动 Session,则返回该进程而不是
1451
+ * 创建第二个;同一 SDK 页面内相同 Session ID 会复用同一个 proxy 对象。
1452
+ * @throws {@link HbMiniProgramSDKError} alias 不符合格式时在请求前以 `INVALID_PARAMS`
1453
+ * 拒绝。真正创建新进程时,缺少新的可信用户手势以 `USER_GESTURE_REQUIRED` 拒绝,用户
1454
+ * 取消 Host 授权以 `COMPANION_USER_CANCELLED` 拒绝,产物尚未 ready 以
1455
+ * `COMPANION_NOT_PREPARED` 拒绝;描述符不可用、操作系统阻止、启动失败或未来管理员权限
1456
+ * 被拒绝时,可能以 `COMPANION_DESCRIPTOR_UNAVAILABLE`、`COMPANION_OS_BLOCKED`、
1457
+ * `COMPANION_LAUNCH_FAILED`、`COMPANION_ELEVATION_DENIED` 拒绝。
1458
+ *
1459
+ * 当前版本未声明 alias、当前平台没有匹配 target、预览 Host 不支持 Companion 或当前
1460
+ * Host 未开放能力时,可能以 `COMPANION_NOT_DECLARED`、`COMPANION_TARGET_UNSUPPORTED`、
1461
+ * `COMPANION_PREVIEW_UNSUPPORTED`、`COMPANION_UNSUPPORTED` 或 `METHOD_FORBIDDEN` 拒绝。
1462
+ * 未声明或未获批 `companion` 权限时分别以 `PERMISSION_NOT_DECLARED`、
1463
+ * `PERMISSION_DENIED` 拒绝;Host 返回非法 Session 快照时以 `COMPANION_HOST_FAILED` 拒绝,
1464
+ * 同一 Session ID 的 alias、target 或 capability 集合发生不兼容变化时以
1465
+ * `COMPANION_SESSION_VERSION_MISMATCH` 拒绝。握手失败、SDK/Runtime 已销毁及其他 bridge
1466
+ * 或 Host 失败会保留对应 SDK 错误码。
1467
+ *
1468
+ * @remarks
1469
+ * `launch()` 不会隐式调用 {@link MiniProgramCompanionModule.prepare | companion.prepare},
1470
+ * 也不会下载、校验或解压产物。没有活动 Session 时,产物必须已通过原子提交进入
1471
+ * `ready`;应先用
1472
+ * {@link MiniProgramCompanionModule.getPreparationStatus | companion.getPreparationStatus}
1473
+ * 展示准备状态,并由单独的用户操作完成准备。
1474
+ *
1475
+ * 真正创建新进程的 `launch()` 与开始新准备的 `prepare()` 必须来自两次独立的可信用户
1476
+ * 手势和两次 Host 授权。不要在一个点击回调中 `await prepare()` 后串联 launch,也不要在
1477
+ * 页面挂载、定时器或 Promise continuation 中自动启动。调用 `launch()` 时应把它作为用户
1478
+ * 回调中的第一个异步操作;SDK/Runtime 会自行处理握手。
1479
+ *
1480
+ * 同一小程序 identity 与 alias 同时最多有一个活动 Session。Runtime 会先查询活动进程;
1481
+ * 若存在,则直接取得并返回它,不要求新的手势、不显示 launch 授权,也不调用 Host 的新
1482
+ * 进程启动原语。页面 reload 后只需恢复现有进程时,优先使用
1483
+ * {@link MiniProgramCompanionModule.getActiveSession | companion.getActiveSession},更清楚地
1484
+ * 表达“重新取得 controller”而不是“启动”。
1485
+ *
1486
+ * 返回的 proxy 公开稳定的 `id`、`alias`、`target`、只读 `capabilities` 与初始
1487
+ * `state: 'running'`,以及 `terminate()`、`waitForExit()`、`onStateChange()`、`onExit()`、
1488
+ * `onOwnershipLost()`。它不暴露 PID、物理路径、命令行、原生句柄或 controller
1489
+ * generation。只有 Host 返回的 capability 集合包含对应项时,`stdio`、`attachments`、
1490
+ * `notifications` 才存在;调用方必须按属性是否存在分支。
1491
+ *
1492
+ * 进程由 Host 持有,页面隐藏或 reload 不会结束它。当前受支持的新 PC Host 提供 Session
1493
+ * event source;其他 Runtime 取得 controller 后,当前 proxy 会触发 `onOwnershipLost()`,控制类操作随后以
1494
+ * `COMPANION_SESSION_OWNERSHIP_LOST` 失败,但 `waitForExit()` 仍等待同一进程退出。退出后
1495
+ * `state` 变为 `exited`,`onExit()` 与 `waitForExit()` 获得同一份退出结果。自定义 Host 若未提供
1496
+ * 可选的 Session 事件源,则这些本地监听不会主动更新,`waitForExit()` 也可能一直 pending;集成方应补齐事件源。
1497
+ *
1498
+ * 该调用需要 Manifest 声明且平台批准 `companion` 权限。V1 真实启动仅支持新 PC Host 的
1499
+ * `windows-x64` 与 `macos-arm64`;Browser Dev Host 只启动确定性 Fake,不下载、不解压、
1500
+ * 不执行本机程序,不能替代目标系统验收。可先用
1501
+ * {@link MiniProgramCompanionModule.getInfo | companion.getInfo} 展示 target、capability、签名
1502
+ * 与产物来源,但这些元数据本身不表示已经 ready。
1503
+ *
1504
+ * @example
1505
+ * ```ts
1506
+ * import hbSDK from '@heybox/hb-sdk'
1507
+ *
1508
+ * launchButton.addEventListener('click', () => {
1509
+ * // launch() 是点击回调中的第一个异步操作,不复用 prepare() 的手势。
1510
+ * void launchRunner().catch(showLaunchError)
1511
+ * })
1512
+ *
1513
+ * async function launchRunner() {
1514
+ * const session = await hbSDK.companion.launch('runner')
1515
+ * const stopOwnership = session.onOwnershipLost(disableCompanionControls)
1516
+ * const stopOutput = session.stdio?.onStdout(handleCompanionBytes)
1517
+ *
1518
+ * const exit = await session.waitForExit()
1519
+ * stopOutput?.()
1520
+ * stopOwnership()
1521
+ * renderCompanionExit(exit)
1522
+ * }
1523
+ * ```
1524
+ *
1525
+ * @see {@link CompanionSession}
1526
+ * @see {@link CompanionSession.waitForExit}
1527
+ * @see {@link CompanionSession.onOwnershipLost}
1528
+ * @see {@link MiniProgramCompanionModule.getInfo | companion.getInfo}
1529
+ * @see {@link MiniProgramCompanionModule.getPreparationStatus | companion.getPreparationStatus}
1530
+ * @see {@link MiniProgramCompanionModule.prepare | companion.prepare}
1531
+ * @see {@link MiniProgramCompanionModule.getActiveSession | companion.getActiveSession}
1532
+ * @see {@link https://docs.xiaoheihe.cn/hb_sdk/guide/companion | 受管桌面程序}
1533
+ * @see {@link https://docs.xiaoheihe.cn/hb_sdk/guide/permissions | 权限声明}
99
1534
  *
100
- * @param alias - `package.json#heybox.companions` 中声明的 Companion alias。
101
- * @returns 新启动进程对应的 Session 代理。
102
- * @remarks 不会隐式准备,未准备时稳定失败;启动不会触发隐式下载。
103
1535
  * @since 0.8.1-alpha.4
104
1536
  * @hbPlatform windows
105
1537
  * @hbPlatform macos
@@ -110,8 +1542,77 @@ export interface MiniProgramCompanionModule {
110
1542
  /**
111
1543
  * 取得指定 alias 当前活动 Session 的控制权。
112
1544
  *
113
- * @param alias - `package.json#heybox.companions` 中声明的 Companion alias。
114
- * @returns 当前活动 Session;没有活动进程时返回 `undefined`。
1545
+ * @param alias - `package.json#heybox.companions` 中声明的 Companion alias。必须完整匹配
1546
+ * `[a-z][a-z0-9-]{0,31}`:长度为 1 至 32,第一个字符是小写 ASCII 字母,其余字符
1547
+ * 只能是小写字母、数字或连字符;SDK 不会 trim 或改变大小写。
1548
+ * @returns Host 没有该 alias 的活动进程时返回 `undefined`;否则返回取得当前 controller
1549
+ * 的 {@link CompanionSession} proxy。`undefined` 只表示没有正在运行的进程,可能是尚未
1550
+ * 启动、已经退出或从未启动,不表示产物未准备。
1551
+ * @throws {@link HbMiniProgramSDKError} alias 不符合格式时在请求前以 `INVALID_PARAMS`
1552
+ * 拒绝;当前审核版本未声明 alias、目标平台不匹配或 Host 不支持时可能以
1553
+ * `COMPANION_NOT_DECLARED`、`COMPANION_TARGET_UNSUPPORTED`、`COMPANION_UNSUPPORTED` 或
1554
+ * `METHOD_FORBIDDEN` 拒绝。未声明或未获批 `companion` 权限时分别以
1555
+ * `PERMISSION_NOT_DECLARED`、`PERMISSION_DENIED` 拒绝;Host 返回非法 Session 快照时以
1556
+ * `COMPANION_HOST_FAILED` 拒绝,同一 Session ID 的 alias、target 或 capability 集合发生
1557
+ * 不兼容变化时以 `COMPANION_SESSION_VERSION_MISMATCH` 拒绝。握手失败、SDK/Runtime 已
1558
+ * 销毁、bridge 超时及其他 Host 失败会保留对应 SDK 错误码。
1559
+ *
1560
+ * @remarks
1561
+ * 这不是只读状态查询。Host 成功返回活动 Session 时会把该 Session 的 controller 转移
1562
+ * 给当前 Runtime,并使用递增的私有 generation 使旧 controller 失效;generation 不会暴露
1563
+ * 在 {@link CompanionSession} 上。其他页面或 Runtime 后续取得控制权时,当前 proxy 的
1564
+ * {@link CompanionSession.onOwnershipLost} 会收到通知,之后 `write()`、`closeStdin()`、
1565
+ * `terminate()`、附件和通知等控制操作以 `COMPANION_SESSION_OWNERSHIP_LOST` 失败。
1566
+ *
1567
+ * SDK 每次调用都会询问 Host,不会因为本地已有 proxy 而跳过请求。同一 SDK 页面内按
1568
+ * Session `id` 缓存 proxy:若 {@link MiniProgramCompanionModule.launch | companion.launch}
1569
+ * 或本方法再次返回同一个 Session ID 和更新的 generation,SDK 更新同一个对象并返回原
1570
+ * 引用,因此 `===` 保持成立,已注册的输出、状态、退出与 ownership listener,以及
1571
+ * {@link CompanionSession.waitForExit} 都继续有效。低于或等于当前值的旧 generation 不会
1572
+ * 让已丢失控制权的 proxy 重新获得控制。页面 reload 会创建新的 SDK 和 proxy,不保证
1573
+ * JavaScript 对象身份跨页面保持。
1574
+ *
1575
+ * 返回的 proxy 公开稳定的 `id`、`alias`、`target`、只读 `capabilities` 和 `state`,不暴露
1576
+ * PID、物理路径、原生句柄或 generation。只有 Host 快照实际包含对应 capability 时,
1577
+ * `stdio`、`attachments`、`notifications` 才存在;调用前应按属性是否存在分支,不能只按
1578
+ * 操作系统猜测。
1579
+ *
1580
+ * 失去控制权不会让进程退出,`state` 仍可为 `running`,
1581
+ * {@link CompanionSession.waitForExit} 也会继续等待同一进程的退出事件。需要继续控制时,
1582
+ * 可在明确的恢复动作中重新调用本方法;不要轮询抢占 controller。该方法本身不会准备或
1583
+ * 启动进程,也不需要可信用户手势或 Host 授权弹窗;创建新进程仍应由新的用户操作调用
1584
+ * `launch()`。
1585
+ *
1586
+ * @example
1587
+ * ```ts
1588
+ * import hbSDK from '@heybox/hb-sdk'
1589
+ *
1590
+ * const session = await hbSDK.companion.getActiveSession('runner')
1591
+ * if (!session) {
1592
+ * const preparation = await hbSDK.companion.getPreparationStatus('runner')
1593
+ * renderIdleState(preparation)
1594
+ * } else {
1595
+ * const stopOwnership = session.onOwnershipLost(() => {
1596
+ * disableCompanionControls()
1597
+ * })
1598
+ *
1599
+ * try {
1600
+ * const exit = await session.waitForExit()
1601
+ * renderExit(exit)
1602
+ * } finally {
1603
+ * stopOwnership()
1604
+ * }
1605
+ * }
1606
+ * ```
1607
+ *
1608
+ * @see {@link CompanionSession}
1609
+ * @see {@link CompanionSession.waitForExit}
1610
+ * @see {@link CompanionSession.onOwnershipLost}
1611
+ * @see {@link MiniProgramCompanionModule.launch | companion.launch}
1612
+ * @see {@link MiniProgramCompanionModule.getPreparationStatus | companion.getPreparationStatus}
1613
+ * @see {@link https://docs.xiaoheihe.cn/hb_sdk/guide/companion | 受管桌面程序}
1614
+ * @see {@link https://docs.xiaoheihe.cn/hb_sdk/guide/permissions | 权限声明}
1615
+ *
115
1616
  * @since 0.8.1-alpha.4
116
1617
  * @hbPlatform windows
117
1618
  * @hbPlatform macos