import { fetchEventSource } from "@microsoft/fetch-event-source";
import * as readline from "readline";
const API_BASE = process.env.API_BASE ?? "https://api.agentharness.com";
const API_KEY = process.env.API_KEY!;
const createRes = await fetch(`${API_BASE}/v1/runs`, {
method: "POST",
headers: {
Authorization: `Bearer ${API_KEY}`,
"Content-Type": "application/json",
"idempotency-key": crypto.randomUUID(),
},
body: JSON.stringify({
input: { goal: "Draft and send the weekly team update email." },
}),
});
const run = await createRes.json();
console.log(`Run created: ${run.id}`);
const ac = new AbortController();
await fetchEventSource(`${API_BASE}/v1/runs/${run.id}/events/stream`, {
signal: ac.signal,
headers: { Authorization: `Bearer ${API_KEY}` },
async onmessage(msg) {
if (msg.event !== "run_event" || !msg.data) return;
const event = JSON.parse(msg.data);
console.log(`[${event.type}] seq=${event.seq}`);
if (event.type === "run.awaiting_input") {
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
const answer = await new Promise<string>((resolve) => {
rl.question("Approve? (yes/no): ", resolve);
});
rl.close();
const action = answer.toLowerCase() === "yes" ? "approve" : "reject";
await fetch(`${API_BASE}/v1/runs/${run.id}/signal`, {
method: "POST",
headers: {
Authorization: `Bearer ${API_KEY}`,
"Content-Type": "application/json",
"idempotency-key": crypto.randomUUID(),
},
body: JSON.stringify({ action }),
});
console.log(`Signal sent: ${action}`);
}
const terminal =
event.type === "run.worker.succeeded" ||
event.type === "run.worker.failed" ||
event.type === "run.cancelled";
if (terminal) {
console.log(`\nRun ended: ${event.type}`);
ac.abort();
}
},
});