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.
97 lines
3.5 KiB
TypeScript
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);
|