tirtc-devtools-cli 0.0.9 → 0.0.11

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 (115) hide show
  1. package/README.md +17 -11
  2. package/USAGE.md +72 -33
  3. package/bin/tirtc-devtools-cli.js +1 -1
  4. package/dist/cli/src/bootstrap_flows.d.ts +46 -0
  5. package/dist/cli/src/bootstrap_flows.js +249 -0
  6. package/dist/{devtools/cli → cli}/src/config.d.ts +4 -15
  7. package/dist/{devtools/cli → cli}/src/config.js +7 -31
  8. package/dist/cli/src/default_paths.d.ts +3 -0
  9. package/dist/cli/src/default_paths.js +23 -0
  10. package/dist/{devtools/cli → cli}/src/embedded_paths.d.ts +1 -0
  11. package/dist/{devtools/cli → cli}/src/embedded_paths.js +18 -1
  12. package/dist/{devtools/cli → cli}/src/facade.d.ts +41 -235
  13. package/dist/{devtools/cli → cli}/src/facade.js +8 -27
  14. package/dist/cli/src/guide.js +47 -0
  15. package/dist/{devtools/cli → cli}/src/index.js +55 -141
  16. package/dist/{devtools/cli → cli}/src/session_manager.js +9 -11
  17. package/dist/{devtools/cli → cli}/src/token_command.js +69 -0
  18. package/dist/{devtools/cli → cli}/src/token_tool.d.ts +26 -0
  19. package/dist/{devtools/cli → cli}/src/token_tool.js +123 -22
  20. package/dist/{devtools/cli → cli}/src/transport.d.ts +1 -1
  21. package/package.json +6 -2
  22. package/script/ensure_ffmpeg.sh +1 -1
  23. package/vendor/app-server/bin/native/linux-x64/credential_napi.node +0 -0
  24. package/vendor/app-server/bin/native/macos-arm64/credential_napi.node +0 -0
  25. package/vendor/app-server/bin/runtime/linux-x64/include/tirtc/credential.h +34 -0
  26. package/vendor/app-server/bin/runtime/linux-x64/include/tirtc/error.h +13 -0
  27. package/vendor/app-server/bin/runtime/linux-x64/include/tirtc/foundation/build_info.h +27 -0
  28. package/vendor/app-server/bin/runtime/linux-x64/include/tirtc/http.h +57 -0
  29. package/vendor/app-server/bin/runtime/linux-x64/include/tirtc/logging.h +3 -1
  30. package/vendor/app-server/bin/runtime/linux-x64/lib/libcrypto.a +0 -0
  31. package/vendor/app-server/bin/runtime/linux-x64/lib/libmatrix_runtime_credential.a +0 -0
  32. package/vendor/app-server/bin/runtime/linux-x64/lib/libmatrix_runtime_foundation_http.a +0 -0
  33. package/vendor/app-server/bin/runtime/linux-x64/lib/libmatrix_runtime_foundation_logging.a +0 -0
  34. package/vendor/app-server/bin/runtime/linux-x64/lib/libssl.a +0 -0
  35. package/vendor/app-server/bin/runtime/linux-x64/manifest.txt +2 -32
  36. package/vendor/app-server/bin/runtime/macos-arm64/include/tirtc/audio.h +176 -133
  37. package/vendor/app-server/bin/runtime/macos-arm64/include/tirtc/av.h +223 -182
  38. package/vendor/app-server/bin/runtime/macos-arm64/include/tirtc/error.h +2 -0
  39. package/vendor/app-server/bin/runtime/macos-arm64/include/tirtc/media_downlink.h +6 -0
  40. package/vendor/app-server/bin/runtime/macos-arm64/include/tirtc/transport.h +58 -133
  41. package/vendor/app-server/bin/runtime/macos-arm64/include/tirtc/trp.h +47 -224
  42. package/vendor/app-server/bin/runtime/macos-arm64/lib/libTGTRP.a +0 -0
  43. package/vendor/app-server/bin/runtime/macos-arm64/lib/libTiRTC.a +0 -0
  44. package/vendor/app-server/bin/runtime/macos-arm64/lib/libmatrix_runtime_audio.a +0 -0
  45. package/vendor/app-server/bin/runtime/macos-arm64/lib/libmatrix_runtime_credential.a +0 -0
  46. package/vendor/app-server/bin/runtime/macos-arm64/lib/libmatrix_runtime_facade.a +0 -0
  47. package/vendor/app-server/bin/runtime/macos-arm64/lib/libmatrix_runtime_foundation_http.a +0 -0
  48. package/vendor/app-server/bin/runtime/macos-arm64/lib/libmatrix_runtime_foundation_logging.a +0 -0
  49. package/vendor/app-server/bin/runtime/macos-arm64/lib/libmatrix_runtime_media.a +0 -0
  50. package/vendor/app-server/bin/runtime/macos-arm64/lib/libmatrix_runtime_transport.a +0 -0
  51. package/vendor/app-server/bin/runtime/macos-arm64/lib/libmatrix_runtime_video.a +0 -0
  52. package/vendor/app-server/bin/runtime/macos-arm64/manifest.txt +19 -15
  53. package/vendor/app-server/dist/host/HostCommandCoordinator.d.ts +19 -0
  54. package/vendor/app-server/dist/host/HostCommandCoordinator.js +196 -0
  55. package/vendor/app-server/dist/host/HostProtocol.d.ts +1 -11
  56. package/vendor/app-server/dist/host/HostProtocol.js +3 -37
  57. package/vendor/app-server/dist/host/HostServer.d.ts +1 -4
  58. package/vendor/app-server/dist/host/HostServer.js +16 -152
  59. package/vendor/app-server/dist/host/RuntimeAdapter.js +2 -2
  60. package/vendor/app-server/dist/host/native/RuntimeCredentialTokenIssuer.js +3 -3
  61. package/vendor/app-server/dist/host/native/RuntimeHostBridge.js +4 -4
  62. package/vendor/app-server/dist/host/runtime_backed_preflight.js +2 -2
  63. package/vendor/app-server/dist/host/tests/helpers/runtime_e2e_local_config.js +1 -1
  64. package/vendor/app-server/dist/protocol/contract.d.ts +5 -64
  65. package/vendor/app-server/dist/protocol/contract.js +3 -12
  66. package/dist/devtools/cli/src/guide.js +0 -50
  67. package/dist/dummy.d.ts +0 -0
  68. package/dist/dummy.js +0 -1
  69. package/dist/index.d.ts +0 -1
  70. package/dist/index.js +0 -48
  71. package/vendor/app-server/bin/native/macos-arm64/libcrypto.dylib +0 -0
  72. package/vendor/app-server/bin/native/macos-arm64/libssl.dylib +0 -0
  73. package/vendor/app-server/bin/native/macos-arm64/runtime_host_napi.node +0 -0
  74. package/vendor/app-server/bin/runtime/linux-x64/include/tirtc/audio_codec.h +0 -23
  75. package/vendor/app-server/bin/runtime/linux-x64/include/tirtc/audio_frame.h +0 -36
  76. package/vendor/app-server/bin/runtime/linux-x64/include/tirtc/audio_io.h +0 -56
  77. package/vendor/app-server/bin/runtime/linux-x64/include/tirtc/audio_io_android.h +0 -19
  78. package/vendor/app-server/bin/runtime/linux-x64/include/tirtc/audio_io_apple.h +0 -19
  79. package/vendor/app-server/bin/runtime/linux-x64/include/tirtc/audio_io_harmony.h +0 -19
  80. package/vendor/app-server/bin/runtime/linux-x64/include/tirtc/audio_io_windows.h +0 -19
  81. package/vendor/app-server/bin/runtime/linux-x64/include/tirtc/audio_processing.h +0 -56
  82. package/vendor/app-server/bin/runtime/linux-x64/include/tirtc/audio_sample_rate.h +0 -18
  83. package/vendor/app-server/bin/runtime/linux-x64/include/tirtc/media_codec.h +0 -21
  84. package/vendor/app-server/bin/runtime/linux-x64/include/tirtc/media_downlink.h +0 -89
  85. package/vendor/app-server/bin/runtime/linux-x64/include/tirtc/media_uplink.h +0 -115
  86. package/vendor/app-server/bin/runtime/linux-x64/include/tirtc/runtime.h +0 -236
  87. package/vendor/app-server/bin/runtime/linux-x64/include/tirtc/video_codec.h +0 -57
  88. package/vendor/app-server/bin/runtime/linux-x64/include/tirtc/video_frame.h +0 -55
  89. package/vendor/app-server/bin/runtime/linux-x64/include/tirtc/video_io.h +0 -46
  90. package/vendor/app-server/bin/runtime/linux-x64/include/tirtc/video_io_android.h +0 -32
  91. package/vendor/app-server/bin/runtime/linux-x64/include/tirtc/video_io_apple.h +0 -34
  92. package/vendor/app-server/bin/runtime/linux-x64/include/tirtc/video_io_harmony.h +0 -32
  93. package/vendor/app-server/bin/runtime/linux-x64/include/tirtc/video_io_windows.h +0 -26
  94. package/vendor/app-server/bin/runtime/linux-x64/include/tirtc/video_processing.h +0 -34
  95. package/vendor/app-server/bin/runtime/linux-x64/lib/libmatrix_runtime_audio.a +0 -0
  96. package/vendor/app-server/bin/runtime/linux-x64/lib/libmatrix_runtime_facade.a +0 -0
  97. package/vendor/app-server/bin/runtime/linux-x64/lib/libmatrix_runtime_media.a +0 -0
  98. package/vendor/app-server/bin/runtime/linux-x64/lib/libmatrix_runtime_video.a +0 -0
  99. package/vendor/app-server/bin/runtime/linux-x64/lib/libwebrtc_apm.a +0 -0
  100. package/vendor/app-server/dist/host/RuntimeCredentialTokenIssuer.d.ts +0 -30
  101. package/vendor/app-server/dist/host/RuntimeCredentialTokenIssuer.js +0 -224
  102. /package/dist/{devtools/cli → cli}/src/dummy.d.ts +0 -0
  103. /package/dist/{devtools/cli → cli}/src/dummy.js +0 -0
  104. /package/dist/{devtools/cli → cli}/src/ffmpeg_tool.d.ts +0 -0
  105. /package/dist/{devtools/cli → cli}/src/ffmpeg_tool.js +0 -0
  106. /package/dist/{devtools/cli → cli}/src/guide.d.ts +0 -0
  107. /package/dist/{devtools/cli → cli}/src/index.d.ts +0 -0
  108. /package/dist/{devtools/cli → cli}/src/media_assets.d.ts +0 -0
  109. /package/dist/{devtools/cli → cli}/src/media_assets.js +0 -0
  110. /package/dist/{devtools/cli → cli}/src/progress.d.ts +0 -0
  111. /package/dist/{devtools/cli → cli}/src/progress.js +0 -0
  112. /package/dist/{devtools/cli → cli}/src/session_manager.d.ts +0 -0
  113. /package/dist/{devtools/cli → cli}/src/token_command.d.ts +0 -0
  114. /package/dist/{devtools/cli → cli}/src/transport.js +0 -0
  115. /package/vendor/app-server/bin/{native/macos-arm64 → runtime/macos-arm64/lib}/libtgrtc.dylib +0 -0
