tirtc-devtools-cli 0.0.1 → 0.0.3

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 (27) hide show
  1. package/README.md +3 -3
  2. package/USAGE.md +47 -47
  3. package/dist/devtools/cli/src/config.js +3 -3
  4. package/dist/devtools/cli/src/embedded_paths.js +1 -1
  5. package/dist/devtools/cli/src/ffmpeg_tool.js +1 -1
  6. package/dist/devtools/cli/src/guide.js +9 -9
  7. package/dist/devtools/cli/src/index.js +6 -6
  8. package/dist/devtools/cli/src/session_manager.js +2 -2
  9. package/dist/devtools/cli/src/token_tool.d.ts +2 -0
  10. package/dist/devtools/cli/src/token_tool.js +87 -27
  11. package/package.json +3 -3
  12. package/vendor/app-server/bin/native/macos-arm64/credential_napi.node +0 -0
  13. package/vendor/app-server/bin/native/macos-arm64/runtime_host_napi.node +0 -0
  14. package/vendor/app-server/bin/runtime/macos-arm64/include/tirtc/audio.h +2 -4
  15. package/vendor/app-server/bin/runtime/macos-arm64/include/tirtc/av.h +2 -0
  16. package/vendor/app-server/bin/runtime/macos-arm64/include/tirtc/trp.h +80 -4
  17. package/vendor/app-server/bin/runtime/macos-arm64/lib/libmatrix_runtime_audio.a +0 -0
  18. package/vendor/app-server/bin/runtime/macos-arm64/lib/libmatrix_runtime_credential.a +0 -0
  19. package/vendor/app-server/bin/runtime/macos-arm64/lib/libmatrix_runtime_facade.a +0 -0
  20. package/vendor/app-server/bin/runtime/macos-arm64/lib/libmatrix_runtime_foundation_http.a +0 -0
  21. package/vendor/app-server/bin/runtime/macos-arm64/lib/libmatrix_runtime_foundation_logging.a +0 -0
  22. package/vendor/app-server/bin/runtime/macos-arm64/lib/libmatrix_runtime_media.a +0 -0
  23. package/vendor/app-server/bin/runtime/macos-arm64/lib/libmatrix_runtime_transport.a +0 -0
  24. package/vendor/app-server/bin/runtime/macos-arm64/lib/libmatrix_runtime_video.a +0 -0
  25. package/vendor/app-server/bin/runtime/macos-arm64/manifest.txt +12 -12
  26. package/vendor/app-server/dist/host/RuntimeAdapter.js +1 -1
  27. /package/bin/{tirtc-devtool.js → tirtc-devtools-cli.js} +0 -0
package/README.md CHANGED
@@ -4,11 +4,11 @@
4
4
 
5
5
  ## 使用说明 (C-Lite)
6
6
 
7
- 关于 `tirtc-devtool` 命令的详细使用方法、参数说明与示例,请参考 [USAGE.md](./USAGE.md)。
7
+ 关于 `tirtc-devtools-cli` 命令的详细使用方法、参数说明与示例,请参考 [USAGE.md](./USAGE.md)。
8
8
 
9
9
  ## 负责什么
10
10
 
11
- - **唯一用户产品门面**:提供 `tirtc-devtool` 命令族,覆盖常见的 RTC 测试操作,让内部研发、外部开发者和 AI agent 脚本无需手写底层协议。
11
+ - **唯一用户产品门面**:提供 `tirtc-devtools-cli` 命令族,覆盖常见的 RTC 测试操作,让内部研发、外部开发者和 AI agent 脚本无需手写底层协议。
12
12
  - **配置解析与翻译**:负责解析用户传入的 CLI 参数和 TOML 配置文件,进行本地必填校验、脱敏,并翻译为 App Server 协议的 request。
13
13
  - **产品级 Observability**:将底层的运行时事件和状态翻译为结构化输出 (JSON) 或友好的终端日志输出。
14
14
  - **调试期工具内聚**:承接调试期必要工具(如 token bootstrap、二维码与媒体预处理)的产品化入口,避免把调试流程散落在 runtime 或外部手工步骤中。
@@ -49,4 +49,4 @@
49
49
 
50
50
  - 本地测试配置文件路径:`devtools/cli/tests/.local/runtime-backed.e2e.local.json`(必需,已在 `.gitignore` 忽略)。
51
51
  - 示例模板:`devtools/cli/tests/runtime-backed.e2e.config.example.json`。
52
- - 推荐先运行 `tirtc-devtool media assets prepare --source .refers/simple.mp4 --output-root ./.tmp/tirtc-devtool/assets`,再把 `assetsDir` 指向返回的 `assets_dir`。
52
+ - 推荐先运行 `tirtc-devtools-cli media assets prepare --source .refers/simple.mp4 --output-root ./.tmp/tirtc-devtools-cli/assets`,再把 `assetsDir` 指向返回的 `assets_dir`。
package/USAGE.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # TiRTC DevTool CLI(用户手册)
2
2
 
3
- `tirtc-devtool` 是基于 `app-server/host` 的命令行门面,用来控制会话、服务、连接、流、命令通道与调试工具。
3
+ `tirtc-devtools-cli` 是基于 `app-server/host` 的命令行门面,用来控制会话、服务、连接、流、命令通道与调试工具。
4
4
 
5
5
  ## 一、先说清楚关系
6
6
 
@@ -26,7 +26,7 @@ npm --prefix app-server ci && \
26
26
  构建后可直接运行:
27
27
 
28
28
  ```bash
29
- node devtools/cli/bin/tirtc-devtool.js --help
29
+ node devtools/cli/bin/tirtc-devtools-cli.js --help
30
30
  ```
31
31
 
32
32
  ### 2) 发布态打包(可分发二进制)
@@ -60,9 +60,9 @@ node devtools/cli/bin/tirtc-devtool.js --help
60
60
 
61
61
  一个 session = 一个常驻 Host 进程 + 一个 endpoint runtime 实例。
62
62
 
63
- - `tirtc-devtool host session start`:创建会话,返回 `sessionId`
64
- - `tirtc-devtool host session list`:查看会话
65
- - `tirtc-devtool host session stop <sessionId>`:停止会话
63
+ - `tirtc-devtools-cli host session start`:创建会话,返回 `sessionId`
64
+ - `tirtc-devtools-cli host session list`:查看会话
65
+ - `tirtc-devtools-cli host session stop <sessionId>`:停止会话
66
66
 
67
67
  设计约束:
68
68
 
@@ -77,22 +77,22 @@ node devtools/cli/bin/tirtc-devtool.js --help
77
77
 
78
78
  用途:初始化 CLI 配置文件,作为后续 `service/debug/logging` 等命令的参数来源。
79
79
 
80
- - `tirtc-devtool init [outputPath]`:生成配置模板;不传路径时默认写入 `./.tmp/tirtc-devtool/config.toml`。
80
+ - `tirtc-devtools-cli init [outputPath]`:生成配置模板;不传路径时默认写入 `./.tmp/tirtc-devtools-cli/config.toml`。
81
81
 
82
82
  ### Host
83
83
 
84
84
  用途:管理 Host 进程生命周期与会话健康状态。
85
85
 
86
- - `tirtc-devtool host status`:查看当前 Host/service/connection/artifact 状态。
87
- - `tirtc-devtool host stop`:停止当前 `--session` 对应的 Host 进程。
88
- - `tirtc-devtool host stop --all`:停止全部 session 对应 Host,并清理本机 orphan host 进程。
86
+ - `tirtc-devtools-cli host status`:查看当前 Host/service/connection/artifact 状态。
87
+ - `tirtc-devtools-cli host stop`:停止当前 `--session` 对应的 Host 进程。
88
+ - `tirtc-devtools-cli host stop --all`:停止全部 session 对应 Host,并清理本机 orphan host 进程。
89
89
 
