class AsyncGuardrailHandler {
constructor(timeout = 30000) {
this.timeout = timeout;
this.pendingGuardrails = new Map();
}
async handle(sessionId, guardrailData) {
// Try automated handling first
const autoResponse = this.tryAutomatic(guardrailData);
if (autoResponse) {
return autoResponse;
}
// Fall back to human with timeout
return this.requestHumanInput(sessionId, guardrailData);
}
tryAutomatic(guardrailData) {
const message = guardrailData.value.toLowerCase();
if (message.includes("login")) {
return {
actionType: "guardrail",
taskDetails: `Username: ${process.env.USERNAME}, Password: ${process.env.PASSWORD}`,
newState: "resume"
};
}
return null;
}
async requestHumanInput(sessionId, guardrailData) {
return new Promise((resolve, reject) => {
const timeoutId = setTimeout(() => {
this.pendingGuardrails.delete(sessionId);
reject(new Error("Guardrail response timeout"));
}, this.timeout);
this.pendingGuardrails.set(sessionId, {
resolve: (response) => {
clearTimeout(timeoutId);
this.pendingGuardrails.delete(sessionId);
resolve(response);
},
reject,
data: guardrailData
});
// Notify UI/human
this.notifyHuman(sessionId, guardrailData);
});
}
respondToGuardrail(sessionId, taskDetails, shouldResume = true) {
const pending = this.pendingGuardrails.get(sessionId);
if (pending) {
pending.resolve({
actionType: "guardrail",
taskDetails,
newState: shouldResume ? "resume" : "stop"
});
}
}
notifyHuman(sessionId, data) {
console.log(`[${sessionId}] Human input needed:`, data.value);
// Send notification to UI, Slack, email, etc.
}
}
// Usage
const handler = new AsyncGuardrailHandler(30000);
socket.on("message", async (data) => {
if (data.type === "guardrail_trigger") {
try {
const response = await handler.handle(session.sessionId, data.data);
socket.emit("message", response);
} catch (error) {
console.error("Guardrail handling failed:", error);
// Stop the task
socket.emit("message", {
actionType: "state",
newState: "stop"
});
}
}
});
// Human responds via UI
app.post("/api/respond-guardrail", (req, res) => {
const { sessionId, response, shouldResume } = req.body;
handler.respondToGuardrail(sessionId, response, shouldResume);
res.json({ success: true });
});