// Typed client for the venos orchestrator REST API.
// All methods return plain objects — no SDK dependency here.
export class VenosClient {
    cfg;
    constructor(cfg) {
        this.cfg = cfg;
    }
    async get(path, params) {
        const url = new URL(path, this.cfg.baseUrl);
        url.searchParams.set("orgId", this.cfg.orgId);
        if (params) {
            for (const [k, v] of Object.entries(params))
                url.searchParams.set(k, v);
        }
        const headers = { "Content-Type": "application/json" };
        if (this.cfg.apiKey)
            headers["Authorization"] = `Bearer ${this.cfg.apiKey}`;
        const res = await fetch(url.toString(), { headers });
        if (!res.ok)
            throw new Error(`venos API ${path} → ${res.status} ${res.statusText}`);
        return res.json();
    }
    // orgId rides in the query string (resolveOrgID reads it there); the bearer
    // key, when present, pins the trusted org header server-side and the analyst
    // role the loop mutation routes require.
    async post(path, body) {
        const url = new URL(path, this.cfg.baseUrl);
        url.searchParams.set("orgId", this.cfg.orgId);
        const headers = { "Content-Type": "application/json" };
        if (this.cfg.apiKey)
            headers["Authorization"] = `Bearer ${this.cfg.apiKey}`;
        const res = await fetch(url.toString(), {
            method: "POST",
            headers,
            body: JSON.stringify(body),
        });
        if (!res.ok)
            throw new Error(`venos API ${path} → ${res.status} ${res.statusText}`);
        return res.json();
    }
    async openLoop(input) {
        return this.post("/api/loops", input);
    }
    async loopStatus(id) {
        return this.get(`/api/loops/${encodeURIComponent(id)}`);
    }
    async stepLoop(id, input) {
        return this.post(`/api/loops/${encodeURIComponent(id)}/step`, input);
    }
    async completeLoop(id) {
        return this.post(`/api/loops/${encodeURIComponent(id)}/complete`, {});
    }
    async delegationChains(limit = 20) {
        const data = await this.get("/api/delegation-chains/recent", { limit: String(limit) });
        return data.chains ?? [];
    }
    async grounding(limit = 20) {
        const data = await this.get("/api/grounding", { limit: String(limit) });
        return data.findings ?? [];
    }
    async overview() {
        return this.get("/api/overview");
    }
    async agents(limit = 20) {
        const data = await this.get("/api/agents", { limit: String(limit) });
        return Array.isArray(data) ? data : data.agents ?? [];
    }
    async recentEvents(limit = 20) {
        const data = await this.get("/api/events", { limit: String(limit) });
        return Array.isArray(data) ? data : data.events ?? [];
    }
    async alerts(limit = 10) {
        const data = await this.get("/api/alerts", { limit: String(limit) });
        return Array.isArray(data) ? data : data.alerts ?? [];
    }
    async enforceMode() {
        const data = await this.get("/api/enforce-mode");
        if ("enforcementMode" in data)
            return data;
        return {
            enforcementMode: data.mode ?? "unknown",
            blockCount: data.blockCount ?? 0,
            allowCount: data.allowCount ?? 0,
        };
    }
    async finops() {
        return this.get("/api/finops/summary");
    }
    async classify(text) {
        // VENOS_SOURCE is injected by each client's CLI adapter (cursor, codex, …)
        // when it wires the MCP server entry, so events land tagged with the
        // correct source. Defaults to "cursor" for back-compat with existing
        // mcp.json files written before VENOS_SOURCE support.
        const source = process.env["VENOS_SOURCE"]?.trim() || "cursor";
        const url = new URL(`/v1/hooks/${source}`, this.cfg.baseUrl);
        const headers = { "Content-Type": "application/json" };
        if (this.cfg.apiKey)
            headers["Authorization"] = `Bearer ${this.cfg.apiKey}`;
        const res = await fetch(url.toString(), {
            method: "POST",
            headers,
            body: JSON.stringify({ orgId: this.cfg.orgId, prompt: text }),
        });
        if (!res.ok)
            throw new Error(`venos hook → ${res.status} ${res.statusText}`);
        return res.json();
    }
    // /api/controls is product-architecture metadata, not tenant data, so it is
    // not org-scoped; get() still appends a harmless orgId the endpoint ignores.
    async controls() {
        return this.get("/api/controls");
    }
    // Proxy-layer enforce-readiness: the same per-rule would-block breakdown the
    // dashboard hub sums for its magnitude band. `from` is an RFC3339 lower bound;
    // omitting it counts all time.
    async almostBlockedBreakdown(from) {
        const data = await this.get("/api/policy-decisions/almost-blocked/breakdown", from ? { from } : undefined);
        return data.breakdown ?? [];
    }
    // Host-layer enforce-readiness: per operator-blocked agent, how many real
    // stored events host-layer enforcement would have stopped in the window.
    async hostWouldBlock(from) {
        const data = await this.get("/api/sensor/would-block", from ? { from } : undefined);
        return { rows: data.rows ?? [], total: data.total ?? 0 };
    }
}
//# sourceMappingURL=client.js.map