feat: add AI knowledge analysis MVP

This commit is contained in:
2026-07-05 00:47:52 -07:00
parent 6aa72d3b43
commit e204974b57
32 changed files with 8705 additions and 4 deletions

View File

@@ -0,0 +1,62 @@
import { generateElderAiAnalysis, listElderAiAnalyses } from "@/modules/ai/server/analysis";
import { jsonFailure, jsonSuccess } from "@/modules/core/server/api";
import { requirePermission } from "@/modules/core/server/auth";
type RouteContext = {
params: Promise<{
id: string;
}>;
};
async function requireAiAnalysisAccess(id: string) {
const aiAuth = await requirePermission("ai:read", {
action: "ai.elder_analysis.access",
targetType: "elder",
targetId: id,
});
if (!aiAuth.success) {
return aiAuth;
}
const elderAuth = await requirePermission("elder:read", {
action: "ai.elder_analysis.access",
targetType: "elder",
targetId: id,
organizationId: aiAuth.context.organization?.id,
});
if (!elderAuth.success) {
return elderAuth;
}
return aiAuth;
}
export async function GET(_request: Request, context: RouteContext): Promise<Response> {
const { id } = await context.params;
const auth = await requireAiAnalysisAccess(id);
if (!auth.success) {
return auth.response;
}
const result = await listElderAiAnalyses(auth.context, id);
if (!result.success) {
return jsonFailure(result.reason, result.status);
}
return jsonSuccess("AI 分析历史已加载", { history: result.data.history });
}
export async function POST(_request: Request, context: RouteContext): Promise<Response> {
const { id } = await context.params;
const auth = await requireAiAnalysisAccess(id);
if (!auth.success) {
return auth.response;
}
const result = await generateElderAiAnalysis(auth.context, id);
if (!result.success) {
return jsonFailure(result.reason, result.status);
}
return jsonSuccess("AI 分析已生成", { analysis: result.data.analysis }, 201);
}

View File

@@ -0,0 +1,74 @@
import { deleteKnowledgeEntry, updateKnowledgeEntry } from "@/modules/ai/server/knowledge";
import { validateKnowledgeEntryInput } from "@/modules/ai/types";
import { jsonFailure, jsonSuccess, readJsonBody } from "@/modules/core/server/api";
import { recordAuditLog } from "@/modules/core/server/audit";
import { requirePermission } from "@/modules/core/server/auth";
type RouteContext = {
params: Promise<{
id: string;
}>;
};
export async function PATCH(request: Request, context: RouteContext): Promise<Response> {
const { id } = await context.params;
const auth = await requirePermission("knowledge:manage", {
action: "ai.knowledge.update",
targetType: "ai_knowledge",
targetId: id,
});
if (!auth.success) {
return auth.response;
}
const input = validateKnowledgeEntryInput(await readJsonBody(request));
if (!input.success) {
return jsonFailure(input.reason);
}
const result = await updateKnowledgeEntry(auth.context, id, input.input);
if (!result.success) {
return jsonFailure(result.reason, result.status);
}
await recordAuditLog({
actor: auth.context.account,
organizationId: result.data.entry.organizationId ?? auth.context.organization?.id,
action: "ai.knowledge.update",
targetType: "ai_knowledge",
targetId: result.data.entry.id,
result: "success",
reason: `更新知识库条目:${result.data.entry.title}`,
});
return jsonSuccess("知识库条目已更新", { entry: result.data.entry });
}
export async function DELETE(_request: Request, context: RouteContext): Promise<Response> {
const { id } = await context.params;
const auth = await requirePermission("knowledge:manage", {
action: "ai.knowledge.delete",
targetType: "ai_knowledge",
targetId: id,
});
if (!auth.success) {
return auth.response;
}
const result = await deleteKnowledgeEntry(auth.context, id);
if (!result.success) {
return jsonFailure(result.reason, result.status);
}
await recordAuditLog({
actor: auth.context.account,
organizationId: result.data.entry.organizationId ?? auth.context.organization?.id,
action: "ai.knowledge.delete",
targetType: "ai_knowledge",
targetId: result.data.entry.id,
result: "success",
reason: `删除知识库条目:${result.data.entry.title}`,
});
return jsonSuccess("知识库条目已删除", { entry: result.data.entry });
}

View File

@@ -0,0 +1,50 @@
import { createKnowledgeEntry, listKnowledgeEntries } from "@/modules/ai/server/knowledge";
import { validateKnowledgeEntryInput } from "@/modules/ai/types";
import { jsonFailure, jsonSuccess, readJsonBody } from "@/modules/core/server/api";
import { recordAuditLog } from "@/modules/core/server/audit";
import { requirePermission } from "@/modules/core/server/auth";
export async function GET(): Promise<Response> {
const auth = await requirePermission("knowledge:read", {
action: "ai.knowledge.list",
targetType: "ai_knowledge",
});
if (!auth.success) {
return auth.response;
}
const entries = await listKnowledgeEntries(auth.context);
return jsonSuccess("知识库已加载", { entries });
}
export async function POST(request: Request): Promise<Response> {
const auth = await requirePermission("knowledge:manage", {
action: "ai.knowledge.create",
targetType: "ai_knowledge",
});
if (!auth.success) {
return auth.response;
}
const input = validateKnowledgeEntryInput(await readJsonBody(request));
if (!input.success) {
return jsonFailure(input.reason);
}
const result = await createKnowledgeEntry(auth.context, input.input);
if (!result.success) {
return jsonFailure(result.reason, result.status);
}
await recordAuditLog({
actor: auth.context.account,
organizationId: result.data.entry.organizationId ?? auth.context.organization?.id,
action: "ai.knowledge.create",
targetType: "ai_knowledge",
targetId: result.data.entry.id,
result: "success",
reason: `创建知识库条目:${result.data.entry.title}`,
});
return jsonSuccess("知识库条目已创建", { entry: result.data.entry }, 201);
}