10
apps/web/src/app/api/ai/chat/knows/route.ts
Normal file
10
apps/web/src/app/api/ai/chat/knows/route.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { handleApi } from "@/lib/api";
|
||||
import { requireUser } from "@/lib/services/user";
|
||||
import { getWhatAiKnows } from "@/lib/services/ai-chat";
|
||||
|
||||
export async function GET() {
|
||||
return handleApi(async () => {
|
||||
const { user } = await requireUser();
|
||||
return getWhatAiKnows(user.id);
|
||||
});
|
||||
}
|
||||
40
apps/web/src/app/api/ai/chat/sessions/[id]/route.ts
Normal file
40
apps/web/src/app/api/ai/chat/sessions/[id]/route.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import { handleApi } from "@/lib/api";
|
||||
import { requireUser } from "@/lib/services/user";
|
||||
import { getChatSession, sendChatMessage, archiveChatSession } from "@/lib/services/ai-chat";
|
||||
|
||||
export async function GET(
|
||||
_request: Request,
|
||||
{ params }: { params: Promise<{ id: string }> }
|
||||
) {
|
||||
const { id } = await params;
|
||||
return handleApi(async () => {
|
||||
const { user } = await requireUser();
|
||||
const data = await getChatSession(user.id, id);
|
||||
if (!data) throw new Error("Session not found");
|
||||
return data;
|
||||
});
|
||||
}
|
||||
|
||||
export async function DELETE(
|
||||
_request: Request,
|
||||
{ params }: { params: Promise<{ id: string }> }
|
||||
) {
|
||||
const { id } = await params;
|
||||
return handleApi(async () => {
|
||||
const { user } = await requireUser();
|
||||
await archiveChatSession(user.id, id);
|
||||
return { ok: true };
|
||||
});
|
||||
}
|
||||
|
||||
export async function POST(
|
||||
request: Request,
|
||||
{ params }: { params: Promise<{ id: string }> }
|
||||
) {
|
||||
const { id } = await params;
|
||||
const body = await request.json();
|
||||
return handleApi(async () => {
|
||||
const { user } = await requireUser();
|
||||
return sendChatMessage(user.id, id, body.content ?? "");
|
||||
});
|
||||
}
|
||||
19
apps/web/src/app/api/ai/chat/sessions/route.ts
Normal file
19
apps/web/src/app/api/ai/chat/sessions/route.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { handleApi } from "@/lib/api";
|
||||
import { requireUser } from "@/lib/services/user";
|
||||
import { listChatSessions, createChatSession } from "@/lib/services/ai-chat";
|
||||
|
||||
export async function GET() {
|
||||
return handleApi(async () => {
|
||||
const { user } = await requireUser();
|
||||
const sessions = await listChatSessions(user.id);
|
||||
return { sessions };
|
||||
});
|
||||
}
|
||||
|
||||
export async function POST(request: Request) {
|
||||
const body = await request.json().catch(() => ({}));
|
||||
return handleApi(async () => {
|
||||
const { user } = await requireUser();
|
||||
return createChatSession(user.id, body.title, body.featureContext);
|
||||
});
|
||||
}
|
||||
33
apps/web/src/app/api/ai/config/route.ts
Executable file
33
apps/web/src/app/api/ai/config/route.ts
Executable file
@@ -0,0 +1,33 @@
|
||||
import { handleApi } from "@/lib/api";
|
||||
import { requireUser } from "@/lib/services/user";
|
||||
import {
|
||||
getAiBehaviorConfig,
|
||||
getAiProviderConfig,
|
||||
saveAiBehaviorConfig,
|
||||
saveAiProviderConfig,
|
||||
} from "@/lib/services/ai-config";
|
||||
|
||||
export async function GET() {
|
||||
return handleApi(async () => {
|
||||
const { user } = await requireUser();
|
||||
const behavior = await getAiBehaviorConfig(user.id);
|
||||
const provider = await getAiProviderConfig(user.id);
|
||||
return { behavior, provider };
|
||||
});
|
||||
}
|
||||
|
||||
export async function PATCH(request: Request) {
|
||||
const body = await request.json();
|
||||
return handleApi(async () => {
|
||||
const { user } = await requireUser();
|
||||
let behavior = await getAiBehaviorConfig(user.id);
|
||||
let provider = await getAiProviderConfig(user.id);
|
||||
if (body.behavior) {
|
||||
behavior = await saveAiBehaviorConfig(user.id, body.behavior);
|
||||
}
|
||||
if (body.provider) {
|
||||
provider = await saveAiProviderConfig(user.id, body.provider);
|
||||
}
|
||||
return { behavior, provider };
|
||||
});
|
||||
}
|
||||
19
apps/web/src/app/api/ai/context/preview/route.ts
Normal file
19
apps/web/src/app/api/ai/context/preview/route.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { handleApi } from "@/lib/api";
|
||||
import { requireUser } from "@/lib/services/user";
|
||||
import { buildMentorContext, formatContextForPrompt } from "@/lib/services/ai-context";
|
||||
|
||||
export async function GET(request: Request) {
|
||||
const { searchParams } = new URL(request.url);
|
||||
const message = searchParams.get("message") ?? "";
|
||||
const feature = searchParams.get("feature") ?? "mentor";
|
||||
return handleApi(async () => {
|
||||
const { user } = await requireUser();
|
||||
const ctx = await buildMentorContext(user.id, { userMessage: message, feature, logContext: false });
|
||||
return {
|
||||
layers: ctx.layers,
|
||||
tokenEstimate: ctx.tokenEstimate,
|
||||
memoryIds: ctx.memoryIds,
|
||||
formatted: formatContextForPrompt(ctx),
|
||||
};
|
||||
});
|
||||
}
|
||||
21
apps/web/src/app/api/ai/health/route.ts
Executable file
21
apps/web/src/app/api/ai/health/route.ts
Executable file
@@ -0,0 +1,21 @@
|
||||
import { handleApi } from "@/lib/api";
|
||||
import { requireUser } from "@/lib/services/user";
|
||||
import { getCachedHealth, runHealthCheck } from "@/lib/services/ai-config";
|
||||
import { getLastHealthLogs } from "@/lib/services/ai-config";
|
||||
|
||||
export async function GET() {
|
||||
return handleApi(async () => {
|
||||
const { user } = await requireUser();
|
||||
const cached = await getCachedHealth(user.id);
|
||||
const logs = await getLastHealthLogs(user.id, 5);
|
||||
return { health: cached, logs };
|
||||
});
|
||||
}
|
||||
|
||||
export async function POST() {
|
||||
return handleApi(async () => {
|
||||
const { user } = await requireUser();
|
||||
const health = await runHealthCheck(user.id);
|
||||
return { health };
|
||||
});
|
||||
}
|
||||
40
apps/web/src/app/api/ai/memory/[id]/route.ts
Normal file
40
apps/web/src/app/api/ai/memory/[id]/route.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import { handleApi } from "@/lib/api";
|
||||
import { requireUser } from "@/lib/services/user";
|
||||
import { getMemory, updateMemory, archiveMemory } from "@/lib/services/ai-memory";
|
||||
|
||||
export async function GET(
|
||||
_request: Request,
|
||||
{ params }: { params: Promise<{ id: string }> }
|
||||
) {
|
||||
const { id } = await params;
|
||||
return handleApi(async () => {
|
||||
const { user } = await requireUser();
|
||||
const memory = await getMemory(user.id, id);
|
||||
if (!memory) throw new Error("Memory not found");
|
||||
return memory;
|
||||
});
|
||||
}
|
||||
|
||||
export async function PATCH(
|
||||
request: Request,
|
||||
{ params }: { params: Promise<{ id: string }> }
|
||||
) {
|
||||
const { id } = await params;
|
||||
const body = await request.json();
|
||||
return handleApi(async () => {
|
||||
const { user } = await requireUser();
|
||||
return updateMemory(user.id, id, body);
|
||||
});
|
||||
}
|
||||
|
||||
export async function DELETE(
|
||||
_request: Request,
|
||||
{ params }: { params: Promise<{ id: string }> }
|
||||
) {
|
||||
const { id } = await params;
|
||||
return handleApi(async () => {
|
||||
const { user } = await requireUser();
|
||||
await archiveMemory(user.id, id);
|
||||
return { ok: true };
|
||||
});
|
||||
}
|
||||
21
apps/web/src/app/api/ai/memory/learning/route.ts
Normal file
21
apps/web/src/app/api/ai/memory/learning/route.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { handleApi } from "@/lib/api";
|
||||
import { requireUser } from "@/lib/services/user";
|
||||
import {
|
||||
getMemoryLearningSettings,
|
||||
saveMemoryLearningSettings,
|
||||
} from "@/lib/services/ai-memory";
|
||||
|
||||
export async function GET() {
|
||||
return handleApi(async () => {
|
||||
const { user } = await requireUser();
|
||||
return getMemoryLearningSettings(user.id);
|
||||
});
|
||||
}
|
||||
|
||||
export async function PATCH(request: Request) {
|
||||
const body = await request.json();
|
||||
return handleApi(async () => {
|
||||
const { user } = await requireUser();
|
||||
return saveMemoryLearningSettings(user.id, body);
|
||||
});
|
||||
}
|
||||
13
apps/web/src/app/api/ai/memory/reset/route.ts
Normal file
13
apps/web/src/app/api/ai/memory/reset/route.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { handleApi } from "@/lib/api";
|
||||
import { requireUser } from "@/lib/services/user";
|
||||
import { resetAllMemories } from "@/lib/services/ai-memory";
|
||||
|
||||
export async function POST(request: Request) {
|
||||
const body = await request.json();
|
||||
return handleApi(async () => {
|
||||
const { user } = await requireUser();
|
||||
if (!body.confirm) throw new Error("Confirmation required");
|
||||
await resetAllMemories(user.id);
|
||||
return { ok: true };
|
||||
});
|
||||
}
|
||||
32
apps/web/src/app/api/ai/memory/route.ts
Normal file
32
apps/web/src/app/api/ai/memory/route.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import { handleApi } from "@/lib/api";
|
||||
import { requireUser } from "@/lib/services/user";
|
||||
import {
|
||||
listMemories,
|
||||
createMemory,
|
||||
getProfileSummary,
|
||||
listSuggestions,
|
||||
exportMemories,
|
||||
} from "@/lib/services/ai-memory";
|
||||
|
||||
export async function GET(request: Request) {
|
||||
const { searchParams } = new URL(request.url);
|
||||
return handleApi(async () => {
|
||||
const { user } = await requireUser();
|
||||
const category = searchParams.get("category") ?? undefined;
|
||||
const q = searchParams.get("q") ?? undefined;
|
||||
const enabledParam = searchParams.get("enabled");
|
||||
const enabled = enabledParam === null ? undefined : enabledParam === "true";
|
||||
const memories = await listMemories(user.id, { category, q, enabled });
|
||||
const summary = await getProfileSummary(user.id);
|
||||
const pending = await listSuggestions(user.id, "pending");
|
||||
return { memories, summary, pendingCount: pending.length };
|
||||
});
|
||||
}
|
||||
|
||||
export async function POST(request: Request) {
|
||||
const body = await request.json();
|
||||
return handleApi(async () => {
|
||||
const { user } = await requireUser();
|
||||
return createMemory(user.id, body);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import { handleApi } from "@/lib/api";
|
||||
import { requireUser } from "@/lib/services/user";
|
||||
import { acceptSuggestion } from "@/lib/services/ai-memory";
|
||||
|
||||
export async function POST(
|
||||
request: Request,
|
||||
{ params }: { params: Promise<{ id: string }> }
|
||||
) {
|
||||
const { id } = await params;
|
||||
const body = await request.json().catch(() => ({}));
|
||||
return handleApi(async () => {
|
||||
const { user } = await requireUser();
|
||||
return acceptSuggestion(user.id, id, body);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import { handleApi } from "@/lib/api";
|
||||
import { requireUser } from "@/lib/services/user";
|
||||
import { ignoreSuggestion } from "@/lib/services/ai-memory";
|
||||
|
||||
export async function POST(
|
||||
_request: Request,
|
||||
{ params }: { params: Promise<{ id: string }> }
|
||||
) {
|
||||
const { id } = await params;
|
||||
return handleApi(async () => {
|
||||
const { user } = await requireUser();
|
||||
await ignoreSuggestion(user.id, id);
|
||||
return { ok: true };
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import { handleApi } from "@/lib/api";
|
||||
import { requireUser } from "@/lib/services/user";
|
||||
import { rejectSuggestion } from "@/lib/services/ai-memory";
|
||||
|
||||
export async function POST(
|
||||
_request: Request,
|
||||
{ params }: { params: Promise<{ id: string }> }
|
||||
) {
|
||||
const { id } = await params;
|
||||
return handleApi(async () => {
|
||||
const { user } = await requireUser();
|
||||
await rejectSuggestion(user.id, id);
|
||||
return { ok: true };
|
||||
});
|
||||
}
|
||||
13
apps/web/src/app/api/ai/memory/suggestions/route.ts
Normal file
13
apps/web/src/app/api/ai/memory/suggestions/route.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { handleApi } from "@/lib/api";
|
||||
import { requireUser } from "@/lib/services/user";
|
||||
import { listSuggestions } from "@/lib/services/ai-memory";
|
||||
|
||||
export async function GET(request: Request) {
|
||||
const { searchParams } = new URL(request.url);
|
||||
const status = searchParams.get("status") ?? "pending";
|
||||
return handleApi(async () => {
|
||||
const { user } = await requireUser();
|
||||
const suggestions = await listSuggestions(user.id, status);
|
||||
return { suggestions };
|
||||
});
|
||||
}
|
||||
54
apps/web/src/app/api/ai/memory/summary/rebuild/route.ts
Normal file
54
apps/web/src/app/api/ai/memory/summary/rebuild/route.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
import { handleApi } from "@/lib/api";
|
||||
import { requireUser } from "@/lib/services/user";
|
||||
import { listMemories, saveProfileSummary } from "@/lib/services/ai-memory";
|
||||
import { getProvider } from "@/lib/ai/provider-registry";
|
||||
import { getAiBehaviorConfig, getAiProviderConfig, buildSystemPrompt } from "@/lib/services/ai-config";
|
||||
import { getTemplateBody } from "@/lib/services/ai-templates";
|
||||
import { renderTemplate } from "@/lib/ai/prompts/render";
|
||||
|
||||
export async function POST() {
|
||||
return handleApi(async () => {
|
||||
const { user } = await requireUser();
|
||||
const memories = await listMemories(user.id, { enabled: true });
|
||||
const verified = memories.filter((m) => m.userVerified);
|
||||
|
||||
const bulletList = verified
|
||||
.map((m) => `- [${m.category}] ${m.title}: ${m.content.slice(0, 120)}`)
|
||||
.join("\n");
|
||||
|
||||
const behavior = await getAiBehaviorConfig(user.id);
|
||||
const providerConfig = await getAiProviderConfig(user.id);
|
||||
|
||||
let summaryText = verified.length === 0
|
||||
? "No verified memories yet. Add memories manually to build your profile."
|
||||
: bulletList.slice(0, 1500);
|
||||
|
||||
if (behavior.enabled && providerConfig.enabled && verified.length > 0) {
|
||||
try {
|
||||
const coreSystem = await getTemplateBody(user.id, "system_core");
|
||||
const templateBody = await getTemplateBody(user.id, "mentor_summary");
|
||||
const system = buildSystemPrompt(behavior, coreSystem);
|
||||
const prompt = renderTemplate(templateBody, {
|
||||
user_name: user.displayName,
|
||||
context: bulletList,
|
||||
});
|
||||
const provider = getProvider(providerConfig.type);
|
||||
const res = await provider.generateText(providerConfig, {
|
||||
model: providerConfig.model,
|
||||
prompt,
|
||||
system,
|
||||
format: "text",
|
||||
temperature: 0.5,
|
||||
maxTokens: 400,
|
||||
timeoutMs: providerConfig.timeoutMs,
|
||||
});
|
||||
if (res.text.trim()) summaryText = res.text.trim();
|
||||
} catch {
|
||||
/* use bullet list fallback */
|
||||
}
|
||||
}
|
||||
|
||||
const summary = await saveProfileSummary(user.id, summaryText);
|
||||
return { ...summary, sourceMemoryCount: verified.length };
|
||||
});
|
||||
}
|
||||
34
apps/web/src/app/api/ai/memory/summary/route.ts
Normal file
34
apps/web/src/app/api/ai/memory/summary/route.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import { handleApi } from "@/lib/api";
|
||||
import { requireUser } from "@/lib/services/user";
|
||||
import {
|
||||
getProfileSummary,
|
||||
saveProfileSummary,
|
||||
exportMemories,
|
||||
importMemories,
|
||||
} from "@/lib/services/ai-memory";
|
||||
|
||||
export async function GET() {
|
||||
return handleApi(async () => {
|
||||
const { user } = await requireUser();
|
||||
return getProfileSummary(user.id);
|
||||
});
|
||||
}
|
||||
|
||||
export async function PATCH(request: Request) {
|
||||
const body = await request.json();
|
||||
return handleApi(async () => {
|
||||
const { user } = await requireUser();
|
||||
return saveProfileSummary(user.id, body.summary ?? "");
|
||||
});
|
||||
}
|
||||
|
||||
export async function POST(request: Request) {
|
||||
const body = await request.json();
|
||||
return handleApi(async () => {
|
||||
const { user } = await requireUser();
|
||||
if (body.action === "import") {
|
||||
return importMemories(user.id, body.data, body.overwrite);
|
||||
}
|
||||
return exportMemories(user.id);
|
||||
});
|
||||
}
|
||||
23
apps/web/src/app/api/ai/models/route.ts
Executable file
23
apps/web/src/app/api/ai/models/route.ts
Executable file
@@ -0,0 +1,23 @@
|
||||
import { handleApi } from "@/lib/api";
|
||||
import { listProviderTypes } from "@/lib/ai/provider-registry";
|
||||
import { requireUser } from "@/lib/services/user";
|
||||
import { getAiProviderConfig } from "@/lib/services/ai-config";
|
||||
import { getProvider } from "@/lib/ai/provider-registry";
|
||||
|
||||
export async function GET() {
|
||||
return handleApi(async () => {
|
||||
const providers = listProviderTypes();
|
||||
return { providers };
|
||||
});
|
||||
}
|
||||
|
||||
export async function POST() {
|
||||
return handleApi(async () => {
|
||||
const { user } = await requireUser();
|
||||
const config = await getAiProviderConfig(user.id);
|
||||
const provider = getProvider(config.type);
|
||||
if (!provider.listModels) return { models: [config.model] };
|
||||
const models = await provider.listModels(config);
|
||||
return { models };
|
||||
});
|
||||
}
|
||||
15
apps/web/src/app/api/ai/suggestions/[id]/dismiss/route.ts
Executable file
15
apps/web/src/app/api/ai/suggestions/[id]/dismiss/route.ts
Executable file
@@ -0,0 +1,15 @@
|
||||
import { handleApi } from "@/lib/api";
|
||||
import { dismissSuggestion } from "@/lib/services/explorations";
|
||||
import { requireUser } from "@/lib/services/user";
|
||||
|
||||
export async function POST(
|
||||
_request: Request,
|
||||
{ params }: { params: Promise<{ id: string }> }
|
||||
) {
|
||||
const { id } = await params;
|
||||
return handleApi(async () => {
|
||||
const { user } = await requireUser();
|
||||
await dismissSuggestion(id, user.id);
|
||||
return { ok: true };
|
||||
});
|
||||
}
|
||||
26
apps/web/src/app/api/ai/suggestions/route.ts
Executable file
26
apps/web/src/app/api/ai/suggestions/route.ts
Executable file
@@ -0,0 +1,26 @@
|
||||
import { handleApi, jsonError } from "@/lib/api";
|
||||
import { getSuggestions, dismissSuggestion, generateDailyQuests } from "@/lib/services/explorations";
|
||||
import { requireUser } from "@/lib/services/user";
|
||||
import { isOllamaAvailable } from "@/lib/services/ai";
|
||||
|
||||
export async function GET(request: Request) {
|
||||
const { searchParams } = new URL(request.url);
|
||||
const role = searchParams.get("role") ?? undefined;
|
||||
return handleApi(async () => {
|
||||
const { user } = await requireUser();
|
||||
const suggestions = await getSuggestions(user.id, role);
|
||||
const ollamaAvailable = await isOllamaAvailable();
|
||||
return { suggestions, ollamaAvailable };
|
||||
});
|
||||
}
|
||||
|
||||
export async function POST(request: Request) {
|
||||
const body = await request.json();
|
||||
return handleApi(async () => {
|
||||
const { user } = await requireUser();
|
||||
if (body.action === "generate_quests") {
|
||||
return generateDailyQuests(user.id);
|
||||
}
|
||||
throw new Error("Unknown action");
|
||||
});
|
||||
}
|
||||
64
apps/web/src/app/api/ai/templates/[key]/route.ts
Executable file
64
apps/web/src/app/api/ai/templates/[key]/route.ts
Executable file
@@ -0,0 +1,64 @@
|
||||
import { handleApi } from "@/lib/api";
|
||||
import { requireUser } from "@/lib/services/user";
|
||||
import {
|
||||
getPromptTemplate,
|
||||
updatePromptTemplate,
|
||||
resetPromptTemplate,
|
||||
previewTemplate,
|
||||
getTemplateVersions,
|
||||
restoreTemplateVersion,
|
||||
} from "@/lib/services/ai-templates";
|
||||
|
||||
export async function GET(
|
||||
_request: Request,
|
||||
{ params }: { params: Promise<{ key: string }> }
|
||||
) {
|
||||
const { key } = await params;
|
||||
return handleApi(async () => {
|
||||
const { user } = await requireUser();
|
||||
const template = await getPromptTemplate(user.id, key);
|
||||
const versions = await getTemplateVersions(user.id, key);
|
||||
return { template, versions };
|
||||
});
|
||||
}
|
||||
|
||||
export async function PATCH(
|
||||
request: Request,
|
||||
{ params }: { params: Promise<{ key: string }> }
|
||||
) {
|
||||
const { key } = await params;
|
||||
const body = await request.json();
|
||||
return handleApi(async () => {
|
||||
const { user } = await requireUser();
|
||||
const template = await updatePromptTemplate(user.id, key, body);
|
||||
return { template };
|
||||
});
|
||||
}
|
||||
|
||||
export async function POST(
|
||||
request: Request,
|
||||
{ params }: { params: Promise<{ key: string }> }
|
||||
) {
|
||||
const { key } = await params;
|
||||
const { searchParams } = new URL(request.url);
|
||||
const action = searchParams.get("action");
|
||||
const body = await request.json().catch(() => ({}));
|
||||
|
||||
return handleApi(async () => {
|
||||
const { user } = await requireUser();
|
||||
|
||||
if (action === "reset") {
|
||||
const template = await resetPromptTemplate(user.id, key);
|
||||
return { template };
|
||||
}
|
||||
if (action === "preview") {
|
||||
const rendered = await previewTemplate(user.id, key, body.body);
|
||||
return { rendered };
|
||||
}
|
||||
if (action === "restore" && body.version) {
|
||||
const template = await restoreTemplateVersion(user.id, key, body.version);
|
||||
return { template };
|
||||
}
|
||||
throw new Error("Unknown action");
|
||||
});
|
||||
}
|
||||
12
apps/web/src/app/api/ai/templates/route.ts
Executable file
12
apps/web/src/app/api/ai/templates/route.ts
Executable file
@@ -0,0 +1,12 @@
|
||||
import { handleApi } from "@/lib/api";
|
||||
import { requireUser } from "@/lib/services/user";
|
||||
import { getPromptTemplates } from "@/lib/services/ai-templates";
|
||||
import { PLACEHOLDER_DOCS } from "@/lib/ai/prompts/defaults";
|
||||
|
||||
export async function GET() {
|
||||
return handleApi(async () => {
|
||||
const { user } = await requireUser();
|
||||
const templates = await getPromptTemplates(user.id);
|
||||
return { templates, placeholders: PLACEHOLDER_DOCS };
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user