@@ -0,0 +1,196 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.HostCommandCoordinator = void 0;
4
+ const HostProtocol_1 = require("./HostProtocol");
5
+ function normalizeCommandPayload(payload) {
6
+ if (typeof payload === 'string') {
7
+ return {
8
+ payloadEncoding: 'utf8',
9
+ payload,
10
+ };
11
+ }
12
+ if (payload instanceof Uint8Array) {
13
+ return {
14
+ payloadEncoding: 'base64',
15
+ payload: Buffer.from(payload).toString('base64'),
16
+ };
17
+ }
18
+ if (Array.isArray(payload) && payload.every((value) => typeof value === 'number')) {
19
+ return {
20
+ payloadEncoding: 'base64',
21
+ payload: Buffer.from(payload).toString('base64'),
22
+ };
23
+ }
24
+ if (typeof payload === 'object' && payload !== null && 'type' in payload && payload.type === 'Buffer') {
25
+ const data = payload.data;
26
+ if (Array.isArray(data) && data.every((value) => typeof value === 'number')) {
27
+ return {
28
+ payloadEncoding: 'base64',
29
+ payload: Buffer.from(data).toString('base64'),
30
+ };
31
+ }
32
+ }
33
+ return {
34
+ payloadEncoding: 'utf8',
35
+ payload: '',
36
+ };
37
+ }
38
+ class HostCommandCoordinator {
39
+ state;
40
+ runtimeAdapter;
41
+ writeEvent;
42
+ snapshotPendingConnectionSummary;
43
+ noteIncomingConnection;
44
+ constructor(state, runtimeAdapter, writeEvent, snapshotPendingConnectionSummary, noteIncomingConnection) {
45
+ this.state = state;
46
+ this.runtimeAdapter = runtimeAdapter;
47
+ this.writeEvent = writeEvent;
48
+ this.snapshotPendingConnectionSummary = snapshotPendingConnectionSummary;
49
+ this.noteIncomingConnection = noteIncomingConnection;
50
+ }
51
+ handleInboundRemoteCommandRequest(payload) {
52
+ const remoteRequestId = Number(payload.remoteRequestId);
53
+ const commandId = Number(payload.commandId);
54
+ if (!Number.isInteger(remoteRequestId) || remoteRequestId <= 0 || !Number.isInteger(commandId)) {
55
+ return;
56
+ }
57
+ this.noteIncomingConnection(payload);
58
+ const normalizedPayload = normalizeCommandPayload(payload.payload);
59
+ const entry = {
60
+ remoteRequestId,
61
+ commandId,
62
+ payloadEncoding: normalizedPayload.payloadEncoding,
63
+ payload: normalizedPayload.payload,
64
+ receivedAt: new Date().toISOString(),
65
+ connection: this.snapshotPendingConnectionSummary(),
66
+ };
67
+ this.state.pendingRemoteCommands.set(remoteRequestId, entry);
68
+ this.writeEvent('command', 'command.remote.requested', {
69
+ ...entry,
70
+ });
71
+ }
72
+ clearPendingRemoteCommands(reason) {
73
+ if (this.state.pendingRemoteCommands.size === 0) {
74
+ return;
75
+ }
76
+ const clearedAt = new Date().toISOString();
77
+ for (const entry of this.state.pendingRemoteCommands.values()) {
78
+ this.writeEvent('command', 'command.remote.cleared', {
79
+ remoteRequestId: entry.remoteRequestId,
80
+ commandId: entry.commandId,
81
+ payloadEncoding: entry.payloadEncoding,
82
+ payload: entry.payload,
83
+ receivedAt: entry.receivedAt,
84
+ connection: entry.connection,
85
+ reason,
86
+ clearedAt,
87
+ });
88
+ }
89
+ this.state.pendingRemoteCommands.clear();
90
+ }
91
+ async handleCommandSend(params, nextSequenceNumber) {
92
+ const response = await this.runtimeAdapter.sendCommand(params.commandId, params.payloadEncoding, params.payload, params.timeoutMs);
93
+ return {
94
+ sequenceNumber: nextSequenceNumber,
95
+ commandId: params.commandId,
96
+ acceptedAt: new Date().toISOString(),
97
+ response,
98
+ };
99
+ }
100
+ async handleCommandReply(params) {
101
+ const requestedAt = new Date().toISOString();
102
+ this.writeEvent('command', 'reply.requested', {
103
+ remoteRequestId: params.remoteRequestId,
104
+ commandId: params.commandId,
105
+ payloadEncoding: params.payloadEncoding,
106
+ payloadLength: params.payload.length,
107
+ pendingCount: this.state.pendingRemoteCommands.size,
108
+ connectionState: this.state.connection.state,
109
+ at: requestedAt,
110
+ });
111
+ const entry = this.state.pendingRemoteCommands.get(params.remoteRequestId);
112
+ if (!entry) {
113
+ this.writeEvent('command', 'reply.rejected', {
114
+ remoteRequestId: params.remoteRequestId,
115
+ commandId: params.commandId,
116
+ reason: 'remote_request_not_pending',
117
+ pendingCount: this.state.pendingRemoteCommands.size,
118
+ connectionState: this.state.connection.state,
119
+ at: new Date().toISOString(),
120
+ });
121
+ throw new HostProtocol_1.HostProtocolError('invalid_request', `remoteRequestId ${params.remoteRequestId} is not pending`, false);
122
+ }
123
+ if (entry.commandId !== params.commandId) {
124
+ this.writeEvent('command', 'reply.rejected', {
125
+ remoteRequestId: params.remoteRequestId,
126
+ commandId: params.commandId,
127
+ expectedCommandId: entry.commandId,
128
+ reason: 'command_id_mismatch',
129
+ pendingCount: this.state.pendingRemoteCommands.size,
130
+ connectionState: this.state.connection.state,
131
+ at: new Date().toISOString(),
132
+ });
133
+ throw new HostProtocol_1.HostProtocolError('invalid_request', 'commandId does not match pending entry', false);
134
+ }
135
+ if (this.state.connection.state !== 'connected') {
136
+ this.writeEvent('command', 'reply.rejected', {
137
+ remoteRequestId: params.remoteRequestId,
138
+ commandId: params.commandId,
139
+ reason: 'connection_not_ready',
140
+ pendingCount: this.state.pendingRemoteCommands.size,
141
+ connectionState: this.state.connection.state,
142
+ at: new Date().toISOString(),
143
+ });
144
+ throw new HostProtocol_1.HostProtocolError('connection_not_ready', 'connection is not established', true);
145
+ }
146
+ try {
147
+ await this.runtimeAdapter.replyRemoteCommand(params.remoteRequestId, params.commandId, params.payloadEncoding, params.payload);
148
+ }
149
+ catch (error) {
150
+ const message = error instanceof Error ? error.message : String(error);
151
+ this.writeEvent('command', 'reply.failed', {
152
+ remoteRequestId: params.remoteRequestId,
153
+ commandId: params.commandId,
154
+ reason: 'runtime_adapter_error',
155
+ message,
156
+ pendingCount: this.state.pendingRemoteCommands.size,
157
+ connectionState: this.state.connection.state,
158
+ at: new Date().toISOString(),
159
+ });
160
+ throw error;
161
+ }
162
+ this.state.pendingRemoteCommands.delete(params.remoteRequestId);
163
+ const repliedAt = new Date().toISOString();
164
+ this.writeEvent('command', 'command.remote.replied', {
165
+ remoteRequestId: params.remoteRequestId,
166
+ commandId: params.commandId,
167
+ payloadEncoding: entry.payloadEncoding,
168
+ payload: entry.payload,
169
+ receivedAt: entry.receivedAt,
170
+ connection: entry.connection,
171
+ repliedAt,
172
+ });
173
+ return {
174
+ remoteRequestId: params.remoteRequestId,
175
+ commandId: params.commandId,
176
+ repliedAt,
177
+ };
178
+ }
179
+ async handleCommandPendingList() {
180
+ const items = Array.from(this.state.pendingRemoteCommands.values())
181
+ .sort((left, right) => left.receivedAt.localeCompare(right.receivedAt));
182
+ const listedAt = new Date().toISOString();
183
+ this.writeEvent('command', 'pending.listed', {
184
+ count: items.length,
185
+ remoteRequestIds: items.map((item) => item.remoteRequestId),
186
+ commandIds: items.map((item) => item.commandId),
187
+ connectionState: this.state.connection.state,
188
+ listedAt,
189
+ });
190
+ return {
191
+ items,
192
+ listedAt,
193
+ };
194
+ }
195
+ }
196
+ exports.HostCommandCoordinator = HostCommandCoordinator;
@@ -24,20 +24,10 @@ export type ServiceStartParams = {
24
24
  timeoutMs: number;
25
25
  bootstrapSendStreams?: StreamSendStartParams[];
26
26
  };
