UNPKG

@phren/cli

Version:

Knowledge layer for AI agents - CLI, MCP server, and data layer

38 lines (37 loc) • 2.1 kB
import { request } from "node:http"; import { BridgeError, object, socketPath } from "./protocol.js"; export async function hookRequest(route, data, options = { socketPath: socketPath() }, timeout = 75_000) { return new Promise((resolve, reject) => { const payload = data === undefined ? undefined : JSON.stringify(data); const method = options.method ?? (payload === undefined ? "GET" : "POST"); const req = request({ ...options, path: route, method, headers: { Host: "phren.local", Connection: "close", ...(payload ? { "Content-Type": "application/json", "Content-Length": Buffer.byteLength(payload) } : {}) } }, response => { const chunks = []; let size = 0; response.on("data", chunk => { size += chunk.length; if (size > 1_048_576) req.destroy(new BridgeError(502, "Hook response is too large.")); else chunks.push(Buffer.from(chunk)); }); response.on("error", reject); response.on("end", () => { try { const value = object(JSON.parse(Buffer.concat(chunks).toString())); // A remote Hook's `code` (why its Herdr is offline, say) travels on with its text. if (response.statusCode !== 200) throw new BridgeError(response.statusCode ?? 502, typeof value.error === "string" ? value.error.slice(0, 500) : "Hook rejected the request.", typeof value.code === "string" && /^[a-z][a-z0-9-]{0,39}$/.test(value.code) ? { code: value.code } : undefined); resolve(value); } catch (error) { reject(error); } }); }); const timer = setTimeout(() => req.destroy(new BridgeError(504, "Hook did not confirm the request. Do not retry a dispatch automatically.")), timeout); req.on("close", () => clearTimeout(timer)); req.on("error", reject); req.end(payload); }); }