tirtc-devtools-cli 0.0.6 → 0.0.7

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.
package/README.md CHANGED
@@ -12,7 +12,7 @@
12
12
 
13
13
  - **唯一用户产品门面**:提供 `tirtc-devtools-cli` 命令族,覆盖常见的 RTC 测试操作,让内部研发、外部开发者和 AI agent 脚本无需手写底层协议。
14
14
  - **配置解析与翻译**:负责解析用户传入的 CLI 参数和 TOML 配置文件,进行本地必填校验、脱敏,并翻译为 App Server 协议的 request。
15
- - **产品级 Observability**:将底层的运行时事件和状态翻译为结构化输出 (JSON) 或友好的终端日志输出。
15
+ - **产品级 Observability**:将底层的运行时事件和状态翻译为结构化输出 (JSON) 或友好的终端日志输出;对长耗时命令补轻量进度提示。
16
16
  - **调试期工具内聚**:承接调试期必要工具(如 token bootstrap、二维码与媒体预处理)的产品化入口,避免把调试流程散落在 runtime 或外部手工步骤中。
17
17
  - **本地 token 工具**:提供直接签发 token、打印组合 JSON、单独 token 与本地二维码 PNG 路径的公开 CLI 能力,服务本地联调与体验验证。
18
18
 
package/USAGE.md CHANGED
@@ -130,8 +130,8 @@ server-only 正式路径只认 `[server] + [logging]`:
130
130
  service_entry = ""
131
131
  license = "runtime-license"
132
132
  mp4_path = "/Users/allenfeng/Development/Repositories/tirtc-nexus/tirtc-matrix/.refers/simple.mp4"
133
- video_stream_id = 10
134
- audio_stream_id = 11
133
+ video_stream_id = 11
134
+ audio_stream_id = 10
135
135
 
136
136
  [logging]
137
137
  root_dir = "./.tmp/tirtc-devtools-cli/logging"
@@ -159,6 +159,8 @@ node devtools/cli/bin/tirtc-devtools-cli.js --config ./server.toml --json servic
159
159
  4. 自动调用两次 `stream/sendStart`:一次音频、一次视频。
160
160
  5. 返回 `autoApplied` 摘要:`preparedAssetsDir`、固定 `mediaSendPolicy=AUTO_ON_CONNECTED`、以及音视频 sendStart 结果。
161
161
 
162
+ 非 `--json` 模式下,CLI 会在 `stderr` 输出轻量进度提示:先显示 MP4 prepare,再显示 service start,避免长时间静默。
163
+
162
164
  ### 3. 自动发送语义
163
165
 
164
166
  - App Server server 角色固定使用 `AUTO_ON_CONNECTED`。
