@mindexec/cli 0.2.152 → 0.2.154
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/scripts/remote-fleet-render-smoke.mjs +131 -102
- package/scripts/remote-input-ws-smoke.mjs +263 -0
- package/server.js +249 -0
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-css3d-manager.js +567 -94
- package/wwwroot/_framework/{MindExecution.Plugins.Concept.5gltgdqyo3.dll → MindExecution.Plugins.Concept.4ncya2e794.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.PlanMaster.cn6ppe6qoz.dll → MindExecution.Plugins.PlanMaster.0yfii1nh3p.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.YouTube.d7nnsxrftv.dll → MindExecution.Plugins.YouTube.y4vxx807fo.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Shared.mnpwk5h86c.dll → MindExecution.Shared.50ptsgk9eg.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Web.ygql0sg6b3.dll → MindExecution.Web.hztii75ar1.dll} +0 -0
- package/wwwroot/_framework/blazor.boot.json +11 -11
- package/wwwroot/service-worker-assets.js +13 -13
- package/wwwroot/service-worker.js +1 -1
package/server.js
CHANGED
|
@@ -2125,10 +2125,13 @@ app.get('/api/local-files/:id', async (req, res) => {
|
|
|
2125
2125
|
const httpServer = createServer(app);
|
|
2126
2126
|
const wss = new WebSocketServer({ noServer: true });
|
|
2127
2127
|
const remoteFrameWss = new WebSocketServer({ noServer: true });
|
|
2128
|
+
const remoteInputWss = new WebSocketServer({ noServer: true });
|
|
2128
2129
|
const wsClients = new Set();
|
|
2129
2130
|
const remoteFrameClients = new Set();
|
|
2131
|
+
const remoteInputClients = new Set();
|
|
2130
2132
|
const shellJobs = new Map();
|
|
2131
2133
|
let remoteFrameClientSeq = 0;
|
|
2134
|
+
let remoteInputClientSeq = 0;
|
|
2132
2135
|
const remoteFrameWsDiagnostics = {
|
|
2133
2136
|
opened: 0,
|
|
2134
2137
|
closed: 0,
|
|
@@ -2157,6 +2160,25 @@ const remoteFrameWsDiagnostics = {
|
|
|
2157
2160
|
lastAutoStartStarted: 0,
|
|
2158
2161
|
lastAutoStartSkipped: 0
|
|
2159
2162
|
};
|
|
2163
|
+
const remoteInputWsDiagnostics = {
|
|
2164
|
+
opened: 0,
|
|
2165
|
+
closed: 0,
|
|
2166
|
+
errors: 0,
|
|
2167
|
+
messagesReceived: 0,
|
|
2168
|
+
messagesInvalid: 0,
|
|
2169
|
+
inputsQueued: 0,
|
|
2170
|
+
inputsFailed: 0,
|
|
2171
|
+
pointerMovesQueued: 0,
|
|
2172
|
+
keyEventsQueued: 0,
|
|
2173
|
+
lastOpenAt: '',
|
|
2174
|
+
lastCloseAt: '',
|
|
2175
|
+
lastErrorAt: '',
|
|
2176
|
+
lastInputAt: '',
|
|
2177
|
+
lastDeviceId: '',
|
|
2178
|
+
lastInputType: '',
|
|
2179
|
+
lastCommandId: '',
|
|
2180
|
+
lastError: ''
|
|
2181
|
+
};
|
|
2160
2182
|
const REMOTE_FRAME_WS_AUTO_START_LIMIT = 120;
|
|
2161
2183
|
const REMOTE_FRAME_WS_DEFAULT_FPS = 12;
|
|
2162
2184
|
const REMOTE_FRAME_WS_DEFAULT_MAX_WIDTH = 960;
|
|
@@ -2183,6 +2205,14 @@ httpServer.on('upgrade', (req, socket, head) => {
|
|
|
2183
2205
|
return;
|
|
2184
2206
|
}
|
|
2185
2207
|
|
|
2208
|
+
if (parsed.pathname === '/api/remote/input/ws'
|
|
2209
|
+
&& (!bridgeAuthRequired || token === bridgeToken)) {
|
|
2210
|
+
remoteInputWss.handleUpgrade(req, socket, head, (ws) => {
|
|
2211
|
+
remoteInputWss.emit('connection', ws, req);
|
|
2212
|
+
});
|
|
2213
|
+
return;
|
|
2214
|
+
}
|
|
2215
|
+
|
|
2186
2216
|
{
|
|
2187
2217
|
socket.write('HTTP/1.1 401 Unauthorized\r\n\r\n');
|
|
2188
2218
|
socket.destroy();
|
|
@@ -2552,6 +2582,195 @@ remoteFrameWss.on('connection', (ws, req) => {
|
|
|
2552
2582
|
});
|
|
2553
2583
|
});
|
|
2554
2584
|
|
|
2585
|
+
function sendRemoteInputClientJson(ws, payload) {
|
|
2586
|
+
if (!ws || ws.readyState !== WebSocket.OPEN) {
|
|
2587
|
+
return false;
|
|
2588
|
+
}
|
|
2589
|
+
|
|
2590
|
+
try {
|
|
2591
|
+
ws.send(JSON.stringify(payload));
|
|
2592
|
+
return true;
|
|
2593
|
+
} catch {
|
|
2594
|
+
return false;
|
|
2595
|
+
}
|
|
2596
|
+
}
|
|
2597
|
+
|
|
2598
|
+
function normalizeRemoteInputWsPayload(payload = {}) {
|
|
2599
|
+
const outer = payload && typeof payload === 'object' ? payload : {};
|
|
2600
|
+
const inputSource = outer.input && typeof outer.input === 'object'
|
|
2601
|
+
? outer.input
|
|
2602
|
+
: outer.Input && typeof outer.Input === 'object'
|
|
2603
|
+
? outer.Input
|
|
2604
|
+
: outer;
|
|
2605
|
+
const input = { ...inputSource };
|
|
2606
|
+
input.type = String(input.type ?? input.Type ?? '').trim();
|
|
2607
|
+
const deviceId = String(
|
|
2608
|
+
outer.deviceId
|
|
2609
|
+
?? outer.DeviceId
|
|
2610
|
+
?? input.deviceId
|
|
2611
|
+
?? input.DeviceId
|
|
2612
|
+
?? ''
|
|
2613
|
+
).trim();
|
|
2614
|
+
delete input.deviceId;
|
|
2615
|
+
delete input.DeviceId;
|
|
2616
|
+
|
|
2617
|
+
return {
|
|
2618
|
+
deviceId,
|
|
2619
|
+
input,
|
|
2620
|
+
requestId: String(outer.requestId ?? outer.RequestId ?? '').trim(),
|
|
2621
|
+
ack: outer.ack === true || outer.Ack === true
|
|
2622
|
+
};
|
|
2623
|
+
}
|
|
2624
|
+
|
|
2625
|
+
function serializeRemoteInputWsDiagnostics() {
|
|
2626
|
+
const clients = [];
|
|
2627
|
+
for (const client of remoteInputClients) {
|
|
2628
|
+
clients.push({
|
|
2629
|
+
id: client.remoteInputClientId || '',
|
|
2630
|
+
readyState: client.readyState,
|
|
2631
|
+
connectedAt: client.remoteInputConnectedAt || '',
|
|
2632
|
+
received: Number(client.remoteInputReceivedCount || 0),
|
|
2633
|
+
queued: Number(client.remoteInputQueuedCount || 0),
|
|
2634
|
+
failed: Number(client.remoteInputFailedCount || 0),
|
|
2635
|
+
bufferedAmount: Number(client.bufferedAmount || 0),
|
|
2636
|
+
lastInputAt: client.remoteInputLastInputAt || '',
|
|
2637
|
+
lastDeviceId: client.remoteInputLastDeviceId || '',
|
|
2638
|
+
lastInputType: client.remoteInputLastInputType || ''
|
|
2639
|
+
});
|
|
2640
|
+
}
|
|
2641
|
+
|
|
2642
|
+
return {
|
|
2643
|
+
protocol: 'mindexec.remote.input.json.v1',
|
|
2644
|
+
path: '/api/remote/input/ws',
|
|
2645
|
+
clientCount: remoteInputClients.size,
|
|
2646
|
+
...remoteInputWsDiagnostics,
|
|
2647
|
+
clients
|
|
2648
|
+
};
|
|
2649
|
+
}
|
|
2650
|
+
|
|
2651
|
+
remoteInputWss.on('connection', (ws) => {
|
|
2652
|
+
remoteInputClients.add(ws);
|
|
2653
|
+
ws.remoteInputClientId = `riws-${++remoteInputClientSeq}`;
|
|
2654
|
+
ws.remoteInputConnectedAt = new Date().toISOString();
|
|
2655
|
+
ws.remoteInputReceivedCount = 0;
|
|
2656
|
+
ws.remoteInputQueuedCount = 0;
|
|
2657
|
+
ws.remoteInputFailedCount = 0;
|
|
2658
|
+
remoteInputWsDiagnostics.opened += 1;
|
|
2659
|
+
remoteInputWsDiagnostics.lastOpenAt = ws.remoteInputConnectedAt;
|
|
2660
|
+
|
|
2661
|
+
ws.on('message', data => {
|
|
2662
|
+
const receivedAt = new Date().toISOString();
|
|
2663
|
+
remoteInputWsDiagnostics.messagesReceived += 1;
|
|
2664
|
+
ws.remoteInputReceivedCount = (ws.remoteInputReceivedCount || 0) + 1;
|
|
2665
|
+
|
|
2666
|
+
let payload = null;
|
|
2667
|
+
try {
|
|
2668
|
+
const text = Buffer.isBuffer(data) ? data.toString('utf8') : String(data || '');
|
|
2669
|
+
payload = JSON.parse(text);
|
|
2670
|
+
} catch {
|
|
2671
|
+
remoteInputWsDiagnostics.messagesInvalid += 1;
|
|
2672
|
+
sendRemoteInputClientJson(ws, {
|
|
2673
|
+
type: 'RemoteInputError',
|
|
2674
|
+
timestamp: receivedAt,
|
|
2675
|
+
error: 'invalid-json'
|
|
2676
|
+
});
|
|
2677
|
+
return;
|
|
2678
|
+
}
|
|
2679
|
+
|
|
2680
|
+
const messageType = String(payload?.type || payload?.Type || '').trim().toLowerCase();
|
|
2681
|
+
if (messageType === 'ping') {
|
|
2682
|
+
sendRemoteInputClientJson(ws, {
|
|
2683
|
+
type: 'RemoteInputPong',
|
|
2684
|
+
timestamp: receivedAt
|
|
2685
|
+
});
|
|
2686
|
+
return;
|
|
2687
|
+
}
|
|
2688
|
+
|
|
2689
|
+
if (messageType !== 'input' && messageType !== 'remote.input') {
|
|
2690
|
+
remoteInputWsDiagnostics.messagesInvalid += 1;
|
|
2691
|
+
sendRemoteInputClientJson(ws, {
|
|
2692
|
+
type: 'RemoteInputError',
|
|
2693
|
+
timestamp: receivedAt,
|
|
2694
|
+
error: 'unsupported-message'
|
|
2695
|
+
});
|
|
2696
|
+
return;
|
|
2697
|
+
}
|
|
2698
|
+
|
|
2699
|
+
const normalized = normalizeRemoteInputWsPayload(payload);
|
|
2700
|
+
if (!normalized.deviceId || !normalized.input.type) {
|
|
2701
|
+
remoteInputWsDiagnostics.messagesInvalid += 1;
|
|
2702
|
+
sendRemoteInputClientJson(ws, {
|
|
2703
|
+
type: 'RemoteInputResult',
|
|
2704
|
+
timestamp: receivedAt,
|
|
2705
|
+
ok: false,
|
|
2706
|
+
requestId: normalized.requestId,
|
|
2707
|
+
deviceId: normalized.deviceId,
|
|
2708
|
+
inputType: normalized.input.type,
|
|
2709
|
+
error: !normalized.deviceId ? 'missing-device-id' : 'missing-input-type'
|
|
2710
|
+
});
|
|
2711
|
+
return;
|
|
2712
|
+
}
|
|
2713
|
+
|
|
2714
|
+
const result = remoteHub.sendInputControl(normalized.deviceId, normalized.input);
|
|
2715
|
+
const ok = result?.ok === true;
|
|
2716
|
+
const inputType = String(normalized.input.type || '').trim();
|
|
2717
|
+
remoteInputWsDiagnostics.lastInputAt = receivedAt;
|
|
2718
|
+
remoteInputWsDiagnostics.lastDeviceId = normalized.deviceId;
|
|
2719
|
+
remoteInputWsDiagnostics.lastInputType = inputType;
|
|
2720
|
+
remoteInputWsDiagnostics.lastCommandId = String(result?.commandId || '');
|
|
2721
|
+
ws.remoteInputLastInputAt = receivedAt;
|
|
2722
|
+
ws.remoteInputLastDeviceId = normalized.deviceId;
|
|
2723
|
+
ws.remoteInputLastInputType = inputType;
|
|
2724
|
+
|
|
2725
|
+
if (ok) {
|
|
2726
|
+
remoteInputWsDiagnostics.inputsQueued += 1;
|
|
2727
|
+
ws.remoteInputQueuedCount = (ws.remoteInputQueuedCount || 0) + 1;
|
|
2728
|
+
if (/^pointermove$/i.test(inputType)) {
|
|
2729
|
+
remoteInputWsDiagnostics.pointerMovesQueued += 1;
|
|
2730
|
+
}
|
|
2731
|
+
if (/^key(up|down)$/i.test(inputType)) {
|
|
2732
|
+
remoteInputWsDiagnostics.keyEventsQueued += 1;
|
|
2733
|
+
}
|
|
2734
|
+
} else {
|
|
2735
|
+
remoteInputWsDiagnostics.inputsFailed += 1;
|
|
2736
|
+
remoteInputWsDiagnostics.lastError = String(result?.error || 'input-failed');
|
|
2737
|
+
ws.remoteInputFailedCount = (ws.remoteInputFailedCount || 0) + 1;
|
|
2738
|
+
}
|
|
2739
|
+
|
|
2740
|
+
const shouldAck = normalized.ack === true || !ok || !/^pointermove$/i.test(inputType);
|
|
2741
|
+
if (shouldAck) {
|
|
2742
|
+
sendRemoteInputClientJson(ws, {
|
|
2743
|
+
type: 'RemoteInputResult',
|
|
2744
|
+
timestamp: receivedAt,
|
|
2745
|
+
ok,
|
|
2746
|
+
requestId: normalized.requestId,
|
|
2747
|
+
deviceId: normalized.deviceId,
|
|
2748
|
+
inputType,
|
|
2749
|
+
commandId: result?.commandId || '',
|
|
2750
|
+
error: result?.error || ''
|
|
2751
|
+
});
|
|
2752
|
+
}
|
|
2753
|
+
});
|
|
2754
|
+
|
|
2755
|
+
ws.on('close', () => {
|
|
2756
|
+
remoteInputClients.delete(ws);
|
|
2757
|
+
remoteInputWsDiagnostics.closed += 1;
|
|
2758
|
+
remoteInputWsDiagnostics.lastCloseAt = new Date().toISOString();
|
|
2759
|
+
});
|
|
2760
|
+
ws.on('error', error => {
|
|
2761
|
+
remoteInputClients.delete(ws);
|
|
2762
|
+
remoteInputWsDiagnostics.errors += 1;
|
|
2763
|
+
remoteInputWsDiagnostics.lastErrorAt = new Date().toISOString();
|
|
2764
|
+
remoteInputWsDiagnostics.lastError = String(error?.message || error || 'input-ws-error');
|
|
2765
|
+
});
|
|
2766
|
+
sendRemoteInputClientJson(ws, {
|
|
2767
|
+
type: 'RemoteInputSocketReady',
|
|
2768
|
+
timestamp: new Date().toISOString(),
|
|
2769
|
+
protocol: 'mindexec.remote.input.json.v1',
|
|
2770
|
+
clientId: ws.remoteInputClientId
|
|
2771
|
+
});
|
|
2772
|
+
});
|
|
2773
|
+
|
|
2555
2774
|
// Helper: Validate path is within workspace
|
|
2556
2775
|
function validatePath(requestedPath) {
|
|
2557
2776
|
const fullPath = resolveWorkspaceBoundPath(requestedPath);
|
|
@@ -10279,11 +10498,13 @@ app.get('/api/status', async (req, res) => {
|
|
|
10279
10498
|
wsToken,
|
|
10280
10499
|
wsPath: '/events',
|
|
10281
10500
|
remoteFrameWsPath: '/api/remote/frames/ws',
|
|
10501
|
+
remoteInputWsPath: '/api/remote/input/ws',
|
|
10282
10502
|
bridgeToken,
|
|
10283
10503
|
bridgeTokenHeader,
|
|
10284
10504
|
bridgeAuthRequired,
|
|
10285
10505
|
remoteHub: remoteHub.getStatus({ includeSecrets: false }),
|
|
10286
10506
|
remoteFrameWs: serializeRemoteFrameWsDiagnostics(),
|
|
10507
|
+
remoteInputWs: serializeRemoteInputWsDiagnostics(),
|
|
10287
10508
|
remoteAgent: serializeRemoteAgentState(),
|
|
10288
10509
|
remoteRegistryFollower: serializeRemoteRegistryFollowerState(),
|
|
10289
10510
|
remoteRegistryRealtime: serializeRemoteRegistryRealtimeState(),
|
|
@@ -12127,6 +12348,34 @@ async function shutdownBridge(signal) {
|
|
|
12127
12348
|
// Ignore if already closed
|
|
12128
12349
|
}
|
|
12129
12350
|
|
|
12351
|
+
for (const client of remoteFrameClients) {
|
|
12352
|
+
try {
|
|
12353
|
+
client.close();
|
|
12354
|
+
} catch {
|
|
12355
|
+
// Ignore close race
|
|
12356
|
+
}
|
|
12357
|
+
}
|
|
12358
|
+
|
|
12359
|
+
for (const client of remoteInputClients) {
|
|
12360
|
+
try {
|
|
12361
|
+
client.close();
|
|
12362
|
+
} catch {
|
|
12363
|
+
// Ignore close race
|
|
12364
|
+
}
|
|
12365
|
+
}
|
|
12366
|
+
|
|
12367
|
+
try {
|
|
12368
|
+
remoteFrameWss.close();
|
|
12369
|
+
} catch {
|
|
12370
|
+
// Ignore if already closed
|
|
12371
|
+
}
|
|
12372
|
+
|
|
12373
|
+
try {
|
|
12374
|
+
remoteInputWss.close();
|
|
12375
|
+
} catch {
|
|
12376
|
+
// Ignore if already closed
|
|
12377
|
+
}
|
|
12378
|
+
|
|
12130
12379
|
try {
|
|
12131
12380
|
stopRemoteRegistryFollower();
|
|
12132
12381
|
} catch {
|