@mindexec/cli 0.2.14 → 0.2.16
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 +94 -0
- package/scripts/remote-fleet-render-smoke.mjs +55 -0
- package/scripts/remote-hub-smoke.mjs +21 -1
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-css3d-manager.js +53 -14
- package/wwwroot/_framework/MindExecution.Core.gvaopvh5wg.dll +0 -0
- package/wwwroot/_framework/{MindExecution.Kernel.lqglgq2jmo.dll → MindExecution.Kernel.hpf3wr4dv3.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.Admin.2jqptn6ylw.dll → MindExecution.Plugins.Admin.y0euqt1gu1.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.Business.8hzwity3fl.dll → MindExecution.Plugins.Business.9zzc31j54n.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.Concept.wqdtoeuumu.dll → MindExecution.Plugins.Concept.sihn2obrrn.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.Directory.hr2p0grenr.dll → MindExecution.Plugins.Directory.zwbshhfvpb.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.PlanMaster.fpq5ydr4s0.dll → MindExecution.Plugins.PlanMaster.47f3afsrf8.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.YouTube.43m89bf01o.dll → MindExecution.Plugins.YouTube.rpolgpee6c.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Shared.y1hdnsq8zq.dll → MindExecution.Shared.zm6btxgvlg.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Web.ox678bzo06.dll → MindExecution.Web.7b082n0t0o.dll} +0 -0
- package/wwwroot/_framework/blazor.boot.json +21 -21
- package/wwwroot/index.html +1 -1
- package/wwwroot/service-worker-assets.js +24 -24
- package/wwwroot/service-worker.js +1 -1
- package/wwwroot/_framework/MindExecution.Core.q469sducjw.dll +0 -0
package/package.json
CHANGED
package/remote-hub.js
CHANGED
|
@@ -5,6 +5,7 @@ import crypto from 'crypto';
|
|
|
5
5
|
const DEFAULT_REMOTE_HUB_PORT = 5197;
|
|
6
6
|
const DEFAULT_REMOTE_HUB_HOST = '127.0.0.1';
|
|
7
7
|
const DEFAULT_HEARTBEAT_MS = 5000;
|
|
8
|
+
const DEFAULT_AGENT_TASK_TIMEOUT_MS = 120000;
|
|
8
9
|
const MAX_LINE_CHARS = 4 * 1024 * 1024;
|
|
9
10
|
const MAX_THUMBNAIL_BASE64_CHARS = 3 * 1024 * 1024;
|
|
10
11
|
const MAX_STREAM_BASE64_CHARS = 3 * 1024 * 1024;
|
|
@@ -79,6 +80,7 @@ function createDeviceCounters(overrides = {}) {
|
|
|
79
80
|
tasksQueued: 0,
|
|
80
81
|
taskResultsReceived: 0,
|
|
81
82
|
taskResultsFailed: 0,
|
|
83
|
+
taskResultsTimedOut: 0,
|
|
82
84
|
...overrides
|
|
83
85
|
};
|
|
84
86
|
}
|
|
@@ -172,6 +174,11 @@ export function createRemoteHub(options = {}) {
|
|
|
172
174
|
const host = safeString(env.REMOTE_HUB_HOST || DEFAULT_REMOTE_HUB_HOST, 128);
|
|
173
175
|
const requestedPort = normalizePort(env.REMOTE_HUB_PORT || DEFAULT_REMOTE_HUB_PORT);
|
|
174
176
|
const heartbeatMs = clampNumber(env.REMOTE_HUB_HEARTBEAT_MS, 1000, 60000, DEFAULT_HEARTBEAT_MS);
|
|
177
|
+
const taskTimeoutMs = clampNumber(
|
|
178
|
+
options.taskTimeoutMs ?? env.REMOTE_HUB_TASK_TIMEOUT_MS,
|
|
179
|
+
50,
|
|
180
|
+
30 * 60 * 1000,
|
|
181
|
+
DEFAULT_AGENT_TASK_TIMEOUT_MS);
|
|
175
182
|
const pairToken = safeString(
|
|
176
183
|
env.REMOTE_HUB_PAIR_TOKEN || env.MINDEXEC_REMOTE_PAIR_TOKEN || crypto.randomBytes(6).toString('hex'),
|
|
177
184
|
256);
|
|
@@ -194,6 +201,7 @@ export function createRemoteHub(options = {}) {
|
|
|
194
201
|
protocol: 'tcp-jsonl',
|
|
195
202
|
protocolVersion: REMOTE_PROTOCOL_VERSION,
|
|
196
203
|
heartbeatMs,
|
|
204
|
+
taskTimeoutMs,
|
|
197
205
|
agentPackage: '@mindexec/remote',
|
|
198
206
|
agentEndpoint: `${host}:${boundPort || requestedPort}`,
|
|
199
207
|
pairToken: includeSecrets ? pairToken : undefined,
|
|
@@ -307,6 +315,7 @@ export function createRemoteHub(options = {}) {
|
|
|
307
315
|
}
|
|
308
316
|
|
|
309
317
|
existing.lastDisconnectReason = 'replaced-by-new-session';
|
|
318
|
+
failAllPendingTasks(existing, 'replaced-by-new-session');
|
|
310
319
|
writeJsonLine(existing.socket, {
|
|
311
320
|
type: 'disconnect',
|
|
312
321
|
reason: 'replaced-by-new-session',
|
|
@@ -427,6 +436,7 @@ export function createRemoteHub(options = {}) {
|
|
|
427
436
|
latestTask,
|
|
428
437
|
recentTasks: latestTask ? [latestTask] : [],
|
|
429
438
|
pendingTaskCommands: new Map(),
|
|
439
|
+
pendingTaskTimers: new Map(),
|
|
430
440
|
counters: createDeviceCounters({
|
|
431
441
|
messagesReceived: 1,
|
|
432
442
|
statusReceived: 1,
|
|
@@ -532,6 +542,7 @@ export function createRemoteHub(options = {}) {
|
|
|
532
542
|
latestTask: null,
|
|
533
543
|
recentTasks: [],
|
|
534
544
|
pendingTaskCommands: new Map(),
|
|
545
|
+
pendingTaskTimers: new Map(),
|
|
535
546
|
synthetic: false,
|
|
536
547
|
counters: createDeviceCounters({ messagesReceived: 1 })
|
|
537
548
|
};
|
|
@@ -573,6 +584,7 @@ export function createRemoteHub(options = {}) {
|
|
|
573
584
|
device.activeLiveStream.stoppedAt = device.disconnectedAt;
|
|
574
585
|
device.activeLiveStream.stopReason = reason;
|
|
575
586
|
}
|
|
587
|
+
failAllPendingTasks(device, 'device-disconnected');
|
|
576
588
|
logWarn('remote', `device disconnected ${device.deviceName} (${deviceId}): ${reason}`);
|
|
577
589
|
emitRemoteEvent('RemoteDeviceDisconnected', device, { reason });
|
|
578
590
|
}
|
|
@@ -601,6 +613,84 @@ export function createRemoteHub(options = {}) {
|
|
|
601
613
|
return task;
|
|
602
614
|
}
|
|
603
615
|
|
|
616
|
+
function clearTaskTimeout(device, commandId) {
|
|
617
|
+
const key = safeString(commandId, 128);
|
|
618
|
+
if (!device?.pendingTaskTimers || !key) {
|
|
619
|
+
return;
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
const timer = device.pendingTaskTimers.get(key);
|
|
623
|
+
if (timer) {
|
|
624
|
+
clearTimeout(timer);
|
|
625
|
+
}
|
|
626
|
+
device.pendingTaskTimers.delete(key);
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
function failPendingTask(device, commandId, error = 'task-timeout') {
|
|
630
|
+
const key = safeString(commandId, 128);
|
|
631
|
+
if (!device?.pendingTaskCommands || !key) {
|
|
632
|
+
return null;
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
const task = device.pendingTaskCommands.get(key);
|
|
636
|
+
if (!task) {
|
|
637
|
+
clearTaskTimeout(device, key);
|
|
638
|
+
return null;
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
const now = new Date().toISOString();
|
|
642
|
+
clearTaskTimeout(device, key);
|
|
643
|
+
task.status = 'failed';
|
|
644
|
+
task.updatedAt = now;
|
|
645
|
+
task.completedAt = now;
|
|
646
|
+
task.error = safeString(error, 500) || 'task-timeout';
|
|
647
|
+
task.resultSummary = task.error;
|
|
648
|
+
task.resultKind = task.resultKind || 'agent-task';
|
|
649
|
+
device.latestTask = task;
|
|
650
|
+
device.pendingTaskCommands.delete(key);
|
|
651
|
+
device.counters.taskResultsReceived += 1;
|
|
652
|
+
device.counters.taskResultsFailed += 1;
|
|
653
|
+
if (task.error === 'task-timeout') {
|
|
654
|
+
device.counters.taskResultsTimedOut += 1;
|
|
655
|
+
}
|
|
656
|
+
emitRemoteEvent('RemoteTaskResult', device, {
|
|
657
|
+
commandId: key,
|
|
658
|
+
taskId: task.taskId,
|
|
659
|
+
status: task.status,
|
|
660
|
+
error: task.error
|
|
661
|
+
});
|
|
662
|
+
return task;
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
function failAllPendingTasks(device, error = 'device-disconnected') {
|
|
666
|
+
if (!device?.pendingTaskCommands) {
|
|
667
|
+
return 0;
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
const commandIds = [...device.pendingTaskCommands.keys()];
|
|
671
|
+
let failed = 0;
|
|
672
|
+
for (const commandId of commandIds) {
|
|
673
|
+
if (failPendingTask(device, commandId, error)) {
|
|
674
|
+
failed += 1;
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
return failed;
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
function scheduleTaskTimeout(device, task) {
|
|
681
|
+
const commandId = safeString(task?.commandId, 128);
|
|
682
|
+
if (!device?.pendingTaskTimers || !commandId) {
|
|
683
|
+
return;
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
clearTaskTimeout(device, commandId);
|
|
687
|
+
const timer = setTimeout(() => {
|
|
688
|
+
failPendingTask(device, commandId, 'task-timeout');
|
|
689
|
+
}, taskTimeoutMs);
|
|
690
|
+
timer.unref?.();
|
|
691
|
+
device.pendingTaskTimers.set(commandId, timer);
|
|
692
|
+
}
|
|
693
|
+
|
|
604
694
|
function summarizeTaskResult(result) {
|
|
605
695
|
if (result && typeof result === 'object') {
|
|
606
696
|
return safeText(
|
|
@@ -634,6 +724,7 @@ export function createRemoteHub(options = {}) {
|
|
|
634
724
|
const status = error
|
|
635
725
|
? 'failed'
|
|
636
726
|
: safeString(result?.status, 40) || 'completed';
|
|
727
|
+
clearTaskTimeout(device, commandId);
|
|
637
728
|
task.status = status;
|
|
638
729
|
task.updatedAt = now;
|
|
639
730
|
task.completedAt = safeString(result?.completedAt, 80) || now;
|
|
@@ -903,6 +994,7 @@ export function createRemoteHub(options = {}) {
|
|
|
903
994
|
|
|
904
995
|
async function close() {
|
|
905
996
|
for (const device of devices.values()) {
|
|
997
|
+
failAllPendingTasks(device, 'hub-shutdown');
|
|
906
998
|
if (device.socket && !device.socket.destroyed) {
|
|
907
999
|
writeJsonLine(device.socket, { type: 'disconnect', reason: 'hub-shutdown' });
|
|
908
1000
|
device.socket.destroy();
|
|
@@ -958,6 +1050,7 @@ export function createRemoteHub(options = {}) {
|
|
|
958
1050
|
device.activeLiveStream.stoppedAt = device.disconnectedAt;
|
|
959
1051
|
device.activeLiveStream.stopReason = reason;
|
|
960
1052
|
}
|
|
1053
|
+
failAllPendingTasks(device, 'device-disconnected');
|
|
961
1054
|
emitRemoteEvent('RemoteDeviceDisconnected', device, { reason, synthetic: true });
|
|
962
1055
|
return true;
|
|
963
1056
|
}
|
|
@@ -1145,6 +1238,7 @@ export function createRemoteHub(options = {}) {
|
|
|
1145
1238
|
device.counters.commandsSent += 1;
|
|
1146
1239
|
device.counters.tasksQueued += 1;
|
|
1147
1240
|
rememberDeviceTask(device, task);
|
|
1241
|
+
scheduleTaskTimeout(device, task);
|
|
1148
1242
|
emitRemoteEvent('RemoteTaskQueued', device, {
|
|
1149
1243
|
commandId,
|
|
1150
1244
|
taskId,
|
|
@@ -408,6 +408,10 @@ async function loadCss3DManager() {
|
|
|
408
408
|
return { manager: context.window.MindMapCss3DManager, document };
|
|
409
409
|
}
|
|
410
410
|
|
|
411
|
+
function wait(ms = 0) {
|
|
412
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
413
|
+
}
|
|
414
|
+
|
|
411
415
|
function buildMonitorNode(devices, hubStatus) {
|
|
412
416
|
const connected = devices.filter(device => device.Connected).length;
|
|
413
417
|
const endpoint = hubStatus.agentEndpoint || '127.0.0.1:5197';
|
|
@@ -527,10 +531,42 @@ try {
|
|
|
527
531
|
const aiCount = devices.filter(device => device.Connected && device.AiAssistEnabled).length;
|
|
528
532
|
const focusedDevice = devices.find(device => device.Connected);
|
|
529
533
|
assert.ok(focusedDevice);
|
|
534
|
+
focusedDevice.LatestTaskId = 'render-smoke-timeout-task';
|
|
535
|
+
focusedDevice.LatestTaskCommandId = 'render-smoke-timeout-command';
|
|
536
|
+
focusedDevice.LatestTaskTitle = 'Timed out smoke task';
|
|
537
|
+
focusedDevice.LatestTaskInstructionPreview = 'This synthetic task timed out before the agent replied.';
|
|
538
|
+
focusedDevice.LatestTaskStatus = 'failed';
|
|
539
|
+
focusedDevice.LatestTaskApprovalLevel = 'task-only';
|
|
540
|
+
focusedDevice.LatestTaskUpdatedAt = new Date().toISOString();
|
|
541
|
+
focusedDevice.LatestTaskError = 'task-timeout';
|
|
542
|
+
focusedDevice.LatestTaskResultSummary = '';
|
|
530
543
|
|
|
531
544
|
const { manager, document } = await loadCss3DManager();
|
|
532
545
|
assert.equal(typeof manager?.renderRemoteFleetMonitorForTest, 'function');
|
|
533
546
|
assert.equal(typeof manager?.renderRemoteFleetDeviceForTest, 'function');
|
|
547
|
+
assert.equal(typeof manager?.setModuleForTest, 'function');
|
|
548
|
+
|
|
549
|
+
const dotNetCalls = [];
|
|
550
|
+
const dotNetHelper = {
|
|
551
|
+
invokeMethodAsync: async (methodName, ...args) => {
|
|
552
|
+
dotNetCalls.push({ methodName, args });
|
|
553
|
+
if (methodName === 'DispatchRemoteFleetTaskBatchFromJs') {
|
|
554
|
+
const targetIds = Array.isArray(args[1]) ? args[1] : [];
|
|
555
|
+
const failedDeviceId = targetIds[targetIds.length - 1] || 'synthetic-pc-failed';
|
|
556
|
+
return {
|
|
557
|
+
success: true,
|
|
558
|
+
total: targetIds.length,
|
|
559
|
+
queued: Math.max(0, targetIds.length - 1),
|
|
560
|
+
failed: 1,
|
|
561
|
+
failedDeviceIds: [failedDeviceId],
|
|
562
|
+
failurePreview: `${failedDeviceId}: device-ai-assist-unavailable`
|
|
563
|
+
};
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
return { success: true };
|
|
567
|
+
}
|
|
568
|
+
};
|
|
569
|
+
manager.setModuleForTest({ dotNetHelper });
|
|
534
570
|
|
|
535
571
|
const bodyView = document.createElement('div');
|
|
536
572
|
bodyView.dataset.remoteFleetAutoMonitor = 'false';
|
|
@@ -550,6 +586,7 @@ try {
|
|
|
550
586
|
assert.ok(bodyView.textContent.includes('all devices, no paging'));
|
|
551
587
|
assert.ok(bodyView.querySelector('code')?.textContent.includes('npx @mindexec/remote connect'));
|
|
552
588
|
assert.ok(bodyView.textContent.includes('synthetic-render-ai'));
|
|
589
|
+
assert.ok(bodyView.textContent.includes('Task timed out waiting for the agent response.'));
|
|
553
590
|
assert.ok(devices.some(device => /^synthetic-response-/.test(device.LatestTaskResultResponseId)));
|
|
554
591
|
|
|
555
592
|
const searchInput = bodyView.querySelector('[data-remote-fleet-search="true"]');
|
|
@@ -580,12 +617,30 @@ try {
|
|
|
580
617
|
assert.ok(bodyView.querySelectorAll('[data-remote-fleet-group-header="true"]').length >= 2);
|
|
581
618
|
assert.equal(bodyView.querySelectorAll('article[data-device-id]').length, SYNTHETIC_COUNT);
|
|
582
619
|
|
|
620
|
+
const taskInput = bodyView.querySelector('[data-remote-fleet-task-input="true"]');
|
|
621
|
+
const sendVisibleButton = bodyView.querySelector('[data-remote-fleet-action="task-visible"]');
|
|
622
|
+
assert.ok(taskInput);
|
|
623
|
+
assert.ok(sendVisibleButton);
|
|
624
|
+
taskInput.value = 'Dispatch smoke partial failure';
|
|
625
|
+
sendVisibleButton.dispatchEvent({ type: 'click' });
|
|
626
|
+
await wait();
|
|
627
|
+
const batchCall = dotNetCalls.find(call => call.methodName === 'DispatchRemoteFleetTaskBatchFromJs');
|
|
628
|
+
assert.ok(batchCall);
|
|
629
|
+
const batchTargetIds = Array.isArray(batchCall.args[1]) ? batchCall.args[1] : [];
|
|
630
|
+
assert.equal(batchTargetIds.length, connectedCount);
|
|
631
|
+
const feedback = bodyView.querySelector('[data-remote-fleet-task-feedback="true"]');
|
|
632
|
+
assert.ok(feedback);
|
|
633
|
+
assert.equal(feedback.style.display, 'block');
|
|
634
|
+
assert.match(feedback.textContent, new RegExp(`Queued ${connectedCount - 1}/${connectedCount} visible remote task\\(s\\); 1 failed`));
|
|
635
|
+
assert.match(feedback.textContent, /device-ai-assist-unavailable/);
|
|
636
|
+
|
|
583
637
|
const deviceBody = document.createElement('div');
|
|
584
638
|
document.body.appendChild(deviceBody);
|
|
585
639
|
manager.renderRemoteFleetDeviceForTest(deviceBody, buildDeviceNode(focusedDevice, hub.getStatus()));
|
|
586
640
|
assert.ok(deviceBody.textContent.includes(focusedDevice.Name));
|
|
587
641
|
assert.ok(deviceBody.querySelector('[data-remote-fleet-action="refresh-device"]'));
|
|
588
642
|
assert.ok(deviceBody.querySelector('[data-remote-fleet-action="task-device"]'));
|
|
643
|
+
assert.ok(deviceBody.textContent.includes('Task timed out waiting for the agent response.'));
|
|
589
644
|
assert.ok(deviceBody.textContent.includes(focusedDevice.DeviceId));
|
|
590
645
|
|
|
591
646
|
console.log(`RemoteFleet render smoke OK (${SYNTHETIC_COUNT} synthetic devices, ${connectedCount} connected, ${aiCount} AI-ready)`);
|
|
@@ -30,7 +30,8 @@ const hub = createRemoteHub({
|
|
|
30
30
|
MINDEXEC_REMOTE_HUB: '1',
|
|
31
31
|
REMOTE_HUB_HOST: '127.0.0.1',
|
|
32
32
|
REMOTE_HUB_PORT: '0',
|
|
33
|
-
REMOTE_HUB_PAIR_TOKEN: 'smoke-token'
|
|
33
|
+
REMOTE_HUB_PAIR_TOKEN: 'smoke-token',
|
|
34
|
+
REMOTE_HUB_TASK_TIMEOUT_MS: '120'
|
|
34
35
|
}
|
|
35
36
|
});
|
|
36
37
|
|
|
@@ -230,6 +231,25 @@ try {
|
|
|
230
231
|
assert.equal(aiTaskDevice.counters.tasksQueued, 2);
|
|
231
232
|
assert.equal(aiTaskDevice.counters.taskResultsReceived, 2);
|
|
232
233
|
|
|
234
|
+
const timeoutTaskCommand = hub.requestAgentTask('smoke-device', {
|
|
235
|
+
instruction: 'This task intentionally receives no agent response.',
|
|
236
|
+
title: 'Timeout task'
|
|
237
|
+
});
|
|
238
|
+
assert.equal(timeoutTaskCommand.ok, true);
|
|
239
|
+
const timeoutTaskDevice = await waitFor(() => {
|
|
240
|
+
const current = hub.listDevices();
|
|
241
|
+
return current[0]?.latestTask?.taskId === timeoutTaskCommand.taskId
|
|
242
|
+
&& current[0]?.latestTask?.status === 'failed'
|
|
243
|
+
? current[0]
|
|
244
|
+
: null;
|
|
245
|
+
}, 1000);
|
|
246
|
+
assert.equal(timeoutTaskDevice.latestTask.error, 'task-timeout');
|
|
247
|
+
assert.equal(timeoutTaskDevice.latestTask.resultSummary, 'task-timeout');
|
|
248
|
+
assert.equal(timeoutTaskDevice.counters.tasksQueued, 3);
|
|
249
|
+
assert.equal(timeoutTaskDevice.counters.taskResultsReceived, 3);
|
|
250
|
+
assert.equal(timeoutTaskDevice.counters.taskResultsFailed, 1);
|
|
251
|
+
assert.equal(timeoutTaskDevice.counters.taskResultsTimedOut, 1);
|
|
252
|
+
|
|
233
253
|
socket.destroy();
|
|
234
254
|
await waitFor(() => hub.listDevices()[0]?.connected === false);
|
|
235
255
|
console.log('RemoteHub smoke OK');
|
|
@@ -11350,6 +11350,10 @@
|
|
|
11350
11350
|
});
|
|
11351
11351
|
}
|
|
11352
11352
|
|
|
11353
|
+
function setModuleForTest(module) {
|
|
11354
|
+
_module = module || null;
|
|
11355
|
+
}
|
|
11356
|
+
|
|
11353
11357
|
function getTemplateCardConfig(nodeModel) {
|
|
11354
11358
|
const raw = nodeModel?.response ?? nodeModel?.Response ?? '';
|
|
11355
11359
|
const metadata = nodeModel?.metadata ?? nodeModel?.Metadata ?? {};
|
|
@@ -12200,6 +12204,22 @@
|
|
|
12200
12204
|
return getRemoteFleetDeviceField(device, 'thumbnailEnabled', 'ThumbnailEnabled', false) === true;
|
|
12201
12205
|
}
|
|
12202
12206
|
|
|
12207
|
+
function formatRemoteFleetTaskError(error) {
|
|
12208
|
+
const value = String(error || '').trim();
|
|
12209
|
+
switch (value) {
|
|
12210
|
+
case 'task-timeout':
|
|
12211
|
+
return 'Task timed out waiting for the agent response.';
|
|
12212
|
+
case 'device-disconnected':
|
|
12213
|
+
return 'Agent disconnected before returning a task result.';
|
|
12214
|
+
case 'replaced-by-new-session':
|
|
12215
|
+
return 'Agent reconnected before returning a task result.';
|
|
12216
|
+
case 'hub-shutdown':
|
|
12217
|
+
return 'RemoteHub shut down before the task completed.';
|
|
12218
|
+
default:
|
|
12219
|
+
return value;
|
|
12220
|
+
}
|
|
12221
|
+
}
|
|
12222
|
+
|
|
12203
12223
|
function getRemoteFleetGroupInfo(device, groupMode) {
|
|
12204
12224
|
const mode = String(groupMode || 'none');
|
|
12205
12225
|
const connected = isRemoteFleetDeviceConnected(device);
|
|
@@ -12597,7 +12617,7 @@
|
|
|
12597
12617
|
: taskLine.textContent;
|
|
12598
12618
|
taskLine.style.cssText = `color:${taskTone === 'error' ? '#991b1b' : taskTone === 'done' ? '#047857' : '#1d4ed8'};font-size:10px;font-weight:900;line-height:1.2;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;letter-spacing:0;`;
|
|
12599
12619
|
const taskSummary = document.createElement('div');
|
|
12600
|
-
taskSummary.textContent = latestTaskError || latestTaskResult || latestTaskTitle || 'Task queued';
|
|
12620
|
+
taskSummary.textContent = formatRemoteFleetTaskError(latestTaskError) || latestTaskResult || latestTaskTitle || 'Task queued';
|
|
12601
12621
|
taskSummary.title = taskSummary.textContent;
|
|
12602
12622
|
taskSummary.style.cssText = 'color:#334155;font-size:11px;font-weight:750;line-height:1.3;overflow:hidden;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;letter-spacing:0;';
|
|
12603
12623
|
taskBox.appendChild(taskLine);
|
|
@@ -13637,7 +13657,7 @@
|
|
|
13637
13657
|
letter-spacing: 0;
|
|
13638
13658
|
`;
|
|
13639
13659
|
const taskSummary = document.createElement('div');
|
|
13640
|
-
taskSummary.textContent = latestTaskError || latestTaskResult || latestTaskTitle || 'Task queued';
|
|
13660
|
+
taskSummary.textContent = formatRemoteFleetTaskError(latestTaskError) || latestTaskResult || latestTaskTitle || 'Task queued';
|
|
13641
13661
|
taskSummary.title = taskSummary.textContent;
|
|
13642
13662
|
taskSummary.style.cssText = `
|
|
13643
13663
|
color: #334155;
|
|
@@ -13775,6 +13795,30 @@
|
|
|
13775
13795
|
? '#047857'
|
|
13776
13796
|
: '#1d4ed8';
|
|
13777
13797
|
};
|
|
13798
|
+
const formatRemoteFleetDispatchFeedback = (result, fallbackTargetCount = 0, modeLabel = 'remote task') => {
|
|
13799
|
+
const total = Number(result?.total || fallbackTargetCount || 0);
|
|
13800
|
+
const queued = Number(result?.queued || 0);
|
|
13801
|
+
const failed = Number(result?.failed || Math.max(0, total - queued));
|
|
13802
|
+
const failurePreview = String(result?.failurePreview || '').trim();
|
|
13803
|
+
if (!result?.success && queued <= 0) {
|
|
13804
|
+
return {
|
|
13805
|
+
tone: 'error',
|
|
13806
|
+
text: result?.error || `No ${modeLabel}s were queued.`
|
|
13807
|
+
};
|
|
13808
|
+
}
|
|
13809
|
+
|
|
13810
|
+
if (failed > 0) {
|
|
13811
|
+
return {
|
|
13812
|
+
tone: 'error',
|
|
13813
|
+
text: `Queued ${queued}/${total || queued} ${modeLabel}(s); ${failed} failed${failurePreview ? ` - ${failurePreview}` : ''}.`
|
|
13814
|
+
};
|
|
13815
|
+
}
|
|
13816
|
+
|
|
13817
|
+
return {
|
|
13818
|
+
tone: 'success',
|
|
13819
|
+
text: `Queued ${queued || total || 1}/${total || queued || 1} ${modeLabel}(s).`
|
|
13820
|
+
};
|
|
13821
|
+
};
|
|
13778
13822
|
|
|
13779
13823
|
const readTaskInstruction = () => String(taskInput.value || '').trim();
|
|
13780
13824
|
const useAiAssist = () => aiToggle.checked === true;
|
|
@@ -13930,12 +13974,9 @@
|
|
|
13930
13974
|
try {
|
|
13931
13975
|
const result = await invokeDotNetAsync('DispatchRemoteFleetTaskBatchFromJs', nodeId, targetIds, instruction, useAiAssist());
|
|
13932
13976
|
await syncRemoteFleetNodeStateFromResult(result);
|
|
13933
|
-
|
|
13934
|
-
|
|
13935
|
-
|
|
13936
|
-
} else {
|
|
13937
|
-
setTaskFeedback(result?.error || 'Task dispatch failed.', 'error');
|
|
13938
|
-
}
|
|
13977
|
+
const mode = useAiAssist() ? 'visible AI task' : 'visible remote task';
|
|
13978
|
+
const feedback = formatRemoteFleetDispatchFeedback(result, targetIds.length, mode);
|
|
13979
|
+
setTaskFeedback(feedback.text, feedback.tone);
|
|
13939
13980
|
} finally {
|
|
13940
13981
|
applyRemoteFleetFilters();
|
|
13941
13982
|
}
|
|
@@ -13956,12 +13997,9 @@
|
|
|
13956
13997
|
try {
|
|
13957
13998
|
const result = await invokeDotNetAsync('DispatchRemoteFleetTaskFromJs', nodeId, '', instruction, useAiAssist());
|
|
13958
13999
|
await syncRemoteFleetNodeStateFromResult(result);
|
|
13959
|
-
|
|
13960
|
-
|
|
13961
|
-
|
|
13962
|
-
} else {
|
|
13963
|
-
setTaskFeedback(result?.error || 'Task dispatch failed.', 'error');
|
|
13964
|
-
}
|
|
14000
|
+
const mode = useAiAssist() ? 'AI task' : 'remote task';
|
|
14001
|
+
const feedback = formatRemoteFleetDispatchFeedback(result, result?.total || 0, mode);
|
|
14002
|
+
setTaskFeedback(feedback.text, feedback.tone);
|
|
13965
14003
|
} finally {
|
|
13966
14004
|
applyRemoteFleetFilters();
|
|
13967
14005
|
}
|
|
@@ -18091,6 +18129,7 @@
|
|
|
18091
18129
|
syncVideoNodeVisibilityPlayback: syncVideoNodeVisibilityPlayback,
|
|
18092
18130
|
syncEditingOverlay: syncEditingOverlay,
|
|
18093
18131
|
syncTextOverlays: syncTextOverlays,
|
|
18132
|
+
setModuleForTest: setModuleForTest,
|
|
18094
18133
|
renderRemoteFleetMonitorForTest: renderRemoteFleetMonitor,
|
|
18095
18134
|
renderRemoteFleetDeviceForTest: renderRemoteFleetDevice,
|
|
18096
18135
|
renderBusinessAutomationEdges: renderBusinessAutomationEdges,
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/wwwroot/_framework/{MindExecution.Web.ox678bzo06.dll → MindExecution.Web.7b082n0t0o.dll}
RENAMED
|
Binary file
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"mainAssemblyName": "MindExecution.Web",
|
|
3
3
|
"resources": {
|
|
4
|
-
"hash": "sha256-
|
|
4
|
+
"hash": "sha256-EOXWPNQzw1iOoooim3bWEvapz9AQ4G5jOFZbf4RgdGg=",
|
|
5
5
|
"fingerprinting": {
|
|
6
6
|
"Google.Protobuf.9h59ukbel7.dll": "Google.Protobuf.dll",
|
|
7
7
|
"Markdig.d1j7v41cl1.dll": "Markdig.dll",
|
|
@@ -123,16 +123,16 @@
|
|
|
123
123
|
"System.m05i39uvk9.dll": "System.dll",
|
|
124
124
|
"netstandard.0xet7jg7ky.dll": "netstandard.dll",
|
|
125
125
|
"System.Private.CoreLib.rkafq04oma.dll": "System.Private.CoreLib.dll",
|
|
126
|
-
"MindExecution.Core.
|
|
127
|
-
"MindExecution.Kernel.
|
|
128
|
-
"MindExecution.Plugins.Admin.
|
|
129
|
-
"MindExecution.Plugins.Business.
|
|
130
|
-
"MindExecution.Plugins.Concept.
|
|
131
|
-
"MindExecution.Plugins.Directory.
|
|
132
|
-
"MindExecution.Plugins.PlanMaster.
|
|
133
|
-
"MindExecution.Plugins.YouTube.
|
|
134
|
-
"MindExecution.Shared.
|
|
135
|
-
"MindExecution.Web.
|
|
126
|
+
"MindExecution.Core.gvaopvh5wg.dll": "MindExecution.Core.dll",
|
|
127
|
+
"MindExecution.Kernel.hpf3wr4dv3.dll": "MindExecution.Kernel.dll",
|
|
128
|
+
"MindExecution.Plugins.Admin.y0euqt1gu1.dll": "MindExecution.Plugins.Admin.dll",
|
|
129
|
+
"MindExecution.Plugins.Business.9zzc31j54n.dll": "MindExecution.Plugins.Business.dll",
|
|
130
|
+
"MindExecution.Plugins.Concept.sihn2obrrn.dll": "MindExecution.Plugins.Concept.dll",
|
|
131
|
+
"MindExecution.Plugins.Directory.zwbshhfvpb.dll": "MindExecution.Plugins.Directory.dll",
|
|
132
|
+
"MindExecution.Plugins.PlanMaster.47f3afsrf8.dll": "MindExecution.Plugins.PlanMaster.dll",
|
|
133
|
+
"MindExecution.Plugins.YouTube.rpolgpee6c.dll": "MindExecution.Plugins.YouTube.dll",
|
|
134
|
+
"MindExecution.Shared.zm6btxgvlg.dll": "MindExecution.Shared.dll",
|
|
135
|
+
"MindExecution.Web.7b082n0t0o.dll": "MindExecution.Web.dll",
|
|
136
136
|
"dotnet.js": "dotnet.js",
|
|
137
137
|
"dotnet.native.xsn1d6x2kd.js": "dotnet.native.js",
|
|
138
138
|
"dotnet.native.vz0adxojrz.wasm": "dotnet.native.wasm",
|
|
@@ -278,18 +278,18 @@
|
|
|
278
278
|
"System.Xml.XDocument.c539ki6cuq.dll": "sha256-MPTRJkptrL9nGa2tl4kF46+wErNUYRPCGblX3ANoKoY=",
|
|
279
279
|
"System.m05i39uvk9.dll": "sha256-5jDfIdbYAigw7/Q/lMzt5W/+cayGbW9ko9FvuaN1GsQ=",
|
|
280
280
|
"netstandard.0xet7jg7ky.dll": "sha256-xENDv620uJ8fHwLJ2bdhrTHz4QPjvqXOztnk2a4wr0c=",
|
|
281
|
-
"MindExecution.Core.
|
|
282
|
-
"MindExecution.Kernel.
|
|
283
|
-
"MindExecution.Plugins.Concept.
|
|
284
|
-
"MindExecution.Plugins.PlanMaster.
|
|
285
|
-
"MindExecution.Shared.
|
|
286
|
-
"MindExecution.Web.
|
|
281
|
+
"MindExecution.Core.gvaopvh5wg.dll": "sha256-DDLjV7zNlhxfza3LBE+Fbjpke9h8yItLJ3qWzf4Yp74=",
|
|
282
|
+
"MindExecution.Kernel.hpf3wr4dv3.dll": "sha256-RV4W3gMSRwcM23iZfhh4tKgdBlTU0Tfuqld6kSEfxhw=",
|
|
283
|
+
"MindExecution.Plugins.Concept.sihn2obrrn.dll": "sha256-dMpQJwHdXztt3B/lhRoqgpaiEoO7HbZie+ST5g1BAIk=",
|
|
284
|
+
"MindExecution.Plugins.PlanMaster.47f3afsrf8.dll": "sha256-sNW33IqNle0U1uYsT1h4saM9T4UN2hDK13YYWPzOIq4=",
|
|
285
|
+
"MindExecution.Shared.zm6btxgvlg.dll": "sha256-WxdOHLbsCW4r0JnzhaIHm4+nSVJW7WbVpjnf1Uwkk2c=",
|
|
286
|
+
"MindExecution.Web.7b082n0t0o.dll": "sha256-k/Gq3iOPlGciTli3OjQY+EZ/29D4FlrU0tzk6Vu2b4E="
|
|
287
287
|
},
|
|
288
288
|
"lazyAssembly": {
|
|
289
|
-
"MindExecution.Plugins.Admin.
|
|
290
|
-
"MindExecution.Plugins.Business.
|
|
291
|
-
"MindExecution.Plugins.Directory.
|
|
292
|
-
"MindExecution.Plugins.YouTube.
|
|
289
|
+
"MindExecution.Plugins.Admin.y0euqt1gu1.dll": "sha256-gqBZLGmu1nofX9cZu7NzT0StnMnDwaG/eLtHfk95Dg8=",
|
|
290
|
+
"MindExecution.Plugins.Business.9zzc31j54n.dll": "sha256-JTgGpzDyzUUKzJelltauxS03YhSFpdAt31BBx1Ng4pg=",
|
|
291
|
+
"MindExecution.Plugins.Directory.zwbshhfvpb.dll": "sha256-rY/yH9+h3canhVFmdWrcynxahBsnQ4PT5wtCx5OQGFg=",
|
|
292
|
+
"MindExecution.Plugins.YouTube.rpolgpee6c.dll": "sha256-X+TTYJklqCsulTbHi89CZkB4lDXfkTLEj6FH5dJZoDs="
|
|
293
293
|
}
|
|
294
294
|
},
|
|
295
295
|
"cacheBootResources": true,
|
package/wwwroot/index.html
CHANGED
|
@@ -558,7 +558,7 @@
|
|
|
558
558
|
}
|
|
559
559
|
|
|
560
560
|
const base = '_content/MindExecution.Shared/js/';
|
|
561
|
-
const scriptVersion = '20260612-remote-
|
|
561
|
+
const scriptVersion = '20260612-remote-task-timeout-v475';
|
|
562
562
|
const scriptUrl = (script) => `${base}${script}?v=${scriptVersion}`;
|
|
563
563
|
console.log(`[Script Loader] Shared JS version: ${scriptVersion}`);
|
|
564
564
|
const criticalScripts = [
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
self.assetsManifest = {
|
|
2
|
-
"version": "
|
|
2
|
+
"version": "HOeNy0HC",
|
|
3
3
|
"assets": [
|
|
4
4
|
{
|
|
5
5
|
"hash": "sha256-+CSYMcqLNTsq3VnH11jgYyOCCdxvHzL74CBmo4sCmMU=",
|
|
@@ -86,7 +86,7 @@
|
|
|
86
86
|
"url": "_content/MindExecution.Shared/js/mind-map-core.js.backup"
|
|
87
87
|
},
|
|
88
88
|
{
|
|
89
|
-
"hash": "sha256-
|
|
89
|
+
"hash": "sha256-e/aMJjefLL0i7yi8x7tn/EY9wrD0pIxU42m2QKgIYz4=",
|
|
90
90
|
"url": "_content/MindExecution.Shared/js/mind-map-css3d-manager.js"
|
|
91
91
|
},
|
|
92
92
|
{
|
|
@@ -410,44 +410,44 @@
|
|
|
410
410
|
"url": "_framework/MimeMapping.og9ys58ylm.dll"
|
|
411
411
|
},
|
|
412
412
|
{
|
|
413
|
-
"hash": "sha256-
|
|
414
|
-
"url": "_framework/MindExecution.Core.
|
|
413
|
+
"hash": "sha256-DDLjV7zNlhxfza3LBE+Fbjpke9h8yItLJ3qWzf4Yp74=",
|
|
414
|
+
"url": "_framework/MindExecution.Core.gvaopvh5wg.dll"
|
|
415
415
|
},
|
|
416
416
|
{
|
|
417
|
-
"hash": "sha256-
|
|
418
|
-
"url": "_framework/MindExecution.Kernel.
|
|
417
|
+
"hash": "sha256-RV4W3gMSRwcM23iZfhh4tKgdBlTU0Tfuqld6kSEfxhw=",
|
|
418
|
+
"url": "_framework/MindExecution.Kernel.hpf3wr4dv3.dll"
|
|
419
419
|
},
|
|
420
420
|
{
|
|
421
|
-
"hash": "sha256-
|
|
422
|
-
"url": "_framework/MindExecution.Plugins.Admin.
|
|
421
|
+
"hash": "sha256-gqBZLGmu1nofX9cZu7NzT0StnMnDwaG/eLtHfk95Dg8=",
|
|
422
|
+
"url": "_framework/MindExecution.Plugins.Admin.y0euqt1gu1.dll"
|
|
423
423
|
},
|
|
424
424
|
{
|
|
425
|
-
"hash": "sha256-
|
|
426
|
-
"url": "_framework/MindExecution.Plugins.Business.
|
|
425
|
+
"hash": "sha256-JTgGpzDyzUUKzJelltauxS03YhSFpdAt31BBx1Ng4pg=",
|
|
426
|
+
"url": "_framework/MindExecution.Plugins.Business.9zzc31j54n.dll"
|
|
427
427
|
},
|
|
428
428
|
{
|
|
429
|
-
"hash": "sha256-
|
|
430
|
-
"url": "_framework/MindExecution.Plugins.Concept.
|
|
429
|
+
"hash": "sha256-dMpQJwHdXztt3B/lhRoqgpaiEoO7HbZie+ST5g1BAIk=",
|
|
430
|
+
"url": "_framework/MindExecution.Plugins.Concept.sihn2obrrn.dll"
|
|
431
431
|
},
|
|
432
432
|
{
|
|
433
|
-
"hash": "sha256-
|
|
434
|
-
"url": "_framework/MindExecution.Plugins.Directory.
|
|
433
|
+
"hash": "sha256-rY/yH9+h3canhVFmdWrcynxahBsnQ4PT5wtCx5OQGFg=",
|
|
434
|
+
"url": "_framework/MindExecution.Plugins.Directory.zwbshhfvpb.dll"
|
|
435
435
|
},
|
|
436
436
|
{
|
|
437
|
-
"hash": "sha256-
|
|
438
|
-
"url": "_framework/MindExecution.Plugins.PlanMaster.
|
|
437
|
+
"hash": "sha256-sNW33IqNle0U1uYsT1h4saM9T4UN2hDK13YYWPzOIq4=",
|
|
438
|
+
"url": "_framework/MindExecution.Plugins.PlanMaster.47f3afsrf8.dll"
|
|
439
439
|
},
|
|
440
440
|
{
|
|
441
|
-
"hash": "sha256-
|
|
442
|
-
"url": "_framework/MindExecution.Plugins.YouTube.
|
|
441
|
+
"hash": "sha256-X+TTYJklqCsulTbHi89CZkB4lDXfkTLEj6FH5dJZoDs=",
|
|
442
|
+
"url": "_framework/MindExecution.Plugins.YouTube.rpolgpee6c.dll"
|
|
443
443
|
},
|
|
444
444
|
{
|
|
445
|
-
"hash": "sha256-
|
|
446
|
-
"url": "_framework/MindExecution.Shared.
|
|
445
|
+
"hash": "sha256-WxdOHLbsCW4r0JnzhaIHm4+nSVJW7WbVpjnf1Uwkk2c=",
|
|
446
|
+
"url": "_framework/MindExecution.Shared.zm6btxgvlg.dll"
|
|
447
447
|
},
|
|
448
448
|
{
|
|
449
|
-
"hash": "sha256-
|
|
450
|
-
"url": "_framework/MindExecution.Web.
|
|
449
|
+
"hash": "sha256-k/Gq3iOPlGciTli3OjQY+EZ/29D4FlrU0tzk6Vu2b4E=",
|
|
450
|
+
"url": "_framework/MindExecution.Web.7b082n0t0o.dll"
|
|
451
451
|
},
|
|
452
452
|
{
|
|
453
453
|
"hash": "sha256-IsZJ91/OW+fHzNqIgEc7Y072ns8z9dGritiSyvR9Wgc=",
|
|
@@ -770,7 +770,7 @@
|
|
|
770
770
|
"url": "_framework/Websocket.Client.vapounvmnl.dll"
|
|
771
771
|
},
|
|
772
772
|
{
|
|
773
|
-
"hash": "sha256-
|
|
773
|
+
"hash": "sha256-sP1JkizV14ASUo9oVPOopzpprSlzkoXZqpimYvOYBIw=",
|
|
774
774
|
"url": "_framework/blazor.boot.json"
|
|
775
775
|
},
|
|
776
776
|
{
|
|
@@ -834,7 +834,7 @@
|
|
|
834
834
|
"url": "image-manifest.json"
|
|
835
835
|
},
|
|
836
836
|
{
|
|
837
|
-
"hash": "sha256-
|
|
837
|
+
"hash": "sha256-ZWKMY1yo6lJvnKON0C9AmGH2YMwnIs07SFC4mTUDTsQ=",
|
|
838
838
|
"url": "index.html"
|
|
839
839
|
},
|
|
840
840
|
{
|
|
Binary file
|