File size: 1,539 Bytes
5456422
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
import type { Brief, RunResponse, Stats } from "./types";

const API_URL = process.env.NEXT_PUBLIC_API_URL ?? "http://localhost:8000";

/** Raised for any non-OK API response, with a user-friendly message. */
export class ApiError extends Error {
  status: number;
  constructor(message: string, status: number) {
    super(message);
    this.name = "ApiError";
    this.status = status;
  }
}

async function parseError(res: Response): Promise<string> {
  if (res.status === 429) {
    return "Rate limit reached (10 runs/minute). Give it a minute and try again.";
  }
  try {
    const data = await res.json();
    if (data?.detail) return String(data.detail);
  } catch {
    /* fall through to generic */
  }
  return `Request failed (${res.status}).`;
}

export async function getStats(): Promise<Stats> {
  const res = await fetch(`${API_URL}/stats`, { cache: "no-store" });
  if (!res.ok) throw new ApiError(await parseError(res), res.status);
  return res.json();
}

export async function runAgent(brief: Brief): Promise<RunResponse> {
  let res: Response;
  try {
    res = await fetch(`${API_URL}/run`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(brief),
    });
  } catch {
    // Network / CORS / backend down.
    throw new ApiError(
      "Could not reach the backend. Is the API running and NEXT_PUBLIC_API_URL set correctly?",
      0,
    );
  }
  if (!res.ok) throw new ApiError(await parseError(res), res.status);
  return res.json();
}

export { API_URL };