tirtc-devtools-cli 0.0.12 → 0.0.14

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 (138) hide show
  1. package/README.md +42 -46
  2. package/USAGE.md +90 -311
  3. package/dist/cli/src/embedded_paths.d.ts +0 -2
  4. package/dist/cli/src/embedded_paths.js +3 -25
  5. package/dist/cli/src/index.js +82 -584
  6. package/dist/cli/src/role_driver.d.ts +33 -0
  7. package/dist/cli/src/role_driver.js +500 -0
  8. package/dist/cli/src/token_command.js +29 -14
  9. package/dist/cli/src/token_issue.d.ts +9 -0
  10. package/dist/cli/src/token_issue.js +138 -0
  11. package/dist/cli/src/token_tool.d.ts +4 -4
  12. package/dist/cli/src/token_tool.js +66 -182
  13. package/package.json +1 -1
  14. package/vendor/devtools/driver/macos-arm64/devtools_driver_probe +0 -0
  15. package/vendor/devtools/driver/macos-arm64/runtime_validation_client_bin +0 -0
  16. package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/include/tirtc/audio.h +83 -2
  17. package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/include/tirtc/audio_io.h +9 -0
  18. package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/include/tirtc/av.h +74 -0
  19. package/vendor/runtime/macos-arm64/include/tirtc/error.h +63 -0
  20. package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/include/tirtc/media_downlink.h +58 -5
  21. package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/include/tirtc/media_uplink.h +4 -0
  22. package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/include/tirtc/transport.h +52 -15
  23. package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/include/tirtc/trp.h +17 -5
  24. package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/include/tirtc/video_codec.h +41 -0
  25. package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/include/tirtc/video_io.h +7 -0
  26. package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/include/tirtc/video_io_android.h +2 -0
  27. package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/lib/libmatrix_runtime_audio.a +0 -0
  28. package/vendor/runtime/macos-arm64/lib/libmatrix_runtime_facade.a +0 -0
  29. package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/lib/libmatrix_runtime_foundation_http.a +0 -0
  30. package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/lib/libmatrix_runtime_foundation_logging.a +0 -0
  31. package/vendor/runtime/macos-arm64/lib/libmatrix_runtime_media.a +0 -0
  32. package/vendor/runtime/macos-arm64/lib/libmatrix_runtime_transport.a +0 -0
  33. package/vendor/runtime/macos-arm64/lib/libmatrix_runtime_video.a +0 -0
  34. package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/manifest.txt +20 -25
  35. package/vendor/runtime/script/prepare_runtime_media_dataset.sh +308 -12
  36. package/dist/app-server/protocol-client/index.d.ts +0 -25
  37. package/dist/app-server/protocol-client/index.js +0 -114
  38. package/dist/cli/src/bootstrap_flows.d.ts +0 -46
  39. package/dist/cli/src/bootstrap_flows.js +0 -249
  40. package/dist/cli/src/config.d.ts +0 -26
  41. package/dist/cli/src/config.js +0 -62
  42. package/dist/cli/src/facade.d.ts +0 -430
  43. package/dist/cli/src/facade.js +0 -170
  44. package/dist/cli/src/guide.d.ts +0 -1
  45. package/dist/cli/src/guide.js +0 -47
  46. package/dist/cli/src/session_manager.d.ts +0 -25
  47. package/dist/cli/src/session_manager.js +0 -391
  48. package/dist/cli/src/transport.d.ts +0 -30
  49. package/dist/cli/src/transport.js +0 -84
  50. package/vendor/app-server/bin/native/linux-x64/credential_napi.node +0 -0
  51. package/vendor/app-server/bin/native/macos-arm64/credential_napi.node +0 -0
  52. package/vendor/app-server/bin/runtime/linux-x64/include/tirtc/credential.h +0 -34
  53. package/vendor/app-server/bin/runtime/linux-x64/include/tirtc/error.h +0 -33
  54. package/vendor/app-server/bin/runtime/linux-x64/lib/libcrypto.a +0 -0
  55. package/vendor/app-server/bin/runtime/linux-x64/lib/libmatrix_runtime_credential.a +0 -0
  56. package/vendor/app-server/bin/runtime/linux-x64/lib/libmatrix_runtime_foundation_http.a +0 -0
  57. package/vendor/app-server/bin/runtime/linux-x64/lib/libmatrix_runtime_foundation_logging.a +0 -0
  58. package/vendor/app-server/bin/runtime/linux-x64/lib/libssl.a +0 -0
  59. package/vendor/app-server/bin/runtime/linux-x64/lib/libxlog.a +0 -0
  60. package/vendor/app-server/bin/runtime/linux-x64/manifest.txt +0 -4
  61. package/vendor/app-server/bin/runtime/macos-arm64/include/tirtc/credential.h +0 -34
  62. package/vendor/app-server/bin/runtime/macos-arm64/include/tirtc/error.h +0 -33
  63. package/vendor/app-server/bin/runtime/macos-arm64/include/tirtc/foundation/build_info.h +0 -27
  64. package/vendor/app-server/bin/runtime/macos-arm64/include/tirtc/http.h +0 -57
  65. package/vendor/app-server/bin/runtime/macos-arm64/include/tirtc/logging.h +0 -55
  66. package/vendor/app-server/bin/runtime/macos-arm64/include/tirtc/media_fixture_av_sync.h +0 -61
  67. package/vendor/app-server/bin/runtime/macos-arm64/include/tirtc/media_fixture_source.h +0 -77
  68. package/vendor/app-server/bin/runtime/macos-arm64/include/tirtc/media_live_source.h +0 -71
  69. package/vendor/app-server/bin/runtime/macos-arm64/lib/libmatrix_runtime_credential.a +0 -0
  70. package/vendor/app-server/bin/runtime/macos-arm64/lib/libmatrix_runtime_facade.a +0 -0
  71. package/vendor/app-server/bin/runtime/macos-arm64/lib/libmatrix_runtime_media.a +0 -0
  72. package/vendor/app-server/bin/runtime/macos-arm64/lib/libmatrix_runtime_transport.a +0 -0
  73. package/vendor/app-server/bin/runtime/macos-arm64/lib/libmatrix_runtime_video.a +0 -0
  74. package/vendor/app-server/bin/tirtc-devtool-host.js +0 -2
  75. package/vendor/app-server/dist/host/ArtifactManager.d.ts +0 -18
  76. package/vendor/app-server/dist/host/ArtifactManager.js +0 -98
  77. package/vendor/app-server/dist/host/HostCommandCoordinator.d.ts +0 -19
  78. package/vendor/app-server/dist/host/HostCommandCoordinator.js +0 -196
  79. package/vendor/app-server/dist/host/HostProtocol.d.ts +0 -103
  80. package/vendor/app-server/dist/host/HostProtocol.js +0 -239
  81. package/vendor/app-server/dist/host/HostServer.d.ts +0 -52
  82. package/vendor/app-server/dist/host/HostServer.js +0 -727
  83. package/vendor/app-server/dist/host/HostState.d.ts +0 -69
  84. package/vendor/app-server/dist/host/HostState.js +0 -19
  85. package/vendor/app-server/dist/host/RuntimeAdapter.d.ts +0 -95
  86. package/vendor/app-server/dist/host/RuntimeAdapter.js +0 -636
  87. package/vendor/app-server/dist/host/RuntimeReceiveWorker.d.ts +0 -37
  88. package/vendor/app-server/dist/host/RuntimeReceiveWorker.js +0 -186
  89. package/vendor/app-server/dist/host/RuntimeSendWorker.d.ts +0 -58
  90. package/vendor/app-server/dist/host/RuntimeSendWorker.js +0 -438
  91. package/vendor/app-server/dist/host/TokenTool.d.ts +0 -15
  92. package/vendor/app-server/dist/host/TokenTool.js +0 -84
  93. package/vendor/app-server/dist/host/WebPreviewGateway.d.ts +0 -28
  94. package/vendor/app-server/dist/host/WebPreviewGateway.js +0 -815
  95. package/vendor/app-server/dist/host/native/RuntimeCredentialTokenIssuer.d.ts +0 -26
  96. package/vendor/app-server/dist/host/native/RuntimeCredentialTokenIssuer.js +0 -118
  97. package/vendor/app-server/dist/host/native/RuntimeHostBridge.d.ts +0 -32
  98. package/vendor/app-server/dist/host/native/RuntimeHostBridge.js +0 -157
  99. package/vendor/app-server/dist/host/runtime_backed_preflight.d.ts +0 -10
  100. package/vendor/app-server/dist/host/runtime_backed_preflight.js +0 -78
  101. package/vendor/app-server/dist/host/tests/helpers/host_socket_client.d.ts +0 -28
  102. package/vendor/app-server/dist/host/tests/helpers/host_socket_client.js +0 -85
  103. package/vendor/app-server/dist/host/tests/helpers/runtime_e2e_local_config.d.ts +0 -10
  104. package/vendor/app-server/dist/host/tests/helpers/runtime_e2e_local_config.js +0 -41
  105. package/vendor/app-server/dist/host/tests/helpers/runtime_test_env.d.ts +0 -11
  106. package/vendor/app-server/dist/host/tests/helpers/runtime_test_env.js +0 -32
  107. package/vendor/app-server/dist/protocol/contract.d.ts +0 -1128
  108. package/vendor/app-server/dist/protocol/contract.js +0 -217
  109. package/vendor/app-server/dist/protocol-client/index.d.ts +0 -25
  110. package/vendor/app-server/dist/protocol-client/index.js +0 -114
  111. package/vendor/app-server/dist/src/index.d.ts +0 -1
  112. package/vendor/app-server/dist/src/index.js +0 -294
  113. /package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/include/tirtc/audio_codec.h +0 -0
  114. /package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/include/tirtc/audio_frame.h +0 -0
  115. /package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/include/tirtc/audio_io_android.h +0 -0
  116. /package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/include/tirtc/audio_io_apple.h +0 -0
  117. /package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/include/tirtc/audio_io_harmony.h +0 -0
  118. /package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/include/tirtc/audio_io_windows.h +0 -0
  119. /package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/include/tirtc/audio_processing.h +0 -0
  120. /package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/include/tirtc/audio_sample_rate.h +0 -0
  121. /package/vendor/{app-server/bin/runtime/linux-x64 → runtime/macos-arm64}/include/tirtc/foundation/build_info.h +0 -0
  122. /package/vendor/{app-server/bin/runtime/linux-x64 → runtime/macos-arm64}/include/tirtc/http.h +0 -0
  123. /package/vendor/{app-server/bin/runtime/linux-x64 → runtime/macos-arm64}/include/tirtc/logging.h +0 -0
  124. /package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/include/tirtc/media_codec.h +0 -0
  125. /package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/include/tirtc/video_frame.h +0 -0
  126. /package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/include/tirtc/video_io_apple.h +0 -0
  127. /package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/include/tirtc/video_io_harmony.h +0 -0
  128. /package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/include/tirtc/video_io_windows.h +0 -0
  129. /package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/include/tirtc/video_processing.h +0 -0
  130. /package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/lib/libTGTRP.a +0 -0
  131. /package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/lib/libTiRTC.a +0 -0
  132. /package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/lib/libcrypto.a +0 -0
  133. /package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/lib/libcrypto.dylib +0 -0
  134. /package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/lib/libssl.a +0 -0
  135. /package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/lib/libssl.dylib +0 -0
  136. /package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/lib/libtgrtc.dylib +0 -0
  137. /package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/lib/libwebrtc_apm.a +0 -0
  138. /package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/lib/libxlog.a +0 -0
