tirtc-devtools-cli 0.2.3 → 0.2.5

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
@@ -57,12 +57,16 @@ node products/cli/bin/tirtc-devtools-cli.js --json device start \
57
57
  ```
58
58
 
59
59
  `device start` 默认持续运行直到用户结束进程;需要自动化限时时再显式传
60
- `--duration-ms <ms>`。prepared asset 会按完整音视频轨循环,任一轨到达源文件末尾时
61
- audio/video 同步回到源头并保持 PTS 继续递增。
60
+ `--duration-ms <ms>`。运行期间 CLI 会把启动、listener ready、client 连接 / 断开、
61
+ 首个音视频包与周期运行状态写到 stderr;`--json` 的结构化 envelope 仍只写 stdout。
62
+ prepared asset 会按完整音视频轨循环,任一轨到达源文件末尾时 audio/video 同步回到
63
+ 源头并保持 PTS 继续递增。
62
64
 
63
65
  `device start` 的启动成功条件是 device listener 已就绪;客户端是否已经扫码连接不属于
64
66
  device 启动失败条件。没有 client 时命令会继续常驻,直到用户结束进程或显式
65
- `--duration-ms` 到期,summary 中 `media_send` 会保持未开始或标记为跳过。
67
+ `--duration-ms` 到期,summary 中 `media_send` 会保持未开始或标记为跳过。有 client
68
+ 连接时 driver 会为该连接送流;client 断开后,device 继续等待下一次连接,并为新连接
69
+ 重新挂载音视频输入和从源资产开头送出新的音视频包。同一时刻最多接受一个 client。
66
70
 
67
71
  native role 失败时,`reason_code` 与 `failed_stage` 仍是主失败事实;`log_upload`
68
72
  只说明失败现场日志是否已上传。上传成功时,CLI JSON 与 `summary.json` 会包含
package/USAGE.md CHANGED
@@ -131,6 +131,11 @@ By default `device start` keeps running until the process is stopped. Use
131
131
  full audio/video source cycle; when either track reaches the source end, both
132
132
  tracks restart from offset 0 while PTS keeps increasing.
133
133
 
134
+ While the device process is running, CLI writes human-readable lifecycle logs to
135
+ stderr: startup, listener readiness, client connect/disconnect, first audio/video
136
+ packet, and periodic running status. With `--json`, the final machine-readable
137
+ envelope remains on stdout.
138
+
134
139
  `device start` is considered started once the device listener is ready. A
135
140
  missing client is not a device startup failure. Without a connected client, the
136
141
  process remains resident until it is stopped or an explicit `--duration-ms`
@@ -139,6 +139,7 @@ Missing flags are read from TIRTC_DEVICE_ID, TIRTC_DEVICE_SECRET_KEY, and TIRTC_
139
139
 
140
140
  device start succeeds once the device listener is ready. It keeps running without a client until
141
141
  the process is stopped or an explicit --duration-ms deadline is reached.
142
+ Runtime lifecycle logs are written to stderr. With --json, the final envelope remains on stdout.
142
143
 
143
144
  bootstrap.json is a local handoff artifact for client/sample/validation automation.
144
145
  It is only written when --client-token-json is provided.
@@ -11,6 +11,7 @@ const fs_1 = __importDefault(require("fs"));
11
11
  const os_1 = __importDefault(require("os"));
12
12
  const path_1 = __importDefault(require("path"));
13
13
  const embedded_paths_1 = require("./embedded_paths");
14
+ const role_live_log_1 = require("./role_live_log");
14
15
  const defaultAudioStreamId = 10;
15
16
  const defaultVideoStreamId = 11;
16
17
  const defaultConnectTimeoutMs = 10000;
@@ -402,7 +403,58 @@ function buildClientRequest(roots, artifactRoot, options) {
402
403
  probe: { app_id: appId },
403
404
  };
404
405
  }
405
- function runDriver(request, artifactRoot, roots) {
406
+ function installSignalForwarding(child, liveLog) {
407
+ const signals = ['SIGINT', 'SIGTERM'];
408
+ const removers = [];
409
+ let forwardedCount = 0;
410
+ for (const signal of signals) {
411
+ const handler = () => {
412
+ forwardedCount += 1;
413
+ liveLog.signalForwarded(signal);
414
+ if (!child.killed) {
415
+ child.kill(forwardedCount > 1 ? 'SIGKILL' : signal);
416
+ }
417
+ };
418
+ process.on(signal, handler);
419
+ removers.push(() => process.off(signal, handler));
420
+ }
421
+ return () => {
422
+ for (const remove of removers) {
423
+ remove();
424
+ }
425
+ };
426
+ }
427
+ function spawnDriverProcess(driverPath, args, stdoutFd, stderrFd, liveLog) {
428
+ return new Promise((resolve) => {
429
+ let child;
430
+ try {
431
+ child = child_process_1.default.spawn(driverPath, args, {
432
+ stdio: ['ignore', stdoutFd, stderrFd],
433
+ });
434
+ }
435
+ catch (error) {
436
+ const normalized = error instanceof Error ? error : new Error(String(error));
437
+ liveLog.processError(normalized);
438
+ resolve({
439
+ status: null,
440
+ signal: null,
441
+ error: normalized,
442
+ });
443
+ return;
444
+ }
445
+ let spawnError;
446
+ const removeSignalHandlers = installSignalForwarding(child, liveLog);
447
+ child.once('error', (error) => {
448
+ spawnError = error;
449
+ liveLog.processError(error);
450
+ });
451
+ child.once('close', (code, signal) => {
452
+ removeSignalHandlers();
453
+ resolve({ status: code, signal, error: spawnError });
454
+ });
455
+ });
456
+ }
457
+ async function runDriver(role, request, artifactRoot, roots) {
406
458
  const platform = resolveRuntimePlatform();
407
459
  const driverPath = resolveDriverPath(roots, platform);
408
460
  const runtimeRoot = resolveRuntimeRoot(roots, platform);
@@ -428,26 +480,41 @@ function runDriver(request, artifactRoot, roots) {
428
480
  }
429
481
  const requestTempDir = fs_1.default.mkdtempSync(path_1.default.join(os_1.default.tmpdir(), 'tirtc-devtools-cli-request-'));
430
482
  const requestPath = path_1.default.join(requestTempDir, 'request.json');
483
+ const summaryPath = path_1.default.join(artifactRoot, 'summary.json');
484
+ fs_1.default.rmSync(summaryPath, { force: true });
485
+ fs_1.default.rmSync(path_1.default.join(artifactRoot, 'events.jsonl'), { force: true });
431
486
  writeJson(requestPath, request);
432
487
  writeJson(path_1.default.join(artifactRoot, 'request.redacted.json'), redactRequestValue(request));
433
488
  const stdoutFd = fs_1.default.openSync(path_1.default.join(artifactRoot, 'stdout.log'), 'w');
434
489
  const stderrFd = fs_1.default.openSync(path_1.default.join(artifactRoot, 'stderr.log'), 'w');
435
- const result = child_process_1.default.spawnSync(driverPath, [
436
- '--request', requestPath,
437
- '--runtime-root', runtimeRoot,
438
- '--asset-root', assetRoot,
439
- '--artifact-root', artifactRoot,
440
- ], {
441
- stdio: ['ignore', stdoutFd, stderrFd],
490
+ const liveLog = (0, role_live_log_1.startRoleLiveLog)({
491
+ role,
492
+ artifactRoot,
493
+ request,
494
+ runtimeRoot,
495
+ assetRoot,
442
496
  });
443
- fs_1.default.closeSync(stdoutFd);
444
- fs_1.default.closeSync(stderrFd);
445
- fs_1.default.rmSync(requestTempDir, { recursive: true, force: true });
446
- const summaryPath = path_1.default.join(artifactRoot, 'summary.json');
497
+ let result = { status: null, signal: null };
498
+ try {
499
+ result = await spawnDriverProcess(driverPath, [
500
+ '--request', requestPath,
501
+ '--runtime-root', runtimeRoot,
502
+ '--asset-root', assetRoot,
503
+ '--artifact-root', artifactRoot,
504
+ ], stdoutFd, stderrFd, liveLog);
505
+ liveLog.processExit(result.status, result.signal);
506
+ }
507
+ finally {
508
+ fs_1.default.closeSync(stdoutFd);
509
+ fs_1.default.closeSync(stderrFd);
510
+ fs_1.default.rmSync(requestTempDir, { recursive: true, force: true });
511
+ liveLog.stop();
512
+ }
447
513
  if (!pathExists(summaryPath)) {
448
514
  const message = result.error instanceof Error
449
515
  ? result.error.message
450
- : 'driver exited without summary: status=' + String(result.status);
516
+ : 'driver exited without summary: status=' + String(result.status) +
517
+ ' signal=' + String(result.signal ?? 'none');
451
518
  if (result.error) {
452
519
  throw new RoleCommandError('artifact_write_failed', 'artifact', roleFailedExitCode, message);
453
520
  }
@@ -472,7 +539,7 @@ async function runRole(role, commandOptions, options) {
472
539
  const request = role === 'device' ?
473
540
  buildDeviceRequest(roots, artifactRoot, commandOptions) :
474
541
  buildClientRequest(roots, artifactRoot, commandOptions);
475
- const summary = runDriver(request, artifactRoot, roots);
542
+ const summary = await runDriver(role, request, artifactRoot, roots);
476
543
  const summaryPath = path_1.default.join(artifactRoot, 'summary.json');
477
544
  const data = {
478
545
  status: summary.status,
@@ -0,0 +1,17 @@
1
+ export type RoleLiveLogOptions = {
2
+ role: 'device' | 'client';
3
+ artifactRoot: string;
4
+ request: Record<string, unknown>;
5
+ runtimeRoot: string;
6
+ assetRoot: string;
7
+ heartbeatIntervalMs?: number;
8
+ pollIntervalMs?: number;
9
+ emit?: (message: string) => void;
10
+ };
11
+ export type RoleLiveLogHandle = {
12
+ processError(error: Error): void;
13
+ processExit(code: number | null, signal: NodeJS.Signals | null): void;
14
+ signalForwarded(signal: NodeJS.Signals): void;
15
+ stop(): void;
16
+ };
17
+ export declare function startRoleLiveLog(options: RoleLiveLogOptions): RoleLiveLogHandle;
@@ -0,0 +1,305 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.startRoleLiveLog = startRoleLiveLog;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const defaultHeartbeatIntervalMs = 5000;
10
+ const defaultPollIntervalMs = 500;
11
+ function asRecord(value) {
12
+ return typeof value === 'object' && value !== null && !Array.isArray(value)
13
+ ? value
14
+ : {};
15
+ }
16
+ function nestedRecord(root, key) {
17
+ return asRecord(root[key]);
18
+ }
19
+ function nestedString(root, first, second) {
20
+ const value = second === undefined ? root[first] : nestedRecord(root, first)[second];
21
+ return typeof value === 'string' && value.length > 0 ? value : undefined;
22
+ }
23
+ function nestedNumber(root, first, second) {
24
+ const value = second === undefined ? root[first] : nestedRecord(root, first)[second];
25
+ return typeof value === 'number' && Number.isFinite(value) ? value : undefined;
26
+ }
27
+ function payloadString(payload, key) {
28
+ const value = payload[key];
29
+ return typeof value === 'string' && value.length > 0 ? value : undefined;
30
+ }
31
+ function payloadNumber(payload, key) {
32
+ const value = payload[key];
33
+ return typeof value === 'number' && Number.isFinite(value) ? value : undefined;
34
+ }
35
+ function payloadBoolean(payload, key) {
36
+ const value = payload[key];
37
+ return typeof value === 'boolean' ? value : undefined;
38
+ }
39
+ function formatDurationMs(ms) {
40
+ if (ms < 1000) {
41
+ return String(ms) + 'ms';
42
+ }
43
+ return (ms / 1000).toFixed(1) + 's';
44
+ }
45
+ function formatDurationUs(us) {
46
+ if (us === undefined) {
47
+ return undefined;
48
+ }
49
+ return formatDurationMs(Math.round(us / 1000));
50
+ }
51
+ function sessionIndex(payload) {
52
+ return payloadNumber(payload, 'session_index');
53
+ }
54
+ function appendField(parts, name, value) {
55
+ if (value !== undefined) {
56
+ parts.push(name + '=' + String(value));
57
+ }
58
+ }
59
+ function makeNoopHandle() {
60
+ return {
61
+ processError: () => undefined,
62
+ processExit: () => undefined,
63
+ signalForwarded: () => undefined,
64
+ stop: () => undefined,
65
+ };
66
+ }
67
+ function startRoleLiveLog(options) {
68
+ if (options.role !== 'device') {
69
+ return makeNoopHandle();
70
+ }
71
+ const emit = options.emit ?? ((message) => console.error(message));
72
+ const startedAt = Date.now();
73
+ const eventsPath = path_1.default.join(options.artifactRoot, 'events.jsonl');
74
+ const summaryPath = path_1.default.join(options.artifactRoot, 'summary.json');
75
+ const request = options.request;
76
+ const stats = {
77
+ listenerReady: false,
78
+ sessionsStarted: 0,
79
+ sessionsEnded: 0,
80
+ firstAudioSessions: new Set(),
81
+ firstVideoSessions: new Set(),
82
+ };
83
+ let processedLineCount = 0;
84
+ let stopped = false;
85
+ const log = (message) => {
86
+ emit('[device] ' + message);
87
+ };
88
+ const media = nestedRecord(request, 'media');
89
+ const codec = payloadString(nestedRecord(media, 'video'), 'codec') ??
90
+ nestedString(request, 'video_codec') ?? 'unknown';
91
+ const sourcePath = payloadString(nestedRecord(media, 'source'), 'path') ?? options.assetRoot;
92
+ const durationMs = nestedNumber(request, 'run', 'duration_ms');
93
+ const deviceId = nestedString(request, 'identity', 'device_id') ?? 'unknown';
94
+ const endpoint = nestedString(request, 'endpoint') ?? 'unknown';
95
+ log('starting device driver device_id=' + deviceId +
96
+ ' endpoint=' + endpoint +
97
+ ' codec=' + codec +
98
+ ' artifact_root=' + options.artifactRoot);
99
+ log('source=' + sourcePath + ' runtime_root=' + options.runtimeRoot);
100
+ if (durationMs === undefined) {
101
+ log('resident mode enabled; waiting for client connections until the process is stopped');
102
+ }
103
+ else {
104
+ log('bounded mode enabled duration=' + formatDurationMs(durationMs));
105
+ }
106
+ const emitHeartbeat = () => {
107
+ const elapsed = Date.now() - startedAt;
108
+ const parts = [
109
+ 'running',
110
+ 'elapsed=' + formatDurationMs(elapsed),
111
+ 'listener=' + (stats.listenerReady ? 'ready' : 'starting'),
112
+ 'sessions=' + String(stats.sessionsStarted) + '/' + String(stats.sessionsEnded),
113
+ 'active_session=' + (stats.activeSession ?? 'none'),
114
+ 'first_audio_sessions=' + String(stats.firstAudioSessions.size),
115
+ 'first_video_sessions=' + String(stats.firstVideoSessions.size),
116
+ ];
117
+ appendField(parts, 'last_event', stats.lastEventKind);
118
+ log(parts.join(' '));
119
+ };
120
+ const emitEventLog = (event) => {
121
+ const kind = typeof event.kind === 'string' ? event.kind : undefined;
122
+ if (!kind) {
123
+ return;
124
+ }
125
+ const payload = asRecord(event.payload);
126
+ stats.lastEventKind = kind;
127
+ if (event.level === 'error') {
128
+ const reason = payloadString(payload, 'reason_code') ?? 'unknown';
129
+ log('driver event failed kind=' + kind + ' reason_code=' + reason);
130
+ }
131
+ switch (kind) {
132
+ case 'connection.listen.done':
133
+ stats.listenerReady = true;
134
+ log('listener ready; waiting for client connections');
135
+ break;
136
+ case 'bootstrap.write.done':
137
+ log('bootstrap written path=' + (payloadString(payload, 'path') ?? 'unknown'));
138
+ break;
139
+ case 'connection.connect.done': {
140
+ const session = sessionIndex(payload);
141
+ if (session !== undefined) {
142
+ stats.sessionsStarted = Math.max(stats.sessionsStarted, session);
143
+ stats.activeSession = session;
144
+ }
145
+ log('client connected session=' + (session ?? 'unknown'));
146
+ break;
147
+ }
148
+ case 'connection.session.start': {
149
+ const session = sessionIndex(payload);
150
+ if (session !== undefined) {
151
+ stats.activeSession = session;
152
+ }
153
+ log('media session started session=' + (session ?? 'unknown'));
154
+ break;
155
+ }
156
+ case 'media.audio_send.start': {
157
+ const parts = ['audio input started'];
158
+ appendField(parts, 'session', sessionIndex(payload));
159
+ appendField(parts, 'stream_id', payloadNumber(payload, 'stream_id'));
160
+ appendField(parts, 'codec', payloadString(payload, 'codec'));
161
+ appendField(parts, 'sample_rate_hz', payloadNumber(payload, 'sample_rate_hz'));
162
+ log(parts.join(' '));
163
+ break;
164
+ }
165
+ case 'media.video_send.start': {
166
+ const parts = ['video input started'];
167
+ appendField(parts, 'session', sessionIndex(payload));
168
+ appendField(parts, 'stream_id', payloadNumber(payload, 'stream_id'));
169
+ appendField(parts, 'codec', payloadString(payload, 'codec'));
170
+ log(parts.join(' '));
171
+ break;
172
+ }
173
+ case 'media.asset_cycle.config': {
174
+ const parts = ['asset cycle ready'];
175
+ appendField(parts, 'session', sessionIndex(payload));
176
+ appendField(parts, 'audio_packets', payloadNumber(payload, 'audio_packet_count'));
177
+ appendField(parts, 'video_packets', payloadNumber(payload, 'video_packet_count'));
178
+ appendField(parts, 'cycle_duration', formatDurationUs(payloadNumber(payload, 'cycle_duration_us')));
179
+ log(parts.join(' '));
180
+ break;
181
+ }
182
+ case 'media.audio_send.session_first_packet': {
183
+ const session = sessionIndex(payload);
184
+ if (session !== undefined) {
185
+ stats.firstAudioSessions.add(session);
186
+ }
187
+ const parts = ['first audio packet sent'];
188
+ appendField(parts, 'session', session);
189
+ appendField(parts, 'pts_us', payloadNumber(payload, 'pts_us'));
190
+ appendField(parts, 'bytes', payloadNumber(payload, 'bytes'));
191
+ log(parts.join(' '));
192
+ break;
193
+ }
194
+ case 'media.video_send.session_first_packet': {
195
+ const session = sessionIndex(payload);
196
+ if (session !== undefined) {
197
+ stats.firstVideoSessions.add(session);
198
+ }
199
+ const parts = ['first video packet sent'];
200
+ appendField(parts, 'session', session);
201
+ appendField(parts, 'codec', payloadString(payload, 'codec'));
202
+ appendField(parts, 'key_frame', payloadBoolean(payload, 'is_key_frame'));
203
+ appendField(parts, 'pts_us', payloadNumber(payload, 'pts_us'));
204
+ appendField(parts, 'bytes', payloadNumber(payload, 'bytes'));
205
+ log(parts.join(' '));
206
+ break;
207
+ }
208
+ case 'connection.session.end': {
209
+ const session = sessionIndex(payload);
210
+ if (session !== undefined) {
211
+ stats.sessionsEnded = Math.max(stats.sessionsEnded, session);
212
+ if (stats.activeSession === session) {
213
+ stats.activeSession = undefined;
214
+ }
215
+ }
216
+ const disconnected = payloadBoolean(payload, 'disconnected');
217
+ const elapsed = payloadNumber(payload, 'elapsed_ms');
218
+ const parts = [disconnected ? 'client disconnected' : 'client session ended'];
219
+ appendField(parts, 'session', session);
220
+ appendField(parts, 'first_audio', payloadBoolean(payload, 'sent_first_audio'));
221
+ appendField(parts, 'first_video', payloadBoolean(payload, 'sent_first_video'));
222
+ appendField(parts, 'elapsed', elapsed === undefined ? undefined : formatDurationMs(elapsed));
223
+ log(parts.join(' '));
224
+ break;
225
+ }
226
+ case 'connection.wait.no_client': {
227
+ const reason = payloadString(payload, 'reason') ?? 'unknown';
228
+ const elapsed = payloadNumber(payload, 'elapsed_ms');
229
+ log('no client connected before stop reason=' + reason +
230
+ (elapsed === undefined ? '' : ' elapsed=' + formatDurationMs(elapsed)));
231
+ break;
232
+ }
233
+ case 'driver.execution.finished': {
234
+ const status = payloadString(payload, 'status') ?? 'unknown';
235
+ const exitCode = payloadNumber(payload, 'exit_code');
236
+ const reason = payloadString(payload, 'reason_code') ?? 'unknown';
237
+ log('driver finished status=' + status +
238
+ ' exit_code=' + String(exitCode ?? 'unknown') +
239
+ ' reason_code=' + reason);
240
+ break;
241
+ }
242
+ default:
243
+ break;
244
+ }
245
+ };
246
+ const pollEvents = (flushPartial = false) => {
247
+ if (!fs_1.default.existsSync(eventsPath)) {
248
+ return;
249
+ }
250
+ let text = '';
251
+ try {
252
+ text = fs_1.default.readFileSync(eventsPath, 'utf8');
253
+ }
254
+ catch {
255
+ return;
256
+ }
257
+ const lines = text.split(/\r?\n/);
258
+ const completeLineCount = text.endsWith('\n')
259
+ ? lines.length - 1
260
+ : (flushPartial ? lines.length : lines.length - 1);
261
+ for (let index = processedLineCount; index < completeLineCount; index += 1) {
262
+ const line = lines[index]?.trim();
263
+ if (!line) {
264
+ continue;
265
+ }
266
+ try {
267
+ emitEventLog(JSON.parse(line));
268
+ }
269
+ catch {
270
+ if (flushPartial) {
271
+ log('skipped malformed driver event line=' + String(index + 1));
272
+ }
273
+ }
274
+ }
275
+ processedLineCount = Math.max(processedLineCount, completeLineCount);
276
+ };
277
+ const pollTimer = setInterval(() => pollEvents(false), options.pollIntervalMs ?? defaultPollIntervalMs);
278
+ const heartbeatTimer = setInterval(emitHeartbeat, options.heartbeatIntervalMs ?? defaultHeartbeatIntervalMs);
279
+ return {
280
+ processError: (error) => {
281
+ pollEvents(true);
282
+ log('driver process error message=' + error.message);
283
+ },
284
+ processExit: (code, signal) => {
285
+ pollEvents(true);
286
+ const elapsed = Date.now() - startedAt;
287
+ log('process exited code=' + String(code ?? 'null') +
288
+ ' signal=' + String(signal ?? 'none') +
289
+ ' elapsed=' + formatDurationMs(elapsed) +
290
+ ' summary=' + summaryPath);
291
+ },
292
+ signalForwarded: (signal) => {
293
+ log('forwarding signal=' + signal + ' to native driver');
294
+ },
295
+ stop: () => {
296
+ if (stopped) {
297
+ return;
298
+ }
299
+ stopped = true;
300
+ clearInterval(pollTimer);
301
+ clearInterval(heartbeatTimer);
302
+ pollEvents(true);
303
+ },
304
+ };
305
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tirtc-devtools-cli",
3
- "version": "0.2.3",
3
+ "version": "0.2.5",
4
4
  "private": false,
5
5
  "main": "dist/cli/src/index.js",
6
6
  "types": "dist/cli/src/index.d.ts",
@@ -1,6 +1,6 @@
1
1
  platform=linux-x64
2
2
  profile=full
3
- staged_at_utc=2026-05-01T15:07:54Z
3
+ staged_at_utc=2026-05-05T13:45:31Z
4
4
  source_sdk=/Users/allenfeng/Development/Repositories/tirtc-nexus/tirtc-matrix/.build/sdk/linux-x64
5
5
 
6
6
  bfc096be1484ac2b1c2776ccabfa2a4c6a982e869abf875192ff06fad85e82ca include/tirtc/audio.h
@@ -36,10 +36,10 @@ b1f4135025cb8e8520a14268d831b9998920a4239f84bb6b409d0e4909fd5bee lib/libcrypto.
36
36
  296ba0b5efa9d2ac49e3bf278c5d467b31436e73fbc608b736e974bcf9759bde lib/libmatrix_runtime_audio.a
37
37
  88f9c545943e4ef80024baf3620e91817ec16a4fea60b0e8c7887a0a41dc9d1b lib/libmatrix_runtime_facade.a
38
38
  ec7bbf8e8744c6645a441a28e24e0645906152cc987d6fcca16af3c3badba940 lib/libmatrix_runtime_foundation_http.a
39
- 009fe1bfa9945c4fc94b40342590d7db157595475975b00cdbd2440da738eded lib/libmatrix_runtime_foundation_logging.a
40
- 9c7108b70cb442dee02cfdb4f98891a8a099f15c379e9e48cf53d7b276f6e894 lib/libmatrix_runtime_media.a
39
+ 4005e0f9ff88f2acc1639b79299c6089ba1b81d1a4fd52fe9d64c5e8603d488a lib/libmatrix_runtime_foundation_logging.a
40
+ 8964ab2d93bf0fd4ee6666459ffec53cd35b07288fccc0d46e042e60b8466d4f lib/libmatrix_runtime_media.a
41
41
  93dd81cfb9ed8aef29bfa3fb9d18aaed140ac25d00beeff1a0156a9333afa8a5 lib/libmatrix_runtime_transport.a
42
- 337d38891e264e76aeb61a4e25a3b0bad56ab26697948805e64dec920874093f lib/libmatrix_runtime_video.a
42
+ ac7b85780c75b5d0c3abf1c5293181739a0fceeb2ad8fa930f98bd86bba5daa2 lib/libmatrix_runtime_video.a
43
43
  511d521f7972df3993e5976d6e2dbcad7a6fbce9be15071274d0cbd9d51157f5 lib/libssl.a
44
44
  a67ec9034848ef24a1b17671e444daa62a8f9e6b8319a1e932593908720ff2a1 lib/libwebrtc_apm.a
45
45
  700e455255897e3cffab13ca593a6e4d9d11383ae609215cbbd6043a63d47161 lib/libxlog.a
@@ -1,6 +1,6 @@
1
1
  platform=macos-arm64
2
2
  profile=full
3
- staged_at_utc=2026-05-01T15:05:49Z
3
+ staged_at_utc=2026-05-05T13:43:48Z
4
4
  source_sdk=/Users/allenfeng/Development/Repositories/tirtc-nexus/tirtc-matrix/.build/sdk/macos-arm64
5
5
 
6
6
  bfc096be1484ac2b1c2776ccabfa2a4c6a982e869abf875192ff06fad85e82ca include/tirtc/audio.h
@@ -35,13 +35,13 @@ cae0bbeb884e5466a56da15182c78cc22baab6c743f349a58d3595f623333585 include/tirtc/
35
35
  8db86d6714264047e8fd4086ddd7315722d675749719e6175f89eb5a636b48a1 lib/libTiRTC.a
36
36
  b39daee6a3d39bf0ca20c45084601133c4198de8dca848dcff6dd9c70ae99016 lib/libcrypto.a
37
37
  c052857ef315e3d61db9c862cad10709a3a6b2487dc41799cbe4d74a805de875 lib/libcrypto.dylib
38
- 144e6dc949d0e67cf6fb2515d7481adaaf681819784da0de8e0e5145d8222da4 lib/libmatrix_runtime_audio.a
39
- 512928f3cff1a491ebea78809458c5b81aac9fa83fc68aa98f520ff015ccdbac lib/libmatrix_runtime_facade.a
40
- 4cf46e46259c036450ab0bd03c4586da835813873d376ae164fb957605f0d16a lib/libmatrix_runtime_foundation_http.a
41
- 14fe5f66ab535ade89cf02381141ec360e7a3106dd34adadf71a81a610d71152 lib/libmatrix_runtime_foundation_logging.a
42
- 7fe25776f2d577aa02fafae8dd21d9bfc35154e1003eb5661ca7fd5348624cc4 lib/libmatrix_runtime_media.a
43
- b00c9435a140f956d65642015bf9275fbfb9c8cfca4d3d37d6ac60479df03a44 lib/libmatrix_runtime_transport.a
44
- 6c2cf719e9530776eded1565386ccb4b0fcc677007906dd3fdc0b5f754d6ebf0 lib/libmatrix_runtime_video.a
38
+ 8cf2dc6547ac1f3aa0d2866005af74c9ae6adf1f358d84cec119205bc1455a2a lib/libmatrix_runtime_audio.a
39
+ 11f5e0e50838b9f521acc0eed761120c550be71b87d0a04f172a02a62e6ea6bd lib/libmatrix_runtime_facade.a
40
+ 6ec439f590f1468763cdcc7ed6e4a5e24e9d169d37ecdb3d7d3449d633a01da3 lib/libmatrix_runtime_foundation_http.a
41
+ 8b49e1ae4eab6cdb74576e28e1df4c34986e65df044bbdf275b4f58daaddc52f lib/libmatrix_runtime_foundation_logging.a
42
+ 8151ddd3e587a169050a733db09e216c347a5733e341da90ec234153cf432297 lib/libmatrix_runtime_media.a
43
+ 05efbdfd1051206fa407dc81f3da9c35e60cf9d21005d01f59a23da688d97b64 lib/libmatrix_runtime_transport.a
44
+ 2f2c455c0fbb4c0d2242586aee3eec6c59f9323b380edeac85f3af0d8b9fb5e4 lib/libmatrix_runtime_video.a
45
45
  c11c65d373a127028350c41fa58cd2d1223f2b5d70a84e13b115d90daaba25ca lib/libssl.a
46
46
  ef1c1104bbdd2528ed7b958fb7252bd6249875f92300b0c9577d6c4bd6c0d88a lib/libssl.dylib
47
47
  e14e846e43d64e240fa0e5745bf4e702b79d0f2442e7f768beb990610735c71b lib/libtgrtc.dylib