Publish Stonks startup respect to Odin

This commit is contained in:
Meta Vens 2026-06-23 22:58:13 +01:00
commit bf0381ae74
4 changed files with 60 additions and 0 deletions

19
package-lock.json generated
View file

@ -10,6 +10,7 @@
"license": "MIT",
"dependencies": {
"cultcache-ts": "file:../CultLib/packages/cultcache-ts",
"cultmesh-ts": "file:../CultLib/packages/cultmesh-ts",
"cultnet-ts": "file:../CultLib/packages/cultnet-ts"
},
"engines": {
@ -28,6 +29,20 @@
"typescript": "^5.9.0"
}
},
"../CultLib/packages/cultmesh-ts": {
"version": "0.1.0",
"license": "MIT",
"dependencies": {
"@msgpack/msgpack": "^3.1.2",
"cultcache-ts": "file:../cultcache-ts",
"cultnet-ts": "file:../cultnet-ts"
},
"devDependencies": {
"@types/node": "^24.0.0",
"typescript": "^5.9.0",
"zod": "^3.25.76"
}
},
"../CultLib/packages/cultnet-ts": {
"version": "0.1.0",
"license": "MIT",
@ -47,6 +62,10 @@
"resolved": "../CultLib/packages/cultcache-ts",
"link": true
},
"node_modules/cultmesh-ts": {
"resolved": "../CultLib/packages/cultmesh-ts",
"link": true
},
"node_modules/cultnet-ts": {
"resolved": "../CultLib/packages/cultnet-ts",
"link": true

View file

@ -10,6 +10,7 @@
},
"dependencies": {
"cultcache-ts": "file:../CultLib/packages/cultcache-ts",
"cultmesh-ts": "file:../CultLib/packages/cultmesh-ts",
"cultnet-ts": "file:../CultLib/packages/cultnet-ts"
},
"engines": {

View file

@ -5,6 +5,7 @@ param(
[string] $IdunnRudpHealth = "127.0.0.1:17870",
[string] $IdunnDaemon = "stonks",
[string] $IdunnHealthContract = "stonks.cultnet-rudp-market-health",
[string] $OdinCultMeshRudp = "127.0.0.1:17871",
[switch] $Foreground
)
@ -41,6 +42,10 @@ $args = @(
"--idunn-health-contract", $IdunnHealthContract
)
if (-not [string]::IsNullOrWhiteSpace($OdinCultMeshRudp)) {
$args += @("--odin-cultmesh-rudp", $OdinCultMeshRudp)
}
if ($Foreground) {
& node @args
exit $LASTEXITCODE
@ -59,3 +64,4 @@ if ($proc.HasExited) {
Write-Host "Stonks started as PID $($proc.Id)."
Write-Host "Health: http://127.0.0.1:$Port/health"
Write-Host "Eve deck: ws://127.0.0.1:$Port/eve/deck"
Write-Host "Odin CultMesh/RUDP: $OdinCultMeshRudp"

View file

@ -12,6 +12,8 @@ const {
defineDocumentRegistry,
defineDocumentType,
} = require("cultcache-ts");
const { CultMesh } = require("cultmesh-ts");
const { defineCultNetDocumentBinding } = require("cultnet-ts");
const { createIdunnRudpHealthPublisher, publishIdunnRudpHealth } = require("./idunn-rudp.cjs");
const repoRoot = path.resolve(__dirname, "..");
@ -28,6 +30,7 @@ const mentionRefreshMs = clampNumber(args.mentionRefreshMs || process.env.STONKS
const idunnRudpHealth = args["idunn-rudp-health"] || process.env.STONKS_IDUNN_RUDP_HEALTH;
const idunnDaemon = args["idunn-daemon"] || process.env.STONKS_IDUNN_DAEMON || "stonks";
const idunnHealthContract = args["idunn-health-contract"] || process.env.STONKS_IDUNN_HEALTH_CONTRACT || "stonks.cultnet-rudp-market-health";
const odinCultMeshRudp = args["odin-cultmesh-rudp"] || process.env.STONKS_ODIN_CULTMESH_RUDP;
const idunnRudpHealthPublisher = createIdunnRudpHealthPublisher(idunnRudpHealth ? {
endpoint: idunnRudpHealth,
daemonId: idunnDaemon,
@ -219,6 +222,7 @@ async function main() {
});
await refresh();
await publishOdinStartupRespect();
scheduleRefresh();
}
@ -293,6 +297,28 @@ async function publishStonksHealth(state, detail) {
}
}
async function publishOdinStartupRespect() {
if (!odinCultMeshRudp) return;
try {
const advertisement = providerAdvertisement(currentState);
await CultMesh.publishRudpDocumentOnce(
idunnDaemon,
0x0d1d0002,
normalizeRudpEndpoint(odinCultMeshRudp),
defineCultNetDocumentBinding({ definition: providerAdvertisementDocument }),
advertisement.providerId,
advertisement,
{
sourceRole: "stonks.provider",
tags: ["startup-respect", "odin-verse-discovery"],
},
);
console.log(`Stonks Odin startup respect published to ${odinCultMeshRudp}`);
} catch (error) {
console.error("Stonks Odin startup respect failed:", error.message);
}
}
function stonksHealthDetail(snapshot) {
return [
`Stonks refreshed market snapshot in ${snapshot.durationMs}ms`,
@ -1038,6 +1064,14 @@ function readSecretFile(filePath) {
}
}
function normalizeRudpEndpoint(endpoint) {
const text = String(endpoint || "").trim();
if (!text) {
throw new Error("Odin CultMesh/RUDP endpoint must be non-empty.");
}
return text.toLowerCase().startsWith("rudp://") ? text : `rudp://${text}`;
}
function radarSymbolsFor(date, mentionedSymbols = []) {
if (radarSymbols.length === 0) return [];
const configured = new Set(radarSymbols);