Publish swarm controls as bound Eve state

This commit is contained in:
Meta Vens 2026-07-15 01:41:41 +01:00
commit 5233283f3a
2 changed files with 36 additions and 7 deletions

View file

@ -978,8 +978,11 @@ function timestampForFile(date) {
}
function loadCultPackages() {
const cultLibRoot = process.env.VOIDBOT_CULTLIB_ROOT
? resolve(process.env.VOIDBOT_CULTLIB_ROOT)
: resolve(repoRoot, "..", "CultLib-codex-cultmesh-reliability");
const candidates = [
resolve(repoRoot, "..", "CultLib", "packages", "cultmesh-ts", "package.json"),
resolve(cultLibRoot, "packages", "cultmesh-ts", "package.json"),
resolve(repoRoot, "..", "CultMeshTS", "package.json"),
];
for (const packageJson of candidates) {
@ -1379,10 +1382,17 @@ function buildEveProviderState(snapshot) {
command: "swarm.set_heat",
transport: "cultmesh-binding",
providerId,
value: summary.globalHeat ?? 1,
min: 0.05,
max: 2,
step: 0.05,
stateBindings: [{
targetProp: "value",
pointerId: "globalHeat",
sourceId: "voidbot.swarm_control_state:voidbot-swarm",
schemaId: "voidbot.swarm_control_state.v1",
routeKind: "cultmesh-rudp",
routeDescription: swarmCultMeshRudpEndpoint,
}],
}),
]),
]),
@ -1713,13 +1723,14 @@ function clampPercent(value) {
}
function eveNode(id, kind, props = {}, children = []) {
const { layout, style, ...nodeProps } = props ?? {};
const { layout, style, stateBindings, ...nodeProps } = props ?? {};
return {
id,
kind,
props: nodeProps,
...(layout && typeof layout === "object" ? { layout } : {}),
...(style && typeof style === "object" ? { style } : {}),
...(Array.isArray(stateBindings) && stateBindings.length > 0 ? { stateBindings } : {}),
children,
};
}

View file

@ -40,6 +40,7 @@ main().catch((error) => {
});
async function main() {
await publishCurrentControlState();
server = CultMesh.createRudpDocumentServer("voidbot-swarm-cultmesh", connectionId, {
bindHost: bind.host,
bindPort: bind.port,
@ -83,6 +84,13 @@ async function main() {
process.once("SIGTERM", shutdown);
}
async function publishCurrentControlState() {
if (!fs.existsSync(controlStorePath)) return;
const controlNode = await CultMesh.createNode(controlStorePath, { documents: [documents.swarmControl] });
const control = controlNode.get(documents.swarmControl, "voidbot-swarm");
if (control) await projectAcceptedHeat(control);
}
async function applySwarmCommand(document) {
if (document.schemaId !== "gamecult.eve.command.v1") return;
const command = document.payload;
@ -101,6 +109,7 @@ async function applySwarmCommand(document) {
};
await node.put(documents.swarmControl, "voidbot-swarm", control);
await node.flush?.(true);
await projectAcceptedHeat(control);
console.log(`Applied swarm heat ${control.globalHeat} from ${control.commandId}`);
return {
binding: bindings.commandReceipt,
@ -118,7 +127,7 @@ async function applySwarmCommand(document) {
sourceVersion: Date.parse(control.updatedAt),
issuedAtUtc: control.updatedAt,
message: `Swarm heat applied at ${control.globalHeat}.`,
diagnostics: [{ binding: "voidbot.swarm.globalHeat", value: control.globalHeat }],
diagnostics: [{ code: "state-published", pointerId: "summary.globalHeat" }],
},
sourceRuntimeId: "voidbot-swarm-cultmesh",
sourceRole: "swarm-control-owner",
@ -126,6 +135,12 @@ async function applySwarmCommand(document) {
};
}
async function projectAcceptedHeat(control) {
const node = await CultMesh.createNode(storePath, { documents: documentDefinitions });
await node.put(documents.swarmControl, "voidbot-swarm", control);
await node.flush?.(true);
}
async function announceToOdin() {
const node = await CultMesh.createNode(storePath, {
documents: documentDefinitions,
@ -268,11 +283,14 @@ function defineDocuments(defineDocumentType) {
}
function loadCultRuntime() {
const packageJson = path.resolve(repoRoot, "..", "CultLib", "packages", "cultmesh-ts", "package.json");
const cultLibRoot = process.env.VOIDBOT_CULTLIB_ROOT
? path.resolve(process.env.VOIDBOT_CULTLIB_ROOT)
: path.resolve(repoRoot, "..", "CultLib-codex-cultmesh-reliability");
const packageJson = path.resolve(cultLibRoot, "packages", "cultmesh-ts", "package.json");
const requireCult = createRequire(packageJson);
const { CultMesh } = requireCult("./dist/index.js");
const { CultNetDocumentRegistry, defineCultNetDocumentBinding } = createRequire(path.resolve(repoRoot, "..", "CultLib", "packages", "cultnet-ts", "package.json"))("./dist/index.js");
const { defineDocumentType } = createRequire(path.resolve(repoRoot, "..", "CultLib", "packages", "cultcache-ts", "package.json"))("./dist/index.js");
const { CultNetDocumentRegistry, defineCultNetDocumentBinding } = createRequire(path.resolve(cultLibRoot, "packages", "cultnet-ts", "package.json"))("./dist/index.js");
const { defineDocumentType } = createRequire(path.resolve(cultLibRoot, "packages", "cultcache-ts", "package.json"))("./dist/index.js");
return { CultMesh, CultNetDocumentRegistry, defineCultNetDocumentBinding, defineDocumentType };
}