90
90
  ### Service
91
91
 
92
92
  用途:控制服务端角色(等待远端连接的一侧)。
93
93
 
94
- - `tirtc-devtool service start [serviceEntry] [license]`:启动服务并进入等待连接状态。
95
- - `tirtc-devtool service stop`:停止服务。
94
+ - `tirtc-devtools-cli service start [serviceEntry] [license]`:启动服务并进入等待连接状态。
95
+ - `tirtc-devtools-cli service stop`:停止服务。
96
96
 
97
97
  说明:`license` 必填;`serviceEntry` 可省略,省略时走 runtime/core/transport 默认值。
98
98
 
@@ -102,9 +102,9 @@ node devtools/cli/bin/tirtc-devtool.js --help
102
102
 
103
103
  用途:控制客户端侧连接动作(主动连接/断开)。
104
104
 
105
- - `tirtc-devtool connection show`:查看当前连接状态。
106
- - `tirtc-devtool connection connect [serviceEntry] <peerId> [token]`:主动发起连接(不传 token 时自动签发)。
107
- - `tirtc-devtool connection disconnect`:主动断开连接。
105
+ - `tirtc-devtools-cli connection show`:查看当前连接状态。
106
+ - `tirtc-devtools-cli connection connect [serviceEntry] <peerId> [token]`:主动发起连接(不传 token 时自动签发)。
107
+ - `tirtc-devtools-cli connection disconnect`:主动断开连接。
108
108
 
109
109
  说明:`connect` 每次都会新建一个 session;省略 `serviceEntry` 时,Host 回退到 runtime 配置默认值。
110
110
 
@@ -118,7 +118,7 @@ node devtools/cli/bin/tirtc-devtool.js --help
118
118
 
119
119
  用途:直接签发 token,并把调试所需的核心信息一次性输出到控制台,同时在本地生成二维码 PNG。
120
120
 
121
- - `tirtc-devtool token issue <accessId> <secretKey> <localId> <peerId>`:签发 token。
121
+ - `tirtc-devtools-cli token issue <accessId> <secretKey> <localId> <peerId>`:签发 token。
122
122
 
123
123
  可选参数:
124
124
 
@@ -144,14 +144,14 @@ node devtools/cli/bin/tirtc-devtool.js --help
144
144
 
145
145
  用途:管理音视频流的发送/接收与远端请求策略。
146
146
 
147
- - `tirtc-devtool stream list`:列出当前流状态。
148
- - `tirtc-devtool media assets prepare --source <mp4> --output-root <dir>`:把 MP4 prepare 为 local assets。
149
- - `tirtc-devtool stream send start <streamId> <media> <assets_dir>`:启动发送流并绑定 prepared local assets。
150
- - `tirtc-devtool stream send stop <streamId>`:停止发送流。
151
- - `tirtc-devtool stream receive start <streamId> <media>`:启动接收流。
152
- - `tirtc-devtool stream receive stop <streamId>`:停止接收流。
153
- - `tirtc-devtool stream request-policy get`:查看远端请求策略。
154
- - `tirtc-devtool stream request-policy set <manual|auto-if-bound>`:设置远端请求策略。
147
+ - `tirtc-devtools-cli stream list`:列出当前流状态。
148
+ - `tirtc-devtools-cli media assets prepare --source <mp4> --output-root <dir>`:把 MP4 prepare 为 local assets。
149
+ - `tirtc-devtools-cli stream send start <streamId> <media> <assets_dir>`:启动发送流并绑定 prepared local assets。
150
+ - `tirtc-devtools-cli stream send stop <streamId>`:停止发送流。
151
+ - `tirtc-devtools-cli stream receive start <streamId> <media>`:启动接收流。
152
+ - `tirtc-devtools-cli stream receive stop <streamId>`:停止接收流。
153
+ - `tirtc-devtools-cli stream request-policy get`:查看远端请求策略。
154
+ - `tirtc-devtools-cli stream request-policy set <manual|auto-if-bound>`:设置远端请求策略。
155
155
 
156
156
  `request-policy` 行为:
157
157
 
@@ -168,8 +168,8 @@ node devtools/cli/bin/tirtc-devtool.js --help
168
168
 
169
169
  用途:把流内容挂到具体消费端(文件、预览页等)。
170
170
 
171
- - `tirtc-devtool output attach <streamId> <consumer> <mediaView> <format> <delivery> [targetPath] [maxFiles]`:附加输出消费。
172
- - `tirtc-devtool output detach <outputId>`:移除输出消费。
171
+ - `tirtc-devtools-cli output attach <streamId> <consumer> <mediaView> <format> <delivery> [targetPath] [maxFiles]`:附加输出消费。
172
+ - `tirtc-devtools-cli output detach <outputId>`:移除输出消费。
173
173
 
174
174
  `output attach` 当前最小稳定组合(CLI 前置校验):
175
175
 
@@ -179,11 +179,11 @@ node devtools/cli/bin/tirtc-devtool.js --help
179
179
  `web_preview` 用法(音视频一起预览):
180
180
 
181
181
  - 先在客户端会话中启动接收(必须两路都起):
182
- - `tirtc-devtool stream receive start <videoStreamId> video`
183
- - `tirtc-devtool stream receive start <audioStreamId> audio`
182
+ - `tirtc-devtools-cli stream receive start <videoStreamId> video`
183
+ - `tirtc-devtools-cli stream receive start <audioStreamId> audio`
184
184
  - 再挂接两路输出到同一个预览页:
185
- - `tirtc-devtool output attach <videoStreamId> web_preview encoded jpeg artifact_path [videoTargetPath]`
186
- - `tirtc-devtool output attach <audioStreamId> web_preview encoded pcm artifact_path [audioTargetPath]`
185
+ - `tirtc-devtools-cli output attach <videoStreamId> web_preview encoded jpeg artifact_path [videoTargetPath]`
186
+ - `tirtc-devtools-cli output attach <audioStreamId> web_preview encoded pcm artifact_path [audioTargetPath]`
187
187
  - 两次 `output attach` 返回的 `result.preview.url` 应一致;用该 URL 在 Chrome 打开本地预览。
188
188
  - 页面打开后会自动触发 `GET /preview/start?token=...`;若浏览器拦截自动播放音频,请手动点击 `Start Stream` 解锁。
189
189
  - 可通过 `GET /preview/status?token=...` 查看 audio/video source 启动状态与 frame 计数。
@@ -192,9 +192,9 @@ node devtools/cli/bin/tirtc-devtool.js --help
192
192
 
193
193
  用途:发送业务命令与实时观察命令事件。
194
194
 
195
- - `tirtc-devtool command send <commandId> <kind> <payloadEncoding> <payload>`:发送命令。
196
- - `tirtc-devtool command send-json <commandId> <kind> <payloadJson>`:以 JSON-first 形态发送命令。
197
- - `tirtc-devtool command tail`:持续监听命令相关事件。
195
+ - `tirtc-devtools-cli command send <commandId> <kind> <payloadEncoding> <payload>`:发送命令。
196
+ - `tirtc-devtools-cli command send-json <commandId> <kind> <payloadJson>`:以 JSON-first 形态发送命令。
197
+ - `tirtc-devtools-cli command tail`:持续监听命令相关事件。
198
198
 
