summaryrefslogtreecommitdiffhomepage
path: root/packages/api/src/app.ts
blob: 3591281cf6a961ab94e73767120134d5ed782bc9 (plain)
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
55
56
57
58
59
60
61
62
import { Hono } from "hono";
import { cors } from "hono/cors";
import { AgentManager } from "./agent-manager.js";
import { PermissionManager } from "./permission-manager.js";
import { configRoutes } from "./routes/config.js";
import { skillsRoutes } from "./routes/skills.js";
import { modelsRoutes } from "./routes/models.js";

export const permissionManager = new PermissionManager();
export const agentManager = new AgentManager(permissionManager);

export const app = new Hono();

app.use(
	"*",
	cors({
		origin: "http://localhost:5173",
		credentials: true,
		allowHeaders: ["Content-Type", "Authorization"],
		allowMethods: ["GET", "POST", "OPTIONS"],
	}),
);

app.get("/health", (c) => {
	return c.json({ ok: true });
});

app.get("/status", (c) => {
	return c.json({
		status: agentManager.getStatus(),
		messageCount: agentManager.getMessageCount(),
	});
});

app.post("/chat", async (c) => {
	const body = await c.req.json<{ message?: unknown; keyId?: unknown; modelId?: unknown; reasoningEffort?: unknown }>();
	const message = body.message;

	if (typeof message !== "string" || message.trim() === "") {
		return c.json({ error: "message must be a non-empty string" }, 400);
	}

	if (agentManager.getStatus() === "running") {
		return c.json({ error: "agent is already running" }, 409);
	}

	const keyId = typeof body.keyId === "string" ? body.keyId : undefined;
	const modelId = typeof body.modelId === "string" ? body.modelId : undefined;
	const validEfforts = ["none", "low", "medium", "high", "max"];
	const reasoningEffort = typeof body.reasoningEffort === "string" && validEfforts.includes(body.reasoningEffort)
		? (body.reasoningEffort as "none" | "low" | "medium" | "high" | "max")
		: undefined;

	// Non-blocking — let the agent run in the background
	agentManager.processMessage(message, keyId, modelId, reasoningEffort).catch(console.error);

	return c.json({ status: "ok" });
});

app.route("/config", configRoutes);
app.route("/skills", skillsRoutes);
app.route("/models", modelsRoutes);