@mindexec/cli 0.2.23 → 0.2.25
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 +1 -1
- package/remote-hub.js +134 -1
- package/scripts/remote-fleet-render-smoke.mjs +87 -53
- package/scripts/remote-http-smoke.mjs +219 -39
- package/scripts/remote-hub-smoke.mjs +139 -0
- package/server.js +20 -1
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-core.js +18 -1
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-css3d-manager.js +670 -395
- package/wwwroot/_framework/{Microsoft.CSharp.qrvp77qmhs.dll → Microsoft.CSharp.8bsm8vx6su.dll} +0 -0
- package/wwwroot/_framework/MindExecution.Core.6rfnfdndxq.dll +0 -0
- package/wwwroot/_framework/{MindExecution.Kernel.badrt1tkvv.dll → MindExecution.Kernel.z56elxihok.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.Admin.73w1bvz4r1.dll → MindExecution.Plugins.Admin.p5cs4ap87v.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.Business.dvd82y422m.dll → MindExecution.Plugins.Business.s35og5uz44.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.Concept.m3ukc0xvom.dll → MindExecution.Plugins.Concept.zczca3fsxz.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.Directory.23tm2uvfvu.dll → MindExecution.Plugins.Directory.y74f55e8x3.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.PlanMaster.8nrc7ge4ob.dll → MindExecution.Plugins.PlanMaster.jpdwbefrh1.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.YouTube.3ox59073d8.dll → MindExecution.Plugins.YouTube.8nz4wv2nsj.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Shared.va1gxp0crd.dll → MindExecution.Shared.v6ani8nfp8.dll} +0 -0
- package/wwwroot/_framework/MindExecution.Web.0cs29v57jl.dll +0 -0
- package/wwwroot/_framework/{System.Collections.x53e19vfsj.dll → System.Collections.23yxgetbju.dll} +0 -0
- package/wwwroot/_framework/{System.Collections.Concurrent.y1zmvuyipi.dll → System.Collections.Concurrent.vow3rm1dku.dll} +0 -0
- package/wwwroot/_framework/{System.Collections.Immutable.ug3j698qms.dll → System.Collections.Immutable.ap9596utv5.dll} +0 -0
- package/wwwroot/_framework/{System.Collections.NonGeneric.h66hj3863h.dll → System.Collections.NonGeneric.npjkaz40oc.dll} +0 -0
- package/wwwroot/_framework/{System.Collections.Specialized.umr3y27ntj.dll → System.Collections.Specialized.ugkjbs6p02.dll} +0 -0
- package/wwwroot/_framework/{System.ComponentModel.Annotations.tz6gnt4ebt.dll → System.ComponentModel.Annotations.clwo0z2oyu.dll} +0 -0
- package/wwwroot/_framework/{System.ComponentModel.Primitives.j7tiphu4rg.dll → System.ComponentModel.Primitives.end4v0xe2c.dll} +0 -0
- package/wwwroot/_framework/{System.ComponentModel.TypeConverter.ujlztox1gx.dll → System.ComponentModel.TypeConverter.tgtp5sm4iv.dll} +0 -0
- package/wwwroot/_framework/{System.ComponentModel.x9xz0ojfb6.dll → System.ComponentModel.wupoltkk1t.dll} +0 -0
- package/wwwroot/_framework/{System.Console.ijzpqmj7ne.dll → System.Console.9dik0wogo2.dll} +0 -0
- package/wwwroot/_framework/{System.Data.Common.1r0sqffq1p.dll → System.Data.Common.4v8jejsiu0.dll} +0 -0
- package/wwwroot/_framework/{System.Diagnostics.DiagnosticSource.9upoqwq09o.dll → System.Diagnostics.DiagnosticSource.e2q75ondtq.dll} +0 -0
- package/wwwroot/_framework/{System.Diagnostics.Process.m99azzntjm.dll → System.Diagnostics.Process.9736yjnxs8.dll} +0 -0
- package/wwwroot/_framework/{System.Diagnostics.TraceSource.pl7wv26myr.dll → System.Diagnostics.TraceSource.h9al53gbbw.dll} +0 -0
- package/wwwroot/_framework/{System.Diagnostics.Tracing.crlhfx6tut.dll → System.Diagnostics.Tracing.h4bcp2fo98.dll} +0 -0
- package/wwwroot/_framework/{System.Drawing.mi7d8hwowb.dll → System.Drawing.64oovy8qts.dll} +0 -0
- package/wwwroot/_framework/{System.Drawing.Primitives.22e4y9ikq9.dll → System.Drawing.Primitives.o6jiqpgbgl.dll} +0 -0
- package/wwwroot/_framework/{System.Formats.Asn1.jx23sjiqnn.dll → System.Formats.Asn1.rylx5ipd40.dll} +0 -0
- package/wwwroot/_framework/{System.IO.Compression.6fyoii3uej.dll → System.IO.Compression.iceabaupns.dll} +0 -0
- package/wwwroot/_framework/{System.IO.Pipelines.vg77t4cd4d.dll → System.IO.Pipelines.uw8csd3mlz.dll} +0 -0
- package/wwwroot/_framework/{System.Linq.Expressions.24xqiypwdt.dll → System.Linq.Expressions.ty95ava37f.dll} +0 -0
- package/wwwroot/_framework/{System.Linq.Queryable.hvd01d6rsa.dll → System.Linq.Queryable.hs2195jrwy.dll} +0 -0
- package/wwwroot/_framework/{System.Linq.1bkoxlqgmq.dll → System.Linq.hssodjwmlf.dll} +0 -0
- package/wwwroot/_framework/{System.Memory.8dx3lwgym4.dll → System.Memory.1k78n7wdxb.dll} +0 -0
- package/wwwroot/_framework/{System.Net.Http.eitrz660my.dll → System.Net.Http.3br8rfql4c.dll} +0 -0
- package/wwwroot/_framework/{System.Net.Http.Json.3mhdm9l1rf.dll → System.Net.Http.Json.860wbh17d8.dll} +0 -0
- package/wwwroot/_framework/{System.Net.NetworkInformation.3pkuofcv9r.dll → System.Net.NetworkInformation.e3wr00853o.dll} +0 -0
- package/wwwroot/_framework/{System.Net.Ping.8clj5pklrp.dll → System.Net.Ping.r5cw4mf1a4.dll} +0 -0
- package/wwwroot/_framework/{System.Net.Primitives.qrp4wcjz1p.dll → System.Net.Primitives.ksxwiwlvhu.dll} +0 -0
- package/wwwroot/_framework/{System.Net.WebSockets.qp6u31zvm5.dll → System.Net.WebSockets.6rt3n3gl2q.dll} +0 -0
- package/wwwroot/_framework/{System.Net.WebSockets.Client.2u6pv01g69.dll → System.Net.WebSockets.Client.z3usrzo7rz.dll} +0 -0
- package/wwwroot/_framework/{System.Numerics.Vectors.kc7ufp2j4l.dll → System.Numerics.Vectors.lbdzx8reja.dll} +0 -0
- package/wwwroot/_framework/{System.ObjectModel.qv82fot1ib.dll → System.ObjectModel.yct1gdirzf.dll} +0 -0
- package/wwwroot/_framework/{System.Private.CoreLib.rkafq04oma.dll → System.Private.CoreLib.ns29bor93l.dll} +0 -0
- package/wwwroot/_framework/{System.Private.Uri.t9542hmr6j.dll → System.Private.Uri.zp9kmg0z93.dll} +0 -0
- package/wwwroot/_framework/{System.Private.Xml.Linq.n8n3ptrbwu.dll → System.Private.Xml.Linq.lgv2n0akl4.dll} +0 -0
- package/wwwroot/_framework/{System.Private.Xml.rxd3tytisn.dll → System.Private.Xml.dpsk8g304y.dll} +0 -0
- package/wwwroot/_framework/{System.Reflection.Emit.ILGeneration.stxyk8zoo1.dll → System.Reflection.Emit.ILGeneration.1tcuz2cmbk.dll} +0 -0
- package/wwwroot/_framework/{System.Reflection.Emit.Lightweight.6xrd5v8vg0.dll → System.Reflection.Emit.Lightweight.ddt2wylovg.dll} +0 -0
- package/wwwroot/_framework/{System.Reflection.Emit.9tjhp6y0j3.dll → System.Reflection.Emit.d8vkadiwhg.dll} +0 -0
- package/wwwroot/_framework/{System.Reflection.Primitives.wgn8fpwwvv.dll → System.Reflection.Primitives.cpsl71xd1z.dll} +0 -0
- package/wwwroot/_framework/{System.Runtime.InteropServices.te07xr2we9.dll → System.Runtime.InteropServices.31vjgsfk1o.dll} +0 -0
- package/wwwroot/_framework/{System.Runtime.InteropServices.JavaScript.sliym526xh.dll → System.Runtime.InteropServices.JavaScript.pn2wvizzet.dll} +0 -0
- package/wwwroot/_framework/{System.Runtime.InteropServices.RuntimeInformation.oji7zut14z.dll → System.Runtime.InteropServices.RuntimeInformation.l5rk496q70.dll} +0 -0
- package/wwwroot/_framework/{System.Runtime.Intrinsics.507y4h8nzq.dll → System.Runtime.Intrinsics.0zee9qcqfy.dll} +0 -0
- package/wwwroot/_framework/{System.Runtime.Loader.v7gk4bse0k.dll → System.Runtime.Loader.xw2jr9wl92.dll} +0 -0
- package/wwwroot/_framework/{System.Runtime.Numerics.eqy5xjv3nd.dll → System.Runtime.Numerics.ezj1dfyvbj.dll} +0 -0
- package/wwwroot/_framework/{System.Runtime.Serialization.Formatters.zpkrub8lab.dll → System.Runtime.Serialization.Formatters.0y019e9zkr.dll} +0 -0
- package/wwwroot/_framework/{System.Runtime.Serialization.Primitives.vhkpnbxjip.dll → System.Runtime.Serialization.Primitives.bia5wb62c8.dll} +0 -0
- package/wwwroot/_framework/{System.Runtime.jn319d5nyg.dll → System.Runtime.h9cduidfkh.dll} +0 -0
- package/wwwroot/_framework/{System.Security.Claims.0ztig1q9vo.dll → System.Security.Claims.2r18wim2rl.dll} +0 -0
- package/wwwroot/_framework/{System.Security.Cryptography.vttizqc9ho.dll → System.Security.Cryptography.qqgybpoucx.dll} +0 -0
- package/wwwroot/_framework/{System.Text.Encoding.Extensions.utdd47ny8f.dll → System.Text.Encoding.Extensions.9t3hs6kyll.dll} +0 -0
- package/wwwroot/_framework/{System.Text.Encodings.Web.wah8r1zoe0.dll → System.Text.Encodings.Web.wftjfh2crk.dll} +0 -0
- package/wwwroot/_framework/{System.Text.Json.kxlfxj0wrs.dll → System.Text.Json.4s25e3op6i.dll} +0 -0
- package/wwwroot/_framework/{System.Text.RegularExpressions.dbqn58klox.dll → System.Text.RegularExpressions.cvkox11l6l.dll} +0 -0
- package/wwwroot/_framework/{System.Threading.Channels.hfa7j0uv2w.dll → System.Threading.Channels.419493szqu.dll} +0 -0
- package/wwwroot/_framework/{System.Threading.Thread.caul0pdqul.dll → System.Threading.Thread.xhmys87xh5.dll} +0 -0
- package/wwwroot/_framework/{System.Threading.42ao9vi047.dll → System.Threading.b66vzsz9g1.dll} +0 -0
- package/wwwroot/_framework/{System.Transactions.Local.fimi2hamzo.dll → System.Transactions.Local.7zfffdvnwf.dll} +0 -0
- package/wwwroot/_framework/{System.Web.HttpUtility.gq8yz50p2e.dll → System.Web.HttpUtility.9up6xfbtuq.dll} +0 -0
- package/wwwroot/_framework/{System.Xml.Linq.kitin4zjoj.dll → System.Xml.Linq.n5rzv9nbf7.dll} +0 -0
- package/wwwroot/_framework/{System.Xml.ReaderWriter.kzvw3qgxb0.dll → System.Xml.ReaderWriter.ag8pilllob.dll} +0 -0
- package/wwwroot/_framework/{System.Xml.XDocument.c539ki6cuq.dll → System.Xml.XDocument.sn51jas17n.dll} +0 -0
- package/wwwroot/_framework/{System.m05i39uvk9.dll → System.brmz7yk5qh.dll} +0 -0
- package/wwwroot/_framework/blazor.boot.json +161 -161
- package/wwwroot/_framework/dotnet.js +1 -1
- package/wwwroot/_framework/{dotnet.native.vz0adxojrz.wasm → dotnet.native.boem75ye5i.wasm} +0 -0
- package/wwwroot/_framework/{dotnet.native.xsn1d6x2kd.js → dotnet.native.qc8g39g30v.js} +1 -1
- package/wwwroot/_framework/{dotnet.runtime.dstopyvqzi.js → dotnet.runtime.opaiwunc3t.js} +1 -1
- package/wwwroot/_framework/{netstandard.0xet7jg7ky.dll → netstandard.yvr3prsx0x.dll} +0 -0
- package/wwwroot/index.html +1 -1
- package/wwwroot/service-worker-assets.js +166 -166
- package/wwwroot/service-worker.js +1 -1
- package/wwwroot/_framework/MindExecution.Core.c9fyqe953v.dll +0 -0
- package/wwwroot/_framework/MindExecution.Web.jmawk7z8d3.dll +0 -0
package/package.json
CHANGED
package/remote-hub.js
CHANGED
|
@@ -15,6 +15,7 @@ const RECENT_TASK_LIMIT = 12;
|
|
|
15
15
|
const RECENT_TASK_BATCH_LIMIT = 16;
|
|
16
16
|
const REMOTE_PROTOCOL_VERSION = 1;
|
|
17
17
|
const MAX_SYNTHETIC_DEVICES = 1000;
|
|
18
|
+
const DEFAULT_HOST_TARGET_LEASE_MS = 30000;
|
|
18
19
|
const SYNTHETIC_FRAME_DATA_URL = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAABCAYAAAD0In+KAAAADElEQVR42mP8z8AAAAMBAQDJ/pLvAAAAAElFTkSuQmCC';
|
|
19
20
|
|
|
20
21
|
function isEnabledValue(value, fallback = true) {
|
|
@@ -205,6 +206,8 @@ export function createRemoteHub(options = {}) {
|
|
|
205
206
|
50,
|
|
206
207
|
30 * 60 * 1000,
|
|
207
208
|
DEFAULT_AGENT_TASK_TIMEOUT_MS);
|
|
209
|
+
const managerPackage = safeString(options.managerPackage ?? env.MINDEXEC_MANAGER_PACKAGE ?? '@mindexec/cli', 128);
|
|
210
|
+
const managerVersion = safeString(options.managerVersion ?? env.MINDEXEC_MANAGER_VERSION ?? '', 64);
|
|
208
211
|
const pairToken = safeString(
|
|
209
212
|
env.REMOTE_HUB_PAIR_TOKEN || env.MINDEXEC_REMOTE_PAIR_TOKEN || crypto.randomBytes(6).toString('hex'),
|
|
210
213
|
256);
|
|
@@ -217,9 +220,129 @@ export function createRemoteHub(options = {}) {
|
|
|
217
220
|
let started = false;
|
|
218
221
|
let boundPort = requestedPort;
|
|
219
222
|
let lastError = '';
|
|
223
|
+
let hostTarget = null;
|
|
224
|
+
|
|
225
|
+
function getAgentEndpoint() {
|
|
226
|
+
return `${host}:${boundPort || requestedPort}`;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function getActiveHostTarget() {
|
|
230
|
+
if (!hostTarget) {
|
|
231
|
+
return null;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
const expiresMs = Date.parse(hostTarget.expiresAt || '');
|
|
235
|
+
if (Number.isFinite(expiresMs) && expiresMs <= Date.now()) {
|
|
236
|
+
const expiredTarget = hostTarget;
|
|
237
|
+
hostTarget = null;
|
|
238
|
+
emitRemoteEvent('RemoteHostTargetExpired', null, {
|
|
239
|
+
hostTarget: {
|
|
240
|
+
...expiredTarget,
|
|
241
|
+
active: false
|
|
242
|
+
}
|
|
243
|
+
});
|
|
244
|
+
return null;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
return hostTarget;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
function serializeHostTarget(target = getActiveHostTarget()) {
|
|
251
|
+
if (!target) {
|
|
252
|
+
return {
|
|
253
|
+
active: false,
|
|
254
|
+
nodeId: '',
|
|
255
|
+
leaseId: '',
|
|
256
|
+
endpoint: '',
|
|
257
|
+
activatedAt: '',
|
|
258
|
+
updatedAt: '',
|
|
259
|
+
expiresAt: ''
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
return {
|
|
264
|
+
active: true,
|
|
265
|
+
nodeId: target.nodeId,
|
|
266
|
+
leaseId: target.leaseId,
|
|
267
|
+
endpoint: target.endpoint,
|
|
268
|
+
activatedAt: target.activatedAt,
|
|
269
|
+
updatedAt: target.updatedAt,
|
|
270
|
+
expiresAt: target.expiresAt
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
function setHostTarget(options = {}) {
|
|
275
|
+
const enabled = options.enabled !== false;
|
|
276
|
+
const nodeId = safeString(options.nodeId, 128);
|
|
277
|
+
if (!enabled) {
|
|
278
|
+
const previous = getActiveHostTarget();
|
|
279
|
+
if (!previous) {
|
|
280
|
+
return {
|
|
281
|
+
ok: true,
|
|
282
|
+
active: false,
|
|
283
|
+
hostTarget: serializeHostTarget(null)
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
if (nodeId && previous.nodeId && nodeId !== previous.nodeId) {
|
|
288
|
+
return {
|
|
289
|
+
ok: false,
|
|
290
|
+
error: 'host-target-node-mismatch',
|
|
291
|
+
active: true,
|
|
292
|
+
hostTarget: serializeHostTarget(previous)
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
hostTarget = null;
|
|
297
|
+
emitRemoteEvent('RemoteHostTargetCleared', null, {
|
|
298
|
+
hostTarget: {
|
|
299
|
+
...serializeHostTarget(previous),
|
|
300
|
+
active: false
|
|
301
|
+
}
|
|
302
|
+
});
|
|
303
|
+
return {
|
|
304
|
+
ok: true,
|
|
305
|
+
active: false,
|
|
306
|
+
hostTarget: serializeHostTarget(null)
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
if (!nodeId) {
|
|
311
|
+
return {
|
|
312
|
+
ok: false,
|
|
313
|
+
error: 'missing-node-id',
|
|
314
|
+
active: false,
|
|
315
|
+
hostTarget: serializeHostTarget()
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
const now = new Date();
|
|
320
|
+
const leaseMs = clampNumber(options.leaseMs, 5000, 10 * 60 * 1000, DEFAULT_HOST_TARGET_LEASE_MS);
|
|
321
|
+
const previous = getActiveHostTarget();
|
|
322
|
+
const activeSameNode = previous?.nodeId === nodeId;
|
|
323
|
+
hostTarget = {
|
|
324
|
+
nodeId,
|
|
325
|
+
leaseId: activeSameNode && previous?.leaseId ? previous.leaseId : crypto.randomUUID(),
|
|
326
|
+
endpoint: getAgentEndpoint(),
|
|
327
|
+
activatedAt: activeSameNode && previous?.activatedAt ? previous.activatedAt : now.toISOString(),
|
|
328
|
+
updatedAt: now.toISOString(),
|
|
329
|
+
expiresAt: new Date(now.getTime() + leaseMs).toISOString()
|
|
330
|
+
};
|
|
331
|
+
|
|
332
|
+
emitRemoteEvent('RemoteHostTargetSet', null, {
|
|
333
|
+
hostTarget: serializeHostTarget(hostTarget),
|
|
334
|
+
replacedNodeId: previous && previous.nodeId !== nodeId ? previous.nodeId : ''
|
|
335
|
+
});
|
|
336
|
+
return {
|
|
337
|
+
ok: true,
|
|
338
|
+
active: true,
|
|
339
|
+
hostTarget: serializeHostTarget(hostTarget)
|
|
340
|
+
};
|
|
341
|
+
}
|
|
220
342
|
|
|
221
343
|
function getStatus({ includeSecrets = false } = {}) {
|
|
222
344
|
const connectedDevices = [...devices.values()].filter(device => device.connected).length;
|
|
345
|
+
const activeHostTarget = serializeHostTarget();
|
|
223
346
|
return {
|
|
224
347
|
enabled,
|
|
225
348
|
started,
|
|
@@ -229,14 +352,23 @@ export function createRemoteHub(options = {}) {
|
|
|
229
352
|
protocolVersion: REMOTE_PROTOCOL_VERSION,
|
|
230
353
|
heartbeatMs,
|
|
231
354
|
taskTimeoutMs,
|
|
355
|
+
managerPackage,
|
|
356
|
+
managerVersion,
|
|
232
357
|
agentPackage: '@mindexec/remote',
|
|
233
|
-
agentEndpoint:
|
|
358
|
+
agentEndpoint: getAgentEndpoint(),
|
|
234
359
|
pairToken: includeSecrets ? pairToken : undefined,
|
|
235
360
|
pairTokenPreview: maskToken(pairToken),
|
|
236
361
|
deviceCount: devices.size,
|
|
237
362
|
connectedDeviceCount: connectedDevices,
|
|
238
363
|
canvasDeviceListMode: 'all-devices',
|
|
239
364
|
canvasPagination: 'none',
|
|
365
|
+
hostTargetActive: activeHostTarget.active,
|
|
366
|
+
hostTargetNodeId: activeHostTarget.nodeId,
|
|
367
|
+
hostTargetLeaseId: activeHostTarget.leaseId,
|
|
368
|
+
hostTargetEndpoint: activeHostTarget.endpoint,
|
|
369
|
+
hostTargetActivatedAt: activeHostTarget.activatedAt,
|
|
370
|
+
hostTargetUpdatedAt: activeHostTarget.updatedAt,
|
|
371
|
+
hostTargetExpiresAt: activeHostTarget.expiresAt,
|
|
240
372
|
externalExposure: host === '0.0.0.0' || host === '::',
|
|
241
373
|
lastError
|
|
242
374
|
};
|
|
@@ -1686,6 +1818,7 @@ export function createRemoteHub(options = {}) {
|
|
|
1686
1818
|
sendCommand,
|
|
1687
1819
|
requestAgentTask,
|
|
1688
1820
|
requestAgentTaskBatch,
|
|
1821
|
+
setHostTarget,
|
|
1689
1822
|
requestThumbnail,
|
|
1690
1823
|
startLiveStream,
|
|
1691
1824
|
stopLiveStream,
|
|
@@ -416,6 +416,9 @@ function buildMonitorNode(devices, hubStatus, latestTaskBatch = null, recentTask
|
|
|
416
416
|
const connected = devices.filter(device => device.Connected).length;
|
|
417
417
|
const endpoint = hubStatus.agentEndpoint || '127.0.0.1:5197';
|
|
418
418
|
const pairToken = hubStatus.pairToken || 'render-smoke-token';
|
|
419
|
+
const hostTargetState = hubStatus.hostTargetActive
|
|
420
|
+
? (hubStatus.hostTargetNodeId === 'remote-fleet-render-smoke' ? 'hosting' : 'other-monitor')
|
|
421
|
+
: 'inactive';
|
|
419
422
|
return {
|
|
420
423
|
id: 'remote-fleet-render-smoke',
|
|
421
424
|
contentType: 'memo',
|
|
@@ -426,12 +429,21 @@ function buildMonitorNode(devices, hubStatus, latestTaskBatch = null, recentTask
|
|
|
426
429
|
RemoteFleetLastRefreshAtUtc: new Date().toISOString(),
|
|
427
430
|
RemoteFleetHubStatus: 'online',
|
|
428
431
|
RemoteFleetHubEndpoint: endpoint,
|
|
432
|
+
RemoteFleetManagerPackage: hubStatus.managerPackage || '@mindexec/cli',
|
|
433
|
+
RemoteFleetManagerVersion: hubStatus.managerVersion || 'render-smoke-manager',
|
|
429
434
|
RemoteFleetAgentPackage: '@mindexec/remote',
|
|
430
435
|
RemoteFleetPairTokenPreview: '<pair-token>',
|
|
431
436
|
RemoteFleetConnectCommand: `npx @mindexec/remote connect --manager ${endpoint} --pair ${pairToken}`,
|
|
432
437
|
RemoteFleetDeviceCount: String(devices.length),
|
|
433
438
|
RemoteFleetConnectedDeviceCount: String(connected),
|
|
434
439
|
RemoteFleetCanvasPagination: 'none',
|
|
440
|
+
RemoteFleetHostTargetState: hostTargetState,
|
|
441
|
+
RemoteFleetHostTargetNodeId: hubStatus.hostTargetNodeId || '',
|
|
442
|
+
RemoteFleetHostTargetLeaseId: hubStatus.hostTargetLeaseId || '',
|
|
443
|
+
RemoteFleetHostTargetEndpoint: hubStatus.hostTargetEndpoint || endpoint,
|
|
444
|
+
RemoteFleetHostTargetActivatedAtUtc: hubStatus.hostTargetActivatedAt || '',
|
|
445
|
+
RemoteFleetHostTargetUpdatedAtUtc: hubStatus.hostTargetUpdatedAt || '',
|
|
446
|
+
RemoteFleetHostTargetExpiresAtUtc: hubStatus.hostTargetExpiresAt || '',
|
|
435
447
|
RemoteFleetDevicesJson: JSON.stringify(devices),
|
|
436
448
|
RemoteFleetLatestTaskBatchJson: latestTaskBatch ? JSON.stringify(latestTaskBatch) : '',
|
|
437
449
|
RemoteFleetRecentTaskBatchesJson: JSON.stringify(recentTaskBatches),
|
|
@@ -452,6 +464,8 @@ function buildDeviceNode(device, hubStatus) {
|
|
|
452
464
|
RemoteFleetLastRefreshAtUtc: new Date().toISOString(),
|
|
453
465
|
RemoteFleetHubStatus: 'online',
|
|
454
466
|
RemoteFleetHubEndpoint: endpoint,
|
|
467
|
+
RemoteFleetManagerPackage: hubStatus.managerPackage || '@mindexec/cli',
|
|
468
|
+
RemoteFleetManagerVersion: hubStatus.managerVersion || 'render-smoke-manager',
|
|
455
469
|
RemoteFleetAgentPackage: '@mindexec/remote',
|
|
456
470
|
RemoteFleetPinnedDeviceId: device.DeviceId,
|
|
457
471
|
RemoteFleetPinnedDeviceJson: JSON.stringify(device),
|
|
@@ -495,6 +509,8 @@ function createThreeStub() {
|
|
|
495
509
|
}
|
|
496
510
|
|
|
497
511
|
const hub = createRemoteHub({
|
|
512
|
+
managerPackage: '@mindexec/cli',
|
|
513
|
+
managerVersion: 'render-smoke-manager',
|
|
498
514
|
env: {
|
|
499
515
|
MINDEXEC_REMOTE_HUB: '1',
|
|
500
516
|
REMOTE_HUB_HOST: '127.0.0.1',
|
|
@@ -639,6 +655,13 @@ try {
|
|
|
639
655
|
};
|
|
640
656
|
}
|
|
641
657
|
|
|
658
|
+
if (methodName === 'SetRemoteFleetHostFromJs') {
|
|
659
|
+
return {
|
|
660
|
+
success: true,
|
|
661
|
+
active: args[1] === true
|
|
662
|
+
};
|
|
663
|
+
}
|
|
664
|
+
|
|
642
665
|
return { success: true };
|
|
643
666
|
}
|
|
644
667
|
};
|
|
@@ -654,15 +677,69 @@ try {
|
|
|
654
677
|
let cards = bodyView.querySelectorAll('article[data-device-id]');
|
|
655
678
|
assert.equal(cards.length, SYNTHETIC_COUNT);
|
|
656
679
|
assert.equal(bodyView.querySelector('[data-remote-fleet-match-count="true"]')?.textContent, `${SYNTHETIC_COUNT}/${SYNTHETIC_COUNT}`);
|
|
657
|
-
assert.
|
|
658
|
-
|
|
659
|
-
assert.equal(
|
|
680
|
+
assert.ok(bodyView.querySelector('[data-remote-fleet-device-grid="true"]'));
|
|
681
|
+
const initialDetailPanel = bodyView.querySelector('[data-remote-fleet-detail-panel="true"]');
|
|
682
|
+
assert.equal(initialDetailPanel?.dataset.deviceId, focusedDevice.DeviceId);
|
|
683
|
+
assert.equal(bodyView.querySelectorAll('[data-remote-fleet-action="pin-device"]').length, 1);
|
|
684
|
+
assert.equal(bodyView.querySelectorAll('[data-remote-fleet-action="task-device"]').length, 0);
|
|
685
|
+
assert.equal(bodyView.querySelectorAll('[data-remote-fleet-action="thumbnail-device"]').length, focusedDevice.Connected && focusedDevice.ThumbnailEnabled ? 1 : 0);
|
|
686
|
+
assert.ok(initialDetailPanel?.textContent.includes('Seen'));
|
|
687
|
+
assert.ok(initialDetailPanel?.textContent.includes('Uptime'));
|
|
688
|
+
assert.ok(initialDetailPanel?.textContent.includes('Mem'));
|
|
689
|
+
assert.ok(initialDetailPanel?.textContent.includes('Load'));
|
|
690
|
+
assert.ok(cards[0]?.querySelector('[data-remote-fleet-device-preview="tile"]'));
|
|
691
|
+
assert.equal(/\b(Seen|Uptime|Mem|Load)\b/.test(cards[0]?.textContent || ''), false);
|
|
692
|
+
const alternateDevice = devices.find(device => device.DeviceId !== focusedDevice.DeviceId);
|
|
693
|
+
assert.ok(alternateDevice);
|
|
694
|
+
const alternateCard = Array.from(cards).find(card => card.dataset.deviceId === alternateDevice.DeviceId);
|
|
695
|
+
assert.ok(alternateCard);
|
|
696
|
+
alternateCard.dispatchEvent({ type: 'click' });
|
|
697
|
+
assert.equal(bodyView.dataset.remoteFleetSelectedDeviceId, alternateDevice.DeviceId);
|
|
698
|
+
assert.equal(bodyView.querySelector('[data-remote-fleet-detail-panel="true"]')?.dataset.deviceId, alternateDevice.DeviceId);
|
|
660
699
|
const livePanel = bodyView.querySelector('[data-remote-fleet-live-panel="true"]');
|
|
661
700
|
assert.equal(livePanel?.dataset.deviceId, focusedDevice.DeviceId);
|
|
662
|
-
assert.equal(bodyView.querySelector('[data-remote-fleet-action="task-visible"]')
|
|
701
|
+
assert.equal(bodyView.querySelector('[data-remote-fleet-action="task-visible"]'), null);
|
|
702
|
+
assert.equal(bodyView.querySelector('[data-remote-fleet-action="task-connected"]'), null);
|
|
703
|
+
assert.equal(bodyView.querySelector('[data-remote-fleet-task-input="true"]'), null);
|
|
704
|
+
assert.equal(bodyView.querySelector('[data-remote-fleet-ai-toggle="true"]'), null);
|
|
663
705
|
assert.ok(bodyView.textContent.includes('all devices, no paging'));
|
|
706
|
+
assert.equal(bodyView.querySelector('[data-remote-fleet-host-state="true"]')?.textContent.includes('Host: Inactive'), true);
|
|
707
|
+
const initialHostButton = bodyView.querySelector('[data-remote-fleet-action="set-host"]');
|
|
708
|
+
assert.equal(initialHostButton?.textContent, 'Set Host');
|
|
709
|
+
initialHostButton.dispatchEvent({ type: 'click' });
|
|
710
|
+
await wait();
|
|
711
|
+
const setHostCall = dotNetCalls.find(call => call.methodName === 'SetRemoteFleetHostFromJs');
|
|
712
|
+
assert.ok(setHostCall);
|
|
713
|
+
assert.equal(setHostCall.args[0], 'remote-fleet-render-smoke');
|
|
714
|
+
assert.equal(setHostCall.args[1], true);
|
|
715
|
+
|
|
716
|
+
hub.setHostTarget({
|
|
717
|
+
nodeId: 'remote-fleet-render-smoke',
|
|
718
|
+
enabled: true,
|
|
719
|
+
leaseMs: 30000
|
|
720
|
+
});
|
|
721
|
+
manager.renderRemoteFleetMonitorForTest(bodyView, buildMonitorNode(devices, hub.getStatus({ includeSecrets: true }), latestTaskBatch, recentTaskBatches));
|
|
722
|
+
assert.equal(bodyView.querySelector('[data-remote-fleet-host-state="true"]')?.textContent.includes('Host: Active'), true);
|
|
723
|
+
assert.equal(bodyView.querySelector('[data-remote-fleet-action="set-host"]')?.textContent, 'Hosting');
|
|
724
|
+
const stopHostButton = bodyView.querySelector('[data-remote-fleet-action="stop-host"]');
|
|
725
|
+
assert.ok(stopHostButton);
|
|
726
|
+
const stopHostStart = dotNetCalls.length;
|
|
727
|
+
stopHostButton.dispatchEvent({ type: 'click' });
|
|
728
|
+
await wait();
|
|
729
|
+
const stopHostCall = dotNetCalls
|
|
730
|
+
.slice(stopHostStart)
|
|
731
|
+
.find(call => call.methodName === 'SetRemoteFleetHostFromJs');
|
|
732
|
+
assert.ok(stopHostCall);
|
|
733
|
+
assert.equal(stopHostCall.args[0], 'remote-fleet-render-smoke');
|
|
734
|
+
assert.equal(stopHostCall.args[1], false);
|
|
735
|
+
|
|
736
|
+
assert.match(bodyView.querySelector('[data-remote-fleet-manager-version="true"]')?.textContent || '', /^@mindexec\/cli render-smoke-manager - 127\.0\.0\.1:\d+$/);
|
|
664
737
|
assert.ok(livePanel?.textContent.includes('RemoteFast 20 fps'), livePanel?.textContent || bodyView.textContent);
|
|
665
|
-
assert.
|
|
738
|
+
assert.equal(bodyView.querySelector('code'), null);
|
|
739
|
+
assert.equal(bodyView.textContent.includes('npx @mindexec/remote connect'), false);
|
|
740
|
+
assert.equal(bodyView.querySelector('[data-remote-fleet-action="copy-command"]'), null);
|
|
741
|
+
assert.equal(bodyView.querySelector('[data-remote-fleet-action="refresh"]'), null);
|
|
742
|
+
assert.equal(bodyView.querySelector('[data-remote-fleet-auto-toggle="true"]'), null);
|
|
666
743
|
assert.ok(bodyView.textContent.includes('synthetic-render-ai'));
|
|
667
744
|
assert.ok(bodyView.textContent.includes('Task timed out waiting for the agent response.'));
|
|
668
745
|
const batchSummary = bodyView.querySelector('[data-remote-fleet-task-batch="true"]');
|
|
@@ -712,63 +789,20 @@ try {
|
|
|
712
789
|
assert.ok(bodyView.querySelectorAll('[data-remote-fleet-group-header="true"]').length >= 2);
|
|
713
790
|
assert.equal(bodyView.querySelectorAll('article[data-device-id]').length, SYNTHETIC_COUNT);
|
|
714
791
|
|
|
715
|
-
const taskInput = bodyView.querySelector('[data-remote-fleet-task-input="true"]');
|
|
716
|
-
const sendVisibleButton = bodyView.querySelector('[data-remote-fleet-action="task-visible"]');
|
|
717
|
-
assert.ok(taskInput);
|
|
718
|
-
assert.ok(sendVisibleButton);
|
|
719
|
-
taskInput.value = 'Dispatch smoke partial failure';
|
|
720
|
-
sendVisibleButton.dispatchEvent({ type: 'click' });
|
|
721
|
-
await wait();
|
|
722
|
-
const batchCall = dotNetCalls.find(call => call.methodName === 'DispatchRemoteFleetTaskBatchFromJs');
|
|
723
|
-
assert.ok(batchCall);
|
|
724
|
-
const batchTargetIds = Array.isArray(batchCall.args[1]) ? batchCall.args[1] : [];
|
|
725
|
-
assert.equal(batchTargetIds.length, connectedCount);
|
|
726
792
|
const feedback = bodyView.querySelector('[data-remote-fleet-task-feedback="true"]');
|
|
727
793
|
assert.ok(feedback);
|
|
728
|
-
assert.equal(feedback.style.display, '
|
|
729
|
-
assert.match(feedback.textContent, new RegExp(`Queued ${connectedCount - 1}/${connectedCount} visible remote task\\(s\\); 1 failed`));
|
|
730
|
-
assert.match(feedback.textContent, /device-ai-assist-unavailable/);
|
|
794
|
+
assert.equal(feedback.style.display, 'none');
|
|
731
795
|
|
|
732
796
|
const activeSelects = bodyView.querySelectorAll('select');
|
|
733
797
|
assert.equal(activeSelects.length, 4);
|
|
734
798
|
const [aiFilterSelect] = activeSelects;
|
|
735
|
-
|
|
736
|
-
assert.ok(aiToggle);
|
|
799
|
+
assert.equal(bodyView.querySelector('[data-remote-fleet-ai-toggle="true"]'), null);
|
|
737
800
|
aiFilterSelect.value = 'ai';
|
|
738
801
|
aiFilterSelect.dispatchEvent({ type: 'change' });
|
|
739
|
-
aiToggle.checked = true;
|
|
740
|
-
aiToggle.dispatchEvent({ type: 'change' });
|
|
741
802
|
assert.equal(bodyView.querySelector('[data-remote-fleet-match-count="true"]')?.textContent, `${aiCount}/${SYNTHETIC_COUNT}`);
|
|
742
|
-
assert.equal(
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
sendVisibleButton.dispatchEvent({ type: 'click' });
|
|
746
|
-
await wait();
|
|
747
|
-
const aiBatchCall = dotNetCalls
|
|
748
|
-
.slice(aiDispatchCallStart)
|
|
749
|
-
.find(call => call.methodName === 'DispatchRemoteFleetTaskBatchFromJs');
|
|
750
|
-
assert.ok(aiBatchCall);
|
|
751
|
-
const aiTargetIds = Array.isArray(aiBatchCall.args[1]) ? aiBatchCall.args[1] : [];
|
|
752
|
-
const expectedAiTargetIds = devices
|
|
753
|
-
.filter(device => device.Connected && device.AiAssistEnabled)
|
|
754
|
-
.map(device => device.DeviceId)
|
|
755
|
-
.sort();
|
|
756
|
-
assert.deepEqual([...aiTargetIds].sort(), expectedAiTargetIds);
|
|
757
|
-
assert.equal(aiBatchCall.args[3], true);
|
|
758
|
-
|
|
759
|
-
const sendConnectedButton = bodyView.querySelector('[data-remote-fleet-action="task-connected"]');
|
|
760
|
-
assert.ok(sendConnectedButton);
|
|
761
|
-
taskInput.value = 'Dispatch all AI smoke';
|
|
762
|
-
const allAiDispatchCallStart = dotNetCalls.length;
|
|
763
|
-
sendConnectedButton.dispatchEvent({ type: 'click' });
|
|
764
|
-
await wait();
|
|
765
|
-
const allAiCall = dotNetCalls
|
|
766
|
-
.slice(allAiDispatchCallStart)
|
|
767
|
-
.find(call => call.methodName === 'DispatchRemoteFleetTaskFromJs');
|
|
768
|
-
assert.ok(allAiCall);
|
|
769
|
-
assert.equal(allAiCall.args[1], '');
|
|
770
|
-
assert.equal(allAiCall.args[3], true);
|
|
771
|
-
assert.match(feedback.textContent, new RegExp(`Queued ${aiCount}/${aiCount} AI task\\(s\\)`));
|
|
803
|
+
assert.equal(dotNetCalls.some(call =>
|
|
804
|
+
call.methodName === 'DispatchRemoteFleetTaskBatchFromJs'
|
|
805
|
+
|| call.methodName === 'DispatchRemoteFleetTaskFromJs'), false);
|
|
772
806
|
|
|
773
807
|
const deviceBody = document.createElement('div');
|
|
774
808
|
document.body.appendChild(deviceBody);
|