@mindexec/cli 0.2.20 → 0.2.22
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/package.json +6 -5
- package/remote-hub.js +4 -4
- package/scripts/remote-fleet-render-smoke.mjs +17 -2
- package/scripts/remote-http-smoke.mjs +268 -0
- package/scripts/remote-hub-scale-smoke.mjs +2 -1
- package/server.js +1 -0
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-css3d-manager.js +1 -1
- package/wwwroot/_framework/{MindExecution.Core.ckgjbdvvxl.dll → MindExecution.Core.c9fyqe953v.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Kernel.lm7kgq8l8h.dll → MindExecution.Kernel.badrt1tkvv.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.Admin.k085kt3dls.dll → MindExecution.Plugins.Admin.73w1bvz4r1.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.Business.dsz9uwkxih.dll → MindExecution.Plugins.Business.dvd82y422m.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.Concept.wnkch6jqjz.dll → MindExecution.Plugins.Concept.m3ukc0xvom.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.Directory.ufbriq6js4.dll → MindExecution.Plugins.Directory.23tm2uvfvu.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.PlanMaster.ygbsp1z4z0.dll → MindExecution.Plugins.PlanMaster.8nrc7ge4ob.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.YouTube.a992061fhz.dll → MindExecution.Plugins.YouTube.3ox59073d8.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Shared.y27t6njaw0.dll → MindExecution.Shared.va1gxp0crd.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Web.bqamgu5gq1.dll → MindExecution.Web.jmawk7z8d3.dll} +0 -0
- package/wwwroot/_framework/blazor.boot.json +21 -21
- package/wwwroot/index.html +1 -1
- package/wwwroot/service-worker-assets.js +24 -24
- package/wwwroot/service-worker.js +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mindexec/cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.22",
|
|
4
4
|
"description": "MindExec local runtime and bridge CLI",
|
|
5
5
|
"main": "server.js",
|
|
6
6
|
"type": "module",
|
|
@@ -20,10 +20,11 @@
|
|
|
20
20
|
"scripts": {
|
|
21
21
|
"start": "node launch-bridge.cjs",
|
|
22
22
|
"dev": "node launch-bridge.cjs --watch",
|
|
23
|
-
"test:syntax": "node --check server.js && node --check remote-hub.js && node --check codex-runtime.js && node --check launch-bridge.cjs && node --check port-guard.cjs && node --check scripts/setup-tree-sitter-grammars.mjs && node --check scripts/remote-hub-smoke.mjs && node --check scripts/remote-hub-scale-smoke.mjs && node --check scripts/remote-fleet-render-smoke.mjs",
|
|
24
|
-
"test:remote": "node scripts/remote-hub-smoke.mjs",
|
|
25
|
-
"test:remote:scale": "node scripts/remote-hub-scale-smoke.mjs",
|
|
26
|
-
"test:remote:render": "node scripts/remote-fleet-render-smoke.mjs",
|
|
23
|
+
"test:syntax": "node --check server.js && node --check remote-hub.js && node --check codex-runtime.js && node --check launch-bridge.cjs && node --check port-guard.cjs && node --check scripts/setup-tree-sitter-grammars.mjs && node --check scripts/remote-hub-smoke.mjs && node --check scripts/remote-hub-scale-smoke.mjs && node --check scripts/remote-fleet-render-smoke.mjs && node --check scripts/remote-http-smoke.mjs",
|
|
24
|
+
"test:remote": "node scripts/remote-hub-smoke.mjs",
|
|
25
|
+
"test:remote:scale": "node scripts/remote-hub-scale-smoke.mjs",
|
|
26
|
+
"test:remote:render": "node scripts/remote-fleet-render-smoke.mjs",
|
|
27
|
+
"test:remote:http": "node scripts/remote-http-smoke.mjs",
|
|
27
28
|
"pack:dry": "npm pack --dry-run",
|
|
28
29
|
"setup:grammars": "node scripts/setup-tree-sitter-grammars.mjs",
|
|
29
30
|
"postinstall": "npm run setup:grammars"
|
package/remote-hub.js
CHANGED
|
@@ -289,7 +289,7 @@ export function createRemoteHub(options = {}) {
|
|
|
289
289
|
mimeType: 'image/png',
|
|
290
290
|
format: 'image/png',
|
|
291
291
|
mode,
|
|
292
|
-
fps: clampNumber(options.fps, 1, 24, mode === 'remote-fast' ?
|
|
292
|
+
fps: clampNumber(options.fps, 1, 24, mode === 'remote-fast' ? 20 : 1),
|
|
293
293
|
capturedAt: now,
|
|
294
294
|
receivedAt: now,
|
|
295
295
|
byteLength: 68,
|
|
@@ -503,7 +503,7 @@ export function createRemoteHub(options = {}) {
|
|
|
503
503
|
commandId: `synthetic-live-command-${ordinal}`,
|
|
504
504
|
active: true,
|
|
505
505
|
mode: 'remote-fast',
|
|
506
|
-
fps:
|
|
506
|
+
fps: 20,
|
|
507
507
|
startedAt: seenAt,
|
|
508
508
|
stoppedAt: '',
|
|
509
509
|
stopReason: '',
|
|
@@ -513,7 +513,7 @@ export function createRemoteHub(options = {}) {
|
|
|
513
513
|
};
|
|
514
514
|
applySyntheticLiveFrame(device, device.activeLiveStream.streamId, {
|
|
515
515
|
commandId: device.activeLiveStream.commandId,
|
|
516
|
-
fps:
|
|
516
|
+
fps: 20
|
|
517
517
|
});
|
|
518
518
|
live += 1;
|
|
519
519
|
}
|
|
@@ -1528,7 +1528,7 @@ export function createRemoteHub(options = {}) {
|
|
|
1528
1528
|
|
|
1529
1529
|
const now = new Date().toISOString();
|
|
1530
1530
|
const streamId = safeString(options.streamId, 128) || `live-${Date.now()}`;
|
|
1531
|
-
const fps = clampNumber(options.fps, 1, 24,
|
|
1531
|
+
const fps = clampNumber(options.fps, 1, 24, 20);
|
|
1532
1532
|
const commandId = safeString(options.commandId, 128) || crypto.randomUUID();
|
|
1533
1533
|
device.counters.commandsSent += 1;
|
|
1534
1534
|
device.activeLiveStream = {
|
|
@@ -526,12 +526,25 @@ try {
|
|
|
526
526
|
});
|
|
527
527
|
assert.equal(renderAiTask.ok, true);
|
|
528
528
|
|
|
529
|
+
const seededLiveTarget = hub.listDevices().find(device =>
|
|
530
|
+
device.connected && device.capabilities?.liveStream);
|
|
531
|
+
assert.ok(seededLiveTarget);
|
|
532
|
+
const renderLive = hub.startLiveStream(seededLiveTarget.deviceId, {
|
|
533
|
+
streamId: 'render-smoke-live',
|
|
534
|
+
fps: 20,
|
|
535
|
+
maxWidth: 960,
|
|
536
|
+
maxHeight: 540,
|
|
537
|
+
quality: 60
|
|
538
|
+
});
|
|
539
|
+
assert.equal(renderLive.ok, true);
|
|
540
|
+
|
|
529
541
|
const rawDevices = hub.listDevices();
|
|
530
542
|
const devices = rawDevices.map(projectDevice);
|
|
531
543
|
const connectedCount = devices.filter(device => device.Connected).length;
|
|
532
544
|
const offlineCount = devices.length - connectedCount;
|
|
533
545
|
const aiCount = devices.filter(device => device.Connected && device.AiAssistEnabled).length;
|
|
534
|
-
const focusedDevice = devices.find(device => device.Connected)
|
|
546
|
+
const focusedDevice = devices.find(device => device.Connected && device.LiveStreamActive)
|
|
547
|
+
|| devices.find(device => device.Connected);
|
|
535
548
|
assert.ok(focusedDevice);
|
|
536
549
|
focusedDevice.LatestTaskId = 'render-smoke-timeout-task';
|
|
537
550
|
focusedDevice.LatestTaskCommandId = 'render-smoke-timeout-command';
|
|
@@ -632,9 +645,11 @@ try {
|
|
|
632
645
|
assert.equal(bodyView.querySelectorAll('[data-remote-fleet-action="pin-device"]').length, SYNTHETIC_COUNT);
|
|
633
646
|
assert.equal(bodyView.querySelectorAll('[data-remote-fleet-action="task-device"]').length, connectedCount);
|
|
634
647
|
assert.equal(bodyView.querySelectorAll('[data-remote-fleet-action="thumbnail-device"]').length, devices.filter(device => device.Connected && device.ThumbnailEnabled).length);
|
|
635
|
-
|
|
648
|
+
const livePanel = bodyView.querySelector('[data-remote-fleet-live-panel="true"]');
|
|
649
|
+
assert.equal(livePanel?.dataset.deviceId, focusedDevice.DeviceId);
|
|
636
650
|
assert.equal(bodyView.querySelector('[data-remote-fleet-action="task-visible"]')?.disabled, false);
|
|
637
651
|
assert.ok(bodyView.textContent.includes('all devices, no paging'));
|
|
652
|
+
assert.ok(livePanel?.textContent.includes('RemoteFast 20 fps'), livePanel?.textContent || bodyView.textContent);
|
|
638
653
|
assert.ok(bodyView.querySelector('code')?.textContent.includes('npx @mindexec/remote connect'));
|
|
639
654
|
assert.ok(bodyView.textContent.includes('synthetic-render-ai'));
|
|
640
655
|
assert.ok(bodyView.textContent.includes('Task timed out waiting for the agent response.'));
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import assert from 'node:assert/strict';
|
|
4
|
+
import net from 'node:net';
|
|
5
|
+
import { spawn } from 'node:child_process';
|
|
6
|
+
import path from 'node:path';
|
|
7
|
+
import { fileURLToPath } from 'node:url';
|
|
8
|
+
|
|
9
|
+
const BRIDGE_TOKEN = 'remote-http-smoke-token';
|
|
10
|
+
const PAIR_TOKEN = 'remote-http-pair-token';
|
|
11
|
+
const SYNTHETIC_COUNT = Number(process.env.REMOTE_HTTP_SMOKE_COUNT || 250);
|
|
12
|
+
|
|
13
|
+
function wait(ms) {
|
|
14
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async function findFreePort() {
|
|
18
|
+
return await new Promise((resolve, reject) => {
|
|
19
|
+
const server = net.createServer();
|
|
20
|
+
server.unref();
|
|
21
|
+
server.once('error', reject);
|
|
22
|
+
server.listen(0, '127.0.0.1', () => {
|
|
23
|
+
const address = server.address();
|
|
24
|
+
const port = typeof address === 'object' && address ? address.port : 0;
|
|
25
|
+
server.close(() => resolve(port));
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async function fetchJson(url, options = {}) {
|
|
31
|
+
const response = await fetch(url, {
|
|
32
|
+
...options,
|
|
33
|
+
headers: {
|
|
34
|
+
...(options.body ? { 'Content-Type': 'application/json' } : {}),
|
|
35
|
+
...(options.token ? { 'X-Bridge-Token': options.token } : {}),
|
|
36
|
+
...(options.headers || {})
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
let payload = null;
|
|
41
|
+
try {
|
|
42
|
+
payload = await response.json();
|
|
43
|
+
} catch {
|
|
44
|
+
// Some failure responses may be empty.
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return {
|
|
48
|
+
status: response.status,
|
|
49
|
+
ok: response.ok,
|
|
50
|
+
payload
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async function waitForBridge(baseUrl, getFailureDetails) {
|
|
55
|
+
const startedAt = Date.now();
|
|
56
|
+
while (Date.now() - startedAt < 30000) {
|
|
57
|
+
try {
|
|
58
|
+
const result = await fetchJson(`${baseUrl}/api/remote/status`, { token: BRIDGE_TOKEN });
|
|
59
|
+
if (result.ok && result.payload?.started === true) {
|
|
60
|
+
return result.payload;
|
|
61
|
+
}
|
|
62
|
+
} catch {
|
|
63
|
+
// Server is still starting.
|
|
64
|
+
}
|
|
65
|
+
await wait(100);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
throw new Error(`Timed out waiting for LocalBridge RemoteHub HTTP API.\n${getFailureDetails()}`);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
72
|
+
const bridgeRoot = path.resolve(__dirname, '..');
|
|
73
|
+
const bridgePort = await findFreePort();
|
|
74
|
+
const remoteHubPort = await findFreePort();
|
|
75
|
+
const baseUrl = `http://127.0.0.1:${bridgePort}`;
|
|
76
|
+
|
|
77
|
+
const child = spawn(process.execPath, ['server.js'], {
|
|
78
|
+
cwd: bridgeRoot,
|
|
79
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
80
|
+
windowsHide: true,
|
|
81
|
+
env: {
|
|
82
|
+
...process.env,
|
|
83
|
+
BRIDGE_PORT: String(bridgePort),
|
|
84
|
+
BRIDGE_TOKEN,
|
|
85
|
+
BRIDGE_REQUIRE_TOKEN: '1',
|
|
86
|
+
MINDEXEC_REMOTE_HUB: '1',
|
|
87
|
+
REMOTE_HUB_HOST: '127.0.0.1',
|
|
88
|
+
REMOTE_HUB_PORT: String(remoteHubPort),
|
|
89
|
+
REMOTE_HUB_PAIR_TOKEN: PAIR_TOKEN,
|
|
90
|
+
MINDEXEC_REMOTE_SYNTHETIC_FLEET: '1',
|
|
91
|
+
NO_COLOR: '1'
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
let stdout = '';
|
|
96
|
+
let stderr = '';
|
|
97
|
+
child.stdout.on('data', chunk => {
|
|
98
|
+
stdout += chunk.toString();
|
|
99
|
+
});
|
|
100
|
+
child.stderr.on('data', chunk => {
|
|
101
|
+
stderr += chunk.toString();
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
const exitPromise = new Promise(resolve => child.once('exit', resolve));
|
|
105
|
+
const details = () => `stdout=${stdout}\nstderr=${stderr}`;
|
|
106
|
+
|
|
107
|
+
try {
|
|
108
|
+
const status = await waitForBridge(baseUrl, details);
|
|
109
|
+
assert.equal(status.started, true);
|
|
110
|
+
assert.equal(status.port, remoteHubPort);
|
|
111
|
+
assert.equal(status.agentPackage, '@mindexec/remote');
|
|
112
|
+
assert.equal(status.canvasPagination, 'none');
|
|
113
|
+
assert.equal(status.canvasDeviceListMode, 'all-devices');
|
|
114
|
+
assert.equal(status.pairToken, PAIR_TOKEN);
|
|
115
|
+
|
|
116
|
+
const unauthorizedStatus = await fetchJson(`${baseUrl}/api/remote/status`);
|
|
117
|
+
assert.equal(unauthorizedStatus.status, 401);
|
|
118
|
+
assert.equal(unauthorizedStatus.payload?.header, 'X-Bridge-Token');
|
|
119
|
+
|
|
120
|
+
const unauthorizedDelete = await fetchJson(`${baseUrl}/api/remote/synthetic`, {
|
|
121
|
+
method: 'DELETE'
|
|
122
|
+
});
|
|
123
|
+
assert.equal(unauthorizedDelete.status, 401);
|
|
124
|
+
|
|
125
|
+
const seed = await fetchJson(`${baseUrl}/api/remote/synthetic/seed`, {
|
|
126
|
+
method: 'POST',
|
|
127
|
+
token: BRIDGE_TOKEN,
|
|
128
|
+
body: JSON.stringify({
|
|
129
|
+
count: SYNTHETIC_COUNT,
|
|
130
|
+
connectedRatio: 0.84,
|
|
131
|
+
thumbnailRatio: 0.72,
|
|
132
|
+
aiAssistRatio: 0.42,
|
|
133
|
+
liveCount: 8,
|
|
134
|
+
replace: true
|
|
135
|
+
})
|
|
136
|
+
});
|
|
137
|
+
assert.equal(seed.ok, true, JSON.stringify(seed.payload));
|
|
138
|
+
assert.equal(seed.payload?.ok, true);
|
|
139
|
+
assert.equal(seed.payload?.seeded, SYNTHETIC_COUNT);
|
|
140
|
+
|
|
141
|
+
const devicesResult = await fetchJson(`${baseUrl}/api/remote/devices`, { token: BRIDGE_TOKEN });
|
|
142
|
+
assert.equal(devicesResult.ok, true, JSON.stringify(devicesResult.payload));
|
|
143
|
+
assert.equal(devicesResult.payload?.total, SYNTHETIC_COUNT);
|
|
144
|
+
assert.equal(devicesResult.payload?.pagination, 'none');
|
|
145
|
+
assert.equal(devicesResult.payload?.canvasDeviceListMode, 'all-devices');
|
|
146
|
+
assert.equal(devicesResult.payload?.devices?.length, SYNTHETIC_COUNT);
|
|
147
|
+
assert.equal(devicesResult.payload.devices.some(device => device.connected === false), true);
|
|
148
|
+
|
|
149
|
+
const connectedTargets = devicesResult.payload.devices
|
|
150
|
+
.filter(device => device.connected && device.capabilities?.taskDispatch)
|
|
151
|
+
.slice(0, 200)
|
|
152
|
+
.map(device => device.deviceId);
|
|
153
|
+
assert.ok(connectedTargets.length >= 100);
|
|
154
|
+
|
|
155
|
+
const batch = await fetchJson(`${baseUrl}/api/remote/tasks`, {
|
|
156
|
+
method: 'POST',
|
|
157
|
+
token: BRIDGE_TOKEN,
|
|
158
|
+
body: JSON.stringify({
|
|
159
|
+
deviceIds: connectedTargets,
|
|
160
|
+
allConnected: false,
|
|
161
|
+
title: 'HTTP smoke task batch',
|
|
162
|
+
instruction: 'HTTP smoke batch: report current status to the manager.',
|
|
163
|
+
approvalLevel: 'task-only'
|
|
164
|
+
})
|
|
165
|
+
});
|
|
166
|
+
assert.equal(batch.ok, true, JSON.stringify(batch.payload));
|
|
167
|
+
assert.equal(batch.payload?.ok, true);
|
|
168
|
+
assert.equal(batch.payload?.total, connectedTargets.length);
|
|
169
|
+
assert.equal(batch.payload?.queued, connectedTargets.length);
|
|
170
|
+
assert.equal(batch.payload?.batch?.completed, connectedTargets.length);
|
|
171
|
+
assert.equal(batch.payload?.batch?.failed, 0);
|
|
172
|
+
assert.equal(batch.payload?.batch?.status, 'completed');
|
|
173
|
+
|
|
174
|
+
const aiTarget = devicesResult.payload.devices.find(device =>
|
|
175
|
+
device.connected && device.capabilities?.taskDispatch && device.capabilities?.aiAssist);
|
|
176
|
+
assert.ok(aiTarget);
|
|
177
|
+
const aiTask = await fetchJson(`${baseUrl}/api/remote/devices/${encodeURIComponent(aiTarget.deviceId)}/tasks`, {
|
|
178
|
+
method: 'POST',
|
|
179
|
+
token: BRIDGE_TOKEN,
|
|
180
|
+
body: JSON.stringify({
|
|
181
|
+
title: 'HTTP smoke AI task',
|
|
182
|
+
instruction: 'HTTP smoke AI assist: summarize fleet condition.',
|
|
183
|
+
approvalLevel: 'ai-assist'
|
|
184
|
+
})
|
|
185
|
+
});
|
|
186
|
+
assert.equal(aiTask.ok, true, JSON.stringify(aiTask.payload));
|
|
187
|
+
assert.equal(aiTask.payload?.ok, true);
|
|
188
|
+
assert.equal(aiTask.payload?.approvalLevel, 'ai-assist');
|
|
189
|
+
|
|
190
|
+
const thumbnailTarget = devicesResult.payload.devices.find(device =>
|
|
191
|
+
device.connected && device.capabilities?.thumbnail);
|
|
192
|
+
assert.ok(thumbnailTarget);
|
|
193
|
+
const thumbnailRequest = await fetchJson(`${baseUrl}/api/remote/devices/${encodeURIComponent(thumbnailTarget.deviceId)}/thumbnail/request`, {
|
|
194
|
+
method: 'POST',
|
|
195
|
+
token: BRIDGE_TOKEN,
|
|
196
|
+
body: JSON.stringify({
|
|
197
|
+
streamId: 'http-smoke-thumb',
|
|
198
|
+
maxWidth: 360,
|
|
199
|
+
maxHeight: 220,
|
|
200
|
+
quality: 50
|
|
201
|
+
})
|
|
202
|
+
});
|
|
203
|
+
assert.equal(thumbnailRequest.ok, true, JSON.stringify(thumbnailRequest.payload));
|
|
204
|
+
assert.equal(thumbnailRequest.payload?.ok, true);
|
|
205
|
+
|
|
206
|
+
const thumbnail = await fetchJson(`${baseUrl}/api/remote/devices/${encodeURIComponent(thumbnailTarget.deviceId)}/thumbnail`, {
|
|
207
|
+
token: BRIDGE_TOKEN
|
|
208
|
+
});
|
|
209
|
+
assert.equal(thumbnail.ok, true, JSON.stringify(thumbnail.payload));
|
|
210
|
+
assert.equal(thumbnail.payload?.thumbnail?.streamId, 'http-smoke-thumb');
|
|
211
|
+
assert.ok(String(thumbnail.payload?.thumbnail?.dataUrl || '').startsWith('data:image/png;base64,'));
|
|
212
|
+
|
|
213
|
+
const liveTarget = devicesResult.payload.devices.find(device =>
|
|
214
|
+
device.connected && device.capabilities?.liveStream);
|
|
215
|
+
assert.ok(liveTarget);
|
|
216
|
+
const liveStart = await fetchJson(`${baseUrl}/api/remote/devices/${encodeURIComponent(liveTarget.deviceId)}/live/start`, {
|
|
217
|
+
method: 'POST',
|
|
218
|
+
token: BRIDGE_TOKEN,
|
|
219
|
+
body: JSON.stringify({
|
|
220
|
+
streamId: 'http-smoke-live',
|
|
221
|
+
fps: 20,
|
|
222
|
+
maxWidth: 960,
|
|
223
|
+
maxHeight: 540,
|
|
224
|
+
quality: 60
|
|
225
|
+
})
|
|
226
|
+
});
|
|
227
|
+
assert.equal(liveStart.ok, true, JSON.stringify(liveStart.payload));
|
|
228
|
+
assert.equal(liveStart.payload?.ok, true);
|
|
229
|
+
|
|
230
|
+
const liveFrame = await fetchJson(`${baseUrl}/api/remote/devices/${encodeURIComponent(liveTarget.deviceId)}/live/frame`, {
|
|
231
|
+
token: BRIDGE_TOKEN
|
|
232
|
+
});
|
|
233
|
+
assert.equal(liveFrame.ok, true, JSON.stringify(liveFrame.payload));
|
|
234
|
+
assert.equal(liveFrame.payload?.frame?.streamId, 'http-smoke-live');
|
|
235
|
+
assert.equal(liveFrame.payload?.frame?.mode, 'remote-fast');
|
|
236
|
+
assert.equal(liveFrame.payload?.frame?.fps, 20);
|
|
237
|
+
|
|
238
|
+
const liveStop = await fetchJson(`${baseUrl}/api/remote/devices/${encodeURIComponent(liveTarget.deviceId)}/live/stop`, {
|
|
239
|
+
method: 'POST',
|
|
240
|
+
token: BRIDGE_TOKEN,
|
|
241
|
+
body: JSON.stringify({
|
|
242
|
+
streamId: 'http-smoke-live'
|
|
243
|
+
})
|
|
244
|
+
});
|
|
245
|
+
assert.equal(liveStop.ok, true, JSON.stringify(liveStop.payload));
|
|
246
|
+
assert.equal(liveStop.payload?.ok, true);
|
|
247
|
+
|
|
248
|
+
const clear = await fetchJson(`${baseUrl}/api/remote/synthetic`, {
|
|
249
|
+
method: 'DELETE',
|
|
250
|
+
token: BRIDGE_TOKEN
|
|
251
|
+
});
|
|
252
|
+
assert.equal(clear.ok, true, JSON.stringify(clear.payload));
|
|
253
|
+
assert.equal(clear.payload?.ok, true);
|
|
254
|
+
assert.equal(clear.payload?.removed, SYNTHETIC_COUNT);
|
|
255
|
+
|
|
256
|
+
console.log(`RemoteHub HTTP smoke OK (${SYNTHETIC_COUNT} synthetic devices, bridge ${bridgePort}, remote ${remoteHubPort})`);
|
|
257
|
+
} finally {
|
|
258
|
+
if (child.exitCode === null && !child.killed) {
|
|
259
|
+
child.kill('SIGTERM');
|
|
260
|
+
await Promise.race([
|
|
261
|
+
exitPromise,
|
|
262
|
+
wait(5000)
|
|
263
|
+
]);
|
|
264
|
+
if (child.exitCode === null && !child.killed) {
|
|
265
|
+
child.kill('SIGKILL');
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
@@ -63,13 +63,14 @@ try {
|
|
|
63
63
|
assert.ok(liveTarget);
|
|
64
64
|
const liveResult = hub.startLiveStream(liveTarget.deviceId, {
|
|
65
65
|
streamId: 'scale-live',
|
|
66
|
-
fps:
|
|
66
|
+
fps: 20,
|
|
67
67
|
maxWidth: 960,
|
|
68
68
|
maxHeight: 540,
|
|
69
69
|
quality: 60
|
|
70
70
|
});
|
|
71
71
|
assert.equal(liveResult.ok, true);
|
|
72
72
|
assert.equal(hub.getDeviceLiveFrame(liveTarget.deviceId).streamId, 'scale-live');
|
|
73
|
+
assert.equal(hub.getDeviceLiveFrame(liveTarget.deviceId).fps, 20);
|
|
73
74
|
const stopResult = hub.stopLiveStream(liveTarget.deviceId, { streamId: 'scale-live' });
|
|
74
75
|
assert.equal(stopResult.ok, true);
|
|
75
76
|
|
package/server.js
CHANGED
|
@@ -1750,6 +1750,7 @@ const PROTECTED_BRIDGE_ROUTES = [
|
|
|
1750
1750
|
{ method: 'POST', prefix: '/api/shell/' },
|
|
1751
1751
|
{ method: 'GET', prefix: '/api/remote/' },
|
|
1752
1752
|
{ method: 'POST', prefix: '/api/remote/' },
|
|
1753
|
+
{ method: 'DELETE', prefix: '/api/remote/' },
|
|
1753
1754
|
{ method: 'POST', prefix: '/project/' },
|
|
1754
1755
|
{ method: 'POST', exact: '/agent/connect' },
|
|
1755
1756
|
{ method: 'POST', exact: '/api/tool/trace' }
|
|
@@ -13554,7 +13554,7 @@
|
|
|
13554
13554
|
liveName.style.cssText = 'color:#0f172a;font-size:15px;font-weight:950;line-height:1.15;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;letter-spacing:0;';
|
|
13555
13555
|
const liveMeta = document.createElement('span');
|
|
13556
13556
|
liveMeta.textContent = liveActive
|
|
13557
|
-
? `RemoteFast ${getRemoteFleetDeviceField(focusedDevice, 'liveStreamFps', 'LiveStreamFps', 0) ||
|
|
13557
|
+
? `RemoteFast ${getRemoteFleetDeviceField(focusedDevice, 'liveStreamFps', 'LiveStreamFps', 0) || 20} fps`
|
|
13558
13558
|
: 'View-only focused screen stream';
|
|
13559
13559
|
liveMeta.style.cssText = 'color:#475569;font-size:11px;font-weight:800;line-height:1.25;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;letter-spacing:0;';
|
|
13560
13560
|
liveTitle.appendChild(liveName);
|
package/wwwroot/_framework/{MindExecution.Core.ckgjbdvvxl.dll → MindExecution.Core.c9fyqe953v.dll}
RENAMED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/wwwroot/_framework/{MindExecution.Web.bqamgu5gq1.dll → MindExecution.Web.jmawk7z8d3.dll}
RENAMED
|
Binary file
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"mainAssemblyName": "MindExecution.Web",
|
|
3
3
|
"resources": {
|
|
4
|
-
"hash": "sha256-
|
|
4
|
+
"hash": "sha256-U10u85TRNQ5EuHSJ6CDlslJbcSBCmbE+UPKJl/T8OtY=",
|
|
5
5
|
"fingerprinting": {
|
|
6
6
|
"Google.Protobuf.9h59ukbel7.dll": "Google.Protobuf.dll",
|
|
7
7
|
"Markdig.d1j7v41cl1.dll": "Markdig.dll",
|
|
@@ -123,16 +123,16 @@
|
|
|
123
123
|
"System.m05i39uvk9.dll": "System.dll",
|
|
124
124
|
"netstandard.0xet7jg7ky.dll": "netstandard.dll",
|
|
125
125
|
"System.Private.CoreLib.rkafq04oma.dll": "System.Private.CoreLib.dll",
|
|
126
|
-
"MindExecution.Core.
|
|
127
|
-
"MindExecution.Kernel.
|
|
128
|
-
"MindExecution.Plugins.Admin.
|
|
129
|
-
"MindExecution.Plugins.Business.
|
|
130
|
-
"MindExecution.Plugins.Concept.
|
|
131
|
-
"MindExecution.Plugins.Directory.
|
|
132
|
-
"MindExecution.Plugins.PlanMaster.
|
|
133
|
-
"MindExecution.Plugins.YouTube.
|
|
134
|
-
"MindExecution.Shared.
|
|
135
|
-
"MindExecution.Web.
|
|
126
|
+
"MindExecution.Core.c9fyqe953v.dll": "MindExecution.Core.dll",
|
|
127
|
+
"MindExecution.Kernel.badrt1tkvv.dll": "MindExecution.Kernel.dll",
|
|
128
|
+
"MindExecution.Plugins.Admin.73w1bvz4r1.dll": "MindExecution.Plugins.Admin.dll",
|
|
129
|
+
"MindExecution.Plugins.Business.dvd82y422m.dll": "MindExecution.Plugins.Business.dll",
|
|
130
|
+
"MindExecution.Plugins.Concept.m3ukc0xvom.dll": "MindExecution.Plugins.Concept.dll",
|
|
131
|
+
"MindExecution.Plugins.Directory.23tm2uvfvu.dll": "MindExecution.Plugins.Directory.dll",
|
|
132
|
+
"MindExecution.Plugins.PlanMaster.8nrc7ge4ob.dll": "MindExecution.Plugins.PlanMaster.dll",
|
|
133
|
+
"MindExecution.Plugins.YouTube.3ox59073d8.dll": "MindExecution.Plugins.YouTube.dll",
|
|
134
|
+
"MindExecution.Shared.va1gxp0crd.dll": "MindExecution.Shared.dll",
|
|
135
|
+
"MindExecution.Web.jmawk7z8d3.dll": "MindExecution.Web.dll",
|
|
136
136
|
"dotnet.js": "dotnet.js",
|
|
137
137
|
"dotnet.native.xsn1d6x2kd.js": "dotnet.native.js",
|
|
138
138
|
"dotnet.native.vz0adxojrz.wasm": "dotnet.native.wasm",
|
|
@@ -278,18 +278,18 @@
|
|
|
278
278
|
"System.Xml.XDocument.c539ki6cuq.dll": "sha256-MPTRJkptrL9nGa2tl4kF46+wErNUYRPCGblX3ANoKoY=",
|
|
279
279
|
"System.m05i39uvk9.dll": "sha256-5jDfIdbYAigw7/Q/lMzt5W/+cayGbW9ko9FvuaN1GsQ=",
|
|
280
280
|
"netstandard.0xet7jg7ky.dll": "sha256-xENDv620uJ8fHwLJ2bdhrTHz4QPjvqXOztnk2a4wr0c=",
|
|
281
|
-
"MindExecution.Core.
|
|
282
|
-
"MindExecution.Kernel.
|
|
283
|
-
"MindExecution.Plugins.Concept.
|
|
284
|
-
"MindExecution.Plugins.PlanMaster.
|
|
285
|
-
"MindExecution.Shared.
|
|
286
|
-
"MindExecution.Web.
|
|
281
|
+
"MindExecution.Core.c9fyqe953v.dll": "sha256-QFzKrrCvQhHKuzHmjZNnWfLRs8Zvg90nlG23JMRuPiA=",
|
|
282
|
+
"MindExecution.Kernel.badrt1tkvv.dll": "sha256-Ay3ypEtsJuNsBYsha1gUwQ98jBnWGZFyOEEd2TmsNew=",
|
|
283
|
+
"MindExecution.Plugins.Concept.m3ukc0xvom.dll": "sha256-YjENe8QVAOo4XYknnQD3hSMouQMSQQQ7sryMHObA0Qc=",
|
|
284
|
+
"MindExecution.Plugins.PlanMaster.8nrc7ge4ob.dll": "sha256-DGJpulGGAuvc9KS9plHJi8BLX8EBiqV3A90QMAadYCY=",
|
|
285
|
+
"MindExecution.Shared.va1gxp0crd.dll": "sha256-ly99wDAapShB+jZ1V95wYNfWyd1Q+JNGxL870fY6XKI=",
|
|
286
|
+
"MindExecution.Web.jmawk7z8d3.dll": "sha256-yz2Mpwuz+oEBj6sVtdQOjSPIrLj4cQICK7ZDFVWwy5o="
|
|
287
287
|
},
|
|
288
288
|
"lazyAssembly": {
|
|
289
|
-
"MindExecution.Plugins.Admin.
|
|
290
|
-
"MindExecution.Plugins.Business.
|
|
291
|
-
"MindExecution.Plugins.Directory.
|
|
292
|
-
"MindExecution.Plugins.YouTube.
|
|
289
|
+
"MindExecution.Plugins.Admin.73w1bvz4r1.dll": "sha256-s0/shhl1o5sjys9RDDMPM5TWYZNk64K5RggeZ8gsDKA=",
|
|
290
|
+
"MindExecution.Plugins.Business.dvd82y422m.dll": "sha256-OcLlpkGPe6VinOzGw5cDKNjIcQLZW+nv6zGjvzewc8w=",
|
|
291
|
+
"MindExecution.Plugins.Directory.23tm2uvfvu.dll": "sha256-vmai+Tkzmk5CeReKLxTMz/gp+uPrt8EaftPIbljEZ0E=",
|
|
292
|
+
"MindExecution.Plugins.YouTube.3ox59073d8.dll": "sha256-Te3jpmTgl3HFoKoMct4HMXhg6a9PgTHmVaQltQjKrak="
|
|
293
293
|
}
|
|
294
294
|
},
|
|
295
295
|
"cacheBootResources": true,
|
package/wwwroot/index.html
CHANGED
|
@@ -558,7 +558,7 @@
|
|
|
558
558
|
}
|
|
559
559
|
|
|
560
560
|
const base = '_content/MindExecution.Shared/js/';
|
|
561
|
-
const scriptVersion = '20260612-remote-
|
|
561
|
+
const scriptVersion = '20260612-remote-fast-20fps-v479';
|
|
562
562
|
const scriptUrl = (script) => `${base}${script}?v=${scriptVersion}`;
|
|
563
563
|
console.log(`[Script Loader] Shared JS version: ${scriptVersion}`);
|
|
564
564
|
const criticalScripts = [
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
self.assetsManifest = {
|
|
2
|
-
"version": "
|
|
2
|
+
"version": "4y4C9wve",
|
|
3
3
|
"assets": [
|
|
4
4
|
{
|
|
5
5
|
"hash": "sha256-+CSYMcqLNTsq3VnH11jgYyOCCdxvHzL74CBmo4sCmMU=",
|
|
@@ -86,7 +86,7 @@
|
|
|
86
86
|
"url": "_content/MindExecution.Shared/js/mind-map-core.js.backup"
|
|
87
87
|
},
|
|
88
88
|
{
|
|
89
|
-
"hash": "sha256-
|
|
89
|
+
"hash": "sha256-E6d/sEnHvzwsyrryEFowSagM2Y3LCxsotUHJe+5X9mE=",
|
|
90
90
|
"url": "_content/MindExecution.Shared/js/mind-map-css3d-manager.js"
|
|
91
91
|
},
|
|
92
92
|
{
|
|
@@ -410,44 +410,44 @@
|
|
|
410
410
|
"url": "_framework/MimeMapping.og9ys58ylm.dll"
|
|
411
411
|
},
|
|
412
412
|
{
|
|
413
|
-
"hash": "sha256-
|
|
414
|
-
"url": "_framework/MindExecution.Core.
|
|
413
|
+
"hash": "sha256-QFzKrrCvQhHKuzHmjZNnWfLRs8Zvg90nlG23JMRuPiA=",
|
|
414
|
+
"url": "_framework/MindExecution.Core.c9fyqe953v.dll"
|
|
415
415
|
},
|
|
416
416
|
{
|
|
417
|
-
"hash": "sha256-
|
|
418
|
-
"url": "_framework/MindExecution.Kernel.
|
|
417
|
+
"hash": "sha256-Ay3ypEtsJuNsBYsha1gUwQ98jBnWGZFyOEEd2TmsNew=",
|
|
418
|
+
"url": "_framework/MindExecution.Kernel.badrt1tkvv.dll"
|
|
419
419
|
},
|
|
420
420
|
{
|
|
421
|
-
"hash": "sha256-
|
|
422
|
-
"url": "_framework/MindExecution.Plugins.Admin.
|
|
421
|
+
"hash": "sha256-s0/shhl1o5sjys9RDDMPM5TWYZNk64K5RggeZ8gsDKA=",
|
|
422
|
+
"url": "_framework/MindExecution.Plugins.Admin.73w1bvz4r1.dll"
|
|
423
423
|
},
|
|
424
424
|
{
|
|
425
|
-
"hash": "sha256-
|
|
426
|
-
"url": "_framework/MindExecution.Plugins.Business.
|
|
425
|
+
"hash": "sha256-OcLlpkGPe6VinOzGw5cDKNjIcQLZW+nv6zGjvzewc8w=",
|
|
426
|
+
"url": "_framework/MindExecution.Plugins.Business.dvd82y422m.dll"
|
|
427
427
|
},
|
|
428
428
|
{
|
|
429
|
-
"hash": "sha256-
|
|
430
|
-
"url": "_framework/MindExecution.Plugins.Concept.
|
|
429
|
+
"hash": "sha256-YjENe8QVAOo4XYknnQD3hSMouQMSQQQ7sryMHObA0Qc=",
|
|
430
|
+
"url": "_framework/MindExecution.Plugins.Concept.m3ukc0xvom.dll"
|
|
431
431
|
},
|
|
432
432
|
{
|
|
433
|
-
"hash": "sha256-
|
|
434
|
-
"url": "_framework/MindExecution.Plugins.Directory.
|
|
433
|
+
"hash": "sha256-vmai+Tkzmk5CeReKLxTMz/gp+uPrt8EaftPIbljEZ0E=",
|
|
434
|
+
"url": "_framework/MindExecution.Plugins.Directory.23tm2uvfvu.dll"
|
|
435
435
|
},
|
|
436
436
|
{
|
|
437
|
-
"hash": "sha256-
|
|
438
|
-
"url": "_framework/MindExecution.Plugins.PlanMaster.
|
|
437
|
+
"hash": "sha256-DGJpulGGAuvc9KS9plHJi8BLX8EBiqV3A90QMAadYCY=",
|
|
438
|
+
"url": "_framework/MindExecution.Plugins.PlanMaster.8nrc7ge4ob.dll"
|
|
439
439
|
},
|
|
440
440
|
{
|
|
441
|
-
"hash": "sha256-
|
|
442
|
-
"url": "_framework/MindExecution.Plugins.YouTube.
|
|
441
|
+
"hash": "sha256-Te3jpmTgl3HFoKoMct4HMXhg6a9PgTHmVaQltQjKrak=",
|
|
442
|
+
"url": "_framework/MindExecution.Plugins.YouTube.3ox59073d8.dll"
|
|
443
443
|
},
|
|
444
444
|
{
|
|
445
|
-
"hash": "sha256-
|
|
446
|
-
"url": "_framework/MindExecution.Shared.
|
|
445
|
+
"hash": "sha256-ly99wDAapShB+jZ1V95wYNfWyd1Q+JNGxL870fY6XKI=",
|
|
446
|
+
"url": "_framework/MindExecution.Shared.va1gxp0crd.dll"
|
|
447
447
|
},
|
|
448
448
|
{
|
|
449
|
-
"hash": "sha256-
|
|
450
|
-
"url": "_framework/MindExecution.Web.
|
|
449
|
+
"hash": "sha256-yz2Mpwuz+oEBj6sVtdQOjSPIrLj4cQICK7ZDFVWwy5o=",
|
|
450
|
+
"url": "_framework/MindExecution.Web.jmawk7z8d3.dll"
|
|
451
451
|
},
|
|
452
452
|
{
|
|
453
453
|
"hash": "sha256-IsZJ91/OW+fHzNqIgEc7Y072ns8z9dGritiSyvR9Wgc=",
|
|
@@ -770,7 +770,7 @@
|
|
|
770
770
|
"url": "_framework/Websocket.Client.vapounvmnl.dll"
|
|
771
771
|
},
|
|
772
772
|
{
|
|
773
|
-
"hash": "sha256-
|
|
773
|
+
"hash": "sha256-YFYbUXsuU5KT0E7N+xUyIA0vztkOHHRPlmdp4kBB67c=",
|
|
774
774
|
"url": "_framework/blazor.boot.json"
|
|
775
775
|
},
|
|
776
776
|
{
|
|
@@ -834,7 +834,7 @@
|
|
|
834
834
|
"url": "image-manifest.json"
|
|
835
835
|
},
|
|
836
836
|
{
|
|
837
|
-
"hash": "sha256-
|
|
837
|
+
"hash": "sha256-tL38lnMES1WBgTPkRcwiazc1i1T3td1aYgwrUvoxQOo=",
|
|
838
838
|
"url": "index.html"
|
|
839
839
|
},
|
|
840
840
|
{
|