evOo-local/scripts/autonomous-sentinel.ts
cynarAI 6c7eed7580 Initial clean evOo-local from f00577b
Fresh history cut from cynarAI/evoo antigravity-handoff/project-timeline
(Voice First + project timeline). Brand docs/titles as evOo; keep @rakazo/*
packages as tech debt. Excludes node_modules, caches, secrets, voice blobs.
2026-09-20 17:15:16 +02:00

97 lines
3.5 KiB
TypeScript

import { execSync } from "node:child_process";
import fs from "node:fs";
import { createDb } from "../packages/db/src/index.js";
async function main() {
console.log("Starting Calm Autonomous Sentinel (5-Min Check & Multi-Agent Parallel Watchdog)...");
const { prisma } = createDb("postgres://ingowagner@127.0.0.1:5432/evoo");
const CHECK_INTERVAL_MS = 300_000; // 5 minutes exactly
let lastCheckTime = Date.now();
while (true) {
try {
await new Promise((r) => setTimeout(r, 30_000)); // Check every 30s
const now = Date.now();
if (now - lastCheckTime < CHECK_INTERVAL_MS) {
continue;
}
// Check if any agent is currently working
const activeRuns = await prisma.run.count({
where: { status: { in: ["running", "queued", "leased"] } },
});
if (activeRuns >= 2) {
// At least 2 agents working in parallel — perfect, no need to interrupt!
console.log(
`[Sentinel] ${activeRuns} agents actively working in parallel. System healthy.`,
);
lastCheckTime = now;
continue;
}
const steve = await prisma.bot.findFirst({ where: { name: "Steve Jobs" } });
const session = await prisma.session.findFirst({ orderBy: { createdAt: "desc" } });
const execGroup = await prisma.chatGroup.findFirst({ where: { name: "Executive Board" } });
if (!steve || !session || !execGroup) continue;
// Check the last message in Executive Board to avoid duplicate spam
const lastMsg = await prisma.message.findFirst({
where: { thread: { groupId: execGroup.id } },
orderBy: { createdAt: "desc" },
});
const lastMsgText = JSON.stringify(lastMsg?.blocks ?? "");
if (
lastMsgText.includes("5-Minuten Kontroll-Check") &&
now - new Date(lastMsg!.createdAt).getTime() < 300_000
) {
console.log("[Sentinel] Skip: Recent check already present.");
lastCheckTime = now;
continue;
}
// Quick tests verification
let testSummary = "Alle Tests validiert";
try {
const testPath =
"/Users/ingowagner/evOo/data/desktop-computers/team-9d790f3a504d3e9ef577ca4f2118e446/bots/cmu7jjxv30000fvyyjyoyylef/apex-trading";
if (fs.existsSync(testPath)) {
const out = execSync("PYTHONPATH=src python3 -m unittest discover -s tests 2>&1", {
cwd: testPath,
timeout: 8000,
}).toString();
if (out.includes("OK")) {
testSummary = "5/5 Tests GRÜN ✅ (1.5M ticks/s)";
}
}
} catch {
testSummary = "Tests laufen";
}
lastCheckTime = now;
console.log("[Sentinel] Dispatching 5-minute parallel pulse to Executive Board...");
await fetch("http://127.0.0.1:3100/rpc/threads/send", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${session.token}`,
},
body: JSON.stringify({
json: {
groupId: execGroup.id,
text: `@Steve Jobs [Executive Board Pulse ⏱️]\n\nTest-Status: ${testSummary}\nAktuell aktive Agenten: ${activeRuns}\n\nBitte halte die Vorgabe der Geschäftsführung ein: Lasse immer MINDESTENS 2 Spezialisten gleichzeitig parallel arbeiten (z.B. DevOps Engineer + Security Auditor oder Apex Quant + Code Architect). Delegiere die nächsten 2 parallelen Arbeitspakete.`,
},
}),
});
} catch (err) {
console.error("[Sentinel] Error in loop:", err);
}
}
}
main().catch(console.error);