Merge branch 'main' into refactor/merge-relay-list-7360990203888330524

This commit is contained in:
thePR0M3TH3AN authored and GitHub committed 2026-02-20 16:35:59 -05:00
commit 756806a99e
12 files changed
+3577 -53

No files matched your search

-10
View File
@@ -55,16 +55,6 @@ function filterActiveLocks(locks) {
return locks.filter((lock) => !lock.expiresAt || lock.expiresAt > now);
}
function withTimeout(promise, timeoutMs, timeoutMessage) {
let timeoutHandle;
const timeoutPromise = new Promise((_, reject) => {
timeoutHandle = setTimeout(() => reject(new Error(timeoutMessage)), timeoutMs);
});
return Promise.race([promise, timeoutPromise]).finally(() => {
if (timeoutHandle) clearTimeout(timeoutHandle);
});
}
function relayListLabel(relays) {
return relays.join(', ');
}
-10
View File
@@ -9,16 +9,6 @@ import {
import { mergeRelayList } from './utils.mjs';
import { defaultHealthManager, buildRelayHealthConfig } from './relay-health-manager.mjs';
function withTimeout(promise, timeoutMs, timeoutMessage) {
let timeoutHandle;
const timeoutPromise = new Promise((_, reject) => {
timeoutHandle = setTimeout(() => reject(new Error(timeoutMessage)), timeoutMs);
});
return Promise.race([promise, timeoutPromise]).finally(() => {
if (timeoutHandle) clearTimeout(timeoutHandle);
});
}
function relayListLabel(relays) {
return relays.join(', ');
}
+2 -10
View File
@@ -1,6 +1,6 @@
import fs from 'node:fs/promises';
import path from 'node:path';
import { todayDateStr, getIsoWeekStr } from './utils.mjs';
import { todayDateStr, getIsoWeekStr, withTimeout } from './utils.mjs';
/**
* Scans the local log directory to identify agents that have already completed their task
@@ -48,15 +48,7 @@ export async function getCompletedAgents(cadence, logDir, deps) {
return completed;
}
export function withTimeout(promise, timeoutMs, timeoutMessage) {
let timeoutHandle;
const timeoutPromise = new Promise((_, reject) => {
timeoutHandle = setTimeout(() => reject(new Error(timeoutMessage)), timeoutMs);
});
return Promise.race([promise, timeoutPromise]).finally(() => {
if (timeoutHandle) clearTimeout(timeoutHandle);
});
}
export { withTimeout };
export function relayListLabel(relays) {
return relays.join(', ');
+1 -8
View File
@@ -4,17 +4,10 @@ import WebSocket from 'ws';
import { finalizeEvent, generateSecretKey, getPublicKey } from 'nostr-tools/pure';
import { getNamespace, getRelays } from './torch-config.mjs';
import { MS_PER_SECOND } from './constants.mjs';
import { withTimeout } from './utils.mjs';
const PROBE_KIND = 27235;
function withTimeout(promise, timeoutMs, message) {
let timeoutId;
const timeoutPromise = new Promise((_, reject) => {
timeoutId = setTimeout(() => reject(new Error(message)), timeoutMs);
});
return Promise.race([promise, timeoutPromise]).finally(() => clearTimeout(timeoutId));
}
function nowIso() {
return new Date().toISOString();
}
+9 -3
View File
@@ -132,8 +132,14 @@ export async function createProposal({ agent, target, newContent, reason }) {
return { id, diff };
}
export async function validateProposal(id) {
const { meta, newContent } = await getProposal(id);
export async function validateProposal(proposalOrId) {
let proposal;
if (typeof proposalOrId === 'string') {
proposal = await getProposal(proposalOrId);
} else {
proposal = proposalOrId;
}
const { meta, newContent } = proposal;
// 1. Allowlist check (redundant but safe)
const { isAllowed } = resolveAndValidateTarget(meta.target);
@@ -165,7 +171,7 @@ export async function applyProposal(id) {
throw new Error(`Proposal is ${meta.status}, cannot apply.`);
}
const validation = await validateProposal(id);
const validation = await validateProposal(proposal);
if (!validation.valid) {
// Mark as rejected if validation fails?
// Or just throw? The governance agent should decide.
+13 -2
View File
@@ -41,13 +41,24 @@ function loadMemoryStore() {
let currentSavePromise = null;
let pendingSavePromise = null;
let pendingSaveResolve = null;
let lastSaveTime = 0;
const MIN_SAVE_INTERVAL_MS = 1000;
async function performSave(store) {
try {
const now = Date.now();
const timeSinceLast = now - lastSaveTime;
if (timeSinceLast < MIN_SAVE_INTERVAL_MS) {
await new Promise((resolve) => setTimeout(resolve, MIN_SAVE_INTERVAL_MS - timeSinceLast));
}
const dir = path.dirname(MEMORY_FILE_PATH);
await fs.promises.mkdir(dir, { recursive: true });
const entries = [...store.entries()];
await fs.promises.writeFile(MEMORY_FILE_PATH, JSON.stringify(entries, null, 2), 'utf8');
const tmpPath = `${MEMORY_FILE_PATH}.${Date.now()}.${Math.random()}.tmp`;
await fs.promises.writeFile(tmpPath, JSON.stringify(entries, null, 2), 'utf8');
await fs.promises.rename(tmpPath, MEMORY_FILE_PATH);
lastSaveTime = Date.now();
} catch (err) {
console.error('Failed to save memory store:', err);
} finally {
@@ -105,7 +116,7 @@ const memoryRepository = {
const updated = { ...existing, last_seen: lastSeen };
memoryStore.set(id, updated);
storeVersion++;
await saveMemoryStore(memoryStore);
saveMemoryStore(memoryStore).catch((err) => console.error('Failed to save memory usage update:', err));
return updated;
},
async listPruneCandidates({ cutoff }) {
+10
View File
@@ -51,3 +51,13 @@ export function ensureDir(dir) {
fs.mkdirSync(dir, { recursive: true });
}
}
export function withTimeout(promise, timeoutMs, timeoutMessage) {
let timeoutHandle;
const timeoutPromise = new Promise((_, reject) => {
timeoutHandle = setTimeout(() => reject(new Error(timeoutMessage)), timeoutMs);
});
return Promise.race([promise, timeoutPromise]).finally(() => {
if (timeoutHandle) clearTimeout(timeoutHandle);
});
}