Vili/scripts/vili-daemon.mjs
Meta Vens f6acfc1c85 Vili worker: Kimodo's text encoder is the cache, not a resident 8B model
The worker builds CachedTextEncoder and passes it to load_model, so Kimodo's own
encoder selection (and the CPU encoder behind TEXT_ENCODER_DEVICE) is never built.
generate() returns the per-request encoder record (identity, hits, misses, seconds,
vector hashes) and the worker identity; /health adds the identity and stored count.
startKimodoWorker drops TEXT_ENCODER_DEVICE and mounts the scripts directory, the
cultcache-py source and .vili/embeddings, with the Kimodo commit and image id read
once per worker start. The encode clock is perf_counter: time.time went backwards
under WSL during a probe.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 21:18:17 +02:00

751 lines
28 KiB
JavaScript

#!/usr/bin/env node
import http from "node:http";
import { mkdir, writeFile } from "node:fs/promises";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { createRequire } from "node:module";
import { execFile } from "node:child_process";
import { WebSocketServer } from "ws";
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const require = createRequire(import.meta.url);
const {
CultCache,
SingleFileMessagePackBackingStore,
defineDocumentRegistry,
defineDocumentType,
} = require("cultcache-ts");
const projectRoot = path.resolve(__dirname, "..");
const ravenBaseUrl = process.env.VILI_PUBLIC_BASE_URL || "http://10.77.0.4:8824";
const ravenDeckUrl = process.env.VILI_PUBLIC_DECK_URL || "ws://10.77.0.4:8824/eve/deck";
const providerId = "vili.animation";
const viliStoreFileName = "vili.service.cc";
const kimodoWorkerName = process.env.VILI_KIMODO_WORKER_NAME || "vili-kimodo-worker";
const kimodoWorkerPort = Number(process.env.VILI_KIMODO_WORKER_PORT || 8825);
const kimodoWorkerUrl = `http://127.0.0.1:${kimodoWorkerPort}`;
const dockerHuggingFaceEnv = [
"export HF_TOKEN=\"$(cat /root/.cache/huggingface/token 2>/dev/null || true)\"",
"export HUGGING_FACE_HUB_TOKEN=\"$HF_TOKEN\"",
].join("; ");
const dockerHuggingFaceArgs = [
"-e HF_TOKEN",
"-e HUGGING_FACE_HUB_TOKEN",
"-v /root/.cache/huggingface:/root/.cache/huggingface",
].join(" ");
const objectSchema = { parse: (value) => value };
const providerAdvertisementDefinition = defineDocumentType({
type: "gamecult.eve.provider_advertisement",
schemaName: "gamecult.eve.provider_advertisement",
schemaId: "gamecult.eve.provider_advertisement.v1",
schemaVersion: "gamecult.eve.provider_advertisement.v1",
name: (value) => value?.providerId || "provider",
schema: objectSchema,
members: [
{ slot: 0, memberName: "providerId", typeName: "string", isName: true },
{ slot: 1, memberName: "title", typeName: "string" },
{ slot: 2, memberName: "verseId", typeName: "string" },
{ slot: 3, memberName: "updatedAt", typeName: "string" },
],
});
const operatorStateDefinition = defineDocumentType({
type: "gamecult.vili.operator_state",
schemaName: "gamecult.vili.operator_state",
schemaId: "gamecult.vili.operator_state.v1",
schemaVersion: "gamecult.vili.operator_state.v1",
name: (value) => value?.service || "vili",
schema: objectSchema,
members: [
{ slot: 0, memberName: "service", typeName: "string", isName: true },
{ slot: 1, memberName: "providerId", typeName: "string" },
{ slot: 2, memberName: "updatedAt", typeName: "string" },
{ slot: 3, memberName: "backend", typeName: "object" },
],
});
const eveSurfaceDefinition = defineDocumentType({
type: "gamecult.eve.surface_state",
schemaName: "gamecult.eve.surface_state",
schemaId: "gamecult.eve.surface_state.v1",
schemaVersion: "gamecult.eve.surface_state.v1",
name: (value) => value?.providerId || "surface",
schema: objectSchema,
members: [
{ slot: 0, memberName: "providerId", typeName: "string", isName: true },
{ slot: 1, memberName: "title", typeName: "string" },
{ slot: 2, memberName: "updatedAt", typeName: "string" },
{ slot: 3, memberName: "surface", typeName: "object" },
],
});
const commandBoundaryDefinition = defineDocumentType({
type: "gamecult.vili.command_boundary",
schemaName: "gamecult.vili.command_boundary",
schemaId: "gamecult.vili.command_boundary.v1",
schemaVersion: "gamecult.vili.command_boundary.v1",
name: (value) => value?.boundaryId || "vili",
schema: objectSchema,
members: [
{ slot: 0, memberName: "boundaryId", typeName: "string", isName: true },
{ slot: 1, memberName: "owner", typeName: "string" },
{ slot: 2, memberName: "commandAuthority", typeName: "object" },
{ slot: 3, memberName: "forbiddenAuthority", typeName: "string" },
{ slot: 4, memberName: "updatedAt", typeName: "string" },
],
});
const transportProfileDefinition = defineDocumentType({
type: "gamecult.vili.transport_profile",
schemaName: "gamecult.vili.transport_profile",
schemaId: "gamecult.vili.transport_profile.v1",
schemaVersion: "gamecult.vili.transport_profile.v1",
name: (value) => value?.profileId || "vili",
schema: objectSchema,
members: [
{ slot: 0, memberName: "profileId", typeName: "string", isName: true },
{ slot: 1, memberName: "daemonId", typeName: "string" },
{ slot: 2, memberName: "targetTransport", typeName: "string" },
{ slot: 3, memberName: "state", typeName: "string" },
{ slot: 4, memberName: "updatedAt", typeName: "string" },
],
});
const viliDocumentRegistry = defineDocumentRegistry(
providerAdvertisementDefinition,
operatorStateDefinition,
eveSurfaceDefinition,
commandBoundaryDefinition,
transportProfileDefinition,
);
function parseArgs(argv) {
const args = {
host: process.env.VILI_DAEMON_HOST || "127.0.0.1",
port: Number(process.env.VILI_DAEMON_PORT || 8824),
stateRoot: process.env.VILI_STATE_ROOT || path.join(projectRoot, ".vili"),
health: false,
printProviderAdvertisement: false,
};
for (let index = 0; index < argv.length; index += 1) {
const arg = argv[index];
if (arg === "--host") args.host = argv[++index];
else if (arg === "--port") args.port = Number(argv[++index]);
else if (arg === "--state-root") args.stateRoot = path.resolve(argv[++index]);
else if (arg === "--health") args.health = true;
else if (arg === "--print-provider-advertisement") args.printProviderAdvertisement = true;
}
return args;
}
const args = parseArgs(process.argv.slice(2));
const startedAt = new Date().toISOString();
let backendStatus = {
checkedAt: null,
dockerImage: "unknown",
nvidiaRuntime: "unknown",
huggingFaceToken: "unknown",
kimodoHelp: "unknown",
kimodoWorker: "unknown",
kimodoWorkerDetail: null,
lastError: null,
};
function run(command, commandArgs, options = {}) {
return new Promise((resolve) => {
execFile(command, commandArgs, {
cwd: projectRoot,
timeout: options.timeout ?? 20000,
env: { ...process.env, ...(options.env || {}) },
windowsHide: true,
maxBuffer: 1024 * 1024 * 4,
}, (error, stdout, stderr) => {
resolve({
ok: !error,
code: error?.code ?? 0,
signal: error?.signal ?? null,
stdout: String(stdout || "").trim(),
stderr: String(stderr || "").trim(),
error: error ? String(error.message || error) : null,
});
});
});
}
function wsl(script, options = {}) {
return run("wsl.exe", ["-d", "Ubuntu-24.04", "-u", "root", "--", "bash", "-lc", script], options);
}
function shQuote(value) {
return `'${String(value).replaceAll("'", "'\\''")}'`;
}
function firstDefined(...values) {
return values.find((value) => value !== undefined && value !== null);
}
function boolValue(value) {
return value === true || String(value).toLowerCase() === "true" || String(value) === "1";
}
async function wslJson(script, options = {}) {
const result = await wsl(script, options);
if (!result.ok) return { ...result, body: null };
try {
return { ...result, body: JSON.parse(result.stdout) };
} catch (error) {
return { ...result, ok: false, body: null, error: `Invalid JSON: ${error.message}`, stderr: result.stderr };
}
}
function json(response, statusCode, body) {
const payload = JSON.stringify(body, null, 2);
response.writeHead(statusCode, {
"content-type": "application/json; charset=utf-8",
"cache-control": "no-store",
"access-control-allow-origin": "*",
});
response.end(payload);
}
function text(response, statusCode, body) {
response.writeHead(statusCode, {
"content-type": "text/plain; charset=utf-8",
"cache-control": "no-store",
"access-control-allow-origin": "*",
});
response.end(body);
}
function providerAdvertisement() {
return {
schema: "gamecult.eve.provider_advertisement.v1",
providerId,
title: "Vili Animation",
description: "Persona animation and Kimodo motion generation daemon on Raven.",
canonicalService: "asgard.vili",
locatedService: "asgard.raven.vili",
verseId: "raven.local",
cultMeshAddress: "asgard.raven.vili/eve/operator",
updatedAt: new Date().toISOString(),
endpoints: {
http: ravenBaseUrl,
health: `${ravenBaseUrl}/health`,
smoke: `${ravenBaseUrl}/smoke`,
providerAdvertisement: `${ravenBaseUrl}/provider-advertisement`,
operatorState: `${ravenBaseUrl}/operator-state`,
operatorSurface: `${ravenBaseUrl}/eve/operator`,
deckBroker: ravenDeckUrl,
providerDeck: `${ravenDeckUrl}/${providerId}`,
},
capabilities: [
"kimodo.motion.generate",
"persona.performance.intent",
"eve.operator.surface",
"cultmesh.provider.discovery",
],
};
}
function operatorState() {
return {
schema: "gamecult.vili.operator_state.v0",
service: "vili",
providerId,
verseId: "raven.local",
host: "raven",
startedAt,
updatedAt: new Date().toISOString(),
backend: backendStatus,
authority: {
owns: [
"animation job intake",
"Kimodo runtime checks",
"Kimodo resident worker lifecycle",
"motion artifact references",
"Vili provider and operator surfaces",
],
doesNotOwn: [
"Persona speech generation",
"Weksa interlingua lowering",
"retargeting and playback",
"Odin discovery truth",
],
},
routes: {
health: "/health",
providerAdvertisement: "/provider-advertisement",
operatorState: "/operator-state",
operatorSurface: "/eve/operator",
deckProviders: "/eve/deck/providers",
smoke: "/smoke",
generate: "/motion/generate",
},
};
}
function commandBoundary() {
return {
schema: "gamecult.vili.command_boundary.v1",
boundaryId: "vili",
daemonId: "vili",
owner: "Vili animation runtime",
updatedAt: new Date().toISOString(),
commandAuthority: {
intake: {
method: "POST",
path: "/motion/generate",
owns: [
"animation job identity",
"request persistence",
"Kimodo resident worker lifecycle",
"timeout handling",
"motion artifact references",
],
},
smoke: {
method: "GET",
path: "/smoke",
owns: ["backend readiness proof", "resident worker warmup"],
},
liveness: {
method: "GET",
path: "/health",
owns: ["compatibility liveness witness"],
doesNotOwn: [],
},
},
forbiddenAuthority:
"HTTP health, WebSocket decks, and JSON sidecars are compatibility/operator lowerings; they do not own daemon health or provider truth when CultCache/CultNet records exist.",
};
}
function transportProfile() {
return {
schema: "gamecult.vili.transport_profile.v1",
profileId: "vili",
daemonId: "vili",
targetTransport: "cultnet.transport.rudp.v0",
currentTransport: "CultCache local state + compatibility HTTP/WS lowerings",
state: "local-cultcache-only",
providerAdvertisementSchema: "gamecult.eve.provider_advertisement.v1",
operatorStateSchema: "gamecult.vili.operator_state.v1",
commandBoundarySchema: "gamecult.vili.command_boundary.v1",
compatibilityMechanisms: [
`${ravenBaseUrl}/health`,
`${ravenBaseUrl}/provider-advertisement`,
`${ravenDeckUrl}/${providerId}`,
],
cutLine:
"Vili owns typed provider, operator, command, and transport state. HTTP/WS/JSON projections are lowerings until Odin consumes Vili provider records over CultNet/RUDP.",
updatedAt: new Date().toISOString(),
};
}
function eveSurface() {
const state = operatorState();
return {
schema: "gamecult.eve.surface.v1",
providerId,
title: "Vili Animation",
updatedAt: state.updatedAt,
surface: {
root: {
type: "panel",
title: "Vili Animation",
children: [
{ type: "stat", label: "Host", value: "Raven" },
{ type: "stat", label: "Verse", value: "raven.local" },
{ type: "stat", label: "Docker image", value: state.backend.dockerImage },
{ type: "stat", label: "NVIDIA runtime", value: state.backend.nvidiaRuntime },
{ type: "stat", label: "Kimodo", value: state.backend.kimodoHelp },
{ type: "stat", label: "Kimodo worker", value: state.backend.kimodoWorker },
{ type: "stat", label: "HF token", value: state.backend.huggingFaceToken },
{ type: "command", label: "Smoke", method: "GET", href: `${ravenBaseUrl}/smoke` },
{ type: "command", label: "Generate motion", method: "POST", href: `${ravenBaseUrl}/motion/generate` },
],
},
},
state,
};
}
async function persistSurfaces() {
await mkdir(args.stateRoot, { recursive: true });
await persistCultCacheSurfaces();
await writeFile(path.join(args.stateRoot, "vili-daemon.pid"), `${process.pid}\n`);
await writeFile(path.join(args.stateRoot, "provider-advertisement.json"), JSON.stringify(providerAdvertisement(), null, 2));
await writeFile(path.join(args.stateRoot, "operator-state.json"), JSON.stringify(operatorState(), null, 2));
await writeFile(path.join(args.stateRoot, "eve-operator-surface.json"), JSON.stringify(eveSurface(), null, 2));
await writeFile(path.join(args.stateRoot, "command-boundary.json"), JSON.stringify(commandBoundary(), null, 2));
await writeFile(path.join(args.stateRoot, "transport-profile.json"), JSON.stringify(transportProfile(), null, 2));
}
async function persistCultCacheSurfaces() {
const cache = CultCache.builder()
.withRegistry(viliDocumentRegistry)
.withGenericStore(new SingleFileMessagePackBackingStore(path.join(args.stateRoot, viliStoreFileName)))
.build();
await cache.put(providerAdvertisementDefinition, providerId, providerAdvertisement());
await cache.put(operatorStateDefinition, "vili", operatorState());
await cache.put(eveSurfaceDefinition, providerId, eveSurface());
await cache.put(commandBoundaryDefinition, "vili", commandBoundary());
await cache.put(transportProfileDefinition, "vili", transportProfile());
}
async function refreshBackendStatus({ includeKimodoHelp = false } = {}) {
const docker = await wsl([
"set -e",
"service docker start >/dev/null 2>&1 || true",
"docker images gamecult/kimodo:latest --format '{{.Repository}}:{{.Tag}}' | head -n 1",
].join("; "), { timeout: 20000 });
let nvidia = await wsl([
"set -e",
"service docker start >/dev/null 2>&1 || true",
"docker info --format '{{json .Runtimes}}' | grep -q nvidia && echo configured || echo missing",
].join("; "), { timeout: 20000 });
const token = await wsl("test -f /root/.cache/huggingface/token && echo present || echo missing", { timeout: 10000 });
const worker = await kimodoWorkerHealth(20000);
let help = { ok: true, stdout: backendStatus.kimodoHelp === "ok" ? "ok" : "not checked", stderr: "" };
if (includeKimodoHelp) {
nvidia = await wsl([
"set -e",
"service docker start >/dev/null 2>&1 || true",
"docker run --rm --runtime=nvidia --gpus all nvidia/cuda:12.4.1-base-ubuntu22.04 nvidia-smi --query-gpu=name --format=csv,noheader | head -n 1",
].join("; "), { timeout: 45000 });
help = await wsl([
"set -e",
"service docker start >/dev/null 2>&1 || true",
dockerHuggingFaceEnv,
`docker run --rm --runtime=nvidia --gpus all ${dockerHuggingFaceArgs} gamecult/kimodo:latest kimodo_gen --help | sed -n '1,6p'`,
].join("; "), { timeout: 60000 });
}
backendStatus = {
checkedAt: new Date().toISOString(),
dockerImage: docker.ok && docker.stdout ? docker.stdout : "missing",
nvidiaRuntime: nvidia.ok && nvidia.stdout ? nvidia.stdout : "unavailable",
huggingFaceToken: token.ok ? token.stdout : "unknown",
kimodoHelp: includeKimodoHelp ? (help.ok ? "ok" : "failed") : backendStatus.kimodoHelp,
kimodoWorker: worker.ok && worker.body?.ok ? "resident" : "not running",
kimodoWorkerDetail: worker.body || null,
lastError: [docker, nvidia, token, help].find((result) => !result.ok)?.stderr || null,
};
await persistSurfaces();
return { docker, nvidia, token, help, backendStatus };
}
async function kimodoWorkerHealth(timeout = 10000) {
return wslJson(`curl -fsS --max-time ${Math.ceil(timeout / 1000)} ${shQuote(`${kimodoWorkerUrl}/health`)}`, { timeout });
}
async function startKimodoWorker({ model = null } = {}) {
const script = [
"set -e",
"service docker start >/dev/null 2>&1 || true",
dockerHuggingFaceEnv,
"mkdir -p /mnt/e/Projects/Vili/.vili/artifacts /mnt/e/Projects/Vili/.vili/logs /mnt/e/Projects/Vili/.vili/embeddings",
"export VILI_KIMODO_COMMIT=\"$(git -C /opt/gamecult/kimodo rev-parse HEAD)\"",
"export VILI_KIMODO_IMAGE=\"$(docker image inspect --format '{{.Id}}' gamecult/kimodo:latest)\"",
"if ! kill -0 $(cat /tmp/vili-wsl-keepalive.pid 2>/dev/null) >/dev/null 2>&1; then nohup bash -c 'while true; do sleep 3600; done' >/tmp/vili-wsl-keepalive.log 2>&1 & echo $! >/tmp/vili-wsl-keepalive.pid; fi",
`if docker ps --format '{{.Names}}' | grep -qx ${shQuote(kimodoWorkerName)}; then echo running; exit 0; fi`,
`docker rm -f ${shQuote(kimodoWorkerName)} >/dev/null 2>&1 || true`,
[
"docker run -d",
`--name ${shQuote(kimodoWorkerName)}`,
"--runtime=nvidia --gpus all",
`-p 127.0.0.1:${kimodoWorkerPort}:${kimodoWorkerPort}`,
dockerHuggingFaceArgs,
"-e VILI_KIMODO_COMMIT -e VILI_KIMODO_IMAGE",
"-e PYTHONPATH=/opt/cultlib/cultcache-py",
"-v /mnt/e/Projects/Vili/scripts:/opt/vili:ro",
"-v /mnt/e/Projects/CultLib/packages/cultcache-py/src:/opt/cultlib/cultcache-py:ro",
"-v /mnt/e/Projects/Vili/.vili/embeddings:/vili-embeddings",
"-v /mnt/e/Projects/Vili/.vili/artifacts:/outputs",
"gamecult/kimodo:latest",
"python",
"/opt/vili/kimodo-resident-worker.py",
`--port ${kimodoWorkerPort}`,
model ? `--model ${shQuote(model)}` : "",
].join(" "),
].join("; ");
return wsl(script, { timeout: 30000 });
}
async function ensureKimodoWorker({ timeoutMs = 1000 * 60 * 8, model = null } = {}) {
const health = await kimodoWorkerHealth(10000);
if (health.ok && health.body?.ok) {
if (!model || health.body.model === model || health.body.displayModel === model) return health;
await wsl(`docker rm -f ${shQuote(kimodoWorkerName)} >/dev/null 2>&1 || true`, { timeout: 30000 });
}
const started = await startKimodoWorker({ model });
if (!started.ok) return started;
const deadline = Date.now() + timeoutMs;
let last = started;
while (Date.now() < deadline) {
await new Promise((resolve) => setTimeout(resolve, 5000));
last = await kimodoWorkerHealth(10000);
if (last.ok && last.body?.ok) return last;
}
return {
ok: false,
stdout: last.stdout || "",
stderr: last.stderr || "",
error: `Kimodo worker did not become healthy within ${timeoutMs}ms.`,
body: last.body || null,
};
}
async function readRequestBody(request) {
const chunks = [];
for await (const chunk of request) chunks.push(chunk);
const raw = Buffer.concat(chunks).toString("utf8");
return raw ? JSON.parse(raw) : {};
}
async function generateMotion(request, response) {
let body;
try {
body = await readRequestBody(request);
} catch (error) {
json(response, 400, { ok: false, error: `Invalid JSON: ${error.message}` });
return;
}
const prompt = String(body.prompt || body.utterance || "").trim();
const hasPromptInput = Boolean(prompt)
|| Array.isArray(body.texts)
|| typeof body.meta === "object"
|| body.inputFolder
|| body.input_folder;
if (!hasPromptInput) {
json(response, 400, { ok: false, error: "Missing prompt, utterance, texts, meta, or inputFolder." });
return;
}
if (Array.isArray(body.texts) && !Array.isArray(body.durations)) {
json(response, 400, { ok: false, error: "Batch text requests require a durations array." });
return;
}
const jobId = `vili-${Date.now()}`;
const artifactDir = path.join(args.stateRoot, "artifacts", jobId);
await mkdir(artifactDir, { recursive: true });
const duration = firstDefined(body.durationSeconds, body.duration, 4);
const bodyMeta = typeof body.meta === "object" && body.meta ? body.meta : {};
const diffusionSteps = Math.max(1, Number(firstDefined(
body.diffusionSteps,
body.diffusion_steps,
bodyMeta.diffusion_steps,
20,
)));
const seed = body.seed === undefined ? null : Number(body.seed);
const numSamples = Math.max(1, Number(firstDefined(
body.numSamples,
body.num_samples,
bodyMeta.num_samples,
1,
)));
const meta = Object.keys(bodyMeta).length > 0
? { ...bodyMeta }
: Array.isArray(body.texts)
? { texts: body.texts, durations: body.durations }
: {
text: prompt,
duration,
};
meta.num_samples = Math.max(1, Number(firstDefined(body.numSamples, body.num_samples, meta.num_samples, 1)));
meta.diffusion_steps = diffusionSteps;
if (Number.isFinite(seed)) meta.seed = seed;
if (body.cfg) meta.cfg = body.cfg;
const constraintsPath = (() => {
if (typeof body.constraints === "string") return body.constraints;
if (body.constraints_path) return body.constraints_path;
if (body.constraintsPath) return body.constraintsPath;
if (body.constraints !== undefined) return `/outputs/${jobId}/constraints.json`;
return undefined;
})();
if (body.constraints !== undefined && typeof body.constraints !== "string") {
await writeFile(path.join(artifactDir, "constraints.json"), JSON.stringify(body.constraints, null, 2));
}
const requestRecord = {
schema: "gamecult.vili.motion_request.v0",
prompt: prompt || undefined,
texts: Array.isArray(body.texts) ? body.texts : undefined,
meta,
model: body.model,
duration,
numSamples,
diffusion_steps: diffusionSteps,
numTransitionFrames: firstDefined(body.numTransitionFrames, body.num_transition_frames),
constraints: constraintsPath,
seed: Number.isFinite(seed) ? seed : undefined,
cfg: body.cfg,
cfgType: firstDefined(body.cfgType, body.cfg_type),
cfgWeight: firstDefined(body.cfgWeight, body.cfg_weight),
bvh: boolValue(body.bvh),
bvhStandardTpose: boolValue(firstDefined(body.bvhStandardTpose, body.bvh_standard_tpose)),
noPostprocess: boolValue(firstDefined(body.noPostprocess, body.no_postprocess)),
saveExampleDir: boolValue(firstDefined(body.saveExampleDir, body.save_example_dir)),
inputFolder: firstDefined(body.inputFolder, body.input_folder),
};
await writeFile(path.join(artifactDir, "meta.json"), JSON.stringify(meta, null, 2));
const worker = await ensureKimodoWorker({
timeoutMs: Number(firstDefined(body.workerTimeoutMs, body.worker_timeout_ms, 1000 * 60 * 8)),
model: body.model || null,
});
let result = worker;
if (worker.ok) {
const workerRequest = {
model: body.model,
prompt: prompt || undefined,
texts: Array.isArray(body.texts) ? body.texts : undefined,
meta,
inputFolder: firstDefined(body.inputFolder, body.input_folder),
duration,
diffusionSteps,
numSamples,
numTransitionFrames: firstDefined(body.numTransitionFrames, body.num_transition_frames),
constraints: constraintsPath,
seed: Number.isFinite(seed) ? seed : undefined,
cfg: body.cfg,
cfgType: firstDefined(body.cfgType, body.cfg_type),
cfgWeight: firstDefined(body.cfgWeight, body.cfg_weight),
bvh: boolValue(body.bvh),
bvhStandardTpose: boolValue(firstDefined(body.bvhStandardTpose, body.bvh_standard_tpose)),
noPostprocess: boolValue(firstDefined(body.noPostprocess, body.no_postprocess)),
saveExampleDir: boolValue(firstDefined(body.saveExampleDir, body.save_example_dir)),
output: `/outputs/${jobId}/motion`,
};
await writeFile(path.join(artifactDir, "request.json"), JSON.stringify(workerRequest, null, 2));
const curlCommand = [
`curl -sS --max-time ${Math.ceil(Number(body.timeoutMs || 1000 * 60 * 30) / 1000)}`,
"-H 'content-type: application/json'",
`--data-binary @${shQuote(`/mnt/e/Projects/Vili/.vili/artifacts/${jobId}/request.json`)}`,
shQuote(`${kimodoWorkerUrl}/generate`),
].join(" ");
result = await wslJson([
"set -e",
curlCommand,
].join("; "), { timeout: Number(body.timeoutMs || 1000 * 60 * 30) });
if (result.body?.ok === false) result = { ...result, ok: false };
}
const job = {
schema: "gamecult.vili.motion_job.v0",
jobId,
createdAt: new Date().toISOString(),
prompt: prompt || null,
model: body.model || result.body?.model || null,
request: requestRecord,
durationSeconds: duration,
diffusionSteps,
seed,
artifactDir,
ok: result.ok,
stdout: result.stdout,
stderr: result.stderr,
error: result.error,
worker: result.body,
};
await writeFile(path.join(args.stateRoot, "jobs", `${jobId}.json`), JSON.stringify(job, null, 2)).catch(async () => {
await mkdir(path.join(args.stateRoot, "jobs"), { recursive: true });
await writeFile(path.join(args.stateRoot, "jobs", `${jobId}.json`), JSON.stringify(job, null, 2));
});
json(response, result.ok ? 200 : 502, job);
}
async function handleRequest(request, response) {
const url = new URL(request.url, `http://${request.headers.host || `${args.host}:${args.port}`}`);
if (request.method === "OPTIONS") {
response.writeHead(204, {
"access-control-allow-origin": "*",
"access-control-allow-methods": "GET,POST,OPTIONS",
"access-control-allow-headers": "content-type",
});
response.end();
return;
}
if (url.pathname === "/" || url.pathname === "/health") {
await refreshBackendStatus({ includeKimodoHelp: false });
json(response, 200, { ok: true, service: "vili", providerId, state: operatorState() });
} else if (url.pathname === "/provider-advertisement") {
json(response, 200, providerAdvertisement());
} else if (url.pathname === "/operator-state") {
json(response, 200, operatorState());
} else if (url.pathname === "/eve/operator") {
json(response, 200, eveSurface());
} else if (url.pathname === "/eve/deck/providers") {
json(response, 200, {
providers: [{
id: providerId,
title: "Vili Animation",
description: "Persona animation and Kimodo motion generation daemon.",
endpoint: `${ravenDeckUrl}/${providerId}`,
}],
});
} else if (url.pathname === "/smoke") {
const result = await refreshBackendStatus({ includeKimodoHelp: true });
const worker = await ensureKimodoWorker();
await refreshBackendStatus({ includeKimodoHelp: false });
const ok = result.backendStatus.kimodoHelp === "ok" && worker.ok && worker.body?.ok;
json(response, ok ? 200 : 502, { ok, ...result, worker: worker.body || worker });
} else if (url.pathname === "/motion/generate" && request.method === "POST") {
await generateMotion(request, response);
} else {
text(response, 404, "not found\n");
}
}
async function healthCheck() {
const host = args.host === "0.0.0.0" ? "127.0.0.1" : args.host;
const response = await fetch(`http://${host}:${args.port}/health`);
if (!response.ok) throw new Error(`health returned ${response.status}`);
const body = await response.json();
if (!body.ok) throw new Error("health returned ok=false");
}
if (args.printProviderAdvertisement) {
console.log(JSON.stringify(providerAdvertisement(), null, 2));
process.exit(0);
}
if (args.health) {
healthCheck().then(() => process.exit(0), (error) => {
console.error(error.message);
process.exit(1);
});
} else {
await mkdir(path.join(args.stateRoot, "jobs"), { recursive: true });
await persistSurfaces();
const server = http.createServer((request, response) => {
handleRequest(request, response).catch((error) => {
json(response, 500, { ok: false, error: error.message, stack: process.env.NODE_ENV === "development" ? error.stack : undefined });
});
});
const wss = new WebSocketServer({ noServer: true });
wss.on("connection", (socket) => {
const sendSurface = () => {
if (socket.readyState === socket.OPEN) socket.send(JSON.stringify(eveSurface()));
};
sendSurface();
const timer = setInterval(sendSurface, 5000);
socket.on("close", () => clearInterval(timer));
});
server.on("upgrade", (request, socket, head) => {
const url = new URL(request.url, `http://${request.headers.host || `${args.host}:${args.port}`}`);
if (url.pathname === `/eve/deck/${providerId}` || url.pathname === "/eve/deck") {
wss.handleUpgrade(request, socket, head, (ws) => wss.emit("connection", ws, request));
} else {
socket.destroy();
}
});
server.listen(args.port, args.host, () => {
console.log(`Vili listening on http://${args.host}:${args.port}`);
});
setInterval(() => persistSurfaces().catch((error) => console.error(error)), 5000);
}