199
199
  `command send-json` 约束:
200
200
 
@@ -205,8 +205,8 @@ node devtools/cli/bin/tirtc-devtool.js --help
205
205
 
206
206
  用途:生成客户端扫码连接所需的 bootstrap 二维码(只包含连接信息,不签发 token)。
207
207
 
208
- - `tirtc-devtool debug bootstrap qrcode <accessId> <secretKey> <peerId> [serviceEntry]`:按命令参数生成二维码。
209
- - `tirtc-devtool debug bootstrap qrcode-from-config`:按 `[debug.connect_bootstrap]` 配置生成二维码。
208
+ - `tirtc-devtools-cli debug bootstrap qrcode <accessId> <secretKey> <peerId> [serviceEntry]`:按命令参数生成二维码。
209
+ - `tirtc-devtools-cli debug bootstrap qrcode-from-config`:按 `[debug.connect_bootstrap]` 配置生成二维码。
210
210
 
211
211
  二维码产物会落到 Host artifact 的 `debug/` 目录。
212
212
 
@@ -214,10 +214,10 @@ node devtools/cli/bin/tirtc-devtool.js --help
214
214
 
215
215
  用途:做运行观测与验收证据导出。
216
216
 
217
- - `tirtc-devtool events tail`:实时查看事件流。
218
- - `tirtc-devtool logs export <outputPath>`:导出日志。
219
- - `tirtc-devtool report show`:查看报告。
220
- - `tirtc-devtool report export <outputPath>`:导出报告。
217
+ - `tirtc-devtools-cli events tail`:实时查看事件流。
218
+ - `tirtc-devtools-cli logs export <outputPath>`:导出日志。
219
+ - `tirtc-devtools-cli report show`:查看报告。
220
+ - `tirtc-devtools-cli report export <outputPath>`:导出报告。
221
221
 
222
222
  ## 六、服务端操作指引(对接安卓扫码)
223
223
 
@@ -226,7 +226,7 @@ node devtools/cli/bin/tirtc-devtool.js --help
226
226
  ### 1) 启动服务端
227
227
 
228
228
  ```bash
229
- node devtools/cli/bin/tirtc-devtool.js service start "" "runtime-license"
229
+ node devtools/cli/bin/tirtc-devtools-cli.js service start "" "runtime-license"
230
230
  ```
231
231
 
232
232
  记下返回里的 `sessionId`。
@@ -239,7 +239,7 @@ node devtools/cli/bin/tirtc-devtool.js service start "" "runtime-license"
239
239
  mode = "auto-if-bound"
240
240
 
241
241
  [streams.send]
242
- assets_dir = "./.tmp/tirtc-devtool/assets/<prepared-assets-id>"
242
+ assets_dir = "./.tmp/tirtc-devtools-cli/assets/<prepared-assets-id>"
243
243
  audio_stream_id = 10
244
244
  video_stream_id = 11
245
245
 
@@ -254,7 +254,7 @@ video_stream_id = 11
254
254
  ### 3) 生成给安卓扫码的 bootstrap 二维码
255
255
 
256
256
  ```bash
257
- node devtools/cli/bin/tirtc-devtool.js --session <SESSION_ID> debug bootstrap qrcode \
257
+ node devtools/cli/bin/tirtc-devtools-cli.js --session <SESSION_ID> debug bootstrap qrcode \
258
258
  "<access-id>" "<secret-key>" "<peer-id>" "<service-entry>"
259
259
  ```
260
260
 
@@ -271,7 +271,7 @@ node devtools/cli/bin/tirtc-devtool.js --session <SESSION_ID> debug bootstrap qr
271
271
  ### 4.1) 本地直接签发 token(公开调试入口)
272
272
 
273
273
  ```bash
274
- node devtools/cli/bin/tirtc-devtool.js token issue \
274
+ node devtools/cli/bin/tirtc-devtools-cli.js token issue \
275
275
  "<access-id>" "<secret-key>" "<local-id>" "<peer-id>" \
276
276
  --service-entry "<service-entry>"
277
277
  ```
@@ -339,7 +339,7 @@ node devtools/cli/bin/tirtc-devtool.js token issue \
339
339
 
340
340
  `[logging]` 段默认已在模板里生成:
341
341
 
342
- - `root_dir`:会话日志根目录(默认 `./.tmp/tirtc-devtool/logging`)
342
+ - `root_dir`:会话日志根目录(默认 `./.tmp/tirtc-devtools-cli/logging`)
343
343
  - `console_mirror`:是否把 Host 关键日志镜像到当前命令终端
344
344
  - `level`:日志级别预留位(当前 Host 以统一关键路径日志为主)
345
345
 
@@ -351,13 +351,13 @@ node devtools/cli/bin/tirtc-devtool.js token issue \
351
351
 
352
352
  实时观察:
353
353
 
354
- - `node devtools/cli/bin/tirtc-devtool.js --session <SESSION_ID> events tail`
354
+ - `node devtools/cli/bin/tirtc-devtools-cli.js --session <SESSION_ID> events tail`
355
355
  - 输出中包含 `family=logs` / `kind=host.line` 的实时日志事件
356
356
 
357
357
  ## 六点六、配置格式说明
358
358
 
359
359
  - 推荐使用 TOML(支持注释,便于人工维护)
360
- - `init` 默认生成 TOML 模板:`.tmp/tirtc-devtool/config.toml`
360
+ - `init` 默认生成 TOML 模板:`.tmp/tirtc-devtools-cli/config.toml`
361
361
 
362
362
  ## 七、本地 E2E 配置(必需)
363
363
 
@@ -372,7 +372,7 @@ cp devtools/cli/tests/runtime-backed.e2e.config.example.json devtools/cli/tests/
372
372
 
