public
anord
read
Ledger
Why work hard when you can work easier?
Languages
Repository composition by tracked source files.
TypeScript
86%
CSS
10%
SQL
3%
Shell
1%
HTML
0%
Trace
apps/api/src/http/routes/ai.ts
Trace helps you understand code history line by line. See who changed each line, when it changed, and which commit introduced it.
Author
Date
Commit
Line
Code
1
import { Router } from "express";
2
import { z } from "zod";
3
import { requireAdmin } from "../middleware/auth.js";
4
import { answerQuestion, getAiSettingsRecord, upsertAiSettings } from "../../services/ai.js";
6
const aiAnswerSchema = z.object({
7
question: z.string().min(3)
8
});
10
const aiSettingsSchema = z.object({
11
provider: z.enum(["none", "openai_compatible", "anthropic_compatible"]),
12
model: z.string(),
13
apiKey: z.string().nullable(),
14
isEnabled: z.boolean()
15
});
17
export const aiRouter = Router();
19
aiRouter.get("/settings", requireAdmin, async (_req, res) => {
20
const settings = await getAiSettingsRecord();
21
return res.json({
22
settings: settings
23
? {
24
provider: settings.provider,
25
model: settings.model,
26
isEnabled: settings.is_enabled,
27
hasApiKey: Boolean(settings.encrypted_api_key)
28
}
29
: {
30
provider: "none",
31
model: "",
32
isEnabled: false,
33
hasApiKey: false
34
}
35
});
36
});
38
aiRouter.put("/settings", requireAdmin, async (req, res) => {
39
const input = aiSettingsSchema.parse(req.body);
40
const updated = await upsertAiSettings(input);
41
return res.json({
42
settings: {
43
provider: updated.provider,
44
model: updated.model,
45
isEnabled: updated.is_enabled,
46
hasApiKey: Boolean(updated.encrypted_api_key)
47
}
48
});
49
});
51
aiRouter.post("/answers", async (req, res) => {
52
const input = aiAnswerSchema.parse(req.body);
53
const result = await answerQuestion(input.question, req.user ?? null);
54
return res.json(result);
55
});