@mindexec/cli 0.2.24 → 0.2.26
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 -6
- package/remote-hub.js +130 -1
- package/scripts/remote-fleet-render-smoke.mjs +122 -93
- package/scripts/remote-http-smoke.mjs +218 -40
- package/scripts/remote-hub-smoke.mjs +139 -0
- package/server.js +17 -0
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-core.js +18 -1
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-css3d-manager.js +676 -456
- 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.qt0p5apeu2.dll → MindExecution.Kernel.z56elxihok.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.Admin.i9eswmhltm.dll → MindExecution.Plugins.Admin.p5cs4ap87v.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.Business.1eayoj2kvc.dll → MindExecution.Plugins.Business.s35og5uz44.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.Concept.a3850nmm3d.dll → MindExecution.Plugins.Concept.zczca3fsxz.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.Directory.l3rmdlu7o7.dll → MindExecution.Plugins.Directory.y74f55e8x3.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.PlanMaster.2x5gsi74yi.dll → MindExecution.Plugins.PlanMaster.jpdwbefrh1.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.YouTube.vbl462eegw.dll → MindExecution.Plugins.YouTube.8nz4wv2nsj.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Shared.l2w05i7sd6.dll → MindExecution.Shared.ihh8mkcn5x.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.ri6sjbi2qk.dll +0 -0
- package/wwwroot/_framework/MindExecution.Web.i4ojmz00kp.dll +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mindexec/cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.26",
|
|
4
4
|
"description": "MindExec local runtime and bridge CLI",
|
|
5
5
|
"main": "server.js",
|
|
6
6
|
"type": "module",
|
|
@@ -20,11 +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 && 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",
|
|
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",
|
|
28
28
|
"pack:dry": "npm pack --dry-run",
|
|
29
29
|
"setup:grammars": "node scripts/setup-tree-sitter-grammars.mjs",
|
|
30
30
|
"postinstall": "npm run setup:grammars"
|
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) {
|
|
@@ -219,9 +220,129 @@ export function createRemoteHub(options = {}) {
|
|
|
219
220
|
let started = false;
|
|
220
221
|
let boundPort = requestedPort;
|
|
221
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
|
+
}
|
|
222
342
|
|
|
223
343
|
function getStatus({ includeSecrets = false } = {}) {
|
|
224
344
|
const connectedDevices = [...devices.values()].filter(device => device.connected).length;
|
|
345
|
+
const activeHostTarget = serializeHostTarget();
|
|
225
346
|
return {
|
|
226
347
|
enabled,
|
|
227
348
|
started,
|
|
@@ -234,13 +355,20 @@ export function createRemoteHub(options = {}) {
|
|
|
234
355
|
managerPackage,
|
|
235
356
|
managerVersion,
|
|
236
357
|
agentPackage: '@mindexec/remote',
|
|
237
|
-
agentEndpoint:
|
|
358
|
+
agentEndpoint: getAgentEndpoint(),
|
|
238
359
|
pairToken: includeSecrets ? pairToken : undefined,
|
|
239
360
|
pairTokenPreview: maskToken(pairToken),
|
|
240
361
|
deviceCount: devices.size,
|
|
241
362
|
connectedDeviceCount: connectedDevices,
|
|
242
363
|
canvasDeviceListMode: 'all-devices',
|
|
243
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,
|
|
244
372
|
externalExposure: host === '0.0.0.0' || host === '::',
|
|
245
373
|
lastError
|
|
246
374
|
};
|
|
@@ -1690,6 +1818,7 @@ export function createRemoteHub(options = {}) {
|
|
|
1690
1818
|
sendCommand,
|
|
1691
1819
|
requestAgentTask,
|
|
1692
1820
|
requestAgentTaskBatch,
|
|
1821
|
+
setHostTarget,
|
|
1693
1822
|
requestThumbnail,
|
|
1694
1823
|
startLiveStream,
|
|
1695
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',
|
|
@@ -434,6 +437,13 @@ function buildMonitorNode(devices, hubStatus, latestTaskBatch = null, recentTask
|
|
|
434
437
|
RemoteFleetDeviceCount: String(devices.length),
|
|
435
438
|
RemoteFleetConnectedDeviceCount: String(connected),
|
|
436
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 || '',
|
|
437
447
|
RemoteFleetDevicesJson: JSON.stringify(devices),
|
|
438
448
|
RemoteFleetLatestTaskBatchJson: latestTaskBatch ? JSON.stringify(latestTaskBatch) : '',
|
|
439
449
|
RemoteFleetRecentTaskBatchesJson: JSON.stringify(recentTaskBatches),
|
|
@@ -547,7 +557,6 @@ try {
|
|
|
547
557
|
const rawDevices = hub.listDevices();
|
|
548
558
|
const devices = rawDevices.map(projectDevice);
|
|
549
559
|
const connectedCount = devices.filter(device => device.Connected).length;
|
|
550
|
-
const offlineCount = devices.length - connectedCount;
|
|
551
560
|
const aiCount = devices.filter(device => device.Connected && device.AiAssistEnabled).length;
|
|
552
561
|
const focusedDevice = devices.find(device => device.Connected && device.LiveStreamActive)
|
|
553
562
|
|| devices.find(device => device.Connected);
|
|
@@ -645,31 +654,112 @@ try {
|
|
|
645
654
|
};
|
|
646
655
|
}
|
|
647
656
|
|
|
657
|
+
if (methodName === 'SetRemoteFleetHostFromJs') {
|
|
658
|
+
return {
|
|
659
|
+
success: true,
|
|
660
|
+
active: args[1] === true
|
|
661
|
+
};
|
|
662
|
+
}
|
|
663
|
+
|
|
648
664
|
return { success: true };
|
|
649
665
|
}
|
|
650
666
|
};
|
|
651
667
|
manager.setModuleForTest({ dotNetHelper });
|
|
652
668
|
|
|
669
|
+
const nodeShell = document.createElement('div');
|
|
670
|
+
nodeShell.setAttribute('class', 'map-node-remote-fleet map-node-memo');
|
|
671
|
+
const header = document.createElement('div');
|
|
672
|
+
header.setAttribute('class', 'map-node-memo__header');
|
|
673
|
+
const iconWrap = document.createElement('div');
|
|
674
|
+
iconWrap.setAttribute('class', 'map-node-memo__icon-wrap');
|
|
675
|
+
const iconButton = document.createElement('button');
|
|
676
|
+
iconButton.setAttribute('class', 'map-node-memo__icon-button');
|
|
677
|
+
iconWrap.appendChild(iconButton);
|
|
678
|
+
const titleWrap = document.createElement('div');
|
|
679
|
+
titleWrap.setAttribute('class', 'map-node-memo__title-wrap');
|
|
680
|
+
titleWrap.textContent = 'Remote Fleet Monitor';
|
|
681
|
+
header.appendChild(iconWrap);
|
|
682
|
+
header.appendChild(titleWrap);
|
|
653
683
|
const bodyView = document.createElement('div');
|
|
654
684
|
bodyView.dataset.remoteFleetAutoMonitor = 'false';
|
|
655
685
|
bodyView.dataset.remoteFleetFocusDeviceId = focusedDevice.DeviceId;
|
|
656
|
-
|
|
686
|
+
nodeShell.appendChild(header);
|
|
687
|
+
nodeShell.appendChild(bodyView);
|
|
688
|
+
document.body.appendChild(nodeShell);
|
|
657
689
|
|
|
658
690
|
manager.renderRemoteFleetMonitorForTest(bodyView, buildMonitorNode(devices, hub.getStatus({ includeSecrets: true }), latestTaskBatch, recentTaskBatches));
|
|
659
691
|
|
|
660
692
|
let cards = bodyView.querySelectorAll('article[data-device-id]');
|
|
661
693
|
assert.equal(cards.length, SYNTHETIC_COUNT);
|
|
662
|
-
assert.equal(bodyView.querySelector('[data-remote-fleet-match-count="true"]')
|
|
663
|
-
assert.equal(bodyView.
|
|
664
|
-
assert.equal(bodyView.querySelectorAll('
|
|
665
|
-
assert.
|
|
694
|
+
assert.equal(bodyView.querySelector('[data-remote-fleet-match-count="true"]'), null);
|
|
695
|
+
assert.equal(bodyView.querySelector('[data-remote-fleet-search="true"]'), null);
|
|
696
|
+
assert.equal(bodyView.querySelectorAll('select').length, 0);
|
|
697
|
+
assert.ok(bodyView.querySelector('[data-remote-fleet-device-grid="true"]'));
|
|
698
|
+
const initialDetailPanel = bodyView.querySelector('[data-remote-fleet-detail-panel="true"]');
|
|
699
|
+
assert.equal(initialDetailPanel?.dataset.deviceId, focusedDevice.DeviceId);
|
|
700
|
+
assert.equal(bodyView.querySelectorAll('[data-remote-fleet-action="pin-device"]').length, 1);
|
|
701
|
+
assert.equal(bodyView.querySelectorAll('[data-remote-fleet-action="task-device"]').length, 0);
|
|
702
|
+
assert.equal(bodyView.querySelectorAll('[data-remote-fleet-action="thumbnail-device"]').length, focusedDevice.Connected && focusedDevice.ThumbnailEnabled ? 1 : 0);
|
|
703
|
+
assert.ok(initialDetailPanel?.textContent.includes('Seen'));
|
|
704
|
+
assert.ok(initialDetailPanel?.textContent.includes('Uptime'));
|
|
705
|
+
assert.ok(initialDetailPanel?.textContent.includes('Mem'));
|
|
706
|
+
assert.ok(initialDetailPanel?.textContent.includes('Load'));
|
|
707
|
+
assert.ok(cards[0]?.querySelector('[data-remote-fleet-device-preview="tile"]'));
|
|
708
|
+
assert.equal(/\b(Seen|Uptime|Mem|Load)\b/.test(cards[0]?.textContent || ''), false);
|
|
709
|
+
const alternateDevice = devices.find(device => device.DeviceId !== focusedDevice.DeviceId);
|
|
710
|
+
assert.ok(alternateDevice);
|
|
711
|
+
const alternateCard = Array.from(cards).find(card => card.dataset.deviceId === alternateDevice.DeviceId);
|
|
712
|
+
assert.ok(alternateCard);
|
|
713
|
+
alternateCard.dispatchEvent({ type: 'click' });
|
|
714
|
+
assert.equal(bodyView.dataset.remoteFleetSelectedDeviceId, alternateDevice.DeviceId);
|
|
715
|
+
assert.equal(bodyView.querySelector('[data-remote-fleet-detail-panel="true"]')?.dataset.deviceId, alternateDevice.DeviceId);
|
|
666
716
|
const livePanel = bodyView.querySelector('[data-remote-fleet-live-panel="true"]');
|
|
667
717
|
assert.equal(livePanel?.dataset.deviceId, focusedDevice.DeviceId);
|
|
668
|
-
assert.equal(bodyView.querySelector('[data-remote-fleet-action="task-visible"]')
|
|
669
|
-
assert.
|
|
670
|
-
assert.
|
|
718
|
+
assert.equal(bodyView.querySelector('[data-remote-fleet-action="task-visible"]'), null);
|
|
719
|
+
assert.equal(bodyView.querySelector('[data-remote-fleet-action="task-connected"]'), null);
|
|
720
|
+
assert.equal(bodyView.querySelector('[data-remote-fleet-task-input="true"]'), null);
|
|
721
|
+
assert.equal(bodyView.querySelector('[data-remote-fleet-ai-toggle="true"]'), null);
|
|
722
|
+
assert.equal(bodyView.textContent.includes('all devices, no paging'), false);
|
|
723
|
+
assert.equal(bodyView.textContent.includes('Host: Inactive'), false);
|
|
724
|
+
assert.equal(bodyView.textContent.includes('No screen'), false);
|
|
725
|
+
assert.equal(bodyView.textContent.includes('@mindexec/cli'), false);
|
|
726
|
+
assert.equal(nodeShell.querySelector('[data-remote-fleet-host-indicator="true"]')?.dataset.remoteFleetHostActive, 'false');
|
|
727
|
+
const initialHostButton = nodeShell.querySelector('[data-remote-fleet-action="set-host"]');
|
|
728
|
+
assert.equal(initialHostButton?.textContent, 'Set Host');
|
|
729
|
+
initialHostButton.dispatchEvent({ type: 'click' });
|
|
730
|
+
await wait();
|
|
731
|
+
const setHostCall = dotNetCalls.find(call => call.methodName === 'SetRemoteFleetHostFromJs');
|
|
732
|
+
assert.ok(setHostCall);
|
|
733
|
+
assert.equal(setHostCall.args[0], 'remote-fleet-render-smoke');
|
|
734
|
+
assert.equal(setHostCall.args[1], true);
|
|
735
|
+
|
|
736
|
+
hub.setHostTarget({
|
|
737
|
+
nodeId: 'remote-fleet-render-smoke',
|
|
738
|
+
enabled: true,
|
|
739
|
+
leaseMs: 30000
|
|
740
|
+
});
|
|
741
|
+
manager.renderRemoteFleetMonitorForTest(bodyView, buildMonitorNode(devices, hub.getStatus({ includeSecrets: true }), latestTaskBatch, recentTaskBatches));
|
|
742
|
+
assert.equal(bodyView.textContent.includes('Host: Active'), false);
|
|
743
|
+
assert.equal(nodeShell.querySelector('[data-remote-fleet-host-indicator="true"]')?.dataset.remoteFleetHostActive, 'true');
|
|
744
|
+
assert.equal(nodeShell.querySelector('[data-remote-fleet-action="set-host"]')?.textContent, 'Set Host');
|
|
745
|
+
const stopHostButton = nodeShell.querySelector('[data-remote-fleet-action="stop-host"]');
|
|
746
|
+
assert.ok(stopHostButton);
|
|
747
|
+
const stopHostStart = dotNetCalls.length;
|
|
748
|
+
stopHostButton.dispatchEvent({ type: 'click' });
|
|
749
|
+
await wait();
|
|
750
|
+
const stopHostCall = dotNetCalls
|
|
751
|
+
.slice(stopHostStart)
|
|
752
|
+
.find(call => call.methodName === 'SetRemoteFleetHostFromJs');
|
|
753
|
+
assert.ok(stopHostCall);
|
|
754
|
+
assert.equal(stopHostCall.args[0], 'remote-fleet-render-smoke');
|
|
755
|
+
assert.equal(stopHostCall.args[1], false);
|
|
756
|
+
|
|
671
757
|
assert.ok(livePanel?.textContent.includes('RemoteFast 20 fps'), livePanel?.textContent || bodyView.textContent);
|
|
672
|
-
assert.
|
|
758
|
+
assert.equal(bodyView.querySelector('code'), null);
|
|
759
|
+
assert.equal(bodyView.textContent.includes('npx @mindexec/remote connect'), false);
|
|
760
|
+
assert.equal(bodyView.querySelector('[data-remote-fleet-action="copy-command"]'), null);
|
|
761
|
+
assert.equal(bodyView.querySelector('[data-remote-fleet-action="refresh"]'), null);
|
|
762
|
+
assert.equal(bodyView.querySelector('[data-remote-fleet-auto-toggle="true"]'), null);
|
|
673
763
|
assert.ok(bodyView.textContent.includes('synthetic-render-ai'));
|
|
674
764
|
assert.ok(bodyView.textContent.includes('Task timed out waiting for the agent response.'));
|
|
675
765
|
const batchSummary = bodyView.querySelector('[data-remote-fleet-task-batch="true"]');
|
|
@@ -691,91 +781,30 @@ try {
|
|
|
691
781
|
assert.equal(bodyView.dataset.remoteFleetTaskFollowKey, 'render-smoke-batch');
|
|
692
782
|
assert.ok(Number(bodyView.dataset.remoteFleetTaskFollowTicks || '0') >= 1);
|
|
693
783
|
|
|
694
|
-
const searchInput = bodyView.querySelector('[data-remote-fleet-search="true"]');
|
|
695
|
-
searchInput.value = 'synthetic pc 0001';
|
|
696
|
-
searchInput.dispatchEvent({ type: 'input' });
|
|
697
|
-
cards = bodyView.querySelectorAll('article[data-device-id]');
|
|
698
|
-
assert.equal(cards.filter(card => card.style.display !== 'none').length, 1);
|
|
699
|
-
assert.equal(bodyView.querySelector('[data-remote-fleet-match-count="true"]')?.textContent, `1/${SYNTHETIC_COUNT}`);
|
|
700
|
-
|
|
701
|
-
const selects = bodyView.querySelectorAll('select');
|
|
702
|
-
assert.equal(selects.length, 4);
|
|
703
|
-
const [filterSelect, , groupSelect] = selects;
|
|
704
|
-
searchInput.value = '';
|
|
705
|
-
searchInput.dispatchEvent({ type: 'input' });
|
|
706
|
-
filterSelect.value = 'offline';
|
|
707
|
-
filterSelect.dispatchEvent({ type: 'change' });
|
|
708
|
-
assert.equal(bodyView.querySelector('[data-remote-fleet-match-count="true"]')?.textContent, `${offlineCount}/${SYNTHETIC_COUNT}`);
|
|
709
|
-
|
|
710
|
-
filterSelect.value = 'ai';
|
|
711
|
-
filterSelect.dispatchEvent({ type: 'change' });
|
|
712
|
-
assert.equal(bodyView.querySelector('[data-remote-fleet-match-count="true"]')?.textContent, `${aiCount}/${SYNTHETIC_COUNT}`);
|
|
713
|
-
|
|
714
|
-
filterSelect.value = 'all';
|
|
715
|
-
filterSelect.dispatchEvent({ type: 'change' });
|
|
716
|
-
groupSelect.value = 'status';
|
|
717
|
-
groupSelect.dispatchEvent({ type: 'change' });
|
|
718
|
-
assert.equal(bodyView.dataset.remoteFleetGroup, 'status');
|
|
719
|
-
assert.ok(bodyView.querySelectorAll('[data-remote-fleet-group-header="true"]').length >= 2);
|
|
720
|
-
assert.equal(bodyView.querySelectorAll('article[data-device-id]').length, SYNTHETIC_COUNT);
|
|
721
|
-
|
|
722
|
-
const taskInput = bodyView.querySelector('[data-remote-fleet-task-input="true"]');
|
|
723
|
-
const sendVisibleButton = bodyView.querySelector('[data-remote-fleet-action="task-visible"]');
|
|
724
|
-
assert.ok(taskInput);
|
|
725
|
-
assert.ok(sendVisibleButton);
|
|
726
|
-
taskInput.value = 'Dispatch smoke partial failure';
|
|
727
|
-
sendVisibleButton.dispatchEvent({ type: 'click' });
|
|
728
|
-
await wait();
|
|
729
|
-
const batchCall = dotNetCalls.find(call => call.methodName === 'DispatchRemoteFleetTaskBatchFromJs');
|
|
730
|
-
assert.ok(batchCall);
|
|
731
|
-
const batchTargetIds = Array.isArray(batchCall.args[1]) ? batchCall.args[1] : [];
|
|
732
|
-
assert.equal(batchTargetIds.length, connectedCount);
|
|
733
784
|
const feedback = bodyView.querySelector('[data-remote-fleet-task-feedback="true"]');
|
|
734
785
|
assert.ok(feedback);
|
|
735
|
-
|
|
736
|
-
assert.
|
|
737
|
-
assert.
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
const
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
assert.ok(aiBatchCall);
|
|
758
|
-
const aiTargetIds = Array.isArray(aiBatchCall.args[1]) ? aiBatchCall.args[1] : [];
|
|
759
|
-
const expectedAiTargetIds = devices
|
|
760
|
-
.filter(device => device.Connected && device.AiAssistEnabled)
|
|
761
|
-
.map(device => device.DeviceId)
|
|
762
|
-
.sort();
|
|
763
|
-
assert.deepEqual([...aiTargetIds].sort(), expectedAiTargetIds);
|
|
764
|
-
assert.equal(aiBatchCall.args[3], true);
|
|
765
|
-
|
|
766
|
-
const sendConnectedButton = bodyView.querySelector('[data-remote-fleet-action="task-connected"]');
|
|
767
|
-
assert.ok(sendConnectedButton);
|
|
768
|
-
taskInput.value = 'Dispatch all AI smoke';
|
|
769
|
-
const allAiDispatchCallStart = dotNetCalls.length;
|
|
770
|
-
sendConnectedButton.dispatchEvent({ type: 'click' });
|
|
771
|
-
await wait();
|
|
772
|
-
const allAiCall = dotNetCalls
|
|
773
|
-
.slice(allAiDispatchCallStart)
|
|
774
|
-
.find(call => call.methodName === 'DispatchRemoteFleetTaskFromJs');
|
|
775
|
-
assert.ok(allAiCall);
|
|
776
|
-
assert.equal(allAiCall.args[1], '');
|
|
777
|
-
assert.equal(allAiCall.args[3], true);
|
|
778
|
-
assert.match(feedback.textContent, new RegExp(`Queued ${aiCount}/${aiCount} AI task\\(s\\)`));
|
|
786
|
+
|
|
787
|
+
assert.equal(bodyView.querySelector('[data-remote-fleet-ai-toggle="true"]'), null);
|
|
788
|
+
assert.equal(dotNetCalls.some(call =>
|
|
789
|
+
call.methodName === 'DispatchRemoteFleetTaskBatchFromJs'
|
|
790
|
+
|| call.methodName === 'DispatchRemoteFleetTaskFromJs'), false);
|
|
791
|
+
|
|
792
|
+
const emptyShell = document.createElement('div');
|
|
793
|
+
emptyShell.setAttribute('class', 'map-node-remote-fleet map-node-memo');
|
|
794
|
+
const emptyHeader = document.createElement('div');
|
|
795
|
+
emptyHeader.setAttribute('class', 'map-node-memo__header');
|
|
796
|
+
emptyHeader.appendChild(document.createElement('div'));
|
|
797
|
+
emptyHeader.appendChild(document.createElement('div'));
|
|
798
|
+
const emptyBody = document.createElement('div');
|
|
799
|
+
emptyShell.appendChild(emptyHeader);
|
|
800
|
+
emptyShell.appendChild(emptyBody);
|
|
801
|
+
document.body.appendChild(emptyShell);
|
|
802
|
+
manager.renderRemoteFleetMonitorForTest(emptyBody, buildMonitorNode([], hub.getStatus({ includeSecrets: true })));
|
|
803
|
+
assert.equal(emptyBody.querySelectorAll('[data-remote-fleet-empty-screen="true"]').length, 6);
|
|
804
|
+
assert.equal(emptyBody.textContent.includes('No devices connected yet.'), false);
|
|
805
|
+
assert.equal(emptyBody.textContent.includes('Select a screen'), false);
|
|
806
|
+
assert.equal(emptyBody.textContent.includes('No screen'), false);
|
|
807
|
+
assert.equal(emptyBody.textContent.includes('Endpoint 127.0.0.1'), false);
|
|
779
808
|
|
|
780
809
|
const deviceBody = document.createElement('div');
|
|
781
810
|
document.body.appendChild(deviceBody);
|