373
373
  ```json
374
374
  {
375
- "assetsDir": "./.tmp/tirtc-devtool/assets/<prepared-assets-id>",
375
+ "assetsDir": "./.tmp/tirtc-devtools-cli/assets/<prepared-assets-id>",
376
376
  "license": "<license>",
377
377
  "peerId": "<peer-id>",
378
378
  "useFakeToken": false,
@@ -396,7 +396,7 @@ cp devtools/cli/tests/runtime-backed.e2e.config.example.json devtools/cli/tests/
396
396
 
397
397
  ## 九、新手入口
398
398
 
399
- - `node devtools/cli/bin/tirtc-devtool.js guide quickstart`
399
+ - `node devtools/cli/bin/tirtc-devtools-cli.js guide quickstart`
400
400
 
401
401
  会直接打印“服务端启动 -> 绑定自动发流 -> 生成 bootstrap 二维码 -> 客户端扫码签发 token 并连接 -> 打开 Web Preview 后手动 Start/Stop -> 观测报告”的最小闭环步骤。
402
402
 
@@ -30,7 +30,7 @@ function resolveConfigOutputPath(outputPath) {
30
30
  if (outputPath && outputPath.trim().length > 0) {
31
31
  return path_1.default.resolve(outputPath.trim());
32
32
  }
33
- return path_1.default.resolve(process.cwd(), '.tmp/tirtc-devtool/config.toml');
33
+ return path_1.default.resolve(process.cwd(), '.tmp/tirtc-devtools-cli/config.toml');
34
34
  }
35
35
  function renderTomlConfigTemplate() {
36
36
  return [
@@ -65,13 +65,13 @@ function renderTomlConfigTemplate() {
65
65
  'mode = "manual"',
66
66
  '',
67
67
  '[streams.send]',
68
- 'assets_dir = "./.tmp/tirtc-devtool/assets/<prepared-assets-id>"',
68
+ 'assets_dir = "./.tmp/tirtc-devtools-cli/assets/<prepared-assets-id>"',
69
69
  'audio_stream_id = 10',
70
70
  'video_stream_id = 11',
71
71
  '',
72
72
  '[logging]',
73
73
  '# session 日志根目录;每个 session 会写到 <root_dir>/<session_id>/',
74
- 'root_dir = "./.tmp/tirtc-devtool/logging"',
74
+ 'root_dir = "./.tmp/tirtc-devtools-cli/logging"',
75
75
  '# 是否镜像 Host 控制台日志到当前终端',
76
76
  'console_mirror = true',
77
77
  '# verbose|debug|info|warn|error|fatal(预留)',
@@ -25,7 +25,7 @@ function resolveCliPackageRoot(fromDir) {
25
25
  path_1.default.resolve(process.cwd(), 'devtools/cli'),
26
26
  ];
27
27
  for (const candidate of candidates) {
28
- if (pathExists(path_1.default.join(candidate, 'package.json')) && pathExists(path_1.default.join(candidate, 'bin/tirtc-devtool.js'))) {
28
+ if (pathExists(path_1.default.join(candidate, 'package.json')) && pathExists(path_1.default.join(candidate, 'bin/tirtc-devtools-cli.js'))) {
29
29
  return candidate;
30
30
  }
31
31
  }
@@ -23,7 +23,7 @@ function resolveFfmpegCacheRoot() {
23
23
  if (explicit && explicit.trim().length > 0) {
24
24
  return path_1.default.resolve(explicit.trim());
25
25
  }
26
- return path_1.default.join(os_1.default.homedir(), '.tirtc-devtool', 'tools', 'ffmpeg');
26
+ return path_1.default.join(os_1.default.homedir(), '.tirtc-devtools-cli', 'tools', 'ffmpeg');
27
27
  }
28
28
  function resolveCachedToolDir(platform) {
29
29
  return path_1.default.join(resolveFfmpegCacheRoot(), platform);
@@ -12,17 +12,17 @@ function printQuickstartGuide() {
12
12
  '2) 服务端已准备可发送媒体文件(示例:.refers/simple.mp4)',
13
13
  '',
14
14
  '步骤 1:启动服务(自动创建 session)',
15
- ' node devtools/cli/bin/tirtc-devtool.js service start "" "<LICENSE>"',
15
+ ' node devtools/cli/bin/tirtc-devtools-cli.js service start "" "<LICENSE>"',
16
16
  ' # 记下输出里的 sessionId,后续命令都显式带 --session',
17
17
  '',
18
18
  '步骤 2:先 prepare local assets,再配置 assets_dir + 显式音视频 stream id 并启动自动按需发流',
19
- ' node devtools/cli/bin/tirtc-devtool.js media assets prepare --source .refers/simple.mp4 --output-root ./.tmp/tirtc-devtool/assets',
19
+ ' node devtools/cli/bin/tirtc-devtools-cli.js media assets prepare --source .refers/simple.mp4 --output-root ./.tmp/tirtc-devtools-cli/assets',
20
20
  ' [stream.request_policy] mode = "auto-if-bound"',
21
- ' [streams.send] assets_dir = "./.tmp/tirtc-devtool/assets/<prepared-assets-id>" audio_stream_id = 10 video_stream_id = 11',
21
+ ' [streams.send] assets_dir = "./.tmp/tirtc-devtools-cli/assets/<prepared-assets-id>" audio_stream_id = 10 video_stream_id = 11',
22
22
  ' # service start 成功后会自动应用上述 request_policy + send 绑定',
23
23
  '',
24
24
  '步骤 3:生成连接 bootstrap 二维码(给安卓扫码)',
25
- ' node devtools/cli/bin/tirtc-devtool.js --session <SESSION_ID> debug bootstrap qrcode \\',
25
+ ' node devtools/cli/bin/tirtc-devtools-cli.js --session <SESSION_ID> debug bootstrap qrcode \\',
26
26
  ' "<ACCESS_ID>" "<SECRET_KEY>" "<PEER_ID>" "<SERVICE_ENTRY>"',
27
27
  '',
28
28
  '步骤 4:安卓扫码后流程(客户端侧)',
@@ -31,19 +31,19 @@ function printQuickstartGuide() {
31
31
  ' - 持 token + peer_id 连接服务端;连接成功后请求 audio_stream_id/video_stream_id',
32
32
  '',
33
33
  '额外:如果你只想本地直接签发并拿到可扫码 payload,可执行:',
34
- ' node devtools/cli/bin/tirtc-devtool.js token issue "<ACCESS_ID>" "<SECRET_KEY>" "<LOCAL_ID>" "<PEER_ID>" \\',
34
+ ' node devtools/cli/bin/tirtc-devtools-cli.js token issue "<ACCESS_ID>" "<SECRET_KEY>" "<LOCAL_ID>" "<PEER_ID>" \\',
35
35
  ' --service-entry "<SERVICE_ENTRY>"',
36
36
  ' # CLI 会直接打印摘要、payload JSON、token,并生成本地二维码 PNG 路径',
37
37
  '',
38
38
  '步骤 5:服务端观测',
39
- ' node devtools/cli/bin/tirtc-devtool.js --session <SESSION_ID> events tail',
40
- ' node devtools/cli/bin/tirtc-devtool.js --session <SESSION_ID> report show',
39
+ ' node devtools/cli/bin/tirtc-devtools-cli.js --session <SESSION_ID> events tail',
40
+ ' node devtools/cli/bin/tirtc-devtools-cli.js --session <SESSION_ID> report show',
41
41
  '',
42
42
  '补充:',
43
43
  '- debug bootstrap qrcode 仅生成连接信息二维码,不签发 token',
44
44
  '- 机器可读输出:在命令后追加 --json',
45
- '- 查看全部命令:node devtools/cli/bin/tirtc-devtool.js --help',
46
- '- 查看单命令说明:node devtools/cli/bin/tirtc-devtool.js <command> --help',
45
+ '- 查看全部命令:node devtools/cli/bin/tirtc-devtools-cli.js --help',
46
+ '- 查看单命令说明:node devtools/cli/bin/tirtc-devtools-cli.js <command> --help',
47
47
  ];
48
48
  console.log(lines.join('\n'));
49
49
  }
@@ -9,7 +9,7 @@ const session_manager_1 = require("./session_manager");
9
9
  const media_assets_1 = require("./media_assets");
10
10
  const transport_1 = require("./transport");
11
11
  const token_tool_1 = require("./token_tool");
12
- const CLI_VERSION = '0.0.1';
12
+ const CLI_VERSION = '0.0.3';
13
13
  const HOST_VERSION = '1.0.0';
14
14
  const PROTOCOL_VERSION = '1.0.0';
15
15
  if (process.argv.includes('--version') || process.argv.includes('-V')) {
@@ -161,7 +161,7 @@ async function runCommand(cmdName, params, options) {
161
161
  const session = resolveSessionForCommand(cmdName, options, config);
162
162
  transport = createSessionTransport(session.sessionId);
163
163
  const client = new protocol_client_1.AppServerClient(transport);
164
- await client.initialize({ name: 'tirtc-devtool-cli', version: CLI_VERSION });
164
+ await client.initialize({ name: 'tirtc-devtools-cli', version: CLI_VERSION });
165
165
  const method = facade_1.CommandToHostMethodMapping[cmdName];
166
166
  if (!method) {
167
167
  throw new Error('Unknown command mapping for: ' + cmdName);
@@ -226,7 +226,7 @@ async function tailEvents(_cmdName, families, options) {
226
226
  }
227
227
  transport?.stop();
228
228
  });
229
- await client.initialize({ name: 'tirtc-devtool-cli', version: CLI_VERSION });
229
+ await client.initialize({ name: 'tirtc-devtools-cli', version: CLI_VERSION });
230
230
  await client.subscribeEvents(families);
231
231
  await new Promise((resolve) => {
232
232
  process.on('SIGINT', () => {
@@ -339,8 +339,8 @@ function mustParseJsonPayload(input) {
339
339
  throw new Error('payloadJson must be valid JSON text');
340
340
  }
341
341
  }
342
- program.name('tirtc-devtool')
343
- .description('TiRTC DevTool CLI')
342
+ program.name('tirtc-devtools-cli')
343
+ .description('TiRTC DevTools CLI')
344
344
  .option('--config <path>', '配置文件路径(TOML)')
345
345
  .option('--json', '以机器可读 JSON 输出(便于脚本集成)')
346
346
  .option('--session <sessionId>', '指定会话 ID;除 service start/connect 外必须传');
@@ -468,7 +468,7 @@ function handleConfigInit(outputPath) {
468
468
  console.error('Error:', normalized.message);
469
469
  }
470
470
  }
471
- const init = program.command('init [outputPath]').description('新手第一步:生成 CLI 配置模板(默认输出到 ./.tmp/tirtc-devtool/config.toml)');
471
+ const init = program.command('init [outputPath]').description('新手第一步:生成 CLI 配置模板(默认输出到 ./.tmp/tirtc-devtools-cli/config.toml)');
472
472
  init.action((outputPath) => {
473
473
  handleConfigInit(outputPath);
474
474
  });
@@ -30,7 +30,7 @@ function getStateDir() {
30
30
  if (explicit && explicit.trim().length > 0) {
31
31
  return explicit.trim();
32
32
  }
33
- return path_1.default.join(os_1.default.homedir(), '.tirtc-devtool');
33
+ return path_1.default.join(os_1.default.homedir(), '.tirtc-devtools-cli');
34
34
  }
35
35
  function getSocketDir() {
36
36
  const explicit = process.env.TIRTC_DEVTOOL_SOCKET_DIR;
@@ -191,7 +191,7 @@ function waitForSocketReady(socketPath, pid) {
191
191
  throw new Error(`session startup timeout: socket not ready within ${kStartupTimeoutMs}ms`);
192
192
  }
193
193
  function resolveDefaultLogRootDir() {
194
- return path_1.default.resolve(process.cwd(), '.tmp/tirtc-devtool/logging');
194
+ return path_1.default.resolve(process.cwd(), '.tmp/tirtc-devtools-cli/logging');
195
195
  }
196
196
  function createSession(options) {
197
197
  const runtimePlatform = resolveRuntimePlatform();
@@ -25,9 +25,11 @@ export type TokenIssueOutput = {
25
25
  payloadJson: string;
26
26
  token: string;
27
27
  qrCodePngPath: string;
28
+ qrCodeAscii: string;
28
29
  };
29
30
  export declare function issueToken(input: TokenIssueInput): Promise<string>;
30
31
  export declare function buildIssuedTokenPayload(input: TokenIssueInput, token: string): IssuedTokenPayload;
31
32
  export declare function writePngQrcode(payloadJson: string, outputPath: string): Promise<string>;
33
+ export declare function buildAsciiQrcode(payloadJson: string): Promise<string>;
32
34
  export declare function issueTokenWithQrcode(input: TokenIssueInput): Promise<TokenIssueOutput>;
33
35
  export declare function formatTokenIssueConsoleOutput(output: TokenIssueOutput): string;
@@ -6,17 +6,20 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.issueToken = issueToken;
7
7
  exports.buildIssuedTokenPayload = buildIssuedTokenPayload;
8
8
  exports.writePngQrcode = writePngQrcode;
9
+ exports.buildAsciiQrcode = buildAsciiQrcode;
9
10
  exports.issueTokenWithQrcode = issueTokenWithQrcode;
10
11
  exports.formatTokenIssueConsoleOutput = formatTokenIssueConsoleOutput;
11
- const module_1 = require("module");
12
+ const child_process_1 = require("child_process");
12
13
  const fs_1 = __importDefault(require("fs"));
13
14
  const path_1 = __importDefault(require("path"));
14
15
  const qrcode_1 = __importDefault(require("qrcode"));
15
16
  const embedded_paths_1 = require("./embedded_paths");
16
- const runtimeRequire = (0, module_1.createRequire)(__filename);
17
17
  const kDefaultOpenapiEntry = 'http://api-test-tirtc.tange365.com';
18
18
  const kDefaultUserTtlSeconds = 86400;
19
19
  const kDefaultChannelTtlSeconds = 300;
20
+ const kAsciiQrBlack = '██';
21
+ const kAsciiQrWhite = ' ';
22
+ const kAsciiQrQuietZoneModules = 2;
20
23
  function pathExists(filePath) {
21
24
  return fs_1.default.existsSync(filePath);
22
25
  }
@@ -27,7 +30,7 @@ function sanitizePathSegment(text) {
27
30
  return text.replace(/[^a-zA-Z0-9._-]+/g, '-').replace(/^-+|-+$/g, '') || 'value';
28
31
  }
29
32
  function resolveQrCodeOutputDir() {
30
- return path_1.default.resolve(process.cwd(), '.tmp/tirtc-devtool/qrcode');
33
+ return path_1.default.resolve(process.cwd(), '.tmp/tirtc-devtools-cli/qrcode');
31
34
  }
32
35
  function buildQrCodePngPath(payload) {
33
36
  const fileName = [
@@ -117,18 +120,6 @@ function resolveAddonPath(repoRoot, runtimePlatform) {
117
120
  throw new Error('credential addon missing for platform ' + runtimePlatform +
118
121
  '; run: npm --prefix app-server run build:native');
119
122
  }
120
- function loadCredentialBinding() {
121
- const runtimePlatform = resolveRuntimePlatform();
122
- const runtimeBundleRoot = resolveRuntimeBundleRoot(runtimePlatform);
123
- const repoRoot = resolveRepoRoot();
124
- ensureRuntimeBundleReady(runtimeBundleRoot);
125
- const addonPath = resolveAddonPath(repoRoot, runtimePlatform);
126
- const loaded = runtimeRequire(addonPath);
127
- if (!loaded || typeof loaded.issueToken !== 'function') {
128
- throw new Error('credential addon missing issueToken() export: ' + addonPath);
129
- }
130
- return loaded;
131
- }
132
123
  function normalizeIssuedToken(token) {
133
124
  const normalized = token.trim();
134
125
  if (normalized.length === 0) {
@@ -136,25 +127,68 @@ function normalizeIssuedToken(token) {
136
127
  }
137
128
  return normalized;
138
129
  }
130
+ function buildIssueTokenHelperSource() {
131
+ return [
132
+ 'const addon = require(process.env.TIRTC_CREDENTIAL_ADDON_PATH_HELPER);',
133
+ 'const input = JSON.parse(process.env.TIRTC_CREDENTIAL_INPUT_JSON || "{}");',
134
+ 'const originalWrite = process.stderr.write.bind(process.stderr);',
135
+ 'process.stderr.write = ((chunk, encoding, callback) => {',
136
+ ' if (typeof callback === "function") {',
137
+ ' callback();',
138
+ ' }',
139
+ ' return true;',
140
+ '});',
141
+ 'try {',
142
+ ' const token = addon.issueToken({',
143
+ ' openapiEntry: input.openapiEntry,',
144
+ ' accessId: input.accessId,',
145
+ ' secretKey: input.secretKey,',
146
+ ' localId: input.localId,',
147
+ ' peerId: input.peerId,',
148
+ ' userTtlSeconds: input.userTtlSeconds,',
149
+ ' channelTtlSeconds: input.channelTtlSeconds,',
150
+ ' });',
151
+ ' process.stdout.write(String(token).trim());',
152
+ '} finally {',
153
+ ' process.stderr.write = originalWrite;',
154
+ '}',
155
+ ].join('\n');
156
+ }
157
+ function issueTokenViaSubprocess(addonPath, input) {
158
+ const result = (0, child_process_1.spawnSync)(process.execPath, ['-e', buildIssueTokenHelperSource()], {
159
+ encoding: 'utf8',
160
+ env: {
161
+ ...process.env,
162
+ TIRTC_CREDENTIAL_ADDON_PATH_HELPER: addonPath,
163
+ TIRTC_CREDENTIAL_INPUT_JSON: JSON.stringify(input),
164
+ },
165
+ stdio: ['ignore', 'pipe', 'pipe'],
166
+ });
167
+ if (result.error) {
168
+ throw result.error;
169
+ }
170
+ if (result.status !== 0) {
171
+ const details = String(result.stderr || result.stdout || 'issue token subprocess failed').trim();
172
+ throw new Error(details || 'issue token subprocess failed');
173
+ }
174
+ return normalizeIssuedToken(String(result.stdout || ''));
175
+ }
176
+ function readQrModule(modules, row, column) {
177
+ return Boolean(modules.data[row * modules.size + column]);
178
+ }
139
179
  async function issueToken(input) {
140
- const binding = loadCredentialBinding();
141
- let token;
180
+ const runtimePlatform = resolveRuntimePlatform();
181
+ const runtimeBundleRoot = resolveRuntimeBundleRoot(runtimePlatform);
182
+ const repoRoot = resolveRepoRoot();
183
+ ensureRuntimeBundleReady(runtimeBundleRoot);
184
+ const addonPath = resolveAddonPath(repoRoot, runtimePlatform);
142
185
  try {
143
- token = binding.issueToken({
144
- openapiEntry: input.openapiEntry,
145
- accessId: input.accessId,
146
- secretKey: input.secretKey,
147
- localId: input.localId,
148
- peerId: input.peerId,
149
- userTtlSeconds: input.userTtlSeconds,
150
- channelTtlSeconds: input.channelTtlSeconds,
151
- });
186
+ return issueTokenViaSubprocess(addonPath, input);
152
187
  }
153
188
  catch (error) {
154
189
  const message = error instanceof Error ? error.message : String(error);
155
190
  throw new Error('issue token failed: ' + message);
156
191
  }
157
- return normalizeIssuedToken(token);
158
192
  }
159
193
  function buildIssuedTokenPayload(input, token) {
160
194
  return {
@@ -181,16 +215,39 @@ async function writePngQrcode(payloadJson, outputPath) {
181
215
  });
182
216
  return resolvedPath;
183
217
  }
218
+ async function buildAsciiQrcode(payloadJson) {
219
+ const qr = qrcode_1.default.create(payloadJson, { errorCorrectionLevel: 'M' });
220
+ const quietZone = kAsciiQrWhite.repeat(kAsciiQrQuietZoneModules);
221
+ const fullQuietLine = quietZone + kAsciiQrWhite.repeat(qr.modules.size) + quietZone;
222
+ const lines = [];
223
+ for (let index = 0; index < kAsciiQrQuietZoneModules; index += 1) {
224
+ lines.push(fullQuietLine);
225
+ }
226
+ for (let row = 0; row < qr.modules.size; row += 1) {
227
+ let line = quietZone;
228
+ for (let column = 0; column < qr.modules.size; column += 1) {
229
+ line += readQrModule(qr.modules, row, column) ? kAsciiQrBlack : kAsciiQrWhite;
230
+ }
231
+ line += quietZone;
232
+ lines.push(line);
233
+ }
234
+ for (let index = 0; index < kAsciiQrQuietZoneModules; index += 1) {
235
+ lines.push(fullQuietLine);
236
+ }
237
+ return lines.join('\n');
238
+ }
184
239
  async function issueTokenWithQrcode(input) {
185
240
  const token = await issueToken(input);
186
241
  const payload = buildIssuedTokenPayload(input, token);
187
242
  const payloadJson = JSON.stringify(payload);
188
243
  const qrCodePngPath = await writePngQrcode(payloadJson, buildQrCodePngPath(payload));
244
+ const qrCodeAscii = await buildAsciiQrcode(payloadJson);
189
245
  return {
190
246
  payload,
191
247
  payloadJson,
192
248
  token,
193
249
  qrCodePngPath,
250
+ qrCodeAscii,
194
251
  };
195
252
  }
196
253
  function formatTokenIssueConsoleOutput(output) {
@@ -210,6 +267,9 @@ function formatTokenIssueConsoleOutput(output) {
210
267
  'Payload JSON:',
211
268
  JSON.stringify(output.payload, null, 2),
212
269
  '',
270
+ 'QR Code ASCII:',
271
+ output.qrCodeAscii,
272
+ '',
213
273
  'QR Code PNG:',
214
274
  output.qrCodePngPath,
215
275
  ];
package/package.json CHANGED
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "name": "tirtc-devtools-cli",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "private": false,
5
5
  "main": "dist/index.js",
6
6
  "bin": {
7
- "tirtc-devtool": "./bin/tirtc-devtool.js"
7
+ "tirtc-devtools-cli": "./bin/tirtc-devtools-cli.js"
8
8
  },
9
9
  "files": [
10
10
  "README.md",
11
11
  "USAGE.md",
12
- "bin/tirtc-devtool.js",
12
+ "bin/tirtc-devtools-cli.js",
13
13
  "dist",
14
14
  "script/ensure_ffmpeg.sh",
15
15
  "vendor"
@@ -209,8 +209,7 @@ TirtcError tirtc_conn_attach_audio_input(TirtcConn* connection, uint8_t stream_i
209
209
  * ::tirtc_audio_output_set_aout and any desired options before attaching it.
210
210
  *
211
211
  * If an observer is already installed, a successful attach typically reports an
212
- * initial IDLE state before playback begins. A successful attach also asks the
213
- * remote peer to start sending audio for this ::stream_id on this connection.
212
+ * initial IDLE state before playback begins.
214
213
  *
215
214
  * @param connection Target connection.
216
215
  * @param stream_id Remote audio stream identifier to render.
@@ -235,8 +234,7 @@ TirtcError tirtc_conn_detach_audio_input(TirtcConn* connection, uint8_t stream_i
235
234
  /**
236
235
  * @brief Detach an audio output from a connection stream.
237
236
  *
238
- * This call is idempotent. A successful detach also asks the remote peer to
239
- * stop sending audio for this ::stream_id on this connection.
237
+ * This call is idempotent.
240
238
  *
241
239
  * @param connection Target connection.
242
240
  * @param stream_id Stream identifier to detach.
@@ -239,6 +239,8 @@ TirtcError tirtc_conn_attach_video_input(TirtcConn* connection, uint8_t stream_i
239
239
  *
240
240
  * If an observer is already installed, a successful attach typically reports an
241
241
  * initial IDLE state before decoded frames begin to render.
242
+ * Attach is a local bind only; it does not send a remote request for this
243
+ * stream.
242
244
  *
243
245
  * @param connection Target connection.
244
246
  * @param stream_id Remote video stream identifier to render.
@@ -79,6 +79,27 @@ typedef struct TirtcOptions {
79
79
  int environment;
80
80
  } TirtcOptions;
81
81
 
82
+ /**
83
+ * @brief Default media send policy applied by the facade.
84
+ *
85
+ * The effective send gate still uses `connection + stream_id + media_kind` as
86
+ * the smallest scope. The policy only decides how those gates become open.
87
+ */
88
+ typedef enum TirtcMediaSendPolicy {
89
+ /**
90
+ * @brief Keep send gates closed until the consumer explicitly opens them.
91
+ */
92
+ TIRTC_MEDIA_SEND_POLICY_ON_REQUEST = 0,
93
+
94
+ /**
95
+ * @brief Open send gates automatically once the accepted connection exists.
96
+ *
97
+ * When the bound input is ready, the facade may start sending without first
98
+ * waiting for an explicit remote request.
99
+ */
100
+ TIRTC_MEDIA_SEND_POLICY_AUTO_ON_CONNECTED = 1,
101
+ } TirtcMediaSendPolicy;
102
+
82
103
  /**
83
104
  * @brief Options for starting a service-side connection listener.
84
105
  *
@@ -102,6 +123,15 @@ typedef struct TirtcConnServiceStartOptions {
102
123
  * This field is required and must be non-zero.
103
124
  */
104
125
  uint32_t max_connections;
126
+
127
+ /**
128
+ * @brief Service-level media send policy applied to accepted connections.
129
+ *
130
+ * This policy controls how the facade opens per-connection send gates after
131
+ * a connection becomes available. It does not change the underlying
132
+ * transport request/release primitives.
133
+ */
134
+ TirtcMediaSendPolicy media_send_policy;
105
135
  } TirtcConnServiceStartOptions;
106
136
 
107
137
  /**
@@ -199,9 +229,21 @@ typedef struct TirtcStreamMessage {
199
229
 
200
230
  /**
201
231
  * @brief Fire-and-forget command payload.
232
+ *
233
+ * Command identifiers are application-defined and must be agreed with the
234
+ * remote peer.
235
+ *
236
+ * The current runtime accepts application command ids in the range
237
+ * `[0x1000, 0x7FFF]`. Values below `0x1000` are reserved for
238
+ * runtime-internal commands and must not be used by consumers.
202
239
  */
203
240
  typedef struct TirtcConnCommand {
204
- /** @brief Application-defined command identifier. */
241
+ /**
242
+ * @brief Application-defined command identifier agreed with the remote peer.
243
+ *
244
+ * A request and its reply typically reuse the same ::command_id, while the
245
+ * per-request correlation is carried separately by ::remote_request_id.
246
+ */
205
247
  uint16_t command_id;
206
248
 
207
249
  /** @brief Payload bytes, or NULL when ::length is zero. */
@@ -213,9 +255,21 @@ typedef struct TirtcConnCommand {
213
255
 
214
256
  /**
215
257
  * @brief Request payload for an asynchronous command round-trip.
258
+ *
259
+ * Command identifiers are application-defined and must be agreed with the
260
+ * remote peer.
261
+ *
262
+ * The current runtime accepts application command ids in the range
263
+ * `[0x1000, 0x7FFF]`. Values below `0x1000` are reserved for
264
+ * runtime-internal commands and must not be used by consumers.
216
265
  */
217
266
  typedef struct TirtcConnCommandRequest {
218
- /** @brief Application-defined command identifier. */
267
+ /**
268
+ * @brief Application-defined command identifier agreed with the remote peer.
269
+ *
270
+ * In the common request-response pattern, the responder echoes the same
271
+ * ::command_id back in ::TirtcConnCommandResponse.
272
+ */
219
273
  uint16_t command_id;
220
274
 
221
275
  /** @brief Payload bytes, or NULL when ::length is zero. */
@@ -235,9 +289,20 @@ typedef struct TirtcConnCommandRequest {
235
289
 
236
290
  /**
237
291
  * @brief Response payload returned by a remote peer or local reply logic.
292
+ *
293
+ * Command identifiers are application-defined and must be agreed with the
294
+ * remote peer.
295
+ *
296
+ * The current runtime accepts application command ids in the range
297
+ * `[0x1000, 0x7FFF]`. Values below `0x1000` are reserved for
298
+ * runtime-internal commands and must not be used by consumers.
238
299
  */
239
300
  typedef struct TirtcConnCommandResponse {
240
- /** @brief Application-defined command identifier. */
301
+ /**
302
+ * @brief Application-defined command identifier agreed with the remote peer.
303
+ *
304
+ * This usually matches the original request's ::command_id.
305
+ */
241
306
  uint16_t command_id;
242
307
 
243
308
  /** @brief Payload bytes, or NULL when ::length is zero. */
@@ -490,6 +555,11 @@ TirtcError tirtc_conn_send_stream_message(TirtcConn* connection, uint8_t stream_
490
555
  /**
491
556
  * @brief Send an application-defined command without waiting for a response.
492
557
  *
558
+ * Choose ::TirtcConnCommand.command_id from the command ids agreed with the
559
+ * remote peer. The current runtime accepts application command ids in
560
+ * `[0x1000, 0x7FFF]`; values below `0x1000` are reserved for
561
+ * runtime-internal commands.
562
+ *
493
563
  * @param connection Target connection.
494
564
  * @param command Non-NULL command payload.
495
565
  * @return ::TIRTC_ERROR_OK on success.
@@ -500,6 +570,11 @@ TirtcError tirtc_conn_send_command(TirtcConn* connection, const TirtcConnCommand
500
570
  * @brief Send an application-defined request command and complete it
501
571
  * asynchronously.
502
572
  *
573
+ * Choose ::TirtcConnCommandRequest.command_id from the command ids agreed
574
+ * with the remote peer. The current runtime accepts application command
575
+ * ids in `[0x1000, 0x7FFF]`; values below `0x1000` are reserved for
576
+ * runtime-internal commands.
577
+ *
503
578
  * Callback delivery is mixed synchronous/asynchronous. If request submission
504
579
  * fails immediately after the facade has accepted the request, ::callback may
505
580
  * run before this function returns. After request submission succeeds,
@@ -521,7 +596,8 @@ TirtcError tirtc_conn_request_command(TirtcConn* connection, const TirtcConnComm
521
596
  /**
522
597
  * @brief Reply to an inbound remote command request.
523
598
  *
524
- * Use the ::remote_request_id delivered by
599
+ * In the common request-response pattern, ::TirtcConnCommandResponse.command_id
600
+ * matches the inbound request's ::command_id. Use the ::remote_request_id delivered by
525
601
  * ::TirtcConnObserver.on_remote_command_request on the same connection. If the
526
602
  * request is no longer pending, this function returns a not-ready error.
527
603
  * In the normal case, reply at most once for each delivered request id.
@@ -1,8 +1,8 @@
1
1
  platform=macos-arm64
2
- staged_at_utc=2026-04-09T05:05:37Z
2
+ staged_at_utc=2026-04-09T05:56:18Z
3
3
  source_sdk=/Users/allenfeng/Development/Repositories/tirtc-nexus/tirtc-matrix/.build/sdk/macos-arm64
4
4
 
5
- 58cbe872af5a68a1f5832912ab9deb7ef5af1ac5d19439b523ce6619978214c0 include/tirtc/audio.h
5
+ dcca0b7ab8055d84e5bcfab7f1dde56df9037c40ddb99e9ca924ef2e867d8309 include/tirtc/audio.h
6
6
  6d972ccfe150a3b4f2d7f18fa92b3ade9210c1c8bb754d061ac6b7997b59e2cb include/tirtc/audio_codec.h
7
7
  7bacbdb2d8bb10d6444036a8fef42f2a8e3ea34dfc38e165ee678d61f189db41 include/tirtc/audio_frame.h
8
8
  84f1bbe67efa15ab3b2d995d661025aac43e2fe547a14a012a24d89cfe3cb859 include/tirtc/audio_io.h
@@ -12,7 +12,7 @@ c2e1f31dcc75be461c577d18b1cebe32774f212d51cb4dd2a5b5a9bfe62b693e include/tirtc/
12
12
  51cbc911fe9f9834046f0e0a1a7cdd814a8e194a615894a8b4d11f9e5f095610 include/tirtc/audio_io_windows.h
13
13
  21f60729117260a44af22c1af986ef17d22673b102b7b7a035f492d0665cce16 include/tirtc/audio_processing.h
14
14
  0ca7c3c630b1242f51a0fd8154097c0a332b4c816a5707090e4381719852998c include/tirtc/audio_sample_rate.h
15
- 64d0005d726ed7d29e6c5a9c7bc25e931693ba8fa4ab6af8d21e7adc8767f66e include/tirtc/av.h
15
+ 59b7df33fdc2ad92b3142299ffab832443179ef895784ad51a2f6544c5b02766 include/tirtc/av.h
16
16
  4198c95c48ae579d1c782635b00fa5c9009d0c56ba466e6e3873e8298faae029 include/tirtc/credential.h
17
17
  92da1614c1cbc22d5ba7c1aefd3bbfba88be4a698d1b9990f470fe959ddd84ba include/tirtc/error.h
18
18
  ae805545a9515edc9b94262e72ad2c7b7d649288166f4daeb450d8a55e82ae0b include/tirtc/foundation/build_info.h
@@ -25,7 +25,7 @@ ae805545a9515edc9b94262e72ad2c7b7d649288166f4daeb450d8a55e82ae0b include/tirtc/
25
25
  a4f8ab44c1a20ad37f250363a403a9d4d007e61ddb2426c7966dbc05f6a04b4f include/tirtc/media_live_source.h
26
26
  1b3be6954e547f91a047866438bff1820c8406afaf91cef68ddee29a6ac70234 include/tirtc/media_uplink.h
27
27
  1e12daf9c5fc2e2f848444688081c9be0cb738245f0155327e8003b49308058f include/tirtc/transport.h
28
- f836768a4dd8b8595bd53cd96cca98bb56e802dd3ee3e520b18546d999908928 include/tirtc/trp.h
28
+ 99b4b31b8359009ee74f0f2a52be6473d9c6c37b184e53eeb554d4bf61f6ee33 include/tirtc/trp.h
29
29
  dff5b0a0ac4a40ad17c93e1e56b3c416371c81ab365e287ea8cd6ce37ccbed3b include/tirtc/video_codec.h
30
30
  e51379666c199588cc33279ccf52248035d1cae3d1d468b1615ebf29f0b39c9c include/tirtc/video_frame.h
31
31
  d920afad955b9f206b02b19ca152315190fa84ab6f24e895a5b24c3ab9ffd701 include/tirtc/video_io.h
@@ -36,14 +36,14 @@ cae0bbeb884e5466a56da15182c78cc22baab6c743f349a58d3595f623333585 include/tirtc/
36
36
  8cd6b66bea14890a665cc317f8572429b2c3e4463773f8b77c1e4dc30a4a8747 include/tirtc/video_processing.h
37
37
  b39daee6a3d39bf0ca20c45084601133c4198de8dca848dcff6dd9c70ae99016 lib/libcrypto.a
38
38
  c052857ef315e3d61db9c862cad10709a3a6b2487dc41799cbe4d74a805de875 lib/libcrypto.dylib
39
- e96e6d57ff90f3cb34d98d69036987c4d4839c48094168261fbe776a524185a1 lib/libmatrix_runtime_audio.a
40
- 8255fc3eb34a44c5ee5cd6f1ca88d06392527fbe91d492692152eb719fda9887 lib/libmatrix_runtime_credential.a
41
- 467c2440813c73211dd71775d7a49fdeb785975c998ab1c7268e967c07650399 lib/libmatrix_runtime_facade.a
42
- 9499a182dde5cd3cd908ddd2d44b1d6b2cd884bd5041379f2d1144cbb49297b3 lib/libmatrix_runtime_foundation_http.a
43
- 79aba2a4f43ca5f4aca9187d07c656b6696e9b644bf678418ed2e79ed718ce2e lib/libmatrix_runtime_foundation_logging.a
44
- 99ae6ebbe3f3faa3b9591e049691842cef8bdbc3fd6f1e0cb82c7f9acb7ac85e lib/libmatrix_runtime_media.a
45
- a9cba88ca9db63c2712b3e0088c8525e55763ce62836b238b042bb0514b0f669 lib/libmatrix_runtime_transport.a
46
- 86845113a79fa1c7503b17bcf44cff061b5491127d38995206c2afce59aa4560 lib/libmatrix_runtime_video.a
39
+ 6ad596f3ad055be11f121f418aeff4e02c650f3cec6b37c471ed54e9498a1268 lib/libmatrix_runtime_audio.a
40
+ 42d1a2e4aa59d53c0c35ad204a365b7d7d83698c21857f5ffe7421da240da3e1 lib/libmatrix_runtime_credential.a
41
+ 2153ac1352ebb401f7920e8358c4988f9bd7f5275009ab94f6c4b7d7eb2a71c3 lib/libmatrix_runtime_facade.a
42
+ 25d70d18d4b69e0f28514035811a4ae8e18a1dcbcdd88d6a68e3d7609e2537bb lib/libmatrix_runtime_foundation_http.a
43
+ 78b82c288d2e58f1219d5f56772a1dc8683e8da5f2f4724c160e6bf97f9ddadc lib/libmatrix_runtime_foundation_logging.a
44
+ 548230c283e262838d2492ae28817870cd191eb3b9cb3e943446645562a2e20f lib/libmatrix_runtime_media.a
45
+ e5afb3d24fd62ad5f4fd68ea7ba65957e79bf27d5669a8d6bceb44aa9f297c16 lib/libmatrix_runtime_transport.a
46
+ e0a087c9d0b0c929a20677db1aa8e053813baa3682458f407f04dc751d0d225a lib/libmatrix_runtime_video.a
47
47
  c11c65d373a127028350c41fa58cd2d1223f2b5d70a84e13b115d90daaba25ca lib/libssl.a
48
48
  ef1c1104bbdd2528ed7b958fb7252bd6249875f92300b0c9577d6c4bd6c0d88a lib/libssl.dylib
49
49
  dc3e0e6ded26e90fd59c166933a5289d57f4cf25fbe6246b6b83c86fe898e63d lib/libwebrtc_apm.a
@@ -101,7 +101,7 @@ function resolveOutputRoot() {
101
101
  if (explicit && explicit.trim().length > 0) {
102
102
  return path.resolve(explicit.trim());
103
103
  }
104
- return path.join(path.resolve(process.cwd()), '.tmp', 'tirtc-devtool', 'output');
104
+ return path.join(path.resolve(process.cwd()), '.tmp', 'tirtc-devtools-cli', 'output');
105
105
  }
106
106
  function normalizeMedia(media) {
107
107
  if (media === 'audio') {
File without changes