@@ -0,0 +1,138 @@
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.issueToken = issueToken;
7
+ const crypto_1 = __importDefault(require("crypto"));
8
+ const http_1 = __importDefault(require("http"));
9
+ const https_1 = __importDefault(require("https"));
10
+ const defaultOpenapiEndpoint = 'http://api-test-tirtc.tange365.com';
11
+ const defaultUserTtlSeconds = 86400;
12
+ const defaultChannelTtlSeconds = 300;
13
+ const defaultHttpTimeoutMs = 15000;
14
+ function normalizeRequired(value, field) {
15
+ const normalized = value.trim();
16
+ if (normalized.length === 0) {
17
+ throw new Error('missing required credential field: ' + field);
18
+ }
19
+ return normalized;
20
+ }
21
+ function timestampUtc() {
22
+ return new Date().toISOString().replace(/\.\d{3}Z$/, 'Z');
23
+ }
24
+ function sha256Hex(input) {
25
+ return crypto_1.default.createHash('sha256').update(input).digest('hex');
26
+ }
27
+ function base64Url(input) {
28
+ return input.toString('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/g, '');
29
+ }
30
+ function buildAuthorization(method, requestPath, query, timestamp, body, accessId, secretKey) {
31
+ const bodyHash = sha256Hex(body);
32
+ const stringToSign = [method, requestPath, query, timestamp, bodyHash].join('\n');
33
+ const signature = crypto_1.default.createHmac('sha256', secretKey).update(stringToSign).digest();
34
+ return 'TGServer ' + accessId + ':' + base64Url(signature);
35
+ }
36
+ function postJson(endpoint, requestPath, headers, body) {
37
+ const url = new URL(endpoint);
38
+ const client = url.protocol === 'https:' ? https_1.default : http_1.default;
39
+ const port = url.port.length > 0 ? Number.parseInt(url.port, 10) : (url.protocol === 'https:' ? 443 : 80);
40
+ return new Promise((resolve, reject) => {
41
+ const request = client.request({
42
+ protocol: url.protocol,
43
+ hostname: url.hostname,
44
+ port,
45
+ method: 'POST',
46
+ path: requestPath,
47
+ headers: {
48
+ ...headers,
49
+ 'Content-Length': Buffer.byteLength(body),
50
+ },
51
+ timeout: defaultHttpTimeoutMs,
52
+ }, (response) => {
53
+ const chunks = [];
54
+ response.on('data', (chunk) => chunks.push(chunk));
55
+ response.on('end', () => {
56
+ resolve({
57
+ statusCode: response.statusCode ?? 0,
58
+ body: Buffer.concat(chunks).toString('utf8'),
59
+ });
60
+ });
61
+ });
62
+ request.on('timeout', () => {
63
+ request.destroy(new Error('token issue request timeout'));
64
+ });
65
+ request.on('error', reject);
66
+ request.write(body);
67
+ request.end();
68
+ });
69
+ }
70
+ function findStringByKey(value, key) {
71
+ if (typeof value !== 'object' || value === null) {
72
+ return '';
73
+ }
74
+ if (Array.isArray(value)) {
75
+ for (const entry of value) {
76
+ const found = findStringByKey(entry, key);
77
+ if (found.length > 0) {
78
+ return found;
79
+ }
80
+ }
81
+ return '';
82
+ }
83
+ const record = value;
84
+ if (typeof record[key] === 'string') {
85
+ return record[key];
86
+ }
87
+ for (const entry of Object.values(record)) {
88
+ const found = findStringByKey(entry, key);
89
+ if (found.length > 0) {
90
+ return found;
91
+ }
92
+ }
93
+ return '';
94
+ }
95
+ function readJsonString(body, key) {
96
+ try {
97
+ return findStringByKey(JSON.parse(body), key);
98
+ }
99
+ catch {
100
+ return '';
101
+ }
102
+ }
103
+ function issueFailure(statusCode) {
104
+ return new Error('issue token failed error=3 http_status=' + statusCode);
105
+ }
106
+ async function issueToken(input) {
107
+ const accessId = normalizeRequired(input.accessId, 'accessId');
108
+ const secretKey = normalizeRequired(input.secretKey, 'secretKey');
109
+ const remoteId = normalizeRequired(input.remoteId, 'remoteId');
110
+ const endpoint = input.openapiEndpoint?.trim() || defaultOpenapiEndpoint;
111
+ const userTtlSeconds = input.userTtlSeconds && input.userTtlSeconds > 0 ?
112
+ input.userTtlSeconds :
113
+ defaultUserTtlSeconds;
114
+ const channelTtlSeconds = input.channelTtlSeconds && input.channelTtlSeconds > 0 ?
115
+ input.channelTtlSeconds :
116
+ defaultChannelTtlSeconds;
117
+ const timestamp = timestampUtc();
118
+ const userBody = JSON.stringify({ access_id: accessId, uid: remoteId, ttl: userTtlSeconds });
119
+ const userResponse = await postJson(endpoint, '/v1/user_token', {
120
+ 'Content-Type': 'application/json',
121
+ Authorization: buildAuthorization('POST', '/v1/user_token', '', timestamp, userBody, accessId, secretKey),
122
+ 'X-TG-Timestamp': timestamp,
123
+ }, userBody);
124
+ const userToken = readJsonString(userResponse.body, 'user_token');
125
+ if (userResponse.statusCode < 200 || userResponse.statusCode >= 300 || userToken.length === 0) {
126
+ throw issueFailure(userResponse.statusCode);
127
+ }
128
+ const channelBody = JSON.stringify({ device_id: remoteId, ttl: channelTtlSeconds });
129
+ const channelResponse = await postJson(endpoint, '/v1/token', {
130
+ 'Content-Type': 'application/json',
131
+ Authorization: 'Bearer ' + userToken,
132
+ }, channelBody);
133
+ const token = readJsonString(channelResponse.body, 'token').trim();
134
+ if (channelResponse.statusCode < 200 || channelResponse.statusCode >= 300 || token.length === 0) {
135
+ throw issueFailure(channelResponse.statusCode);
136
+ }
137
+ return token;
138
+ }
@@ -1,6 +1,7 @@
1
1
  export type TokenIssueInput = {
2
2
  accessId: string;
3
3
  secretKey: string;
4
+ appId: string;
4
5
  remoteId: string;
5
6
  openapiEndpoint?: string;
6
7
  endpoint?: string;
@@ -8,6 +9,7 @@ export type TokenIssueInput = {
8
9
  asciiMaxColumns?: number;
9
10
  };
10
11
  export type IssuedTokenPayload = {
12
+ app_id: string;
11
13
  remote_id: string;
12
14
  token: string;
13
15
  endpoint?: string;
@@ -38,11 +40,9 @@ export type LicenseQrcodeOutput = {
38
40
  qrCodeAscii: string;
39
41
  qrCodeAsciiIncluded: boolean;
40
42
  };
41
- export declare function resolveIssueTokenEnvironment(runtimePlatform?: string, fromDir?: string): {
43
+ export declare function resolveIssueTokenEnvironment(): {
42
44
  runtimePlatform: string;
43
- runtimeBundleRoot: string;
44
- repoRoot: string;
45
- addonPath: string;
45
+ provider: string;
46
46
  };
47
47
  export declare function issueToken(input: TokenIssueInput): Promise<string>;
48
48
  export declare function buildIssuedTokenPayload(input: TokenIssueInput, token: string): IssuedTokenPayload;
@@ -1,37 +1,4 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
2
  var __importDefault = (this && this.__importDefault) || function (mod) {
36
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
37
4
  };
@@ -46,15 +13,11 @@ exports.issueTokenWithQrcode = issueTokenWithQrcode;
46
13
  exports.buildLicenseQrcode = buildLicenseQrcode;
47
14
  exports.formatTokenIssueConsoleOutput = formatTokenIssueConsoleOutput;
48
15
  exports.formatLicenseQrcodeConsoleOutput = formatLicenseQrcodeConsoleOutput;
49
- const childProcess = __importStar(require("child_process"));
50
16
  const fs_1 = __importDefault(require("fs"));
51
17
  const path_1 = __importDefault(require("path"));
52
18
  const qrcode_1 = __importDefault(require("qrcode"));
53
- const embedded_paths_1 = require("./embedded_paths");
19
+ const token_issue_1 = require("./token_issue");
54
20
  const kAsciiQrQuietZoneModules = 2;
55
- function pathExists(filePath) {
56
- return fs_1.default.existsSync(filePath);
57
- }
58
21
  function ensureDirectory(dirPath) {
59
22
  fs_1.default.mkdirSync(dirPath, { recursive: true });
60
23
  }
@@ -78,109 +41,10 @@ function buildTokenQrCodePngPath(payload) {
78
41
  function buildLicenseQrCodePngPath(payload) {
79
42
  return buildQrCodePngPath('license', payload.license);
80
43
  }
81
- function resolveRuntimePlatform() {
82
- const raw = process.env.TIRTC_RUNTIME_PLATFORM;
83
- if (raw && raw.trim().length > 0) {
84
- return raw.trim();
85
- }
86
- if (process.platform === 'darwin' && process.arch === 'arm64') {
87
- return 'macos-arm64';
88
- }
89
- return 'linux-x64';
90
- }
91
- function resolveRuntimeBundleRoot(runtimePlatform, fromDir = __dirname) {
92
- const explicit = process.env.TIRTC_RUNTIME_BUNDLE_ROOT;
93
- if (explicit && explicit.trim().length > 0) {
94
- return explicit.trim();
95
- }
96
- const embedded = (0, embedded_paths_1.resolveEmbeddedRuntimeBundleRoot)(fromDir, runtimePlatform);
97
- if (embedded) {
98
- return embedded;
99
- }
100
- const execDir = path_1.default.dirname(process.execPath);
101
- const candidates = [
102
- path_1.default.resolve(execDir, 'runtime', runtimePlatform),
103
- path_1.default.resolve(execDir, '../runtime', runtimePlatform),
104
- path_1.default.resolve(__dirname, '../bin/runtime', runtimePlatform),
105
- path_1.default.resolve(__dirname, '../../../../bin/runtime', runtimePlatform),
106
- path_1.default.resolve(process.cwd(), 'products/cli/bin/runtime', runtimePlatform),
107
- path_1.default.resolve(process.cwd(), 'bin/runtime', runtimePlatform),
108
- path_1.default.resolve(process.cwd(), '../bin/runtime', runtimePlatform),
109
- ];
110
- for (const candidate of candidates) {
111
- if (pathExists(path_1.default.join(candidate, 'manifest.txt'))) {
112
- return candidate;
113
- }
114
- }
115
- return candidates[0];
116
- }
117
- function resolveRepoRoot(fromDir = __dirname) {
118
- const embeddedAppServerRoot = (0, embedded_paths_1.resolveEmbeddedAppServerRoot)(fromDir);
119
- if (embeddedAppServerRoot) {
120
- return path_1.default.resolve(embeddedAppServerRoot, '..');
121
- }
122
- const candidates = [
123
- path_1.default.resolve(__dirname, '../../../../../../'),
124
- path_1.default.resolve(__dirname, '../../../../../'),
125
- path_1.default.resolve(__dirname, '../../../..'),
126
- path_1.default.resolve(process.cwd()),
127
- ];
128
- for (const candidate of candidates) {
129
- if (pathExists(path_1.default.join(candidate, 'products/app-server')) && pathExists(path_1.default.join(candidate, 'products/cli'))) {
130
- return candidate;
131
- }
132
- }
133
- return candidates[0];
134
- }
135
- function resolveEmbeddedAddonPath(runtimePlatform, fromDir = __dirname) {
136
- const embeddedAppServerRoot = (0, embedded_paths_1.resolveEmbeddedAppServerRoot)(fromDir);
137
- if (!embeddedAppServerRoot) {
138
- return undefined;
139
- }
140
- const candidate = path_1.default.join(embeddedAppServerRoot, 'bin/native', runtimePlatform, 'credential_napi.node');
141
- if (pathExists(candidate)) {
142
- return candidate;
143
- }
144
- return undefined;
145
- }
146
- function ensureRuntimeBundleReady(runtimeBundleRoot) {
147
- const includeDir = path_1.default.join(runtimeBundleRoot, 'include');
148
- const libDir = path_1.default.join(runtimeBundleRoot, 'lib');
149
- if (!pathExists(includeDir) || !pathExists(libDir)) {
150
- throw new Error('runtime-backed sdk bundle is missing: ' + runtimeBundleRoot);
151
- }
152
- }
153
- function resolveAddonPath(repoRoot, runtimePlatform, fromDir = __dirname) {
154
- const explicit = process.env.TIRTC_CREDENTIAL_ADDON_PATH;
155
- const embedded = resolveEmbeddedAddonPath(runtimePlatform, fromDir);
156
- const candidates = [
157
- explicit,
158
- embedded,
159
- path_1.default.join(repoRoot, `products/app-server/bin/native/${runtimePlatform}/credential_napi.node`),
160
- path_1.default.join(repoRoot, `app-server/bin/native/${runtimePlatform}/credential_napi.node`),
161
- path_1.default.join(repoRoot, `.build/app-server/native/${runtimePlatform}/credential_napi.node`),
162
- path_1.default.resolve(process.cwd(), `products/app-server/bin/native/${runtimePlatform}/credential_napi.node`),
163
- path_1.default.resolve(process.cwd(), `app-server/bin/native/${runtimePlatform}/credential_napi.node`),
164
- path_1.default.resolve(process.cwd(), `.build/app-server/native/${runtimePlatform}/credential_napi.node`),
165
- ].filter((entry) => typeof entry === 'string' && entry.trim().length > 0);
166
- for (const candidate of candidates) {
167
- const normalized = path_1.default.resolve(candidate);
168
- if (pathExists(normalized)) {
169
- return normalized;
170
- }
171
- }
172
- throw new Error('credential addon missing for platform ' + runtimePlatform +
173
- '; run: npm --prefix products/app-server run build:native');
174
- }
175
- function resolveIssueTokenEnvironment(runtimePlatform = resolveRuntimePlatform(), fromDir = __dirname) {
176
- const runtimeBundleRoot = resolveRuntimeBundleRoot(runtimePlatform, fromDir);
177
- const repoRoot = resolveRepoRoot(fromDir);
178
- ensureRuntimeBundleReady(runtimeBundleRoot);
44
+ function resolveIssueTokenEnvironment() {
179
45
  return {
180
- runtimePlatform,
181
- runtimeBundleRoot,
182
- repoRoot,
183
- addonPath: resolveAddonPath(repoRoot, runtimePlatform, fromDir),
46
+ runtimePlatform: 'node',
47
+ provider: 'products/cli',
184
48
  };
185
49
  }
186
50
  function normalizeIssuedToken(token) {
@@ -190,48 +54,61 @@ function normalizeIssuedToken(token) {
190
54
  }
191
55
  return normalized;
192
56
  }
193
- function buildIssueTokenHelperSource() {
194
- return [
195
- 'const addon = require(process.env.TIRTC_CREDENTIAL_ADDON_PATH_HELPER);',
196
- 'const input = JSON.parse(process.env.TIRTC_CREDENTIAL_INPUT_JSON || "{}");',
197
- 'const originalWrite = process.stderr.write.bind(process.stderr);',
198
- 'process.stderr.write = ((chunk, encoding, callback) => {',
199
- ' if (typeof callback === "function") {',
200
- ' callback();',
201
- ' }',
202
- ' return true;',
203
- '});',
204
- 'try {',
205
- ' const token = addon.issueToken({',
206
- ' openapiEndpoint: input.openapiEndpoint,',
207
- ' accessId: input.accessId,',
208
- ' secretKey: input.secretKey,',
209
- ' remoteId: input.remoteId,',
210
- ' });',
211
- ' process.stdout.write(String(token).trim());',
212
- '} finally {',
213
- ' process.stderr.write = originalWrite;',
214
- '}',
215
- ].join('\n');
57
+ function parseIssueTokenFailure(message) {
58
+ const matched = message.match(/issue token failed error=(\d+) http_status=(\d+)/i);
59
+ if (!matched) {
60
+ return {};
61
+ }
62
+ const errorCode = Number.parseInt(matched[1] ?? '', 10);
63
+ const httpStatus = Number.parseInt(matched[2] ?? '', 10);
64
+ return {
65
+ errorCode: Number.isNaN(errorCode) ? undefined : errorCode,
66
+ httpStatus: Number.isNaN(httpStatus) ? undefined : httpStatus,
67
+ };
216
68
  }
217
- function issueTokenViaSubprocess(addonPath, input) {
218
- const result = childProcess.spawnSync(process.execPath, ['-e', buildIssueTokenHelperSource()], {
219
- encoding: 'utf8',
220
- env: {
221
- ...process.env,
222
- TIRTC_CREDENTIAL_ADDON_PATH_HELPER: addonPath,
223
- TIRTC_CREDENTIAL_INPUT_JSON: JSON.stringify(input),
224
- },
225
- stdio: ['ignore', 'pipe', 'pipe'],
226
- });
227
- if (result.error) {
228
- throw result.error;
69
+ function isNodeStackNoise(line) {
70
+ return line.startsWith('[eval]:') ||
71
+ line.startsWith('at [eval]') ||
72
+ line.startsWith('at runScriptInThisContext') ||
73
+ line.startsWith('at node:internal/') ||
74
+ line.startsWith('Node.js v');
75
+ }
76
+ function sanitizeIssueTokenFailureText(message) {
77
+ const lines = message
78
+ .split(/\r?\n/)
79
+ .map((line) => line.trim())
80
+ .filter((line) => line.length > 0 && !isNodeStackNoise(line));
81
+ const collapsed = lines.join(' | ');
82
+ if (collapsed.length === 0) {
83
+ return 'token issuing failed';
229
84
  }
230
- if (result.status !== 0) {
231
- const details = String(result.stderr || result.stdout || 'issue token subprocess failed').trim();
232
- throw new Error(details || 'issue token subprocess failed');
85
+ return collapsed;
86
+ }
87
+ function formatIssueTokenFailureMessage(message) {
88
+ const parsed = parseIssueTokenFailure(message);
89
+ const detail = sanitizeIssueTokenFailureText(message);
90
+ if (parsed.httpStatus === 200 && parsed.errorCode === 3) {
91
+ return [
92
+ 'token issuing failed: remote service rejected the request.',
93
+ 'Check whether remote_id, access_key_id, secret_key_id, and openapi-endpoint are correct.',
94
+ 'detail: error=3 http_status=200',
95
+ ].join(' ');
96
+ }
97
+ if (parsed.httpStatus !== undefined || parsed.errorCode !== undefined) {
98
+ const detailParts = [];
99
+ if (parsed.errorCode !== undefined) {
100
+ detailParts.push('error=' + parsed.errorCode);
101
+ }
102
+ if (parsed.httpStatus !== undefined) {
103
+ detailParts.push('http_status=' + parsed.httpStatus);
104
+ }
105
+ return [
106
+ 'token issuing failed: remote authentication request was not accepted.',
107
+ 'Check whether remote_id, access_key_id, secret_key_id, and openapi-endpoint are correct.',
108
+ 'detail: ' + detailParts.join(' '),
109
+ ].join(' ');
233
110
  }
234
- return normalizeIssuedToken(String(result.stdout || ''));
111
+ return 'token issuing failed: ' + detail;
235
112
  }
236
113
  function readQrModule(modules, row, column) {
237
114
  return Boolean(modules.data[row * modules.size + column]);
@@ -289,17 +166,23 @@ function renderHalfBlockQr(modules) {
289
166
  return lines.join('\n');
290
167
  }
291
168
  async function issueToken(input) {
292
- const resolved = resolveIssueTokenEnvironment();
169
+ resolveIssueTokenEnvironment();
293
170
  try {
294
- return issueTokenViaSubprocess(resolved.addonPath, input);
171
+ return normalizeIssuedToken(await (0, token_issue_1.issueToken)({
172
+ accessId: input.accessId,
173
+ secretKey: input.secretKey,
174
+ remoteId: input.remoteId,
175
+ openapiEndpoint: input.openapiEndpoint,
176
+ }));
295
177
  }
296
178
  catch (error) {
297
179
  const message = error instanceof Error ? error.message : String(error);
298
- throw new Error('issue token failed: ' + message);
180
+ throw new Error(formatIssueTokenFailureMessage(message));
299
181
  }
300
182
  }
301
183
  function buildIssuedTokenPayload(input, token) {
302
184
  const payload = {
185
+ app_id: input.appId.trim(),
303
186
  remote_id: input.remoteId,
304
187
  token,
305
188
  };
@@ -381,6 +264,7 @@ async function buildLicenseQrcode(input) {
381
264
  function formatTokenIssueConsoleOutput(output) {
382
265
  const summaryLines = [
383
266
  'Issued Token Summary:',
267
+ ' app_id: ' + output.payload.app_id,
384
268
  ' remote_id: ' + output.payload.remote_id,
385
269
  ' endpoint: ' + (output.payload.endpoint ?? '(omitted)'),
386
270
  ' openapi_endpoint: ' + (output.payload.openapi_endpoint ?? '(omitted)'),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tirtc-devtools-cli",
3
- "version": "0.0.12",
3
+ "version": "0.0.14",
4
4
  "private": false,
5
5
  "main": "dist/cli/src/index.js",
6
6
  "types": "dist/cli/src/index.d.ts",
@@ -3,8 +3,10 @@
3
3
 
4
4
  #include <stdint.h>
5
5
 
6
+ #include "tirtc/audio_frame.h"
6
7
  #include "tirtc/audio_io.h"
7
8
  #include "tirtc/audio_processing.h"
9
+ #include "tirtc/media_codec.h"
8
10
  #include "tirtc/trp.h"
9
11
 
10
12
  #ifdef __cplusplus
@@ -13,6 +15,8 @@ extern "C" {
13
15
 
14
16
  typedef struct TirtcAudioInput TirtcAudioInput;
15
17
 
18
+ typedef struct TirtcAudioEncodedInput TirtcAudioEncodedInput;
19
+
16
20
  typedef struct TirtcAudioOutput TirtcAudioOutput;
17
21
 
18
22
  typedef enum TirtcInputState {
@@ -47,14 +51,51 @@ typedef struct TirtcAudioInputOptions {
47
51
  TirtcAudioAnsLevel ans_level;
48
52
  } TirtcAudioInputOptions;
49
53
 
54
+ /**
55
+ * Options for a facade audio encoded input.
56
+ *
57
+ * The encoded input does not own or create an audio source. Callers submit already-encoded audio
58
+ * frames with `tirtc_audio_encoded_input_submit_frame()`. Non-NONE fields constrain submitted
59
+ * frames and reject mismatched packets with `TIRTC_ERROR_INVALID_ARGUMENT`.
60
+ */
61
+ typedef struct TirtcAudioEncodedInputOptions {
62
+ TirtcMediaCodec codec;
63
+
64
+ TirtcAudioSampleRate sample_rate;
65
+ } TirtcAudioEncodedInputOptions;
66
+
50
67
  typedef struct TirtcAudioOutputOptions {
51
68
  uint32_t volume_percent;
52
69
 
53
- int gain_level;
70
+ TirtcAudioAgcLevel agc_level;
54
71
 
55
- int noise_reduction_level;
72
+ TirtcAudioAnsLevel ans_level;
56
73
  } TirtcAudioOutputOptions;
57
74
 
75
+ typedef struct TirtcOutputStutterMetrics {
76
+ int session_started;
77
+ uint64_t session_duration_ms;
78
+ uint64_t session_stutter_total_ms;
79
+ uint32_t session_stutter_count;
80
+ uint64_t session_stutter_peak_ms;
81
+ double session_stutter_ratio;
82
+ uint32_t recent_window_duration_ms;
83
+ uint64_t recent_window_stutter_total_ms;
84
+ uint32_t recent_window_stutter_count;
85
+ uint64_t recent_window_stutter_peak_ms;
86
+ double recent_window_stutter_ratio;
87
+ } TirtcOutputStutterMetrics;
88
+
89
+ typedef struct TirtcPendingDurationMetrics {
90
+ uint64_t undecoded_duration_ms;
91
+ uint64_t decoded_duration_ms;
92
+ } TirtcPendingDurationMetrics;
93
+
94
+ typedef struct TirtcAudioOutputMetricsSnapshot {
95
+ TirtcOutputStutterMetrics stutter;
96
+ TirtcPendingDurationMetrics pending;
97
+ } TirtcAudioOutputMetricsSnapshot;
98
+
58
99
  /**
59
100
  * Audio input observer.
60
101
  *
@@ -68,6 +109,20 @@ typedef struct TirtcAudioInputObserver {
68
109
  void* user_data);
69
110
  } TirtcAudioInputObserver;
70
111
 
112
+ /**
113
+ * Audio encoded input observer.
114
+ *
115
+ * State callbacks report only facade input lifecycle changes. They do not mean a remote consumer
116
+ * has subscribed to, decoded, or rendered the stream. `owned_message` is allocated by facade for
117
+ * this callback dispatch; consumers must release it with `tirtc_owned_string_release()`.
118
+ */
119
+ typedef struct TirtcAudioEncodedInputObserver {
120
+ void (*on_state_changed)(TirtcAudioEncodedInput* input, TirtcInputState state, void* user_data);
121
+
122
+ void (*on_error)(TirtcAudioEncodedInput* input, TirtcError error, TirtcOwnedString* owned_message,
123
+ void* user_data);
124
+ } TirtcAudioEncodedInputObserver;
125
+
71
126
  /**
72
127
  * Audio output observer.
73
128
  *
@@ -106,6 +161,29 @@ TirtcError tirtc_audio_input_detach(TirtcAudioInput* input, TirtcConn* connectio
106
161
 
107
162
  void tirtc_audio_input_destroy(TirtcAudioInput* input);
108
163
 
164
+ TirtcError tirtc_audio_encoded_input_create(TirtcAudioEncodedInput** out_input);
165
+
166
+ TirtcError tirtc_audio_encoded_input_set_options(TirtcAudioEncodedInput* input,
167
+ const TirtcAudioEncodedInputOptions* options);
168
+
169
+ TirtcError tirtc_audio_encoded_input_set_observer(TirtcAudioEncodedInput* input,
170
+ const TirtcAudioEncodedInputObserver* observer,
171
+ void* user_data);
172
+
173
+ TirtcError tirtc_audio_encoded_input_start(TirtcAudioEncodedInput* input);
174
+
175
+ TirtcError tirtc_audio_encoded_input_stop(TirtcAudioEncodedInput* input);
176
+
177
+ TirtcError tirtc_audio_encoded_input_attach(TirtcAudioEncodedInput* input, TirtcConn* connection,
178
+ uint8_t stream_id);
179
+
180
+ TirtcError tirtc_audio_encoded_input_detach(TirtcAudioEncodedInput* input, TirtcConn* connection);
181
+
182
+ TirtcError tirtc_audio_encoded_input_submit_frame(TirtcAudioEncodedInput* input,
183
+ const TirtcAudioEncodedFrame* frame);
184
+
185
+ void tirtc_audio_encoded_input_destroy(TirtcAudioEncodedInput* input);
186
+
109
187
  TirtcError tirtc_audio_output_create(TirtcAudioOutput** out_output);
110
188
 
111
189
  TirtcError tirtc_audio_output_set_aout(TirtcAudioOutput* output, TirtcAudioAout* aout);
@@ -128,6 +206,9 @@ TirtcError tirtc_audio_output_start_raw_dump(TirtcAudioOutput* output);
128
206
 
129
207
  TirtcError tirtc_audio_output_stop_raw_dump(TirtcAudioOutput* output);
130
208
 
209
+ TirtcError tirtc_metrics_audio_output_get_snapshot(TirtcAudioOutput* output,
210
+ TirtcAudioOutputMetricsSnapshot* out_snapshot);
211
+
131
212
  #ifdef __cplusplus
132
213
  }
133
214
  #endif
@@ -19,6 +19,12 @@ typedef struct TirtcAudioIoConfig {
19
19
  uint32_t samples_per_buffer;
20
20
  } TirtcAudioIoConfig;
21
21
 
22
+ typedef struct TirtcAudioHeadlessAoutOptions {
23
+ const char* first_output_json_path;
24
+ const char* pcm_path;
25
+ uint32_t max_capture_bytes;
26
+ } TirtcAudioHeadlessAoutOptions;
27
+
22
28
  typedef void (*TirtcAudioAinOnFrameFn)(TirtcAudioAin* ain, const TirtcAudioPcmFrame* frame,
23
29
  void* user_data);
24
30
 
@@ -43,6 +49,9 @@ void tirtc_audio_ain_destroy(TirtcAudioAin* ain);
43
49
  TirtcError tirtc_audio_aout_open(TirtcAudioAout* aout, const TirtcAudioIoConfig* config,
44
50
  TirtcAudioAoutRenderFn render, void* user_data);
45
51
 
52
+ TirtcError tirtc_audio_aout_create_headless_capture(const TirtcAudioHeadlessAoutOptions* options,
53
+ TirtcAudioAout** out_aout);
54
+
46
55
  TirtcError tirtc_audio_aout_set_volume(TirtcAudioAout* aout, uint32_t volume_percent);
47
56
  TirtcError tirtc_audio_aout_pause(TirtcAudioAout* aout, int pause_on);
48
57
  TirtcError tirtc_audio_aout_flush(TirtcAudioAout* aout);