Fix Odin health actuation and share discovery pass

This commit is contained in:
Meta Vens 2026-06-23 18:36:59 +01:00
commit e1eb4b45a7
7 changed files with 415 additions and 251 deletions

View file

@ -1768,6 +1768,12 @@ fn daemon_surgery_plan(target: &DaemonTarget, updated_at: &str) -> IdunnDaemonSu
fn swarm_targets(options: &SwarmOptions) -> Result<Vec<DaemonTarget>> {
let repo_root = options.repo_root.display().to_string();
let script = |name: &str| format!(r"{}\scripts\{}", repo_root, name);
let powershell_script = |name: &str| {
format!(
r#"C:\WINDOWS\System32\WindowsPowerShell\v1.0\powershell.exe -NoProfile -ExecutionPolicy Bypass -File "{}\scripts\{}""#,
repo_root, name
)
};
let project = |name: &str| PathBuf::from(format!(r"E:\Projects\{name}"));
match options.profile.as_str() {
@ -1777,9 +1783,9 @@ fn swarm_targets(options: &SwarmOptions) -> Result<Vec<DaemonTarget>> {
verse_id: "starfire.local".to_string(),
name: "Odin all-seer".to_string(),
health_contract: health_contract("odin.cultnet-rudp-provider-health", "failed"),
health_command: Some(script("health-odin.cmd")),
health_command: Some(powershell_script("health-odin.ps1")),
deploy_command: None,
restart_command: Some(script("restart-odin.cmd")),
restart_command: Some(powershell_script("restart-odin.ps1")),
release: None,
enabled: true,
interval_seconds: 30,
@ -2701,9 +2707,15 @@ mod tests {
verse_id: "starfire.local".to_string(),
name: "Odin".to_string(),
health_contract: health_contract("odin.cultnet-rudp-provider-health", "failed"),
health_command: Some("health-odin.cmd".to_string()),
health_command: Some(
r#"C:\WINDOWS\System32\WindowsPowerShell\v1.0\powershell.exe -NoProfile -ExecutionPolicy Bypass -File "E:\Projects\Odin\scripts\health-odin.ps1""#
.to_string(),
),
deploy_command: None,
restart_command: Some("restart-odin.cmd".to_string()),
restart_command: Some(
r#"C:\WINDOWS\System32\WindowsPowerShell\v1.0\powershell.exe -NoProfile -ExecutionPolicy Bypass -File "E:\Projects\Odin\scripts\restart-odin.ps1""#
.to_string(),
),
release: None,
enabled: true,
interval_seconds: 30,

View file

@ -1,2 +1,2 @@
@echo off
curl.exe -fsS http://127.0.0.1:8797/health >NUL
"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -ExecutionPolicy Bypass -File E:\Projects\Odin\scripts\health-odin.ps1

80
scripts/health-odin.ps1 Normal file
View file

@ -0,0 +1,80 @@
param(
[int] $Port = 8797,
[string] $StateDir = "E:\Projects\Odin\scratch\odin",
[int] $MaxSilenceSeconds = 120,
[string] $CultNetRudpBind = "0.0.0.0:17871"
)
$ErrorActionPreference = "Stop"
$pidPath = Join-Path $StateDir "odin.pid"
$outLog = Join-Path $StateDir "odin.out.log"
$errLog = Join-Path $StateDir "odin.err.log"
if (-not (Test-Path -LiteralPath $pidPath)) {
throw "Odin PID file is missing at $pidPath"
}
$pidText = (Get-Content -LiteralPath $pidPath -Raw).Trim()
if ($pidText -notmatch '^\d+$') {
throw "Odin PID file is invalid at ${pidPath}: '$pidText'"
}
$process = Get-CimInstance Win32_Process -Filter "ProcessId = $pidText" -ErrorAction SilentlyContinue
if ($null -eq $process) {
throw "Odin process $pidText is not running"
}
foreach ($pattern in @(
'node.exe',
'src\odin-coordinator.cjs',
"--port $Port",
"--stateDir $StateDir",
"--cultnet-rudp-bind $CultNetRudpBind",
'--idunn-daemon odin',
'--idunn-health-contract odin.cultnet-rudp-provider-health'
)) {
if ($process.CommandLine -notlike "*$pattern*") {
throw "Odin process command line is missing expected segment ${pattern}: $($process.CommandLine)"
}
}
foreach ($logPath in @($outLog, $errLog)) {
if (-not (Test-Path -LiteralPath $logPath)) {
throw "Odin log is missing at $logPath"
}
}
$newestLogWriteUtc = @($outLog, $errLog) |
ForEach-Object { (Get-Item -LiteralPath $_).LastWriteTimeUtc } |
Sort-Object -Descending |
Select-Object -First 1
$logAgeSeconds = ([DateTime]::UtcNow - $newestLogWriteUtc).TotalSeconds
$healthUri = "http://127.0.0.1:$Port/health"
try {
$health = Invoke-RestMethod -Uri $healthUri -TimeoutSec 10
} catch {
throw "Odin health endpoint is unavailable at ${healthUri}: $($_.Exception.Message)"
}
if (-not $health.ok) {
throw "Odin health endpoint reports ok=false"
}
$tcpListener = Get-NetTCPConnection -State Listen -LocalPort $Port -ErrorAction SilentlyContinue |
Where-Object { $_.OwningProcess -eq [int]$pidText } |
Select-Object -First 1
if ($null -eq $tcpListener) {
throw "Odin is not listening on TCP port $Port as process $pidText"
}
$rudpPort = [int](($CultNetRudpBind -split ':')[-1])
$udpListener = Get-NetUDPEndpoint -LocalPort $rudpPort -ErrorAction SilentlyContinue |
Where-Object { $_.OwningProcess -eq [int]$pidText } |
Select-Object -First 1
if ($null -eq $udpListener) {
throw "Odin is not listening on UDP port $rudpPort as process $pidText"
}
Write-Host "Odin healthy: pid=$pidText tcp=$Port udp=$rudpPort log_age=$([math]::Round($logAgeSeconds))s"

View file

@ -1,2 +1,2 @@
@echo off
powershell.exe -NoProfile -ExecutionPolicy Bypass -File E:\Projects\Odin\scripts\start-odin.ps1
"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -ExecutionPolicy Bypass -File E:\Projects\Odin\scripts\restart-odin.ps1

35
scripts/restart-odin.ps1 Normal file
View file

@ -0,0 +1,35 @@
param(
[int] $Port = 8797,
[string] $StateDir = "E:\Projects\Odin\scratch\odin",
[string] $CultNetRudpBind = "0.0.0.0:17871",
[string] $IdunnRudpHealth = "127.0.0.1:17870",
[string] $IdunnDaemon = "odin",
[string] $IdunnHealthContract = "odin.cultnet-rudp-provider-health"
)
$ErrorActionPreference = "Stop"
$repoRoot = Split-Path -Parent $PSScriptRoot
$stopScript = Join-Path $PSScriptRoot "stop-odin.ps1"
$startScript = Join-Path $PSScriptRoot "start-odin.ps1"
$healthScript = Join-Path $PSScriptRoot "health-odin.ps1"
$powerShellExe = Join-Path $env:WINDIR "System32\WindowsPowerShell\v1.0\powershell.exe"
if (-not (Test-Path -LiteralPath $powerShellExe)) {
throw "PowerShell executable is missing at $powerShellExe"
}
& $powerShellExe -NoProfile -ExecutionPolicy Bypass -File $stopScript -StateDir $StateDir
& $powerShellExe -NoProfile -ExecutionPolicy Bypass -File $startScript `
-Port $Port `
-StateDir $StateDir `
-CultNetRudpBind $CultNetRudpBind `
-IdunnRudpHealth $IdunnRudpHealth `
-IdunnDaemon $IdunnDaemon `
-IdunnHealthContract $IdunnHealthContract
& $powerShellExe -NoProfile -ExecutionPolicy Bypass -File $healthScript `
-Port $Port `
-StateDir $StateDir `
-CultNetRudpBind $CultNetRudpBind

View file

@ -24,9 +24,102 @@ function createInterfaceDiscovery({
let lastLanScanAt = 0;
async function discoverInterfaces() {
const { interfaces } = await discoverAll();
return interfaces;
}
async function discoverProviderAdvertisements() {
const { providerAdvertisements } = await discoverAll();
return providerAdvertisements;
}
async function discoverAll() {
await refreshLanDeckDiscovery();
const manifestsByProvider = await discoverDeckProviderManifests();
const eveInterfaces = await Promise.all(
[...manifestsByProvider.values()].map(({ provider, deckUrl }) => fetchEveProvider(deckUrl, provider.id, provider)),
);
const { interfaces: cultMeshInterfaces, providerAdvertisements } = await discoverCultMeshEntries();
const interfaces = [...eveInterfaces];
for (const entry of cultMeshInterfaces) {
const existingIndex = interfaces.findIndex((candidate) => candidate.providerId === entry.providerId);
if (existingIndex >= 0) {
interfaces[existingIndex] = entry;
} else {
interfaces.push(entry);
}
}
interfaces.sort((left, right) => left.providerId.localeCompare(right.providerId));
providerAdvertisements.sort((left, right) => String(left.id).localeCompare(String(right.id)));
return { interfaces, providerAdvertisements };
}
function cultMeshDocumentsAvailable() {
const {
interfaceBindingDefinition,
idunnDaemonHealthDefinition,
muninnCaptureStreamDefinition,
muninnCommandBoundaryDefinition,
muninnMoveControllerStateDefinition,
muninnMoveIdentityDefinition,
muninnMoveLightCommandDefinition,
muninnMoveMarkerCandidateDefinition,
muninnObsStreamCatalogDefinition,
muninnQuestAccessDefinition,
muninnTelemetrySurfaceDefinition,
muninnTransportProfileDefinition,
operatorStateDefinition,
providerAdvertisementDefinition,
stonksCommandBoundaryDefinition,
stonksMarketSnapshotDefinition,
stonksRequestEventDefinition,
stonksTransportProfileDefinition,
streamPixelsCommandBoundaryDefinition,
streamPixelsTransportProfileDefinition,
surfaceDefinition,
viliCommandBoundaryDefinition,
viliTransportProfileDefinition,
weksaCommandBoundaryDefinition,
weksaOperatorStateDefinition,
weksaTransportProfileDefinition,
voidbotSwarmSnapshotDefinition,
} = documents;
return Boolean(
CultMesh &&
interfaceBindingDefinition &&
idunnDaemonHealthDefinition &&
muninnCaptureStreamDefinition &&
muninnCommandBoundaryDefinition &&
muninnMoveControllerStateDefinition &&
muninnMoveIdentityDefinition &&
muninnMoveLightCommandDefinition &&
muninnMoveMarkerCandidateDefinition &&
muninnObsStreamCatalogDefinition &&
muninnQuestAccessDefinition &&
muninnTelemetrySurfaceDefinition &&
muninnTransportProfileDefinition &&
operatorStateDefinition &&
providerAdvertisementDefinition &&
stonksCommandBoundaryDefinition &&
stonksMarketSnapshotDefinition &&
stonksRequestEventDefinition &&
stonksTransportProfileDefinition &&
streamPixelsCommandBoundaryDefinition &&
streamPixelsTransportProfileDefinition &&
surfaceDefinition &&
viliCommandBoundaryDefinition &&
viliTransportProfileDefinition &&
weksaCommandBoundaryDefinition &&
weksaOperatorStateDefinition &&
weksaTransportProfileDefinition &&
voidbotSwarmSnapshotDefinition
);
}
async function discoverDeckProviderManifests() {
const manifestsByProvider = new Map();
for (const deckUrl of discoveredDeckUrls) {
await Promise.all(discoveredDeckUrls.map(async (deckUrl) => {
const manifestUrl = deckUrl.replace(/^ws:/, "http:").replace(/\/eve\/deck.*$/, "/eve/deck/providers");
try {
const catalog = JSON.parse(await httpGet(manifestUrl, 2500));
@ -40,25 +133,11 @@ function createInterfaceDiscovery({
} catch {
// Discovery is opportunistic. Failed endpoints fall out of the next pass.
}
}
const interfaces = [];
for (const { provider, deckUrl } of manifestsByProvider.values()) {
interfaces.push(await fetchEveProvider(deckUrl, provider.id, provider));
}
for (const entry of await discoverCultMeshInterfaceBindings()) {
const existingIndex = interfaces.findIndex((candidate) => candidate.providerId === entry.providerId);
if (existingIndex >= 0) {
interfaces[existingIndex] = entry;
} else {
interfaces.push(entry);
}
}
interfaces.sort((left, right) => left.providerId.localeCompare(right.providerId));
return interfaces;
}));
return manifestsByProvider;
}
async function discoverProviderAdvertisements() {
async function discoverCultMeshEntries() {
const {
interfaceBindingDefinition,
idunnDaemonHealthDefinition,
@ -88,280 +167,87 @@ function createInterfaceDiscovery({
weksaTransportProfileDefinition,
voidbotSwarmSnapshotDefinition,
} = documents;
if (!CultMesh || !interfaceBindingDefinition || !idunnDaemonHealthDefinition || !muninnCaptureStreamDefinition || !muninnCommandBoundaryDefinition || !muninnMoveControllerStateDefinition || !muninnMoveIdentityDefinition || !muninnMoveLightCommandDefinition || !muninnMoveMarkerCandidateDefinition || !muninnObsStreamCatalogDefinition || !muninnQuestAccessDefinition || !muninnTelemetrySurfaceDefinition || !muninnTransportProfileDefinition || !operatorStateDefinition || !stonksCommandBoundaryDefinition || !stonksMarketSnapshotDefinition || !stonksRequestEventDefinition || !stonksTransportProfileDefinition || !streamPixelsCommandBoundaryDefinition || !streamPixelsTransportProfileDefinition || !surfaceDefinition || !viliCommandBoundaryDefinition || !viliTransportProfileDefinition || !weksaCommandBoundaryDefinition || !weksaOperatorStateDefinition || !weksaTransportProfileDefinition || !voidbotSwarmSnapshotDefinition || !providerAdvertisementDefinition) {
return [];
if (!cultMeshDocumentsAvailable()) {
return { interfaces: [], providerAdvertisements: [] };
}
const providers = [];
for (const storeSpec of interfaceBindingStores) {
const nodeDocuments = [
voidbotSwarmSnapshotDefinition,
stonksRequestEventDefinition,
stonksMarketSnapshotDefinition,
providerAdvertisementDefinition,
interfaceBindingDefinition,
surfaceDefinition,
stonksCommandBoundaryDefinition,
stonksTransportProfileDefinition,
streamPixelsCommandBoundaryDefinition,
streamPixelsTransportProfileDefinition,
idunnDaemonHealthDefinition,
muninnCaptureStreamDefinition,
muninnCommandBoundaryDefinition,
muninnMoveControllerStateDefinition,
muninnMoveIdentityDefinition,
muninnMoveLightCommandDefinition,
muninnMoveMarkerCandidateDefinition,
muninnObsStreamCatalogDefinition,
muninnQuestAccessDefinition,
muninnTelemetrySurfaceDefinition,
muninnTransportProfileDefinition,
operatorStateDefinition,
viliCommandBoundaryDefinition,
viliTransportProfileDefinition,
weksaOperatorStateDefinition,
weksaCommandBoundaryDefinition,
weksaTransportProfileDefinition,
];
const storeEntries = await Promise.all(interfaceBindingStores.map(async (storeSpec) => {
let resolvedStore = null;
try {
resolvedStore = resolveInterfaceBindingStore(storeSpec);
if (!resolvedStore) {
continue;
return { interfaces: [], providerAdvertisements: [] };
}
const { localPath: storePath, sourceId } = resolvedStore;
if (!fs.existsSync(storePath)) {
continue;
return { interfaces: [], providerAdvertisements: [] };
}
const node = await CultMesh.createNode(storePath, {
documents: [
voidbotSwarmSnapshotDefinition,
stonksRequestEventDefinition,
stonksMarketSnapshotDefinition,
providerAdvertisementDefinition,
interfaceBindingDefinition,
surfaceDefinition,
stonksCommandBoundaryDefinition,
stonksTransportProfileDefinition,
streamPixelsCommandBoundaryDefinition,
streamPixelsTransportProfileDefinition,
idunnDaemonHealthDefinition,
muninnCaptureStreamDefinition,
muninnCommandBoundaryDefinition,
muninnMoveControllerStateDefinition,
muninnMoveIdentityDefinition,
muninnMoveLightCommandDefinition,
muninnMoveMarkerCandidateDefinition,
muninnObsStreamCatalogDefinition,
muninnQuestAccessDefinition,
muninnTelemetrySurfaceDefinition,
muninnTransportProfileDefinition,
operatorStateDefinition,
viliCommandBoundaryDefinition,
viliTransportProfileDefinition,
weksaOperatorStateDefinition,
weksaCommandBoundaryDefinition,
weksaTransportProfileDefinition,
],
const node = await CultMesh.createNode(storePath, { documents: nodeDocuments });
return inspectCultMeshStore({
documents,
interfaceBindingDefinition,
muninnTelemetrySurfaceDefinition,
node,
providerAdvertisementDefinition,
sourceId,
storePath,
});
const advertisements = typeof node.cache?.getAll === "function"
? node.cache.getAll(providerAdvertisementDefinition).map(unwrapDocumentRecord)
: [];
for (const advertisement of advertisements) {
const providerId = advertisement?.providerId || advertisement?.provider?.id || advertisement?.id;
if (!providerId) {
continue;
}
providers.push({
id: providerId,
title: advertisement.title || advertisement.provider?.title || providerId,
description: advertisement.description || "Provider-owned CultMesh advertisement.",
version: String(advertisement.version || 0),
endpoint: advertisement.cultMeshAddress || advertisement.endpoints?.[0]?.address || advertisement.provider?.endpoint || `cultmesh:${sourceId}`,
canonicalService: advertisement.canonicalService || null,
locatedService: advertisement.locatedService || null,
cultMeshAddress: advertisement.cultMeshAddress || null,
endpoints: advertisement.endpoints || [],
routes: advertisement.routes || [],
transportEndpoint: advertisement.routes?.find((route) => route.transport === "cultnet")?.address
|| advertisement.routes?.find((route) => route.transport === "compatibility-eve-deck")?.address
|| advertisement.provider?.endpoint
|| `cultmesh:${sourceId}`,
capabilities: advertisement.provider?.capabilities || advertisement.capabilities || [],
operatorState: providerRecord(node, [
operatorStateDefinition,
weksaOperatorStateDefinition,
], advertisement) || null,
commandBoundary: providerRecord(node, [
muninnCommandBoundaryDefinition,
viliCommandBoundaryDefinition,
weksaCommandBoundaryDefinition,
stonksCommandBoundaryDefinition,
streamPixelsCommandBoundaryDefinition,
], advertisement) || null,
transportProfile: providerRecord(node, [
muninnTransportProfileDefinition,
viliTransportProfileDefinition,
weksaTransportProfileDefinition,
stonksTransportProfileDefinition,
streamPixelsTransportProfileDefinition,
], advertisement) || null,
usesCultMesh: true,
transport: advertisement.provider?.transport || "CultMesh provider advertisement",
status: advertisement.status || "unknown",
updatedAt: advertisement.updatedAt || new Date().toISOString(),
source: `cultmesh:${sourceId}`,
commandSurface: advertisement.commandSurface || null,
});
}
} catch {
// Provider advertisements are optional discovery hints; broken stores
// are still surfaced through interface discovery when possible.
} catch (error) {
const interfaces = [];
const providerAdvertisements = [];
if (resolvedStore?.localPath && fs.existsSync(resolvedStore.localPath)) {
providers.push(...inspectProviderAdvertisementsFromStore(
interfaces.push(...inspectCultMeshInterfacesFromStore(
resolvedStore.localPath,
resolvedStore.sourceId,
));
providerAdvertisements.push(...inspectProviderAdvertisementsFromStore(
resolvedStore.localPath,
resolvedStore.sourceId,
));
}
if (interfaces.length === 0) {
interfaces.push(dashboardUnavailable(`cultmesh:${storeSpec}`, `cultmesh:${storeSpec}`, error.message));
}
return { interfaces, providerAdvertisements };
} finally {
resolvedStore?.cleanup?.();
}
}
}));
providers.sort((left, right) => String(left.id).localeCompare(String(right.id)));
return providers;
}
async function discoverCultMeshInterfaceBindings() {
const {
interfaceBindingDefinition,
idunnDaemonHealthDefinition,
muninnCaptureStreamDefinition,
muninnCommandBoundaryDefinition,
muninnMoveControllerStateDefinition,
muninnMoveIdentityDefinition,
muninnMoveLightCommandDefinition,
muninnMoveMarkerCandidateDefinition,
muninnObsStreamCatalogDefinition,
muninnQuestAccessDefinition,
muninnTelemetrySurfaceDefinition,
muninnTransportProfileDefinition,
operatorStateDefinition,
providerAdvertisementDefinition,
stonksCommandBoundaryDefinition,
stonksMarketSnapshotDefinition,
stonksRequestEventDefinition,
stonksTransportProfileDefinition,
streamPixelsCommandBoundaryDefinition,
streamPixelsTransportProfileDefinition,
surfaceDefinition,
viliCommandBoundaryDefinition,
viliTransportProfileDefinition,
weksaCommandBoundaryDefinition,
weksaOperatorStateDefinition,
weksaTransportProfileDefinition,
voidbotSwarmSnapshotDefinition,
} = documents;
if (!CultMesh || !interfaceBindingDefinition || !idunnDaemonHealthDefinition || !muninnCaptureStreamDefinition || !muninnCommandBoundaryDefinition || !muninnMoveControllerStateDefinition || !muninnMoveIdentityDefinition || !muninnMoveLightCommandDefinition || !muninnMoveMarkerCandidateDefinition || !muninnObsStreamCatalogDefinition || !muninnQuestAccessDefinition || !muninnTelemetrySurfaceDefinition || !muninnTransportProfileDefinition || !operatorStateDefinition || !stonksCommandBoundaryDefinition || !stonksMarketSnapshotDefinition || !stonksRequestEventDefinition || !stonksTransportProfileDefinition || !streamPixelsCommandBoundaryDefinition || !streamPixelsTransportProfileDefinition || !surfaceDefinition || !viliCommandBoundaryDefinition || !viliTransportProfileDefinition || !weksaCommandBoundaryDefinition || !weksaOperatorStateDefinition || !weksaTransportProfileDefinition || !voidbotSwarmSnapshotDefinition || !providerAdvertisementDefinition) {
return [];
}
const interfaces = [];
for (const storeSpec of interfaceBindingStores) {
let resolvedStore = null;
try {
resolvedStore = resolveInterfaceBindingStore(storeSpec);
if (!resolvedStore) {
continue;
}
const { localPath: storePath, sourceId } = resolvedStore;
if (!fs.existsSync(storePath)) {
continue;
}
const node = await CultMesh.createNode(storePath, {
documents: [
voidbotSwarmSnapshotDefinition,
stonksRequestEventDefinition,
stonksMarketSnapshotDefinition,
providerAdvertisementDefinition,
interfaceBindingDefinition,
surfaceDefinition,
stonksCommandBoundaryDefinition,
stonksTransportProfileDefinition,
streamPixelsCommandBoundaryDefinition,
streamPixelsTransportProfileDefinition,
idunnDaemonHealthDefinition,
muninnCaptureStreamDefinition,
muninnCommandBoundaryDefinition,
muninnMoveControllerStateDefinition,
muninnMoveIdentityDefinition,
muninnMoveLightCommandDefinition,
muninnMoveMarkerCandidateDefinition,
muninnObsStreamCatalogDefinition,
muninnQuestAccessDefinition,
muninnTelemetrySurfaceDefinition,
muninnTransportProfileDefinition,
operatorStateDefinition,
viliCommandBoundaryDefinition,
viliTransportProfileDefinition,
weksaOperatorStateDefinition,
weksaCommandBoundaryDefinition,
weksaTransportProfileDefinition,
],
});
const advertisements = typeof node.cache?.getAll === "function"
? node.cache.getAll(providerAdvertisementDefinition).map(unwrapDocumentRecord)
: [];
for (const advertisement of advertisements) {
if (!advertisement?.providerId) {
continue;
}
const state = providerSurfaceState(
node,
advertisement,
surfaceDefinition,
muninnTelemetrySurfaceDefinition,
);
if (!state?.surface?.root) {
continue;
}
interfaces.push(cultMeshProviderInterface({
advertisement,
state,
storePath: sourceId,
operatorState: providerRecord(node, [
operatorStateDefinition,
weksaOperatorStateDefinition,
], advertisement) || null,
commandBoundary: providerRecord(node, [
muninnCommandBoundaryDefinition,
viliCommandBoundaryDefinition,
weksaCommandBoundaryDefinition,
stonksCommandBoundaryDefinition,
streamPixelsCommandBoundaryDefinition,
], advertisement) || null,
transportProfile: providerRecord(node, [
muninnTransportProfileDefinition,
viliTransportProfileDefinition,
weksaTransportProfileDefinition,
stonksTransportProfileDefinition,
streamPixelsTransportProfileDefinition,
], advertisement) || null,
}));
}
const bindings = typeof node.cache?.getAll === "function"
? node.cache.getAll(interfaceBindingDefinition).map(unwrapDocumentRecord)
: [unwrapDocumentRecord(node.get(interfaceBindingDefinition, "voidbot.swarm"))].filter(Boolean);
for (const binding of bindings) {
if (!binding?.providerId) {
continue;
}
const state = unwrapDocumentRecord(node.get(surfaceDefinition, binding.providerId));
const surface = state?.surface || binding.surface || null;
interfaces.push({
providerId: binding.providerId,
title: binding.title || state?.title || binding.providerId,
state: "active",
detail: `${surface?.root?.kind || binding.kind || "surface"} ${countSurfaceNodes(surface, state)} nodes via CultMesh`,
version: state?.version || 0,
updatedAt: state?.updatedAt || binding.updatedAt || new Date().toISOString(),
source: `cultmesh:${sourceId}`,
manifest: binding.provider || null,
canonicalService: binding.provider?.canonicalService || null,
locatedService: binding.provider?.locatedService || null,
cultMeshAddress: binding.provider?.cultMeshAddress || binding.provider?.endpoint || null,
endpoints: binding.provider?.endpoints || [],
routes: binding.provider?.routes || [],
surface,
});
}
} catch (error) {
if (resolvedStore?.localPath && fs.existsSync(resolvedStore.localPath)) {
const fallbackInterfaces = inspectCultMeshInterfacesFromStore(
resolvedStore.localPath,
resolvedStore.sourceId,
);
if (fallbackInterfaces.length > 0) {
interfaces.push(...fallbackInterfaces);
continue;
}
}
interfaces.push(dashboardUnavailable(`cultmesh:${storeSpec}`, `cultmesh:${storeSpec}`, error.message));
} finally {
resolvedStore?.cleanup?.();
}
}
return interfaces;
return {
interfaces: storeEntries.flatMap((entry) => entry.interfaces),
providerAdvertisements: storeEntries.flatMap((entry) => entry.providerAdvertisements),
};
}
async function refreshLanDeckDiscovery() {
@ -383,6 +269,7 @@ function createInterfaceDiscovery({
}
return {
discoverAll,
discoverProviderAdvertisements,
discoverInterfaces,
getDiscoveredDeckUrls: () => [...discoveredDeckUrls],
@ -421,6 +308,146 @@ function cultMeshProviderInterface({
};
}
function inspectCultMeshStore({
documents,
interfaceBindingDefinition,
muninnTelemetrySurfaceDefinition,
node,
providerAdvertisementDefinition,
sourceId,
}) {
const {
operatorStateDefinition,
stonksCommandBoundaryDefinition,
stonksTransportProfileDefinition,
streamPixelsCommandBoundaryDefinition,
streamPixelsTransportProfileDefinition,
surfaceDefinition,
viliCommandBoundaryDefinition,
viliTransportProfileDefinition,
weksaCommandBoundaryDefinition,
weksaOperatorStateDefinition,
weksaTransportProfileDefinition,
muninnCommandBoundaryDefinition,
muninnTransportProfileDefinition,
} = documents;
const providerAdvertisements = [];
const interfaces = [];
const advertisements = typeof node.cache?.getAll === "function"
? node.cache.getAll(providerAdvertisementDefinition).map(unwrapDocumentRecord)
: [];
for (const advertisement of advertisements) {
const providerId = advertisement?.providerId || advertisement?.provider?.id || advertisement?.id;
if (!providerId) {
continue;
}
providerAdvertisements.push({
id: providerId,
title: advertisement.title || advertisement.provider?.title || providerId,
description: advertisement.description || "Provider-owned CultMesh advertisement.",
version: String(advertisement.version || 0),
endpoint: advertisement.cultMeshAddress || advertisement.endpoints?.[0]?.address || advertisement.provider?.endpoint || `cultmesh:${sourceId}`,
canonicalService: advertisement.canonicalService || null,
locatedService: advertisement.locatedService || null,
cultMeshAddress: advertisement.cultMeshAddress || null,
endpoints: advertisement.endpoints || [],
routes: advertisement.routes || [],
transportEndpoint: advertisement.routes?.find((route) => route.transport === "cultnet")?.address
|| advertisement.routes?.find((route) => route.transport === "compatibility-eve-deck")?.address
|| advertisement.provider?.endpoint
|| `cultmesh:${sourceId}`,
capabilities: advertisement.provider?.capabilities || advertisement.capabilities || [],
operatorState: providerRecord(node, [
operatorStateDefinition,
weksaOperatorStateDefinition,
], advertisement) || null,
commandBoundary: providerRecord(node, [
muninnCommandBoundaryDefinition,
viliCommandBoundaryDefinition,
weksaCommandBoundaryDefinition,
stonksCommandBoundaryDefinition,
streamPixelsCommandBoundaryDefinition,
], advertisement) || null,
transportProfile: providerRecord(node, [
muninnTransportProfileDefinition,
viliTransportProfileDefinition,
weksaTransportProfileDefinition,
stonksTransportProfileDefinition,
streamPixelsTransportProfileDefinition,
], advertisement) || null,
usesCultMesh: true,
transport: advertisement.provider?.transport || "CultMesh provider advertisement",
status: advertisement.status || "unknown",
updatedAt: advertisement.updatedAt || new Date().toISOString(),
source: `cultmesh:${sourceId}`,
commandSurface: advertisement.commandSurface || null,
});
const state = providerSurfaceState(
node,
advertisement,
surfaceDefinition,
muninnTelemetrySurfaceDefinition,
);
if (state?.surface?.root) {
interfaces.push(cultMeshProviderInterface({
advertisement,
state,
storePath: sourceId,
operatorState: providerRecord(node, [
operatorStateDefinition,
weksaOperatorStateDefinition,
], advertisement) || null,
commandBoundary: providerRecord(node, [
muninnCommandBoundaryDefinition,
viliCommandBoundaryDefinition,
weksaCommandBoundaryDefinition,
stonksCommandBoundaryDefinition,
streamPixelsCommandBoundaryDefinition,
], advertisement) || null,
transportProfile: providerRecord(node, [
muninnTransportProfileDefinition,
viliTransportProfileDefinition,
weksaTransportProfileDefinition,
stonksTransportProfileDefinition,
streamPixelsTransportProfileDefinition,
], advertisement) || null,
}));
}
}
const bindings = typeof node.cache?.getAll === "function"
? node.cache.getAll(interfaceBindingDefinition).map(unwrapDocumentRecord)
: [unwrapDocumentRecord(node.get(interfaceBindingDefinition, "voidbot.swarm"))].filter(Boolean);
for (const binding of bindings) {
if (!binding?.providerId) {
continue;
}
const state = unwrapDocumentRecord(node.get(surfaceDefinition, binding.providerId));
const surface = state?.surface || binding.surface || null;
interfaces.push({
providerId: binding.providerId,
title: binding.title || state?.title || binding.providerId,
state: "active",
detail: `${surface?.root?.kind || binding.kind || "surface"} ${countSurfaceNodes(surface, state)} nodes via CultMesh`,
version: state?.version || 0,
updatedAt: state?.updatedAt || binding.updatedAt || new Date().toISOString(),
source: `cultmesh:${sourceId}`,
manifest: binding.provider || null,
canonicalService: binding.provider?.canonicalService || null,
locatedService: binding.provider?.locatedService || null,
cultMeshAddress: binding.provider?.cultMeshAddress || binding.provider?.endpoint || null,
endpoints: binding.provider?.endpoints || [],
routes: binding.provider?.routes || [],
surface,
});
}
return { interfaces, providerAdvertisements };
}
function providerSurfaceState(node, advertisement, surfaceDefinition, muninnTelemetrySurfaceDefinition) {
const surfaceKey = advertisement.surfaceId || advertisement.surface_id || advertisement.providerId;
const surfaceState = unwrapDocumentRecord(node.get?.(surfaceDefinition, surfaceKey));

View file

@ -39,17 +39,27 @@ function createStateBuilder({ cachePath, gamecultTextDocumentStorePath, interfac
async function buildState() {
version += 1;
const observedAt = new Date().toISOString();
const [docker, adb, hosts, yggdrasilServices, nightwingServices, nightwingGpu, discoveredInterfaces, providerAdvertisements, observations] = await Promise.all([
const [
docker,
adb,
hosts,
yggdrasilServices,
nightwingServices,
nightwingGpu,
discovery,
observations,
] = await Promise.all([
dockerSnapshot(),
adbSnapshot(),
hostChecks(),
remoteServices("ygg", ["nginx", "streampixels-web", "streampixels-service", "heimdall", "repixelizer-gui", "bifrost"]),
remoteServices("nightwing", ["ssh", "nightwing-eve-dashboard", "nightwing-eve-browser-reference", "gjallar", "docker"]),
remoteGpu("nightwing"),
interfaceDiscovery.discoverInterfaces(),
interfaceDiscovery.discoverProviderAdvertisements(),
interfaceDiscovery.discoverAll(),
observationSnapshot(observationLogPath, observationFreshSeconds),
]);
const discoveredInterfaces = discovery.interfaces;
const providerAdvertisements = discovery.providerAdvertisements;
const interfaceById = new Map(discoveredInterfaces.map((entry) => [entry.providerId, entry]));
const interfaces = [...interfaceById.values()];
const marqueeText = await buildMarqueeText({ interfaces, textDocumentStorePath: gamecultTextDocumentStorePath, stonksBurstSize, stonksStateUrl });