agent-ecosystem/agent-teams-controller/src/internal/processStore.js
iliya 01dd87caaa feat: integrate runtime helpers and enhance lead session handling
- Replaced legacy references with new runtimeHelpers in context, processStore, tasks, and review modules for improved maintainability.
- Introduced leadSessionId handling in review requests and approvals, ensuring consistent tracking of session identifiers across operations.
- Added new utility functions in runtimeHelpers for path management and process checks, streamlining task-related functionalities.
- Updated tests to validate the inclusion of leadSessionId in various workflows, enhancing the robustness of the messaging system.
2026-03-08 00:56:31 +02:00

168 lines
4.6 KiB
JavaScript

const fs = require('fs');
const path = require('path');
const crypto = require('crypto');
const runtimeHelpers = require('./runtimeHelpers.js');
function nowIso() {
return new Date().toISOString();
}
function readJson(filePath, fallbackValue) {
try {
return JSON.parse(fs.readFileSync(filePath, 'utf8'));
} catch {
return fallbackValue;
}
}
function writeJson(filePath, value) {
fs.mkdirSync(path.dirname(filePath), { recursive: true });
const tempPath = `${filePath}.${process.pid}.${Date.now()}.tmp`;
fs.writeFileSync(tempPath, JSON.stringify(value, null, 2));
fs.renameSync(tempPath, filePath);
}
function readProcesses(paths) {
const rows = readJson(paths.processesPath, []);
if (!Array.isArray(rows)) return [];
return rows.filter((entry) => entry && typeof entry === 'object' && Number.isInteger(entry.pid));
}
function writeProcesses(paths, processes) {
writeJson(paths.processesPath, processes);
}
function listProcesses(paths) {
const existing = readProcesses(paths);
const processes = existing.map((entry) => {
const alive =
!entry.stoppedAt &&
Number.isFinite(Number(entry.pid)) &&
runtimeHelpers.isProcessAlive(Number(entry.pid));
if (!alive && !entry.stoppedAt) {
return {
...entry,
stoppedAt: nowIso(),
alive: false,
};
}
return {
...entry,
alive,
};
});
const changed = processes.some((entry, index) => entry.stoppedAt !== existing[index]?.stoppedAt);
if (changed) {
writeProcesses(
paths,
processes.map(({ alive, ...rest }) => rest)
);
}
return processes;
}
function registerProcess(paths, flags) {
const pid = Number(flags.pid);
if (!Number.isInteger(pid) || pid <= 0) {
throw new Error('Invalid pid');
}
const label = typeof flags.label === 'string' && flags.label.trim() ? flags.label.trim() : '';
if (!label) {
throw new Error('Missing label');
}
const list = readProcesses(paths);
const existingActiveIndex = list.findIndex((entry) => entry.pid === pid && !entry.stoppedAt);
const existingActive =
existingActiveIndex >= 0
? {
...list[existingActiveIndex],
...(runtimeHelpers.isProcessAlive(pid) ? {} : { stoppedAt: nowIso() }),
}
: null;
if (existingActiveIndex >= 0 && existingActive && existingActive.stoppedAt) {
list[existingActiveIndex] = existingActive;
}
const now = nowIso();
const entry = {
id: existingActive && !existingActive.stoppedAt ? existingActive.id : crypto.randomUUID(),
label,
pid,
...(flags.port != null ? { port: Number(flags.port) } : {}),
...(typeof flags.url === 'string' && flags.url.trim() ? { url: flags.url.trim() } : {}),
...(typeof flags['claude-process-id'] === 'string' && flags['claude-process-id'].trim()
? { claudeProcessId: flags['claude-process-id'].trim() }
: {}),
...(typeof flags.from === 'string' && flags.from.trim() ? { registeredBy: flags.from.trim() } : {}),
...(typeof flags.command === 'string' && flags.command.trim()
? { command: flags.command.trim() }
: {}),
registeredAt: existingActive && !existingActive.stoppedAt ? existingActive.registeredAt : now,
};
if (existingActiveIndex >= 0 && existingActive && !existingActive.stoppedAt) {
list[existingActiveIndex] = entry;
} else {
list.push(entry);
}
writeProcesses(paths, list);
return entry;
}
function stopProcess(paths, flags) {
const pid = flags.pid != null ? Number(flags.pid) : null;
const id =
typeof flags.id === 'string' && flags.id.trim().length > 0 ? flags.id.trim() : null;
if (!pid && !id) {
throw new Error('Missing pid or id');
}
const list = readProcesses(paths);
const index = list.findIndex((entry) => {
if (pid) return entry.pid === pid && !entry.stoppedAt;
return entry.id === id && !entry.stoppedAt;
});
if (index < 0) {
throw new Error('Process not found');
}
list[index] = {
...list[index],
stoppedAt: list[index].stoppedAt || nowIso(),
};
writeProcesses(paths, list);
return list[index];
}
function unregisterProcess(paths, flags) {
const pid = flags.pid != null ? Number(flags.pid) : null;
const id =
typeof flags.id === 'string' && flags.id.trim().length > 0 ? flags.id.trim() : null;
if (!pid && !id) {
throw new Error('Missing pid or id');
}
const list = readProcesses(paths);
const next = list.filter((entry) => {
if (pid) return entry.pid !== pid;
return entry.id !== id;
});
writeProcesses(paths, next);
return next;
}
module.exports = {
listProcesses,
readProcesses,
registerProcess,
stopProcess,
unregisterProcess,
writeProcesses,
};