27
- export type ConnectionAutoTokenConfig = {
28
- openapiEntry?: string;
29
- accessId: string;
30
- secretKey: string;
31
- localId?: string;
32
- userTtlSeconds?: number;
33
- channelTtlSeconds?: number;
34
- };
35
27
  export type ConnectionConnectParams = {
36
28
  serviceEntry?: string;
37
29
  peerId: string;
38
- token?: string;
39
- tokenMode?: 'manual' | 'auto';
40
- autoToken?: ConnectionAutoTokenConfig;
30
+ token: string;
41
31
  timeoutMs: number;
42
32
  };
43
33
  export type StreamSendStartParams = {
@@ -89,16 +89,6 @@ function getOptionalNumber(params, key) {
89
89
  }
90
90
  return value;
91
91
  }
92
- function getOptionalBoolean(params, key) {
93
- const value = params[key];
94
- if (value === undefined) {
95
- return undefined;
96
- }
97
- if (typeof value !== 'boolean') {
98
- throw new HostProtocolError('invalid_request', `Invalid ${key}`, false);
99
- }
100
- return value;
101
- }
102
92
  function getRecord(params, key) {
103
93
  const value = params[key];
104
94
  if (!isRecord(value)) {
@@ -144,38 +134,14 @@ function parseServiceStartParams(params) {
144
134
  };
145
135
  }
146
136
  function parseConnectionConnectParams(params) {
147
- const token = getOptionalString(params, 'token');
148
- const rawTokenMode = getOptionalString(params, 'tokenMode');
149
- const tokenMode = rawTokenMode === undefined ? undefined : (() => {
150
- if (rawTokenMode !== 'manual' && rawTokenMode !== 'auto') {
151
- throw new HostProtocolError('invalid_request', 'Invalid tokenMode', false);
152
- }
153
- return rawTokenMode;
154
- })();
155
- const autoTokenRaw = params.autoToken;
156
- let autoToken;
157
- if (autoTokenRaw !== undefined) {
158
- if (!isRecord(autoTokenRaw)) {
159
- throw new HostProtocolError('invalid_request', 'Invalid autoToken', false);
160
- }
161
- autoToken = {
162
- openapiEntry: getOptionalString(autoTokenRaw, 'openapiEntry'),
163
- accessId: getString(autoTokenRaw, 'accessId'),
164
- secretKey: getString(autoTokenRaw, 'secretKey'),
165
- localId: getOptionalString(autoTokenRaw, 'localId'),
166
- userTtlSeconds: getOptionalNumber(autoTokenRaw, 'userTtlSeconds'),
167
- channelTtlSeconds: getOptionalNumber(autoTokenRaw, 'channelTtlSeconds'),
168
- };
169
- }
170
- if (!token && !autoToken) {
171
- throw new HostProtocolError('invalid_request', 'connection/connect requires token or autoToken', false);
137
+ const token = getString(params, 'token').trim();
138
+ if (token.length === 0) {
139
+ throw new HostProtocolError('invalid_request', 'connection/connect requires non-empty token', false);
172
140
  }
173
141
  return {
174
142
  serviceEntry: getOptionalString(params, 'serviceEntry'),
175
143
  peerId: getString(params, 'peerId'),
176
144
  token,
177
- tokenMode,
178
- autoToken,
179
145
  timeoutMs: getNumber(params, 'timeoutMs'),
180
146
  };
181
147
  }
@@ -4,11 +4,11 @@ export declare class HostServer {
4
4
  private state;
5
5
  private artifactManager;
6
6
  private runtimeAdapter;
7
+ private commandCoordinator;
7
8
  private isInitialized;
8
9
  private eventCounter;
9
10
  private commandSequence;
10
11
  private tokenTool;
11
- private runtimeCredentialTokenIssuer;
12
12
  private eventSinks;
13
13
  constructor(artifactManager: ArtifactManager, runtimeAdapter: RuntimeAdapter, hostEndpoint?: string);
14
14
  handleMessage(message: string): Promise<string | undefined>;
@@ -19,8 +19,6 @@ export declare class HostServer {
19
19
  appendHostLog(line: string): void;
20
20
  private handleRuntimeEvent;
21
21
  private snapshotPendingConnectionSummary;
22
- private handleInboundRemoteCommandRequest;
23
- private clearPendingRemoteCommands;
24
22
  private noteIncomingConnection;
25
23
  private handleIncomingConnectionDisconnected;
26
24
  private maybeAutoStartStreamFromRemoteDemand;
@@ -31,7 +29,6 @@ export declare class HostServer {
31
29
  private handleServiceStart;
32
30
  private handleServiceStop;
33
31
  private handleConnectionGet;
34
- private resolveConnectionToken;
35
32
  private handleConnectionConnect;
36
33
  private startDeferredSendStreamsOnConnected;
37
34
  private activatePendingStreamsOnConnected;
@@ -36,8 +36,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.HostServer = void 0;
37
37
  const fs = __importStar(require("fs"));
38
38
  const path = __importStar(require("path"));
39
+ const HostCommandCoordinator_1 = require("./HostCommandCoordinator");
39
40
  const TokenTool_1 = require("./TokenTool");
40
- const RuntimeCredentialTokenIssuer_1 = require("./native/RuntimeCredentialTokenIssuer");
41
41
  const HostState_1 = require("./HostState");
42
42
  const HostProtocol_1 = require("./HostProtocol");
43
43
  function streamBindingKey(streamId, media) {
@@ -64,48 +64,15 @@ function resolveLocalAssetsDir(source) {
64
64
  }
65
65
  return assetsDir;
66
66
  }
67
- function normalizeCommandPayload(payload) {
68
- if (typeof payload === 'string') {
69
- return {
70
- payloadEncoding: 'utf8',
71
- payload,
72
- };
73
- }
74
- if (payload instanceof Uint8Array) {
75
- return {
76
- payloadEncoding: 'base64',
77
- payload: Buffer.from(payload).toString('base64'),
78
- };
79
- }
80
- if (Array.isArray(payload) && payload.every((value) => typeof value === 'number')) {
81
- return {
82
- payloadEncoding: 'base64',
83
- payload: Buffer.from(payload).toString('base64'),
84
- };
85
- }
86
- if (typeof payload === 'object' && payload !== null && 'type' in payload && payload.type === 'Buffer') {
87
- const data = payload.data;
88
- if (Array.isArray(data) && data.every((value) => typeof value === 'number')) {
89
- return {
90
- payloadEncoding: 'base64',
91
- payload: Buffer.from(data).toString('base64'),
92
- };
93
- }
94
- }
95
- return {
96
- payloadEncoding: 'utf8',
97
- payload: '',
98
- };
99
- }
100
67
  class HostServer {
101
68
  state;
102
69
  artifactManager;
103
70
  runtimeAdapter;
71
+ commandCoordinator;
104
72
  isInitialized = false;
105
73
  eventCounter = 1;
106
74
  commandSequence = 1;
107
75
  tokenTool;
108
- runtimeCredentialTokenIssuer;
109
76
  eventSinks = new Set();
110
77
  constructor(artifactManager, runtimeAdapter, hostEndpoint) {
111
78
  this.state = new HostState_1.HostState();
@@ -114,11 +81,7 @@ class HostServer {
114
81
  this.state.runtimeTarget = runtimeAdapter.runtimeTarget;
115
82
  this.state.hostEndpoint = hostEndpoint ?? runtimeAdapter.hostEndpoint;
116
83
  this.tokenTool = new TokenTool_1.TokenTool(this.artifactManager.getPaths().rootPath);
117
- this.runtimeCredentialTokenIssuer = new RuntimeCredentialTokenIssuer_1.RuntimeCredentialTokenIssuer({
118
- repoRoot: runtimeAdapter.repoRoot,
119
- platform: runtimeAdapter.platform,
120
- runtimeBundleRoot: runtimeAdapter.runtimeBundleRoot,
121
- });
84
+ this.commandCoordinator = new HostCommandCoordinator_1.HostCommandCoordinator(this.state, this.runtimeAdapter, (family, kind, payload) => this.writeEvent(family, kind, payload), () => this.snapshotPendingConnectionSummary(), (payload) => this.noteIncomingConnection(payload));
122
85
  this.runtimeAdapter.setEventHandler((family, kind, payload) => {
123
86
  this.handleRuntimeEvent(family, kind, payload);
124
87
  });
@@ -218,7 +181,7 @@ class HostServer {
218
181
  return;
219
182
  }
220
183
  if (kind === 'command.remote.requested') {
221
- this.handleInboundRemoteCommandRequest(payload);
184
+ this.commandCoordinator.handleInboundRemoteCommandRequest(payload);
222
185
  return;
223
186
  }
224
187
  if (kind === 'transport.remote.request_audio' ||
@@ -240,46 +203,6 @@ class HostServer {
240
203
  peerId: this.state.connection.peerId,
241
204
  };
242
205
  }
243
- handleInboundRemoteCommandRequest(payload) {
244
- const remoteRequestId = Number(payload.remoteRequestId);
245
- const commandId = Number(payload.commandId);
246
- if (!Number.isInteger(remoteRequestId) || remoteRequestId <= 0 || !Number.isInteger(commandId)) {
247
- return;
248
- }
249
- this.noteIncomingConnection(payload);
250
- const normalizedPayload = normalizeCommandPayload(payload.payload);
251
- const entry = {
252
- remoteRequestId,
253
- commandId,
254
- payloadEncoding: normalizedPayload.payloadEncoding,
255
- payload: normalizedPayload.payload,
256
- receivedAt: new Date().toISOString(),
257
- connection: this.snapshotPendingConnectionSummary(),
258
- };
259
- this.state.pendingRemoteCommands.set(remoteRequestId, entry);
260
- this.writeEvent('command', 'command.remote.requested', {
261
- ...entry,
262
- });
263
- }
264
- clearPendingRemoteCommands(reason) {
265
- if (this.state.pendingRemoteCommands.size === 0) {
266
- return;
267
- }
268
- const clearedAt = new Date().toISOString();
269
- for (const entry of this.state.pendingRemoteCommands.values()) {
270
- this.writeEvent('command', 'command.remote.cleared', {
271
- remoteRequestId: entry.remoteRequestId,
272
- commandId: entry.commandId,
273
- payloadEncoding: entry.payloadEncoding,
274
- payload: entry.payload,
275
- receivedAt: entry.receivedAt,
276
- connection: entry.connection,
277
- reason,
278
- clearedAt,
279
- });
280
- }
281
- this.state.pendingRemoteCommands.clear();
282
- }
283
206
  noteIncomingConnection(payload) {
284
207
  if (this.state.connection.state === 'connected') {
285
208
  return;
@@ -295,7 +218,7 @@ class HostServer {
295
218
  if (this.state.connection.state === 'idle' || this.state.connection.state === 'disconnected') {
296
219
  return;
297
220
  }
298
- this.clearPendingRemoteCommands('connection_disconnect');
221
+ this.commandCoordinator.clearPendingRemoteCommands('connection_disconnect');
299
222
  const disconnectedAt = new Date().toISOString();
300
223
  this.state.connection = {
301
224
  state: 'disconnected',
@@ -442,7 +365,7 @@ class HostServer {
442
365
  };
443
366
  }
444
367
  async handleHostShutdown() {
445
- this.clearPendingRemoteCommands('host_shutdown');
368
+ this.commandCoordinator.clearPendingRemoteCommands('host_shutdown');
446
369
  return {
447
370
  acceptedAt: new Date().toISOString(),
448
371
  service: this.state.service,
@@ -513,7 +436,7 @@ class HostServer {
513
436
  };
514
437
  }
515
438
  await this.runtimeAdapter.stopService();
516
- this.clearPendingRemoteCommands('service_stop');
439
+ this.commandCoordinator.clearPendingRemoteCommands('service_stop');
517
440
  this.state.service.state = 'stopped';
518
441
  this.state.service.stoppedAt = new Date().toISOString();
519
442
  return {
@@ -525,29 +448,6 @@ class HostServer {
525
448
  async handleConnectionGet() {
526
449
  return this.state.connection;
527
450
  }
528
- async resolveConnectionToken(params) {
529
- const trimmedToken = params.token?.trim();
530
- const wantsAuto = params.tokenMode === "auto" || (!trimmedToken && params.autoToken !== undefined);
531
- if (!wantsAuto) {
532
- if (!trimmedToken || trimmedToken.length === 0) {
533
- throw new HostProtocol_1.HostProtocolError("invalid_request", "token is required when tokenMode is manual", false);
534
- }
535
- return { token: trimmedToken, mode: "manual" };
536
- }
537
- if (!params.autoToken) {
538
- throw new HostProtocol_1.HostProtocolError("invalid_request", "auto token mode requires autoToken config", false);
539
- }
540
- const issued = await this.runtimeCredentialTokenIssuer.issueToken({
541
- openapiEntry: params.autoToken.openapiEntry,
542
- accessId: params.autoToken.accessId,
543
- secretKey: params.autoToken.secretKey,
544
- localId: params.autoToken.localId ?? params.peerId,
545
- peerId: params.peerId,
546
- userTtlSeconds: params.autoToken.userTtlSeconds,
547
- channelTtlSeconds: params.autoToken.channelTtlSeconds,
548
- });
549
- return { token: issued, mode: "auto" };
550
- }
551
451
  async handleConnectionConnect(params) {
552
452
  if (this.state.connection.state !== "idle" &&
553
453
  this.state.connection.state !== "disconnected" &&
@@ -557,14 +457,13 @@ class HostServer {
557
457
  if (this.state.service.state !== "stopped") {
558
458
  throw new HostProtocol_1.HostProtocolError("busy", "Service is not stopped", false);
559
459
  }
560
- const tokenResolve = await this.resolveConnectionToken(params);
561
460
  this.writeEvent("connection", "token.prepared", {
562
- mode: tokenResolve.mode,
461
+ mode: 'manual',
563
462
  peerId: params.peerId,
564
- tokenLength: tokenResolve.token.length,
463
+ tokenLength: params.token.length,
565
464
  at: new Date().toISOString(),
566
465
  });
567
- const resolvedServiceEntry = await this.runtimeAdapter.connect(params.serviceEntry, params.peerId, tokenResolve.token, params.timeoutMs);
466
+ const resolvedServiceEntry = await this.runtimeAdapter.connect(params.serviceEntry, params.peerId, params.token, params.timeoutMs);
568
467
  this.state.connection = {
569
468
  state: 'connecting',
570
469
  direction: 'outgoing',
@@ -640,7 +539,7 @@ class HostServer {
640
539
  };
641
540
  }
642
541
  await this.runtimeAdapter.disconnect();
643
- this.clearPendingRemoteCommands('connection_disconnect');
542
+ this.commandCoordinator.clearPendingRemoteCommands('connection_disconnect');
644
543
  this.state.connection.state = 'disconnected';
645
544
  this.state.connection.disconnectedAt = new Date().toISOString();
646
545
  return {
@@ -765,50 +664,15 @@ class HostServer {
765
664
  };
766
665
  }
767
666
  async handleCommandSend(params) {
768
- const response = await this.runtimeAdapter.sendCommand(params.commandId, params.payloadEncoding, params.payload, params.timeoutMs);
769
- return {
770
- sequenceNumber: this.commandSequence++,
771
- commandId: params.commandId,
772
- acceptedAt: new Date().toISOString(),
773
- response,
774
- };
667
+ const result = await this.commandCoordinator.handleCommandSend(params, this.commandSequence);
668
+ this.commandSequence += 1;
669
+ return result;
775
670
  }
776
671
  async handleCommandReply(params) {
777
- const entry = this.state.pendingRemoteCommands.get(params.remoteRequestId);
778
- if (!entry) {
779
- throw new HostProtocol_1.HostProtocolError('invalid_request', `remoteRequestId ${params.remoteRequestId} is not pending`, false);
780
- }
781
- if (entry.commandId !== params.commandId) {
782
- throw new HostProtocol_1.HostProtocolError('invalid_request', 'commandId does not match pending entry', false);
783
- }
784
- if (this.state.connection.state !== 'connected') {
785
- throw new HostProtocol_1.HostProtocolError('connection_not_ready', 'connection is not established', true);
786
- }
787
- await this.runtimeAdapter.replyRemoteCommand(params.remoteRequestId, params.commandId, params.payloadEncoding, params.payload);
788
- this.state.pendingRemoteCommands.delete(params.remoteRequestId);
789
- const repliedAt = new Date().toISOString();
790
- this.writeEvent('command', 'command.remote.replied', {
791
- remoteRequestId: params.remoteRequestId,
792
- commandId: params.commandId,
793
- payloadEncoding: entry.payloadEncoding,
794
- payload: entry.payload,
795
- receivedAt: entry.receivedAt,
796
- connection: entry.connection,
797
- repliedAt,
798
- });
799
- return {
800
- remoteRequestId: params.remoteRequestId,
801
- commandId: params.commandId,
802
- repliedAt,
803
- };
672
+ return this.commandCoordinator.handleCommandReply(params);
804
673
  }
805
674
  async handleCommandPendingList() {
806
- const items = Array.from(this.state.pendingRemoteCommands.values())
807
- .sort((left, right) => left.receivedAt.localeCompare(right.receivedAt));
808
- return {
809
- items,
810
- listedAt: new Date().toISOString(),
811
- };
675
+ return this.commandCoordinator.handleCommandPendingList();
812
676
  }
813
677
  async handleEventsSubscribe(params) {
814
678
  const families = params.families ?? [];
@@ -78,8 +78,8 @@ function resolveRepoRoot() {
78
78
  const normalized = path.resolve(candidate);
79
79
  if (pathExists(path.join(normalized, 'bin/runtime')) ||
80
80
  pathExists(path.join(normalized, 'bin/native')) ||
81
- pathExists(path.join(normalized, 'app-server/bin/runtime')) ||
82
- pathExists(path.join(normalized, 'app-server'))) {
81
+ pathExists(path.join(normalized, 'products/app-server/bin/runtime')) ||
82
+ pathExists(path.join(normalized, 'products/app-server'))) {
83
83
  return normalized;
84
84
  }
85
85
  }
@@ -63,9 +63,9 @@ class RuntimeCredentialTokenIssuer {
63
63
  const candidates = [
64
64
  explicit,
65
65
  path.join(this.repoRoot, `bin/native/${this.platform}/credential_napi.node`),
66
- path.join(this.repoRoot, `app-server/bin/native/${this.platform}/credential_napi.node`),
66
+ path.join(this.repoRoot, `products/app-server/bin/native/${this.platform}/credential_napi.node`),
67
67
  path.join(this.repoRoot, `.build/app-server/native/${this.platform}/credential_napi.node`),
68
- path.resolve(process.cwd(), `app-server/bin/native/${this.platform}/credential_napi.node`),
68
+ path.resolve(process.cwd(), `products/app-server/bin/native/${this.platform}/credential_napi.node`),
69
69
  path.resolve(process.cwd(), `.build/app-server/native/${this.platform}/credential_napi.node`),
70
70
  ].filter((entry) => typeof entry === 'string' && entry.trim().length > 0);
71
71
  for (const candidate of candidates) {
@@ -75,7 +75,7 @@ class RuntimeCredentialTokenIssuer {
75
75
  }
76
76
  }
77
77
  throw new Error('credential addon missing for platform ' + this.platform +
78
- '; run: npm --prefix app-server run build:native');
78
+ '; run: npm --prefix products/app-server run build:native');
79
79
  }
80
80
  ensureBinding() {
81
81
  if (this.binding) {
@@ -54,9 +54,9 @@ class RuntimeHostBridge {
54
54
  const candidates = [
55
55
  explicit,
56
56
  path.join(this.repoRoot, `bin/native/${this.platform}/runtime_host_napi.node`),
57
- path.join(this.repoRoot, `app-server/bin/native/${this.platform}/runtime_host_napi.node`),
57
+ path.join(this.repoRoot, `products/app-server/bin/native/${this.platform}/runtime_host_napi.node`),
58
58
  path.join(this.repoRoot, `.build/app-server/native/${this.platform}/runtime_host_napi.node`),
59
- path.resolve(process.cwd(), `app-server/bin/native/${this.platform}/runtime_host_napi.node`),
59
+ path.resolve(process.cwd(), `products/app-server/bin/native/${this.platform}/runtime_host_napi.node`),
60
60
  path.resolve(process.cwd(), `.build/app-server/native/${this.platform}/runtime_host_napi.node`),
61
61
  ].filter((entry) => typeof entry === 'string' && entry.trim().length > 0);
62
62
  for (const candidate of candidates) {
@@ -66,7 +66,7 @@ class RuntimeHostBridge {
66
66
  }
67
67
  }
68
68
  throw new Error('runtime host addon missing for platform ' + this.platform +
69
- '; run: npm --prefix app-server run build:native');
69
+ '; run: npm --prefix products/app-server run build:native');
70
70
  }
71
71
  resolveRuntimeLibDirs() {
72
72
  const dirs = [];
@@ -75,7 +75,7 @@ class RuntimeHostBridge {
75
75
  ? path.join(path.resolve(envBundleRoot.trim()), 'lib')
76
76
  : '';
77
77
  const runtimeBundleLib = path.join(this.repoRoot, `bin/runtime/${this.platform}/lib`);
78
- const repoRuntimeBundleLib = path.join(this.repoRoot, `app-server/bin/runtime/${this.platform}/lib`);
78
+ const repoRuntimeBundleLib = path.join(this.repoRoot, `products/app-server/bin/runtime/${this.platform}/lib`);
79
79
  const nanoLib = path.join(this.repoRoot, `runtime/core/3rd/tirtc-nano/install/${this.platform}/TIRTC_NANO/lib`);
80
80
  if (runtimeBundleLibFromEnv && pathExists(runtimeBundleLibFromEnv)) {
81
81
  dirs.push(runtimeBundleLibFromEnv);
@@ -32,7 +32,7 @@ function resolveRuntimeBundleRoot(repoRoot, runtimePlatform) {
32
32
  if (pathExists(path_1.default.resolve(repoRoot, 'bin/runtime', runtimePlatform))) {
33
33
  return path_1.default.resolve(repoRoot, 'bin/runtime', runtimePlatform);
34
34
  }
35
- return path_1.default.resolve(repoRoot, 'app-server/bin/runtime', runtimePlatform);
35
+ return path_1.default.resolve(repoRoot, 'products/app-server/bin/runtime', runtimePlatform);
36
36
  }
37
37
  function dockerAvailable() {
38
38
  try {
@@ -57,7 +57,7 @@ function probeRuntimeBackedPreflight(repoRoot) {
57
57
  if (required.some((entry) => !pathExists(entry))) {
58
58
  return {
59
59
  ready: false,
60
- reason: 'runtime-backed sdk bundle is missing under app-server/bin/runtime/<platform>',
60
+ reason: 'runtime-backed sdk bundle is missing under products/app-server/bin/runtime/<platform>',
61
61
  runtimePlatform,
62
62
  runtimeBundleRoot,
63
63
  };
@@ -13,7 +13,7 @@ function asBoolean(value) {
13
13
  return typeof value === 'boolean' ? value : undefined;
14
14
  }
15
15
  function resolveConfigPath(repoRoot) {
16
- return path_1.default.resolve(repoRoot, 'app-server/host/tests/.local/runtime-backed.e2e.local.json');
16
+ return path_1.default.resolve(repoRoot, 'products/app-server/host/tests/.local/runtime-backed.e2e.local.json');
17
17
  }
18
18
  function requireString(raw, key) {
19
19
  const value = asString(raw[key]);