@mindexec/cli 0.2.456 → 0.2.458
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 +77 -77
- package/remote-fast/osx-arm64/mindexec-remote-fast.dll +0 -0
- package/remote-fast/osx-x64/mindexec-remote-fast.dll +0 -0
- package/remote-fast/win-x64/mindexec-remote-fast.dll +0 -0
- package/scripts/remote-fleet-render-smoke.mjs +50 -229
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-css3d-manager.js +301 -604
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-pipeline.js +1326 -1323
- package/wwwroot/_framework/{MindExecution.Core.glgqkah960.dll → MindExecution.Core.2ch68iyy8o.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Kernel.1nb0zfmie1.dll → MindExecution.Kernel.dh617xfv36.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.Admin.4pdpv5q991.dll → MindExecution.Plugins.Admin.0sm50hbae9.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.Business.jpl2k4nnhh.dll → MindExecution.Plugins.Business.3wq01orrbu.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.Concept.rissr3n74r.dll → MindExecution.Plugins.Concept.z8yl28fa2a.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.Directory.tkopeqv16k.dll → MindExecution.Plugins.Directory.m7murp5oes.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.PlanMaster.jmjftycwo4.dll → MindExecution.Plugins.PlanMaster.yuyrbpf0vh.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.YouTube.drj98vf3ti.dll → MindExecution.Plugins.YouTube.rwxvn00rm2.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Shared.cbieupjmfp.dll → MindExecution.Shared.r9k48iyijb.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Web.xl8ygqgy0i.dll → MindExecution.Web.742aribkxm.dll} +0 -0
- package/wwwroot/_framework/blazor.boot.json +21 -21
- package/wwwroot/index.html +722 -722
- package/wwwroot/service-worker-assets.js +25 -25
- 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.458",
|
|
4
4
|
"description": "MindExec local runtime and bridge CLI",
|
|
5
5
|
"main": "server.js",
|
|
6
6
|
"type": "module",
|
|
@@ -16,24 +16,24 @@
|
|
|
16
16
|
"codex-runtime.js",
|
|
17
17
|
"codex-model-catalog.js",
|
|
18
18
|
"port-guard.cjs",
|
|
19
|
-
"remote-fast/",
|
|
20
|
-
"wwwroot/",
|
|
21
|
-
"electron/",
|
|
22
|
-
"scripts/",
|
|
19
|
+
"remote-fast/",
|
|
20
|
+
"wwwroot/",
|
|
21
|
+
"electron/",
|
|
22
|
+
"scripts/",
|
|
23
23
|
"tree-sitter-grammars/",
|
|
24
24
|
"README.md"
|
|
25
25
|
],
|
|
26
|
-
"scripts": {
|
|
27
|
-
"start": "node launch-bridge.cjs",
|
|
28
|
-
"dev": "node launch-bridge.cjs --watch",
|
|
29
|
-
"desktop:start": "electron electron/main.cjs",
|
|
30
|
-
"desktop:build:win": "electron-builder --win --x64 --publish never",
|
|
31
|
-
"test:desktop": "node electron/source-smoke.mjs",
|
|
32
|
-
"test:desktop:win": "node electron/windows-package-smoke.mjs",
|
|
33
|
-
"test:syntax": "node --check server.js && node --check remote-hub.js && node --check lzo1x.js && node --check mode4-atlas.js && node --check mode4-atlas-worker.js && node --check codex-runtime.js && node --check codex-model-catalog.js && node --check launch-bridge.cjs && node --check port-guard.cjs && node --check electron/main.cjs && node --check electron/source-smoke.mjs && node --check electron/windows-package-smoke.mjs && node --check scripts/setup-tree-sitter-grammars.mjs && node --check scripts/npm-fresh-install-smoke.mjs && node --check scripts/auth-session-smoke.mjs && node --check scripts/codex-model-catalog-smoke.mjs && node --check scripts/codex-sdk-runtime-smoke.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 && node --check scripts/remote-frame-ws-smoke.mjs && node --check scripts/remote-input-ws-smoke.mjs && node --check scripts/remote-agent-ws-smoke.mjs && node --check scripts/remote-agent-managed-smoke.mjs && node --check scripts/remote-registry-follower-smoke.mjs && node --check scripts/remote-agent-package-smoke.mjs && node --check scripts/remote-fast-live-rate-smoke.mjs && node --check scripts/remote-fast-mdm-browser-smoke.mjs",
|
|
34
|
-
"test:codex-sdk": "node scripts/codex-sdk-runtime-smoke.mjs",
|
|
35
|
-
"test:codex-sdk:live": "node scripts/codex-sdk-runtime-smoke.mjs --live",
|
|
36
|
-
"test:codex-sdk:live-tools": "node scripts/codex-sdk-runtime-smoke.mjs --live-tools",
|
|
26
|
+
"scripts": {
|
|
27
|
+
"start": "node launch-bridge.cjs",
|
|
28
|
+
"dev": "node launch-bridge.cjs --watch",
|
|
29
|
+
"desktop:start": "electron electron/main.cjs",
|
|
30
|
+
"desktop:build:win": "electron-builder --win --x64 --publish never",
|
|
31
|
+
"test:desktop": "node electron/source-smoke.mjs",
|
|
32
|
+
"test:desktop:win": "node electron/windows-package-smoke.mjs",
|
|
33
|
+
"test:syntax": "node --check server.js && node --check remote-hub.js && node --check lzo1x.js && node --check mode4-atlas.js && node --check mode4-atlas-worker.js && node --check codex-runtime.js && node --check codex-model-catalog.js && node --check launch-bridge.cjs && node --check port-guard.cjs && node --check electron/main.cjs && node --check electron/source-smoke.mjs && node --check electron/windows-package-smoke.mjs && node --check scripts/setup-tree-sitter-grammars.mjs && node --check scripts/npm-fresh-install-smoke.mjs && node --check scripts/auth-session-smoke.mjs && node --check scripts/codex-model-catalog-smoke.mjs && node --check scripts/codex-sdk-runtime-smoke.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 && node --check scripts/remote-frame-ws-smoke.mjs && node --check scripts/remote-input-ws-smoke.mjs && node --check scripts/remote-agent-ws-smoke.mjs && node --check scripts/remote-agent-managed-smoke.mjs && node --check scripts/remote-registry-follower-smoke.mjs && node --check scripts/remote-agent-package-smoke.mjs && node --check scripts/remote-fast-live-rate-smoke.mjs && node --check scripts/remote-fast-mdm-browser-smoke.mjs",
|
|
34
|
+
"test:codex-sdk": "node scripts/codex-sdk-runtime-smoke.mjs",
|
|
35
|
+
"test:codex-sdk:live": "node scripts/codex-sdk-runtime-smoke.mjs --live",
|
|
36
|
+
"test:codex-sdk:live-tools": "node scripts/codex-sdk-runtime-smoke.mjs --live-tools",
|
|
37
37
|
"test:codex-model-catalog": "node scripts/codex-model-catalog-smoke.mjs",
|
|
38
38
|
"test:codex-model-catalog:live": "node scripts/codex-model-catalog-smoke.mjs --live",
|
|
39
39
|
"test:auth": "node scripts/auth-session-smoke.mjs",
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
"local",
|
|
62
62
|
"ai"
|
|
63
63
|
],
|
|
64
|
-
"author": "lovecrdm77",
|
|
64
|
+
"author": "lovecrdm77",
|
|
65
65
|
"license": "MIT",
|
|
66
66
|
"publishConfig": {
|
|
67
67
|
"access": "public"
|
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
},
|
|
72
72
|
"dependencies": {
|
|
73
73
|
"@ffmpeg-installer/ffmpeg": "^1.1.0",
|
|
74
|
-
"@mindexec/remote": "^0.1.18",
|
|
74
|
+
"@mindexec/remote": "^0.1.18",
|
|
75
75
|
"@openai/codex-sdk": "^0.144.1",
|
|
76
76
|
"chokidar": "^3.6.0",
|
|
77
77
|
"cors": "^2.8.5",
|
|
@@ -90,62 +90,62 @@
|
|
|
90
90
|
"mindexec": "launch-bridge.cjs",
|
|
91
91
|
"mind-bridge": "launch-bridge.cjs"
|
|
92
92
|
},
|
|
93
|
-
"devDependencies": {
|
|
94
|
-
"electron": "43.2.0",
|
|
95
|
-
"electron-builder": "26.15.3",
|
|
96
|
-
"tree-sitter-wasms": "^0.1.13"
|
|
97
|
-
},
|
|
98
|
-
"build": {
|
|
99
|
-
"appId": "com.mindexec.desktop",
|
|
100
|
-
"productName": "MindExec",
|
|
101
|
-
"copyright": "Copyright © 2026 lovecrdm77",
|
|
102
|
-
"asar": false,
|
|
103
|
-
"extraMetadata": {
|
|
104
|
-
"main": "electron/main.cjs"
|
|
105
|
-
},
|
|
106
|
-
"directories": {
|
|
107
|
-
"output": "../artifacts/electron"
|
|
108
|
-
},
|
|
109
|
-
"files": [
|
|
110
|
-
"*.js",
|
|
111
|
-
"*.cjs",
|
|
112
|
-
"*.json",
|
|
113
|
-
"electron/main.cjs",
|
|
114
|
-
"remote-fast/**/*",
|
|
115
|
-
"scripts/**/*",
|
|
116
|
-
"tree-sitter-grammars/**/*",
|
|
117
|
-
"wwwroot/**/*",
|
|
118
|
-
"node_modules/**/*"
|
|
119
|
-
],
|
|
120
|
-
"win": {
|
|
121
|
-
"icon": "../MindExecution.Web/wwwroot/app-icon-1024.png",
|
|
122
|
-
"executableName": "MindExec",
|
|
123
|
-
"target": [
|
|
124
|
-
{
|
|
125
|
-
"target": "nsis",
|
|
126
|
-
"arch": [
|
|
127
|
-
"x64"
|
|
128
|
-
]
|
|
129
|
-
},
|
|
130
|
-
{
|
|
131
|
-
"target": "portable",
|
|
132
|
-
"arch": [
|
|
133
|
-
"x64"
|
|
134
|
-
]
|
|
135
|
-
}
|
|
136
|
-
]
|
|
137
|
-
},
|
|
138
|
-
"nsis": {
|
|
139
|
-
"artifactName": "MindExec-Setup-${version}-${arch}.${ext}",
|
|
140
|
-
"oneClick": false,
|
|
141
|
-
"perMachine": false,
|
|
142
|
-
"allowToChangeInstallationDirectory": true,
|
|
143
|
-
"createDesktopShortcut": true,
|
|
144
|
-
"createStartMenuShortcut": true,
|
|
145
|
-
"shortcutName": "MindExec"
|
|
146
|
-
},
|
|
147
|
-
"portable": {
|
|
148
|
-
"artifactName": "MindExec-Portable-${version}-${arch}.${ext}"
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
}
|
|
93
|
+
"devDependencies": {
|
|
94
|
+
"electron": "43.2.0",
|
|
95
|
+
"electron-builder": "26.15.3",
|
|
96
|
+
"tree-sitter-wasms": "^0.1.13"
|
|
97
|
+
},
|
|
98
|
+
"build": {
|
|
99
|
+
"appId": "com.mindexec.desktop",
|
|
100
|
+
"productName": "MindExec",
|
|
101
|
+
"copyright": "Copyright © 2026 lovecrdm77",
|
|
102
|
+
"asar": false,
|
|
103
|
+
"extraMetadata": {
|
|
104
|
+
"main": "electron/main.cjs"
|
|
105
|
+
},
|
|
106
|
+
"directories": {
|
|
107
|
+
"output": "../artifacts/electron"
|
|
108
|
+
},
|
|
109
|
+
"files": [
|
|
110
|
+
"*.js",
|
|
111
|
+
"*.cjs",
|
|
112
|
+
"*.json",
|
|
113
|
+
"electron/main.cjs",
|
|
114
|
+
"remote-fast/**/*",
|
|
115
|
+
"scripts/**/*",
|
|
116
|
+
"tree-sitter-grammars/**/*",
|
|
117
|
+
"wwwroot/**/*",
|
|
118
|
+
"node_modules/**/*"
|
|
119
|
+
],
|
|
120
|
+
"win": {
|
|
121
|
+
"icon": "../MindExecution.Web/wwwroot/app-icon-1024.png",
|
|
122
|
+
"executableName": "MindExec",
|
|
123
|
+
"target": [
|
|
124
|
+
{
|
|
125
|
+
"target": "nsis",
|
|
126
|
+
"arch": [
|
|
127
|
+
"x64"
|
|
128
|
+
]
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
"target": "portable",
|
|
132
|
+
"arch": [
|
|
133
|
+
"x64"
|
|
134
|
+
]
|
|
135
|
+
}
|
|
136
|
+
]
|
|
137
|
+
},
|
|
138
|
+
"nsis": {
|
|
139
|
+
"artifactName": "MindExec-Setup-${version}-${arch}.${ext}",
|
|
140
|
+
"oneClick": false,
|
|
141
|
+
"perMachine": false,
|
|
142
|
+
"allowToChangeInstallationDirectory": true,
|
|
143
|
+
"createDesktopShortcut": true,
|
|
144
|
+
"createStartMenuShortcut": true,
|
|
145
|
+
"shortcutName": "MindExec"
|
|
146
|
+
},
|
|
147
|
+
"portable": {
|
|
148
|
+
"artifactName": "MindExec-Portable-${version}-${arch}.${ext}"
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -950,9 +950,11 @@ try {
|
|
|
950
950
|
|
|
951
951
|
let cards = bodyView.querySelectorAll('article[data-device-id]');
|
|
952
952
|
assert.equal(cards.length, connectedCount);
|
|
953
|
-
assert.
|
|
954
|
-
assert.
|
|
955
|
-
assert.equal(bodyView.querySelectorAll('select').length,
|
|
953
|
+
assert.ok(bodyView.querySelector('[data-remote-fleet-match-count="true"]'));
|
|
954
|
+
assert.ok(bodyView.querySelector('[data-remote-fleet-search="true"]'));
|
|
955
|
+
assert.equal(bodyView.querySelectorAll('select').length, 4);
|
|
956
|
+
assert.ok(bodyView.querySelector('[data-remote-fleet-task-composer="visible"]'));
|
|
957
|
+
assert.ok(bodyView.querySelector('[data-remote-fleet-task-input="true"]'));
|
|
956
958
|
const deviceGrid = bodyView.querySelector('[data-remote-fleet-device-grid="true"]');
|
|
957
959
|
assert.ok(deviceGrid);
|
|
958
960
|
assert.match(deviceGrid.style.cssText, /padding:\s*0 4px;/);
|
|
@@ -1018,9 +1020,8 @@ try {
|
|
|
1018
1020
|
const patchCard = Array.from(cards).find(card => card.dataset.deviceId === patchTarget.DeviceId);
|
|
1019
1021
|
const patchPreview = patchCard?.querySelector('[data-remote-fleet-device-preview="tile"]');
|
|
1020
1022
|
assert.ok(patchPreview);
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
: 'thumbnail';
|
|
1023
|
+
assert.notEqual(patchPreview.dataset.remoteFleetFrameKind, 'live');
|
|
1024
|
+
const patchKind = 'thumbnail';
|
|
1024
1025
|
const patchUrl = `/api/remote/devices/${encodeURIComponent(patchTarget.DeviceId)}/${patchKind}?token=render-smoke-frame&seq=9999`;
|
|
1025
1026
|
const patchCount = manager.applyRemoteFleetFramePatchesForTest(bodyView, [{
|
|
1026
1027
|
deviceId: patchTarget.DeviceId,
|
|
@@ -1045,168 +1046,13 @@ try {
|
|
|
1045
1046
|
assert.equal(patchPreview.querySelector('img[data-remote-fleet-frame-image="true"]')?.dataset.remoteFleetFrameUrl, patchUrl);
|
|
1046
1047
|
assert.equal(patchPreview.querySelector('[data-remote-fleet-frame-badge="true"]'), null);
|
|
1047
1048
|
|
|
1048
|
-
const objectUrlCountBeforeBinary = diagnostics.objectUrlCalls.length;
|
|
1049
|
-
const imageBitmapCountBeforeBinary = diagnostics.imageBitmapCalls.length;
|
|
1050
|
-
const drawCountBeforeBinary = document.canvasDrawCalls.length;
|
|
1051
|
-
const binaryPatchCount = manager.applyRemoteFleetFramePatchesForTest(bodyView, [{
|
|
1052
|
-
deviceId: patchTarget.DeviceId,
|
|
1053
|
-
kind: 'live',
|
|
1054
|
-
frameSeq: 10000,
|
|
1055
|
-
frameUrl: '',
|
|
1056
|
-
streamId: 'render-smoke-binary-live',
|
|
1057
|
-
contentHash: 'render-smoke-binary-live-10000',
|
|
1058
|
-
receivedAt: new Date().toISOString(),
|
|
1059
|
-
_remoteFleetPayloadBlob: new Blob([new Uint8Array([0xff, 0xd8, 0xff, 0xd9])], { type: 'image/jpeg' }),
|
|
1060
|
-
_remoteFleetBinaryFrame: true
|
|
1061
|
-
}]);
|
|
1062
|
-
assert.equal(binaryPatchCount, 1);
|
|
1063
|
-
await wait(20);
|
|
1064
|
-
const binaryCanvas = patchPreview.querySelector('canvas[data-remote-fleet-frame-canvas="true"]');
|
|
1065
|
-
const binaryImage = patchPreview.querySelector('img[data-remote-fleet-frame-image="true"]');
|
|
1066
|
-
assert.equal(patchPreview.dataset.remoteFleetFrameKind, 'live');
|
|
1067
|
-
assert.equal(patchPreview.dataset.remoteFleetFrameSeq, '10000');
|
|
1068
|
-
assert.equal(binaryCanvas?.dataset.remoteFleetFrameSeq, '10000');
|
|
1069
|
-
assert.equal(binaryCanvas?.style.display, 'block');
|
|
1070
|
-
assert.equal(binaryImage?.style.display, 'none');
|
|
1071
|
-
assert.equal(diagnostics.imageBitmapCalls.length, imageBitmapCountBeforeBinary + 1);
|
|
1072
|
-
assert.equal(diagnostics.objectUrlCalls.length, objectUrlCountBeforeBinary);
|
|
1073
|
-
const binaryDrawCalls = document.canvasDrawCalls.slice(drawCountBeforeBinary);
|
|
1074
|
-
assert.ok(
|
|
1075
|
-
binaryDrawCalls.some(call => call.op === 'drawImage'),
|
|
1076
|
-
'expected binary Blob frame to draw directly to canvas');
|
|
1077
|
-
assert.equal(
|
|
1078
|
-
binaryDrawCalls.some(call => call.op === 'clearRect' || call.op === 'fillRect'),
|
|
1079
|
-
false,
|
|
1080
|
-
'binary Blob frame paint must not clear/fill the canvas before drawing');
|
|
1081
|
-
assert.ok(
|
|
1082
|
-
Number(moduleRef._forceUpdateFrames || 0) >= 2,
|
|
1083
|
-
'binary live frame commits must wake the passive MDM CSS3D frame loop');
|
|
1084
|
-
assert.equal(moduleRef._lastAnimationWakeReason, 'remote-live-css3d-frame');
|
|
1085
|
-
assert.ok(
|
|
1086
|
-
diagnostics.runtimeTrace.some(event => event.type === 'remote.frame.css3dWake'),
|
|
1087
|
-
'binary live frame commits must trace the MDM CSS3D wake path');
|
|
1088
|
-
const binaryCanvasBeforeRerender = binaryCanvas;
|
|
1089
|
-
|
|
1090
|
-
const liveOverlayCard = document.createElement('div');
|
|
1091
|
-
liveOverlayCard.dataset.nodeId = 'remote-fleet-render-smoke';
|
|
1092
|
-
liveOverlayCard.dataset.sourceKind = 'live';
|
|
1093
|
-
liveOverlayCard.dataset.liveInteractive = 'true';
|
|
1094
|
-
liveOverlayCard.style.display = 'block';
|
|
1095
|
-
moduleRef._textOverlayV2State.cards.set('selection:remote-fleet-render-smoke', liveOverlayCard);
|
|
1096
|
-
moduleRef._forceUpdateFrames = 0;
|
|
1097
|
-
moduleRef._animationWakeCount = 0;
|
|
1098
|
-
moduleRef._lastAnimationWakeReason = '';
|
|
1099
|
-
|
|
1100
|
-
await wait(20);
|
|
1101
|
-
const liveWs = diagnostics.webSocketConnections.find(connection =>
|
|
1102
|
-
String(connection?.url || '').includes('/api/remote/atlas/ws'));
|
|
1103
|
-
assert.ok(
|
|
1104
|
-
liveWs,
|
|
1105
|
-
`expected MDM render to open the Mode 4 Atlas WebSocket: ${diagnostics.webSocketConnections.map(connection => connection.url).join(', ')}`
|
|
1106
|
-
);
|
|
1107
|
-
assert.equal(liveWs.readyState, 1, 'Mode 4 Atlas WebSocket should be open before rerender');
|
|
1108
|
-
const wsCountBeforeRerender = diagnostics.webSocketConnections.length;
|
|
1109
|
-
const wsCloseCountBeforeRerender = liveWs.closeCount;
|
|
1110
|
-
const websocketFrameSeq = 10001;
|
|
1111
|
-
liveWs.onmessage?.({
|
|
1112
|
-
data: JSON.stringify({
|
|
1113
|
-
type: 'Mode4AtlasLayout',
|
|
1114
|
-
tiles: [{
|
|
1115
|
-
deviceId: patchTarget.DeviceId,
|
|
1116
|
-
x: 0,
|
|
1117
|
-
y: 0,
|
|
1118
|
-
width: 64,
|
|
1119
|
-
height: 36
|
|
1120
|
-
}]
|
|
1121
|
-
})
|
|
1122
|
-
});
|
|
1123
|
-
liveWs.onmessage?.({
|
|
1124
|
-
data: new Blob([encodeRemoteBinaryFrame({
|
|
1125
|
-
type: 'remote.frame.binary',
|
|
1126
|
-
deviceId: patchTarget.DeviceId,
|
|
1127
|
-
kind: 'live',
|
|
1128
|
-
frameSeq: websocketFrameSeq,
|
|
1129
|
-
streamId: 'render-smoke-ws-live',
|
|
1130
|
-
contentHash: `render-smoke-ws-live-${websocketFrameSeq}`,
|
|
1131
|
-
mimeType: 'image/jpeg',
|
|
1132
|
-
frameMode: 'mode4-h264-atlas',
|
|
1133
|
-
width: 64,
|
|
1134
|
-
height: 36,
|
|
1135
|
-
capturedAt: new Date().toISOString(),
|
|
1136
|
-
receivedAt: new Date().toISOString()
|
|
1137
|
-
})])
|
|
1138
|
-
});
|
|
1139
|
-
await waitFor(
|
|
1140
|
-
() => patchPreview.dataset.remoteFleetFrameSeq === String(websocketFrameSeq)
|
|
1141
|
-
);
|
|
1142
|
-
assert.equal(
|
|
1143
|
-
patchPreview.dataset.remoteFleetFrameSeq,
|
|
1144
|
-
String(websocketFrameSeq),
|
|
1145
|
-
JSON.stringify(diagnostics.runtimeTrace.slice(-12)));
|
|
1146
|
-
assert.ok(
|
|
1147
|
-
diagnostics.runtimeTrace.some(event =>
|
|
1148
|
-
event.type === 'remote.atlas.painted' &&
|
|
1149
|
-
Number(event.frameSeq || 0) === websocketFrameSeq),
|
|
1150
|
-
'Mode 4 Atlas frame must paint its configured device tile');
|
|
1151
|
-
|
|
1152
|
-
manager.renderRemoteFleetMonitorForTest(bodyView, buildMonitorNode(devices, hub.getStatus({ includeSecrets: true }), latestTaskBatch, recentTaskBatches));
|
|
1153
|
-
await wait(30);
|
|
1154
|
-
assert.equal(
|
|
1155
|
-
liveWs.closeCount,
|
|
1156
|
-
wsCloseCountBeforeRerender,
|
|
1157
|
-
'MDM rerender must not close the active Mode 4 Atlas WebSocket');
|
|
1158
|
-
assert.equal(
|
|
1159
|
-
diagnostics.webSocketConnections.length,
|
|
1160
|
-
wsCountBeforeRerender,
|
|
1161
|
-
'MDM rerender must reuse the active Mode 4 Atlas WebSocket instead of opening a replacement');
|
|
1162
|
-
const rerenderedPatchPreview = bodyView
|
|
1163
|
-
.querySelector(`article[data-device-id="${patchTarget.DeviceId}"]`)
|
|
1164
|
-
?.querySelector('[data-remote-fleet-device-preview="tile"]');
|
|
1165
|
-
assert.ok(rerenderedPatchPreview);
|
|
1166
|
-
assert.equal(rerenderedPatchPreview.dataset.remoteFleetFrameSeq, String(websocketFrameSeq));
|
|
1167
|
-
const rerenderedPatchCanvas = rerenderedPatchPreview.querySelector('canvas[data-remote-fleet-frame-canvas="true"]');
|
|
1168
|
-
assert.equal(rerenderedPatchCanvas?.style.display, 'block');
|
|
1169
|
-
assert.equal(
|
|
1170
|
-
rerenderedPatchCanvas,
|
|
1171
|
-
binaryCanvasBeforeRerender,
|
|
1172
|
-
'MDM rerender should reuse the already-painted canvas instead of flashing a blank replacement');
|
|
1173
|
-
|
|
1174
|
-
const otherBoardNodeId = 'remote-fleet-render-smoke-other-board';
|
|
1175
|
-
const { nodeShell: otherBoardShell, bodyView: otherBoardBodyView } =
|
|
1176
|
-
createRemoteFleetTemplateShell(document, focusedDevice.DeviceId, otherBoardNodeId);
|
|
1177
|
-
document.body.appendChild(otherBoardShell);
|
|
1178
|
-
manager.renderRemoteFleetMonitorForTest(
|
|
1179
|
-
otherBoardBodyView,
|
|
1180
|
-
buildMonitorNode(
|
|
1181
|
-
devices,
|
|
1182
|
-
hub.getStatus({ includeSecrets: true }),
|
|
1183
|
-
latestTaskBatch,
|
|
1184
|
-
recentTaskBatches,
|
|
1185
|
-
'',
|
|
1186
|
-
otherBoardNodeId));
|
|
1187
|
-
await wait(30);
|
|
1188
|
-
const otherBoardPatchPreview = otherBoardBodyView
|
|
1189
|
-
.querySelector(`article[data-device-id="${patchTarget.DeviceId}"]`)
|
|
1190
|
-
?.querySelector('[data-remote-fleet-device-preview="tile"]');
|
|
1191
|
-
assert.ok(otherBoardPatchPreview);
|
|
1192
|
-
assert.ok(
|
|
1193
|
-
diagnostics.webSocketConnections.length > wsCountBeforeRerender,
|
|
1194
|
-
'a different-board MDM must own a separate Mode 4 Atlas session');
|
|
1195
|
-
assert.ok(diagnostics.runtimeTrace.some(event =>
|
|
1196
|
-
event.type === 'remote.atlas.wsOpen'
|
|
1197
|
-
&& event.nodeId === otherBoardNodeId));
|
|
1198
|
-
otherBoardShell.remove();
|
|
1199
|
-
|
|
1200
1049
|
const controlCard = bodyView.querySelector(`article[data-device-id="${patchTarget.DeviceId}"]`);
|
|
1201
1050
|
assert.ok(controlCard);
|
|
1202
1051
|
controlCard.dispatchEvent({ type: 'dblclick', button: 0 });
|
|
1203
1052
|
await wait(30);
|
|
1204
1053
|
assert.equal(document.body.querySelector('[data-remote-fleet-control-popup="true"]'), null);
|
|
1205
|
-
const addControlNodeCall = dotNetCalls.find(call =>
|
|
1206
|
-
|
|
1207
|
-
&& call.args[0] === 'remote-fleet-render-smoke'
|
|
1208
|
-
&& call.args[1] === patchTarget.DeviceId);
|
|
1209
|
-
assert.ok(addControlNodeCall, 'double-clicking an MDM tile should create a remote-control canvas node');
|
|
1054
|
+
const addControlNodeCall = dotNetCalls.find(call => call.methodName === 'AddRemoteFleetDeviceNodeFromJs');
|
|
1055
|
+
assert.equal(addControlNodeCall, undefined, 'MDM thumbnails must not create an expanded device node');
|
|
1210
1056
|
|
|
1211
1057
|
const alternateDevice = devices.find(device =>
|
|
1212
1058
|
device.Connected === true
|
|
@@ -1222,10 +1068,20 @@ try {
|
|
|
1222
1068
|
assert.equal(selectedAfterClick?.querySelector('[data-remote-fleet-selected-indicator="true"]'), null);
|
|
1223
1069
|
const livePanel = bodyView.querySelector('[data-remote-fleet-live-panel="true"]');
|
|
1224
1070
|
assert.equal(livePanel, null);
|
|
1225
|
-
assert.
|
|
1226
|
-
assert.
|
|
1227
|
-
assert.
|
|
1228
|
-
assert.
|
|
1071
|
+
assert.ok(bodyView.querySelector('[data-remote-fleet-action="task-selected"]'));
|
|
1072
|
+
assert.ok(bodyView.querySelector('[data-remote-fleet-action="task-connected"]'));
|
|
1073
|
+
assert.ok(bodyView.querySelector('[data-remote-fleet-task-input="true"]'));
|
|
1074
|
+
assert.ok(bodyView.querySelector('[data-remote-fleet-ai-toggle="true"]'));
|
|
1075
|
+
const selectedTaskInput = bodyView.querySelector('[data-remote-fleet-task-input="true"]');
|
|
1076
|
+
const selectedTaskButton = bodyView.querySelector('[data-remote-fleet-action="task-selected"]');
|
|
1077
|
+
selectedTaskInput.value = 'Inspect Git status and report the result.';
|
|
1078
|
+
selectedTaskButton.dispatchEvent({ type: 'click' });
|
|
1079
|
+
await wait(20);
|
|
1080
|
+
const selectedTaskCall = dotNetCalls.find(call =>
|
|
1081
|
+
call.methodName === 'DispatchRemoteFleetTaskFromJs'
|
|
1082
|
+
&& call.args[0] === 'remote-fleet-render-smoke'
|
|
1083
|
+
&& call.args[1] === alternateDevice.DeviceId);
|
|
1084
|
+
assert.ok(selectedTaskCall, 'selected thumbnail must target its agent command');
|
|
1229
1085
|
assert.equal(bodyView.textContent.includes('all devices, no paging'), false);
|
|
1230
1086
|
assert.equal(bodyView.textContent.includes('Host: Inactive'), false);
|
|
1231
1087
|
assert.equal(bodyView.textContent.includes('No screen'), false);
|
|
@@ -1276,40 +1132,29 @@ try {
|
|
|
1276
1132
|
assert.equal(bodyView.querySelector('[data-remote-fleet-action="copy-command"]'), null);
|
|
1277
1133
|
assert.equal(bodyView.querySelector('[data-remote-fleet-action="refresh"]'), null);
|
|
1278
1134
|
assert.equal(bodyView.querySelector('[data-remote-fleet-auto-toggle="true"]'), null);
|
|
1279
|
-
assert.equal(bodyView.textContent.includes('synthetic-render-ai'),
|
|
1280
|
-
assert.equal(bodyView.textContent.includes('Task timed out waiting for the agent response.'),
|
|
1135
|
+
assert.equal(bodyView.textContent.includes('synthetic-render-ai'), true);
|
|
1136
|
+
assert.equal(bodyView.textContent.includes('Task timed out waiting for the agent response.'), true);
|
|
1281
1137
|
const batchSummary = bodyView.querySelector('[data-remote-fleet-task-batch="true"]');
|
|
1282
|
-
assert.
|
|
1138
|
+
assert.ok(batchSummary);
|
|
1283
1139
|
const batchHistory = bodyView.querySelector('[data-remote-fleet-task-history="true"]');
|
|
1284
|
-
assert.
|
|
1140
|
+
assert.ok(batchHistory);
|
|
1285
1141
|
const resultPanel = bodyView.querySelector('[data-remote-fleet-task-results="true"]');
|
|
1286
|
-
assert.
|
|
1142
|
+
assert.ok(resultPanel);
|
|
1287
1143
|
assert.ok(devices.some(device => /^synthetic-response-/.test(device.LatestTaskResultResponseId)));
|
|
1288
1144
|
await wait(20);
|
|
1289
1145
|
const liveStartCalls = dotNetCalls
|
|
1290
1146
|
.filter(call => call.methodName === 'StartRemoteFleetLiveStreamFromJs');
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
.
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
assert.ok(diagnostics.fetchCalls.some(call => call.url.includes('/api/status?remoteFrames=ws')));
|
|
1303
|
-
assert.ok(diagnostics.webSocketConnections.length >= 1, 'expected MDM render to open Mode 4 Atlas WebSocket');
|
|
1304
|
-
assert.ok(atlasConfigure, 'expected MDM render to configure the Mode 4 Atlas WebSocket');
|
|
1305
|
-
assert.equal(atlasConfigure.fps, 20);
|
|
1306
|
-
assert.equal(atlasConfigure.width, 1920);
|
|
1307
|
-
assert.equal(atlasConfigure.height, 1080);
|
|
1308
|
-
assert.equal(atlasConfigure.tileWidth, 320);
|
|
1309
|
-
assert.equal(atlasConfigure.tileHeight, 180);
|
|
1310
|
-
assert.ok(atlasConfigure.deviceIds.length > 1, 'expected visible connected devices in Atlas configuration');
|
|
1311
|
-
assert.ok(diagnostics.runtimeTrace.some(event => event.type === 'remote.live.wsAutoStartRequested'));
|
|
1312
|
-
assert.equal(liveStartCalls.length, 0, 'WebSocket live path must not call DotNet live-start fallback');
|
|
1147
|
+
assert.equal(liveStartCalls.length, 0, 'thumbnail-only MDM must not start live streams');
|
|
1148
|
+
assert.equal(
|
|
1149
|
+
diagnostics.webSocketConnections.some(connection =>
|
|
1150
|
+
String(connection?.url || '').includes('/api/remote/atlas/ws')
|
|
1151
|
+
|| String(connection?.url || '').includes('/api/remote/frames/ws')),
|
|
1152
|
+
false,
|
|
1153
|
+
'thumbnail-only MDM must not open live frame WebSockets');
|
|
1154
|
+
assert.equal(
|
|
1155
|
+
diagnostics.fetchCalls.some(call => call.url.includes('/api/status?remoteFrames=ws')),
|
|
1156
|
+
false,
|
|
1157
|
+
'thumbnail-only MDM must not initialize live-frame transport');
|
|
1313
1158
|
await wait(320);
|
|
1314
1159
|
assert.ok(dotNetCalls.some(call => call.methodName === 'RefreshRemoteFleetMonitorNodeFromJs'));
|
|
1315
1160
|
assert.equal(bodyView.dataset.remoteFleetTaskFollowKey, 'render-smoke-batch');
|
|
@@ -1318,10 +1163,10 @@ try {
|
|
|
1318
1163
|
const feedback = bodyView.querySelector('[data-remote-fleet-task-feedback="true"]');
|
|
1319
1164
|
assert.ok(feedback);
|
|
1320
1165
|
|
|
1321
|
-
assert.
|
|
1322
|
-
assert.
|
|
1323
|
-
call.methodName === '
|
|
1324
|
-
|
|
1166
|
+
assert.ok(bodyView.querySelector('[data-remote-fleet-ai-toggle="true"]'));
|
|
1167
|
+
assert.ok(dotNetCalls.some(call =>
|
|
1168
|
+
call.methodName === 'DispatchRemoteFleetTaskFromJs'
|
|
1169
|
+
&& call.args[1] === alternateDevice.DeviceId));
|
|
1325
1170
|
|
|
1326
1171
|
const { nodeShell: emptyShell, bodyView: emptyBody } = createRemoteFleetTemplateShell(document);
|
|
1327
1172
|
document.body.appendChild(emptyShell);
|
|
@@ -1409,12 +1254,12 @@ try {
|
|
|
1409
1254
|
&& message.type === 'subscribe'
|
|
1410
1255
|
&& message.nodeId === 'remote-device-render-smoke'
|
|
1411
1256
|
&& message.autoStartLive === true
|
|
1412
|
-
&& message.fps ===
|
|
1413
|
-
&& message.mode === '
|
|
1414
|
-
&& message.streamPurpose === '
|
|
1257
|
+
&& message.fps === 2
|
|
1258
|
+
&& message.mode === 'mode2-lzo'
|
|
1259
|
+
&& message.streamPurpose === 'wall'
|
|
1415
1260
|
&& Array.isArray(message.deviceIds)
|
|
1416
1261
|
&& message.deviceIds.includes(focusedDevice.DeviceId));
|
|
1417
|
-
assert.ok(deviceControlSubscribe, '
|
|
1262
|
+
assert.ok(deviceControlSubscribe, 'Remote workstation should subscribe to a 2fps view-only observation stream');
|
|
1418
1263
|
const deviceControlWs = diagnostics.webSocketConnections
|
|
1419
1264
|
.filter(ws => ws.url.includes('/api/remote/frames/ws'))
|
|
1420
1265
|
.at(-1);
|
|
@@ -1469,36 +1314,12 @@ try {
|
|
|
1469
1314
|
});
|
|
1470
1315
|
await wait(50);
|
|
1471
1316
|
const inputWsSends = diagnostics.webSocketSends
|
|
1472
|
-
.filter(send => send.url.includes('/api/remote/input/ws'))
|
|
1473
|
-
|
|
1474
|
-
try {
|
|
1475
|
-
return JSON.parse(send.payload);
|
|
1476
|
-
} catch {
|
|
1477
|
-
return null;
|
|
1478
|
-
}
|
|
1479
|
-
})
|
|
1480
|
-
.filter(Boolean);
|
|
1481
|
-
assert.ok(inputWsSends.length >= 3, 'RemoteFleetDevice node should send pointer and keyboard input over the input WebSocket');
|
|
1482
|
-
const pointerDown = inputWsSends.find(message => message.input?.type === 'pointerDown');
|
|
1483
|
-
const keyDown = inputWsSends.find(message => message.input?.type === 'keyDown');
|
|
1484
|
-
const keyUp = inputWsSends.find(message => message.input?.type === 'keyUp');
|
|
1485
|
-
assert.ok(pointerDown);
|
|
1486
|
-
assert.ok(keyDown);
|
|
1487
|
-
assert.ok(keyUp);
|
|
1488
|
-
assert.equal(pointerDown.nodeId, 'remote-device-render-smoke');
|
|
1489
|
-
assert.equal(pointerDown.deviceId, focusedDevice.DeviceId);
|
|
1490
|
-
assert.equal(pointerDown.input.button, 'left');
|
|
1491
|
-
assert.ok(pointerDown.input.controlLeaseId);
|
|
1492
|
-
assert.ok(pointerDown.input.normalizedX >= 0 && pointerDown.input.normalizedX <= 1);
|
|
1493
|
-
assert.ok(pointerDown.input.normalizedY >= 0 && pointerDown.input.normalizedY <= 1);
|
|
1494
|
-
assert.equal(keyDown.input.key, 'A');
|
|
1495
|
-
assert.equal(keyDown.input.code, 'KeyA');
|
|
1496
|
-
assert.equal(keyUp.input.key, 'A');
|
|
1497
|
-
assert.equal(keyUp.input.code, 'KeyA');
|
|
1317
|
+
.filter(send => send.url.includes('/api/remote/input/ws'));
|
|
1318
|
+
assert.equal(inputWsSends.length, 0, 'Remote workstation must remain view-only and send no pointer or keyboard input');
|
|
1498
1319
|
assert.equal(
|
|
1499
1320
|
dotNetCalls.filter(call => call.methodName === 'SendRemoteFleetInputFromJs').length,
|
|
1500
1321
|
0,
|
|
1501
|
-
'
|
|
1322
|
+
'View-only workstation must not use the DotNet input fallback');
|
|
1502
1323
|
assert.ok(deviceBody.querySelector('[data-remote-fleet-action="refresh-device"]'));
|
|
1503
1324
|
assert.ok(deviceBody.querySelector('[data-remote-fleet-action="task-device"]'));
|
|
1504
1325
|
assert.ok(deviceBody.textContent.includes('Task timed out waiting for the agent response.'));
|