@@ -37,8 +37,8 @@ function renderTomlConfigTemplate() {
37
37
  '# server-only service start 时必填',
38
38
  'license = ""',
39
39
  'mp4_path = "./source.mp4"',
40
- 'video_stream_id = 10',
41
- 'audio_stream_id = 11',
40
+ 'video_stream_id = 11',
41
+ 'audio_stream_id = 10',
42
42
  '',
43
43
  '[connection]',
44
44
  '# 作为客户端 connection connect 默认 service_entry(可留空)',
@@ -16,7 +16,7 @@ function printQuickstartGuide() {
16
16
  ' # 记下输出里的 sessionId,后续命令都显式带 --session',
17
17
  '',
18
18
  '步骤 2:CLI 会自动 prepare MP4 并绑定音视频 stream,不再需要手工 prepare assets_dir',
19
- ' [server] service_entry = "" license = "<LICENSE>" mp4_path = "./.refers/simple.mp4" video_stream_id = 10 audio_stream_id = 11',
19
+ ' [server] service_entry = "" license = "<LICENSE>" mp4_path = "./.refers/simple.mp4" video_stream_id = 11 audio_stream_id = 10',
20
20
  ' # service start 成功后会自动 prepare 并按 AUTO_ON_CONNECTED 进入待发流语义',
21
21
  '',
22
22
  '步骤 3:生成连接 bootstrap 二维码(给安卓扫码)',
@@ -14,6 +14,7 @@ const session_manager_1 = require("./session_manager");
14
14
  const media_assets_1 = require("./media_assets");
15
15
  const token_command_1 = require("./token_command");
16
16
  const transport_1 = require("./transport");
17
+ const progress_1 = require("./progress");
17
18
  const CLI_VERSION = '0.0.6';
18
19
  const HOST_VERSION = '1.0.0';
19
20
  const PROTOCOL_VERSION = '1.0.0';
@@ -161,6 +162,12 @@ function validateServerConfig(config) {
161
162
  videoStreamId,
162
163
  };
163
164
  }
165
+ function createProgressIndicator(options) {
166
+ if (options.json) {
167
+ return undefined;
168
+ }
169
+ return new progress_1.ProgressIndicator();
170
+ }
164
171
  function resolvePrepareOutputRoot(config) {
165
172
  const loggingRoot = config.logging?.root_dir?.trim();
166
173
  if (loggingRoot && loggingRoot.length > 0) {
@@ -168,12 +175,14 @@ function resolvePrepareOutputRoot(config) {
168
175
  }
169
176
  return path_1.default.resolve(process.cwd(), '.tmp', 'tirtc-devtools-cli', 'prepared-assets');
170
177
  }
171
- async function applyConfiguredServerBootstrap(client, config) {
178
+ async function applyConfiguredServerBootstrap(client, config, progress) {
172
179
  const server = validateServerConfig(config);
180
+ progress?.start('Preparing MP4 assets');
173
181
  const prepared = await (0, media_assets_1.prepareMediaAssets)({
174
182
  source: server.mp4Path,
175
183
  outputRoot: resolvePrepareOutputRoot(config),
176
184
  });
185
+ progress?.update('Prepared MP4 assets');
177
186
  const bootstrapSendStreams = [
178
187
  { streamId: server.audioStreamId, media: 'audio' },
179
188
  { streamId: server.videoStreamId, media: 'video' },
@@ -207,20 +216,29 @@ async function runCommand(cmdName, params, options) {
207
216
  }
208
217
  let resultForPrint;
209
218
  if (cmdName === 'service start') {
210
- const autoApplied = await applyConfiguredServerBootstrap(client, config);
211
- const requestParams = {
212
- ...params,
213
- bootstrapSendStreams: autoApplied.bootstrapSendStreams,
214
- };
215
- const result = await client.sendRequest(method, requestParams, 180_000);
216
- const resultObject = toResultObject(result);
217
- resultForPrint = {
218
- ...resultObject,
219
- autoApplied,
220
- };
221
- printSuccess(options, resultForPrint, session, cmdName);
222
- transport.stop();
223
- return 0;
219
+ const progress = createProgressIndicator(options);
220
+ try {
221
+ const autoApplied = await applyConfiguredServerBootstrap(client, config, progress);
222
+ progress?.update('Starting service session');
223
+ const requestParams = {
224
+ ...params,
225
+ bootstrapSendStreams: autoApplied.bootstrapSendStreams,
226
+ };
227
+ const result = await client.sendRequest(method, requestParams, 180_000);
228
+ progress?.succeed('Service session is ready');
229
+ const resultObject = toResultObject(result);
230
+ resultForPrint = {
231
+ ...resultObject,
232
+ autoApplied,
233
+ };
234
+ printSuccess(options, resultForPrint, session, cmdName);
235
+ transport.stop();
236
+ return 0;
237
+ }
238
+ catch (error) {
239
+ progress?.fail('Service start failed');
240
+ throw error;
241
+ }
224
242
  }
225
243
  const result = await client.sendRequest(method, params);
226
244
  resultForPrint = result;
@@ -0,0 +1,19 @@
1
+ export declare const SPINNER_INTERVAL_MS = 120;
2
+ type ProgressStream = {
3
+ isTTY?: boolean;
4
+ write(chunk: string): boolean;
5
+ };
6
+ export declare class ProgressIndicator {
7
+ private readonly stream;
8
+ private timer;
9
+ private frameIndex;
10
+ private activeMessage;
11
+ constructor(stream?: ProgressStream);
12
+ start(message: string): void;
13
+ update(message: string): void;
14
+ succeed(message: string): void;
15
+ fail(message: string): void;
16
+ private render;
17
+ private finish;
18
+ }
19
+ export {};
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ProgressIndicator = exports.SPINNER_INTERVAL_MS = void 0;
4
+ const SPINNER_FRAMES = ['|', '/', '-', '\\'];
5
+ exports.SPINNER_INTERVAL_MS = 120;
6
+ function clearLine(text) {
7
+ return `\r\u001b[2K${text}`;
8
+ }
9
+ class ProgressIndicator {
10
+ stream;
11
+ timer;
12
+ frameIndex = 0;
13
+ activeMessage;
14
+ constructor(stream = process.stderr) {
15
+ this.stream = stream;
16
+ }
17
+ start(message) {
18
+ this.activeMessage = message;
19
+ if (this.stream.isTTY) {
20
+ if (this.timer === undefined) {
21
+ this.render();
22
+ this.timer = setInterval(() => {
23
+ this.render();
24
+ }, exports.SPINNER_INTERVAL_MS);
25
+ return;
26
+ }
27
+ this.render();
28
+ return;
29
+ }
30
+ this.stream.write(`${message}...\n`);
31
+ }
32
+ update(message) {
33
+ this.start(message);
34
+ }
35
+ succeed(message) {
36
+ this.finish('OK', message);
37
+ }
38
+ fail(message) {
39
+ this.finish('FAIL', message);
40
+ }
41
+ render() {
42
+ if (this.activeMessage === undefined) {
43
+ return;
44
+ }
45
+ const frame = SPINNER_FRAMES[this.frameIndex % SPINNER_FRAMES.length];
46
+ this.frameIndex += 1;
47
+ this.stream.write(clearLine(`${frame} ${this.activeMessage}...`));
48
+ }
49
+ finish(tag, message) {
50
+ if (this.timer !== undefined) {
51
+ clearInterval(this.timer);
52
+ this.timer = undefined;
53
+ }
54
+ if (this.stream.isTTY) {
55
+ this.stream.write(`${clearLine(`[${tag}] ${message}`)}\n`);
56
+ }
57
+ else {
58
+ this.stream.write(`[${tag}] ${message}\n`);
59
+ }
60
+ this.activeMessage = undefined;
61
+ }
62
+ }
63
+ exports.ProgressIndicator = ProgressIndicator;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tirtc-devtools-cli",
3
- "version": "0.0.6",
3
+ "version": "0.0.7",
4
4
  "private": false,
5
5
  "main": "dist/index.js",
6
6
  "bin": {