@posthog/agent
Version:
TypeScript agent framework wrapping Claude Agent SDK with Git-based task execution for PostHog
124 lines (121 loc) • 4.6 kB
JavaScript
import { randomBytes } from 'node:crypto';
class TaskManager {
executionStates = new Map();
defaultTimeout = 10 * 60 * 1000; // 10 minutes
generateExecutionId() {
return randomBytes(16).toString("hex");
}
startExecution(taskId, mode, executionId = this.generateExecutionId()) {
const executionState = {
taskId,
status: "running",
mode,
startedAt: Date.now(),
abortController: new AbortController(),
};
this.executionStates.set(executionId, executionState);
this.scheduleTimeout(executionId);
return executionState;
}
async waitForCompletion(executionId) {
const execution = this.executionStates.get(executionId);
if (!execution) {
throw new Error(`Execution ${executionId} not found`);
}
if (execution.result && execution.status === "completed") {
return execution.result;
}
return new Promise((resolve, reject) => {
const checkInterval = setInterval(() => {
const currentExecution = this.executionStates.get(executionId);
if (!currentExecution) {
clearInterval(checkInterval);
reject(new Error(`Execution ${executionId} disappeared`));
return;
}
if (currentExecution.status === "completed" &&
currentExecution.result) {
clearInterval(checkInterval);
resolve(currentExecution.result);
}
else if (currentExecution.status === "failed" ||
currentExecution.status === "canceled" ||
currentExecution.status === "timeout") {
clearInterval(checkInterval);
reject(new Error(`Execution ${executionId} ${currentExecution.status}`));
}
}, 100);
});
}
completeExecution(executionId, result) {
const execution = this.executionStates.get(executionId);
if (!execution) {
throw new Error(`Execution ${executionId} not found`);
}
execution.status = "completed";
execution.result = result;
execution.completedAt = Date.now();
}
failExecution(executionId, error) {
const execution = this.executionStates.get(executionId);
if (!execution) {
throw new Error(`Execution ${executionId} not found`);
}
execution.status = "failed";
execution.completedAt = Date.now();
execution.result = {
error: error.message,
status: "failed",
};
}
cancelExecution(executionId) {
const execution = this.executionStates.get(executionId);
if (!execution) {
throw new Error(`Execution ${executionId} not found`);
}
execution.status = "canceled";
execution.completedAt = Date.now();
execution.abortController?.abort();
if (!execution.result) {
execution.result = {
status: "canceled",
message: "Execution was canceled",
};
}
}
getExecution(executionId) {
return this.executionStates.get(executionId);
}
getAbortSignal(executionId) {
return this.executionStates.get(executionId)?.abortController?.signal;
}
getAbortController(executionId) {
return this.executionStates.get(executionId)?.abortController;
}
scheduleTimeout(executionId, timeout = this.defaultTimeout) {
setTimeout(() => {
const execution = this.executionStates.get(executionId);
if (execution && execution.status === "running") {
execution.status = "timeout";
execution.completedAt = Date.now();
execution.abortController?.abort();
if (!execution.result) {
execution.result = {
status: "timeout",
message: "Execution timed out",
};
}
}
}, timeout);
}
cleanup(olderThan = 60 * 60 * 1000) {
const cutoff = Date.now() - olderThan;
for (const [executionId, execution] of this.executionStates) {
if (execution.completedAt && execution.completedAt < cutoff) {
this.executionStates.delete(executionId);
}
}
}
}
export { TaskManager };
//# sourceMappingURL=task-manager.js.map