添加家人绑定
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
import { ConversationRole } from "@prisma/client";
|
||||
import { NextResponse } from "next/server";
|
||||
|
||||
import { recordConversationTurns } from "@/lib/monitor-data";
|
||||
|
||||
function toConversationRole(rawRole: unknown) {
|
||||
switch (rawRole) {
|
||||
case ConversationRole.USER:
|
||||
return ConversationRole.USER;
|
||||
case ConversationRole.TOOL:
|
||||
return ConversationRole.TOOL;
|
||||
default:
|
||||
return ConversationRole.ASSISTANT;
|
||||
}
|
||||
}
|
||||
|
||||
export async function POST(request: Request) {
|
||||
const body = (await request.json().catch(() => null)) as
|
||||
| {
|
||||
deviceUuid?: string;
|
||||
sessionId?: string;
|
||||
turns?: unknown;
|
||||
}
|
||||
| null;
|
||||
|
||||
if (!body?.deviceUuid || typeof body.deviceUuid !== "string") {
|
||||
return NextResponse.json(
|
||||
{ error: "deviceUuid 是必填项。" },
|
||||
{ status: 400 },
|
||||
);
|
||||
}
|
||||
|
||||
if (!Array.isArray(body.turns)) {
|
||||
return NextResponse.json(
|
||||
{ error: "turns 必须是数组。" },
|
||||
{ status: 400 },
|
||||
);
|
||||
}
|
||||
|
||||
const turns = body.turns
|
||||
.filter((turn): turn is Record<string, unknown> => !!turn && typeof turn === "object")
|
||||
.map((turn) => ({
|
||||
role: toConversationRole(turn.role),
|
||||
content: typeof turn.content === "string" ? turn.content : "",
|
||||
metaJson: typeof turn.metaJson === "string" ? turn.metaJson : undefined,
|
||||
createdAt: typeof turn.createdAt === "string" ? turn.createdAt : undefined,
|
||||
}))
|
||||
.filter((turn) => turn.content.trim().length > 0);
|
||||
|
||||
if (turns.length === 0) {
|
||||
return NextResponse.json(
|
||||
{ error: "至少需要一条有效对话内容。" },
|
||||
{ status: 400 },
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await recordConversationTurns({
|
||||
deviceUuid: body.deviceUuid,
|
||||
sessionId: typeof body.sessionId === "string" ? body.sessionId : undefined,
|
||||
turns,
|
||||
});
|
||||
|
||||
return NextResponse.json({ ok: true, count: result.count });
|
||||
} catch (error) {
|
||||
return NextResponse.json(
|
||||
{
|
||||
error:
|
||||
error instanceof Error ? error.message : "对话记录保存失败,请稍后再试。",
|
||||
},
|
||||
{ status: 400 },
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
import { NextResponse } from "next/server";
|
||||
|
||||
import { markFamilyMessagesAsRead } from "@/lib/monitor-data";
|
||||
|
||||
export async function POST(request: Request) {
|
||||
const body = (await request.json().catch(() => null)) as
|
||||
| {
|
||||
deviceUuid?: string;
|
||||
messageIds?: unknown;
|
||||
}
|
||||
| null;
|
||||
|
||||
if (!body?.deviceUuid || typeof body.deviceUuid !== "string") {
|
||||
return NextResponse.json(
|
||||
{ error: "deviceUuid 是必填项。" },
|
||||
{ status: 400 },
|
||||
);
|
||||
}
|
||||
|
||||
const messageIds = Array.isArray(body.messageIds)
|
||||
? body.messageIds.filter(
|
||||
(messageId): messageId is string => typeof messageId === "string",
|
||||
)
|
||||
: undefined;
|
||||
|
||||
try {
|
||||
await markFamilyMessagesAsRead(body.deviceUuid, messageIds);
|
||||
|
||||
return NextResponse.json({ ok: true });
|
||||
} catch (error) {
|
||||
return NextResponse.json(
|
||||
{
|
||||
error:
|
||||
error instanceof Error ? error.message : "更新留言状态失败,请稍后再试。",
|
||||
},
|
||||
{ status: 400 },
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
|
||||
import { listFamilyMessagesForDevice } from "@/lib/monitor-data";
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
const rawDeviceValue =
|
||||
request.nextUrl.searchParams.get("deviceUuid") ||
|
||||
request.nextUrl.searchParams.get("device") ||
|
||||
"";
|
||||
const take = Number.parseInt(
|
||||
request.nextUrl.searchParams.get("take") || "12",
|
||||
10,
|
||||
);
|
||||
|
||||
if (!rawDeviceValue) {
|
||||
return NextResponse.json(
|
||||
{ error: "deviceUuid 是必填项。" },
|
||||
{ status: 400 },
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
const data = await listFamilyMessagesForDevice(rawDeviceValue, take);
|
||||
|
||||
return NextResponse.json({
|
||||
deviceUuid: data.device.deviceUuid,
|
||||
unreadCount: data.unreadCount,
|
||||
summaryText: data.summaryText,
|
||||
messages: data.messages.map((message) => ({
|
||||
id: message.id,
|
||||
content: message.content,
|
||||
importance: message.importance,
|
||||
status: message.status,
|
||||
createdAt: message.createdAt.toISOString(),
|
||||
deliveredAt: message.deliveredAt?.toISOString() || null,
|
||||
readAt: message.readAt?.toISOString() || null,
|
||||
})),
|
||||
});
|
||||
} catch (error) {
|
||||
return NextResponse.json(
|
||||
{
|
||||
error:
|
||||
error instanceof Error ? error.message : "读取家属留言失败,请稍后再试。",
|
||||
},
|
||||
{ status: 400 },
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
import { NextResponse } from "next/server";
|
||||
|
||||
import { createBindUrl, ensureDeviceRegistration } from "@/lib/monitor-data";
|
||||
|
||||
export async function POST(request: Request) {
|
||||
const body = (await request.json().catch(() => null)) as
|
||||
| {
|
||||
deviceUuid?: string;
|
||||
displayName?: string;
|
||||
appVersion?: string;
|
||||
}
|
||||
| null;
|
||||
|
||||
if (!body?.deviceUuid || typeof body.deviceUuid !== "string") {
|
||||
return NextResponse.json(
|
||||
{ error: "deviceUuid 是必填项。" },
|
||||
{ status: 400 },
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
const device = await ensureDeviceRegistration({
|
||||
deviceUuid: body.deviceUuid,
|
||||
displayName:
|
||||
typeof body.displayName === "string" ? body.displayName : undefined,
|
||||
appVersion:
|
||||
typeof body.appVersion === "string" ? body.appVersion : undefined,
|
||||
});
|
||||
|
||||
return NextResponse.json({
|
||||
deviceUuid: device.deviceUuid,
|
||||
bindUrl: createBindUrl(device.deviceUuid),
|
||||
});
|
||||
} catch (error) {
|
||||
return NextResponse.json(
|
||||
{
|
||||
error:
|
||||
error instanceof Error ? error.message : "设备注册失败,请稍后再试。",
|
||||
},
|
||||
{ status: 500 },
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
import { ToolCallStatus } from "@prisma/client";
|
||||
import { NextResponse } from "next/server";
|
||||
|
||||
import { recordToolCall } from "@/lib/monitor-data";
|
||||
|
||||
function toToolCallStatus(rawStatus: unknown) {
|
||||
return rawStatus === ToolCallStatus.FAILURE
|
||||
? ToolCallStatus.FAILURE
|
||||
: ToolCallStatus.SUCCESS;
|
||||
}
|
||||
|
||||
function toArguments(rawArguments: unknown) {
|
||||
if (
|
||||
rawArguments &&
|
||||
typeof rawArguments === "object" &&
|
||||
!Array.isArray(rawArguments)
|
||||
) {
|
||||
return rawArguments as Record<string, unknown>;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
export async function POST(request: Request) {
|
||||
const body = (await request.json().catch(() => null)) as
|
||||
| {
|
||||
deviceUuid?: string;
|
||||
toolName?: string;
|
||||
arguments?: unknown;
|
||||
outputText?: string;
|
||||
status?: string;
|
||||
callId?: string;
|
||||
sessionId?: string;
|
||||
}
|
||||
| null;
|
||||
|
||||
if (!body?.deviceUuid || typeof body.deviceUuid !== "string") {
|
||||
return NextResponse.json(
|
||||
{ error: "deviceUuid 是必填项。" },
|
||||
{ status: 400 },
|
||||
);
|
||||
}
|
||||
|
||||
if (!body.toolName || typeof body.toolName !== "string") {
|
||||
return NextResponse.json(
|
||||
{ error: "toolName 是必填项。" },
|
||||
{ status: 400 },
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
const log = await recordToolCall({
|
||||
deviceUuid: body.deviceUuid,
|
||||
toolName: body.toolName,
|
||||
arguments: toArguments(body.arguments),
|
||||
outputText: typeof body.outputText === "string" ? body.outputText : undefined,
|
||||
status: toToolCallStatus(body.status),
|
||||
callId: typeof body.callId === "string" ? body.callId : undefined,
|
||||
sessionId:
|
||||
typeof body.sessionId === "string" ? body.sessionId : undefined,
|
||||
});
|
||||
|
||||
return NextResponse.json({ ok: true, logId: log.id });
|
||||
} catch (error) {
|
||||
return NextResponse.json(
|
||||
{
|
||||
error:
|
||||
error instanceof Error ? error.message : "工具调用记录失败,请稍后再试。",
|
||||
},
|
||||
{ status: 400 },
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
import { UsageEventType } from "@prisma/client";
|
||||
import { NextResponse } from "next/server";
|
||||
|
||||
import { recordUsageEvent } from "@/lib/monitor-data";
|
||||
|
||||
function toUsageEventType(rawType: unknown) {
|
||||
switch (rawType) {
|
||||
case UsageEventType.APP_OPEN:
|
||||
return UsageEventType.APP_OPEN;
|
||||
case UsageEventType.SETTINGS_OPENED:
|
||||
return UsageEventType.SETTINGS_OPENED;
|
||||
case UsageEventType.AI_SESSION_STARTED:
|
||||
return UsageEventType.AI_SESSION_STARTED;
|
||||
case UsageEventType.AI_SESSION_ENDED:
|
||||
return UsageEventType.AI_SESSION_ENDED;
|
||||
case UsageEventType.CAMERA_ENABLED:
|
||||
return UsageEventType.CAMERA_ENABLED;
|
||||
case UsageEventType.CAMERA_DISABLED:
|
||||
return UsageEventType.CAMERA_DISABLED;
|
||||
default:
|
||||
return UsageEventType.TOOL_CALLED;
|
||||
}
|
||||
}
|
||||
|
||||
export async function POST(request: Request) {
|
||||
const body = (await request.json().catch(() => null)) as
|
||||
| {
|
||||
deviceUuid?: string;
|
||||
eventType?: string;
|
||||
detailJson?: string;
|
||||
}
|
||||
| null;
|
||||
|
||||
if (!body?.deviceUuid || typeof body.deviceUuid !== "string") {
|
||||
return NextResponse.json(
|
||||
{ error: "deviceUuid 是必填项。" },
|
||||
{ status: 400 },
|
||||
);
|
||||
}
|
||||
|
||||
if (!body.eventType || typeof body.eventType !== "string") {
|
||||
return NextResponse.json(
|
||||
{ error: "eventType 是必填项。" },
|
||||
{ status: 400 },
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
await recordUsageEvent({
|
||||
deviceUuid: body.deviceUuid,
|
||||
eventType: toUsageEventType(body.eventType),
|
||||
detailJson: typeof body.detailJson === "string" ? body.detailJson : undefined,
|
||||
});
|
||||
|
||||
return NextResponse.json({ ok: true });
|
||||
} catch (error) {
|
||||
return NextResponse.json(
|
||||
{
|
||||
error:
|
||||
error instanceof Error ? error.message : "使用记录保存失败,请稍后再试。",
|
||||
},
|
||||
{ status: 400 },
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user