@mindexec/cli 0.2.187 → 0.2.189
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 +4 -2
- package/scripts/remote-hub-identity-smoke.mjs +146 -0
- package/scripts/remote-registry-follower-smoke.mjs +2 -2
- package/server.js +158 -15
- package/wwwroot/_framework/MindExecution.Web.7on7otq3do.dll +0 -0
- package/wwwroot/_framework/blazor.boot.json +3 -3
- package/wwwroot/service-worker-assets.js +4 -4
- package/wwwroot/service-worker.js +1 -1
- package/wwwroot/_framework/MindExecution.Web.ubzzp2laor.dll +0 -0
package/package.json
CHANGED
package/remote-hub.js
CHANGED
|
@@ -875,7 +875,7 @@ export function createRemoteHub(options = {}) {
|
|
|
875
875
|
const publicEndpoint = safeString(env.MINDEXEC_REMOTE_PUBLIC_ENDPOINT || env.REMOTE_HUB_PUBLIC_ENDPOINT, 256);
|
|
876
876
|
const publicHost = safeString(env.MINDEXEC_REMOTE_PUBLIC_HOST || env.REMOTE_HUB_PUBLIC_HOST, 128);
|
|
877
877
|
const pairToken = safeString(
|
|
878
|
-
env.REMOTE_HUB_PAIR_TOKEN || env.MINDEXEC_REMOTE_PAIR_TOKEN || crypto.randomBytes(6).toString('hex'),
|
|
878
|
+
options.pairToken || env.REMOTE_HUB_PAIR_TOKEN || env.MINDEXEC_REMOTE_PAIR_TOKEN || crypto.randomBytes(6).toString('hex'),
|
|
879
879
|
256);
|
|
880
880
|
|
|
881
881
|
const devices = new Map();
|
|
@@ -1043,7 +1043,9 @@ export function createRemoteHub(options = {}) {
|
|
|
1043
1043
|
const routeInfo = getAgentEndpointRouteInfo();
|
|
1044
1044
|
hostTarget = {
|
|
1045
1045
|
nodeId,
|
|
1046
|
-
leaseId: activeSameNode && previous?.leaseId
|
|
1046
|
+
leaseId: activeSameNode && previous?.leaseId
|
|
1047
|
+
? previous.leaseId
|
|
1048
|
+
: (safeString(options.leaseId, 128) || crypto.randomUUID()),
|
|
1047
1049
|
hostInstanceId,
|
|
1048
1050
|
endpoint: routeInfo.endpoint,
|
|
1049
1051
|
endpointCandidates: routeInfo.candidates,
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import assert from 'node:assert/strict';
|
|
4
|
+
import { spawn } from 'node:child_process';
|
|
5
|
+
import { mkdtemp, mkdir, rm } from 'node:fs/promises';
|
|
6
|
+
import net from 'node:net';
|
|
7
|
+
import os from 'node:os';
|
|
8
|
+
import path from 'node:path';
|
|
9
|
+
import { fileURLToPath } from 'node:url';
|
|
10
|
+
|
|
11
|
+
const BRIDGE_TOKEN = 'remote-hub-identity-smoke-token';
|
|
12
|
+
const LOCAL_BRIDGE_DIR = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
13
|
+
|
|
14
|
+
function wait(ms) {
|
|
15
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async function findFreePort() {
|
|
19
|
+
return await new Promise((resolve, reject) => {
|
|
20
|
+
const server = net.createServer();
|
|
21
|
+
server.unref();
|
|
22
|
+
server.once('error', reject);
|
|
23
|
+
server.listen(0, '127.0.0.1', () => {
|
|
24
|
+
const address = server.address();
|
|
25
|
+
const port = typeof address === 'object' && address ? address.port : 0;
|
|
26
|
+
server.close(() => resolve(port));
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async function fetchJson(url, options = {}) {
|
|
32
|
+
const response = await fetch(url, {
|
|
33
|
+
...options,
|
|
34
|
+
headers: {
|
|
35
|
+
'X-Bridge-Token': BRIDGE_TOKEN,
|
|
36
|
+
...(options.headers || {})
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
let payload = null;
|
|
40
|
+
try {
|
|
41
|
+
payload = await response.json();
|
|
42
|
+
} catch {
|
|
43
|
+
// Ignore non-JSON diagnostics.
|
|
44
|
+
}
|
|
45
|
+
return { ok: response.ok, status: response.status, payload };
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function spawnBridge({ bridgePort, remoteHubPort, workspacePath, authDataRoot, label }) {
|
|
49
|
+
const child = spawn(process.execPath, ['server.js'], {
|
|
50
|
+
cwd: LOCAL_BRIDGE_DIR,
|
|
51
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
52
|
+
windowsHide: true,
|
|
53
|
+
env: {
|
|
54
|
+
...process.env,
|
|
55
|
+
BRIDGE_PORT: String(bridgePort),
|
|
56
|
+
BRIDGE_TOKEN,
|
|
57
|
+
BRIDGE_REQUIRE_TOKEN: '1',
|
|
58
|
+
MINDEXEC_REMOTE_HUB: '1',
|
|
59
|
+
MINDEXEC_REMOTE_REGISTRY_FOLLOWER: '0',
|
|
60
|
+
REMOTE_HUB_HOST: '127.0.0.1',
|
|
61
|
+
REMOTE_HUB_PORT: String(remoteHubPort),
|
|
62
|
+
WORKSPACE_PATH: workspacePath,
|
|
63
|
+
MINDEXEC_AUTH_DATA_ROOT: authDataRoot,
|
|
64
|
+
REMOTE_HUB_PAIR_TOKEN: '',
|
|
65
|
+
MINDEXEC_REMOTE_PAIR_TOKEN: '',
|
|
66
|
+
MINDEXEC_BRIDGE_INSTANCE_ID: '',
|
|
67
|
+
NO_COLOR: '1'
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
let stdout = '';
|
|
72
|
+
let stderr = '';
|
|
73
|
+
child.stdout.on('data', chunk => {
|
|
74
|
+
stdout += chunk.toString();
|
|
75
|
+
});
|
|
76
|
+
child.stderr.on('data', chunk => {
|
|
77
|
+
stderr += chunk.toString();
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
const exitPromise = new Promise(resolve => child.once('exit', resolve));
|
|
81
|
+
const details = () => `${label} stdout=${stdout}\n${label} stderr=${stderr}`;
|
|
82
|
+
const stop = async () => {
|
|
83
|
+
if (child.exitCode === null && !child.killed) {
|
|
84
|
+
child.kill('SIGTERM');
|
|
85
|
+
await Promise.race([exitPromise, wait(3000)]);
|
|
86
|
+
if (child.exitCode === null && !child.killed) {
|
|
87
|
+
child.kill('SIGKILL');
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
return {
|
|
93
|
+
baseUrl: `http://127.0.0.1:${bridgePort}`,
|
|
94
|
+
details,
|
|
95
|
+
stop
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
async function waitForStatus(bridge) {
|
|
100
|
+
const startedAt = Date.now();
|
|
101
|
+
while (Date.now() - startedAt < 30000) {
|
|
102
|
+
try {
|
|
103
|
+
const result = await fetchJson(`${bridge.baseUrl}/api/remote/status`);
|
|
104
|
+
if (result.ok && result.payload?.started === true) {
|
|
105
|
+
return result.payload;
|
|
106
|
+
}
|
|
107
|
+
} catch {
|
|
108
|
+
// Bridge still starting.
|
|
109
|
+
}
|
|
110
|
+
await wait(100);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
throw new Error(`Timed out waiting for bridge status.\n${bridge.details()}`);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
async function runOnce({ workspacePath, authDataRoot, label }) {
|
|
117
|
+
const bridgePort = await findFreePort();
|
|
118
|
+
const remoteHubPort = await findFreePort();
|
|
119
|
+
const bridge = spawnBridge({ bridgePort, remoteHubPort, workspacePath, authDataRoot, label });
|
|
120
|
+
try {
|
|
121
|
+
return await waitForStatus(bridge);
|
|
122
|
+
} finally {
|
|
123
|
+
await bridge.stop();
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const tempRoot = await mkdtemp(path.join(os.tmpdir(), 'mindexec-remote-hub-identity-smoke-'));
|
|
128
|
+
try {
|
|
129
|
+
const workspacePath = path.join(tempRoot, 'workspace');
|
|
130
|
+
const authDataRoot = path.join(tempRoot, 'auth');
|
|
131
|
+
await mkdir(workspacePath, { recursive: true });
|
|
132
|
+
await mkdir(authDataRoot, { recursive: true });
|
|
133
|
+
|
|
134
|
+
const first = await runOnce({ workspacePath, authDataRoot, label: 'first' });
|
|
135
|
+
const second = await runOnce({ workspacePath, authDataRoot, label: 'second' });
|
|
136
|
+
|
|
137
|
+
assert.ok(first.pairToken, JSON.stringify(first));
|
|
138
|
+
assert.ok(first.hostInstanceId, JSON.stringify(first));
|
|
139
|
+
assert.equal(second.pairToken, first.pairToken);
|
|
140
|
+
assert.equal(second.hostInstanceId, first.hostInstanceId);
|
|
141
|
+
assert.match(first.hostInstanceId, /^bridge-[a-f0-9]{32}$/);
|
|
142
|
+
|
|
143
|
+
console.log('RemoteHub identity persistence smoke OK');
|
|
144
|
+
} finally {
|
|
145
|
+
await rm(tempRoot, { recursive: true, force: true });
|
|
146
|
+
}
|
|
@@ -72,13 +72,13 @@ async function waitFor(predicate, timeoutMs, label) {
|
|
|
72
72
|
throw new Error(`Timed out waiting for ${label}${lastError ? `: ${lastError.message}` : ''}.`);
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
function createRegistryTarget({ endpoint, endpointCandidates, leaseId, active = true }) {
|
|
75
|
+
function createRegistryTarget({ endpoint, endpointCandidates, leaseId, active = true, pairToken = PAIR_TOKEN }) {
|
|
76
76
|
return {
|
|
77
77
|
user_id: USER_ID,
|
|
78
78
|
active,
|
|
79
79
|
endpoint,
|
|
80
80
|
endpoint_candidates: endpointCandidates,
|
|
81
|
-
pair_token:
|
|
81
|
+
pair_token: pairToken,
|
|
82
82
|
lease_id: leaseId,
|
|
83
83
|
node_id: 'remote-registry-follower-node',
|
|
84
84
|
host_instance_id: `host-${leaseId}`,
|
package/server.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
import express from 'express';
|
|
10
10
|
import cors from 'cors';
|
|
11
|
-
import { promises as fs, readFileSync, statSync, createReadStream, chmodSync } from 'fs';
|
|
11
|
+
import { promises as fs, readFileSync, statSync, createReadStream, chmodSync, mkdirSync, writeFileSync } from 'fs';
|
|
12
12
|
import path from 'path';
|
|
13
13
|
import { exec, spawn, spawnSync, execFile } from 'child_process';
|
|
14
14
|
import { promisify } from 'util';
|
|
@@ -32,10 +32,14 @@ const { normalizePort, releaseBridgePort } = portGuard;
|
|
|
32
32
|
const app = express();
|
|
33
33
|
const PORT = normalizePort(process.env.BRIDGE_PORT);
|
|
34
34
|
const BRIDGE_ROOT = path.dirname(fileURLToPath(import.meta.url));
|
|
35
|
-
const PACKAGE_INFO = JSON.parse(readFileSync(path.join(BRIDGE_ROOT, 'package.json'), 'utf8'));
|
|
35
|
+
const PACKAGE_INFO = JSON.parse(readFileSync(path.join(BRIDGE_ROOT, 'package.json'), 'utf8'));
|
|
36
36
|
const BRIDGE_PACKAGE_NAME = String(PACKAGE_INFO.name || '@mindexec/cli');
|
|
37
37
|
const BRIDGE_VERSION = String(PACKAGE_INFO.version || '0.1.0');
|
|
38
|
-
const
|
|
38
|
+
const REMOTE_HUB_IDENTITY_FILE_PREFIX = 'remote-hub-identity';
|
|
39
|
+
const REMOTE_HUB_IDENTITY_SCOPE = createRemoteHubIdentityScope();
|
|
40
|
+
const REMOTE_HUB_IDENTITY = loadOrCreateRemoteHubIdentity(REMOTE_HUB_IDENTITY_SCOPE);
|
|
41
|
+
const BRIDGE_INSTANCE_ID = String(process.env.MINDEXEC_BRIDGE_INSTANCE_ID || REMOTE_HUB_IDENTITY.hostInstanceId || crypto.randomUUID()).trim() || crypto.randomUUID();
|
|
42
|
+
const REMOTE_HUB_PAIR_TOKEN = String(process.env.REMOTE_HUB_PAIR_TOKEN || process.env.MINDEXEC_REMOTE_PAIR_TOKEN || REMOTE_HUB_IDENTITY.pairToken || crypto.randomBytes(18).toString('hex')).trim() || crypto.randomBytes(18).toString('hex');
|
|
39
43
|
const TREE_SITTER_GRAMMAR_DIR = path.join(BRIDGE_ROOT, 'tree-sitter-grammars');
|
|
40
44
|
const VERBOSE_CODEX_TRACE = /^(1|true|yes|on)$/i.test(String(process.env.BRIDGE_VERBOSE_CODEX || ''));
|
|
41
45
|
const COLOR_LOGS_ENABLED = Boolean(process.stdout.isTTY) && !process.env.NO_COLOR;
|
|
@@ -404,22 +408,95 @@ function looksLikeWorkspaceRoot(candidatePath) {
|
|
|
404
408
|
|| pathExistsSync(path.join(normalizedPath, 'MindExecution.Shared'));
|
|
405
409
|
}
|
|
406
410
|
|
|
407
|
-
function resolveInitialWorkspacePath() {
|
|
408
|
-
const envWorkspacePath = String(process.env.WORKSPACE_PATH || '').trim();
|
|
409
|
-
if (envWorkspacePath) {
|
|
410
|
-
return envWorkspacePath;
|
|
411
|
-
}
|
|
411
|
+
function resolveInitialWorkspacePath() {
|
|
412
|
+
const envWorkspacePath = String(process.env.WORKSPACE_PATH || '').trim();
|
|
413
|
+
if (envWorkspacePath) {
|
|
414
|
+
return envWorkspacePath;
|
|
415
|
+
}
|
|
412
416
|
|
|
413
417
|
const bridgeSiblingWorkspace = path.resolve(BRIDGE_ROOT, '..');
|
|
414
418
|
if (looksLikeWorkspaceRoot(bridgeSiblingWorkspace)) {
|
|
415
419
|
return bridgeSiblingWorkspace;
|
|
416
420
|
}
|
|
417
|
-
|
|
418
|
-
return path.join(os.homedir(), 'Documents', 'MindExecution');
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
const
|
|
421
|
+
|
|
422
|
+
return path.join(os.homedir(), 'Documents', 'MindExecution');
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
function createRemoteHubIdentityScope() {
|
|
426
|
+
const initialWorkspace = path.resolve(resolveInitialWorkspacePath());
|
|
427
|
+
const user = (() => {
|
|
428
|
+
try {
|
|
429
|
+
return os.userInfo().username || '';
|
|
430
|
+
} catch {
|
|
431
|
+
return '';
|
|
432
|
+
}
|
|
433
|
+
})();
|
|
434
|
+
return [
|
|
435
|
+
initialWorkspace.toLowerCase(),
|
|
436
|
+
os.hostname().toLowerCase(),
|
|
437
|
+
user.toLowerCase()
|
|
438
|
+
].join('\n');
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
function createRemoteHubIdentityHash(scope) {
|
|
442
|
+
return crypto
|
|
443
|
+
.createHash('sha256')
|
|
444
|
+
.update(String(scope || 'mindexec-remote-hub'))
|
|
445
|
+
.digest('hex');
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
function getStableRemoteHubIdentityPath(scope) {
|
|
449
|
+
const scopeHash = createRemoteHubIdentityHash(scope).slice(0, 16);
|
|
450
|
+
return path.join(resolveAuthDataRoot(), `${REMOTE_HUB_IDENTITY_FILE_PREFIX}-${scopeHash}.json`);
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
function createStableRemoteHubInstanceId(scope) {
|
|
454
|
+
return `bridge-${createRemoteHubIdentityHash(scope).slice(0, 32)}`;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
function loadOrCreateRemoteHubIdentity(scope) {
|
|
458
|
+
const identityPath = getStableRemoteHubIdentityPath(scope);
|
|
459
|
+
let existing = null;
|
|
460
|
+
try {
|
|
461
|
+
existing = JSON.parse(readFileSync(identityPath, 'utf8'));
|
|
462
|
+
} catch (err) {
|
|
463
|
+
if (err?.code !== 'ENOENT') {
|
|
464
|
+
// Ignore corrupt identity files and replace them with a fresh stable shape.
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
const hostInstanceId = String(existing?.hostInstanceId || '').trim()
|
|
469
|
+
|| createStableRemoteHubInstanceId(scope);
|
|
470
|
+
const pairToken = String(existing?.pairToken || '').trim()
|
|
471
|
+
|| crypto.randomBytes(18).toString('hex');
|
|
472
|
+
const next = {
|
|
473
|
+
version: 1,
|
|
474
|
+
scopeHash: createRemoteHubIdentityHash(scope).slice(0, 16),
|
|
475
|
+
hostInstanceId,
|
|
476
|
+
pairToken
|
|
477
|
+
};
|
|
478
|
+
const changed = existing?.version !== next.version
|
|
479
|
+
|| existing?.scopeHash !== next.scopeHash
|
|
480
|
+
|| existing?.hostInstanceId !== next.hostInstanceId
|
|
481
|
+
|| existing?.pairToken !== next.pairToken;
|
|
482
|
+
|
|
483
|
+
if (changed) {
|
|
484
|
+
try {
|
|
485
|
+
mkdirSync(path.dirname(identityPath), { recursive: true });
|
|
486
|
+
writeFileSync(identityPath, `${JSON.stringify(next, null, 2)}\n`, {
|
|
487
|
+
encoding: 'utf8',
|
|
488
|
+
mode: 0o600
|
|
489
|
+
});
|
|
490
|
+
} catch (err) {
|
|
491
|
+
console.warn(`[RemoteHubIdentity] Failed to persist identity: ${err?.message || err}`);
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
return next;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
// Default workspace path
|
|
499
|
+
const DEFAULT_WORKSPACE = resolveInitialWorkspacePath();
|
|
423
500
|
let workspacePath = DEFAULT_WORKSPACE;
|
|
424
501
|
const browserSessions = new Map();
|
|
425
502
|
let currentBrowserSessionId = null;
|
|
@@ -3363,7 +3440,8 @@ const remoteHub = createRemoteHub({
|
|
|
3363
3440
|
emitFrame: broadcastRemoteBinaryFrame,
|
|
3364
3441
|
managerPackage: BRIDGE_PACKAGE_NAME,
|
|
3365
3442
|
managerVersion: BRIDGE_VERSION,
|
|
3366
|
-
hostInstanceId: BRIDGE_INSTANCE_ID
|
|
3443
|
+
hostInstanceId: BRIDGE_INSTANCE_ID,
|
|
3444
|
+
pairToken: REMOTE_HUB_PAIR_TOKEN
|
|
3367
3445
|
});
|
|
3368
3446
|
|
|
3369
3447
|
const REMOTE_AGENT_STDIO_TAIL_CHARS = 12000;
|
|
@@ -5841,6 +5919,23 @@ function isRemoteRegistryTargetSameAsLocalHost(localHub, target) {
|
|
|
5841
5919
|
&& localHostInstanceId.toLowerCase() === String(target.hostInstanceId).toLowerCase();
|
|
5842
5920
|
}
|
|
5843
5921
|
|
|
5922
|
+
function isRemoteRegistryTargetEndpointLocal(localHub, target) {
|
|
5923
|
+
const localEndpoints = normalizeRemoteManagerEndpointList(
|
|
5924
|
+
localHub?.agentEndpointCandidates,
|
|
5925
|
+
localHub?.agentEndpoint,
|
|
5926
|
+
localHub?.hostTargetEndpointCandidates,
|
|
5927
|
+
localHub?.hostTargetEndpoint);
|
|
5928
|
+
const targetEndpoints = normalizeRemoteManagerEndpointList(
|
|
5929
|
+
target?.endpointCandidates,
|
|
5930
|
+
target?.endpoint);
|
|
5931
|
+
if (localEndpoints.length === 0 || targetEndpoints.length === 0) {
|
|
5932
|
+
return false;
|
|
5933
|
+
}
|
|
5934
|
+
|
|
5935
|
+
const localSet = new Set(localEndpoints.map(endpoint => endpoint.toLowerCase()));
|
|
5936
|
+
return targetEndpoints.some(endpoint => localSet.has(endpoint.toLowerCase()));
|
|
5937
|
+
}
|
|
5938
|
+
|
|
5844
5939
|
async function fetchRemoteRegistryTarget(config, session) {
|
|
5845
5940
|
const url = new URL('/rest/v1/remote_host_targets', config.url);
|
|
5846
5941
|
url.searchParams.set('select', '*');
|
|
@@ -6609,6 +6704,54 @@ async function runRemoteRegistryFollowerOnce(trigger = 'timer') {
|
|
|
6609
6704
|
await ensureRemoteRegistryRealtimeSubscription(config, session, trigger);
|
|
6610
6705
|
const target = await fetchRemoteRegistryTarget(config, session);
|
|
6611
6706
|
|
|
6707
|
+
if (localHub?.hostTargetActive !== true
|
|
6708
|
+
&& target?.active === true
|
|
6709
|
+
&& !isRemoteRegistryTargetExpired(target)
|
|
6710
|
+
&& isRemoteRegistryTargetEndpointLocal(localHub, target)) {
|
|
6711
|
+
const revived = remoteHub.setHostTarget({
|
|
6712
|
+
enabled: true,
|
|
6713
|
+
nodeId: target.nodeId,
|
|
6714
|
+
leaseId: target.leaseId,
|
|
6715
|
+
leaseMs: REMOTE_HOST_TARGET_LEASE_MS
|
|
6716
|
+
});
|
|
6717
|
+
if (revived?.ok === true) {
|
|
6718
|
+
if (isRemoteAgentProcessRunning()) {
|
|
6719
|
+
await stopRemoteAgentConnection('local-host-target-revived');
|
|
6720
|
+
}
|
|
6721
|
+
const revivedHub = remoteHub.getStatus({ includeSecrets: true });
|
|
6722
|
+
const registry = await publishLocalRemoteHostTargetToRegistry(revivedHub, { takeover: true });
|
|
6723
|
+
updateRemoteRegistryFollowerState({
|
|
6724
|
+
status: 'skipped',
|
|
6725
|
+
reason: 'local-monitor-host-revived',
|
|
6726
|
+
authenticated: true,
|
|
6727
|
+
lastAttemptAt: attemptedAt,
|
|
6728
|
+
lastSuccessAt: attemptedAt,
|
|
6729
|
+
targetEndpoint: registry.endpoint || target.endpoint,
|
|
6730
|
+
targetEndpointCandidates: registry.endpointCandidates?.length ? registry.endpointCandidates : target.endpointCandidates,
|
|
6731
|
+
targetLeaseId: revivedHub.hostTargetLeaseId,
|
|
6732
|
+
targetNodeId: revivedHub.hostTargetNodeId,
|
|
6733
|
+
lastError: registry.ok || isRemoteHostTargetRenewSoftSkipReason(registry.reason) ? '' : (registry.reason || 'host-target-republish-failed')
|
|
6734
|
+
});
|
|
6735
|
+
await reportRemoteRegistryFollowerSync({
|
|
6736
|
+
ok: registry.ok !== false,
|
|
6737
|
+
skipped: true,
|
|
6738
|
+
reason: registry.ok ? 'local-monitor-host-revived' : `local-monitor-host-revived-${registry.reason || 'registry-publish-failed'}`,
|
|
6739
|
+
trigger,
|
|
6740
|
+
authenticated: true,
|
|
6741
|
+
localHostTargetActive: true,
|
|
6742
|
+
targetActive: true,
|
|
6743
|
+
targetEndpoint: registry.endpoint || target.endpoint,
|
|
6744
|
+
targetEndpointCandidates: registry.endpointCandidates?.length ? registry.endpointCandidates : target.endpointCandidates,
|
|
6745
|
+
targetLeaseId: revivedHub.hostTargetLeaseId,
|
|
6746
|
+
targetNodeId: revivedHub.hostTargetNodeId,
|
|
6747
|
+
targetExpiresAt: revivedHub.hostTargetExpiresAt
|
|
6748
|
+
});
|
|
6749
|
+
scheduleRemoteHostTargetRenewWake('local-host-revived');
|
|
6750
|
+
scheduleRemoteRegistryFollower(REMOTE_REGISTRY_FOLLOWER_POLL_MS, 'local-host-revived');
|
|
6751
|
+
return serializeRemoteRegistryFollowerState();
|
|
6752
|
+
}
|
|
6753
|
+
}
|
|
6754
|
+
|
|
6612
6755
|
if (localHub?.hostTargetActive === true) {
|
|
6613
6756
|
resetRemoteRegistryInactiveTargetGrace();
|
|
6614
6757
|
if (target?.active === true
|
|
Binary file
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"mainAssemblyName": "MindExecution.Web",
|
|
3
3
|
"resources": {
|
|
4
|
-
"hash": "sha256-
|
|
4
|
+
"hash": "sha256-e0n1RLLtx0J+Ffwaa005iSuhZrI+q9OH/azLs6RFJdE=",
|
|
5
5
|
"fingerprinting": {
|
|
6
6
|
"Google.Protobuf.9h59ukbel7.dll": "Google.Protobuf.dll",
|
|
7
7
|
"Markdig.d1j7v41cl1.dll": "Markdig.dll",
|
|
@@ -132,7 +132,7 @@
|
|
|
132
132
|
"MindExecution.Plugins.PlanMaster.xt4y5gj8yw.dll": "MindExecution.Plugins.PlanMaster.dll",
|
|
133
133
|
"MindExecution.Plugins.YouTube.kz0lju94md.dll": "MindExecution.Plugins.YouTube.dll",
|
|
134
134
|
"MindExecution.Shared.7rwzquw93z.dll": "MindExecution.Shared.dll",
|
|
135
|
-
"MindExecution.Web.
|
|
135
|
+
"MindExecution.Web.7on7otq3do.dll": "MindExecution.Web.dll",
|
|
136
136
|
"dotnet.js": "dotnet.js",
|
|
137
137
|
"dotnet.native.qc8g39g30v.js": "dotnet.native.js",
|
|
138
138
|
"dotnet.native.boem75ye5i.wasm": "dotnet.native.wasm",
|
|
@@ -284,7 +284,7 @@
|
|
|
284
284
|
"MindExecution.Plugins.Concept.3mpew6v5hz.dll": "sha256-K6GVU9mkcEQatq6shNKDO9xtahvaLBOhrIOzYda8lAI=",
|
|
285
285
|
"MindExecution.Plugins.PlanMaster.xt4y5gj8yw.dll": "sha256-Cx47VicQk4brENQ4Y/9SMJ81sawy9AkvnrxuDnqoAYI=",
|
|
286
286
|
"MindExecution.Shared.7rwzquw93z.dll": "sha256-bZ2rx8V2aQu7Ff4nl/mgbEOg3P/3YNjMmFpIXWcu3cQ=",
|
|
287
|
-
"MindExecution.Web.
|
|
287
|
+
"MindExecution.Web.7on7otq3do.dll": "sha256-l3+AdCxkmuRdpmgy+hg5tQBsNft43p/QZ1jFKlJAz2A="
|
|
288
288
|
},
|
|
289
289
|
"lazyAssembly": {
|
|
290
290
|
"MindExecution.Plugins.Admin.29mytzdaun.dll": "sha256-2mHPbTPcHCi1xPuk3dNMVWxn42xZFUZ3QFhm3xIV/6E=",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
self.assetsManifest = {
|
|
2
|
-
"version": "
|
|
2
|
+
"version": "2A2jXlS/",
|
|
3
3
|
"assets": [
|
|
4
4
|
{
|
|
5
5
|
"hash": "sha256-+CSYMcqLNTsq3VnH11jgYyOCCdxvHzL74CBmo4sCmMU=",
|
|
@@ -446,8 +446,8 @@
|
|
|
446
446
|
"url": "_framework/MindExecution.Shared.7rwzquw93z.dll"
|
|
447
447
|
},
|
|
448
448
|
{
|
|
449
|
-
"hash": "sha256-
|
|
450
|
-
"url": "_framework/MindExecution.Web.
|
|
449
|
+
"hash": "sha256-l3+AdCxkmuRdpmgy+hg5tQBsNft43p/QZ1jFKlJAz2A=",
|
|
450
|
+
"url": "_framework/MindExecution.Web.7on7otq3do.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-/VqlSl0soIWMyeyUaHS8719wDwRJJLAk6Wh9TJo4PVU=",
|
|
774
774
|
"url": "_framework/blazor.boot.json"
|
|
775
775
|
},
|
|
776
776
|
{
|
|
Binary file
|