196 lines
6.2 KiB
TypeScript
196 lines
6.2 KiB
TypeScript
"use client";
|
|
|
|
import { createNotesApiClient } from "@/lib/api-helpers";
|
|
import type {
|
|
PromptTemplate,
|
|
RunPromptInput,
|
|
RunPromptOutput,
|
|
SimilarNote,
|
|
KnowledgeGap,
|
|
} from "@/lib/types";
|
|
|
|
// ── Template CRUD ─────────────────────────────────────────────
|
|
|
|
export async function listPromptTemplates(): Promise<PromptTemplate[]> {
|
|
const api = createNotesApiClient();
|
|
const res = await api.fetch<{ items: PromptTemplate[] }>("/note-prompts");
|
|
return res.items;
|
|
}
|
|
|
|
export async function getPromptTemplate(id: string): Promise<PromptTemplate> {
|
|
const api = createNotesApiClient();
|
|
return api.fetch<PromptTemplate>(`/note-prompts/${encodeURIComponent(id)}`);
|
|
}
|
|
|
|
export async function createPromptTemplate(
|
|
input: Omit<PromptTemplate, "id" | "isBuiltin">,
|
|
): Promise<PromptTemplate> {
|
|
const api = createNotesApiClient();
|
|
return api.fetch<PromptTemplate>("/note-prompts", {
|
|
method: "POST",
|
|
body: JSON.stringify(input),
|
|
});
|
|
}
|
|
|
|
export async function deletePromptTemplate(id: string): Promise<void> {
|
|
const api = createNotesApiClient();
|
|
await api.fetch(`/note-prompts/${encodeURIComponent(id)}`, { method: "DELETE" });
|
|
}
|
|
|
|
// ── Run prompts ───────────────────────────────────────────────
|
|
|
|
export async function runPrompt(input: RunPromptInput): Promise<RunPromptOutput> {
|
|
const api = createNotesApiClient();
|
|
return api.fetch<RunPromptOutput>("/note-prompts/run", {
|
|
method: "POST",
|
|
body: JSON.stringify(input),
|
|
});
|
|
}
|
|
|
|
// ── Run prompts (streaming) ───────────────────────────────────
|
|
|
|
export async function runPromptStream(
|
|
input: RunPromptInput,
|
|
onToken: (content: string) => void,
|
|
onDone: (meta: Partial<RunPromptOutput>) => void,
|
|
onError?: (message: string) => void,
|
|
): Promise<void> {
|
|
const api = createNotesApiClient();
|
|
const baseUrl = (api as unknown as { baseUrl?: string }).baseUrl ?? "";
|
|
const token = typeof window !== "undefined" ? localStorage.getItem("access_token") : null;
|
|
const headers: Record<string, string> = { "Content-Type": "application/json" };
|
|
if (token) headers["Authorization"] = `Bearer ${token}`;
|
|
|
|
const res = await fetch(`${baseUrl}/note-prompts/run-stream`, {
|
|
method: "POST",
|
|
headers,
|
|
body: JSON.stringify(input),
|
|
});
|
|
|
|
if (!res.ok || !res.body) {
|
|
onError?.(res.statusText || "Stream failed");
|
|
return;
|
|
}
|
|
|
|
const reader = res.body.getReader();
|
|
const decoder = new TextDecoder();
|
|
let buffer = "";
|
|
|
|
while (true) {
|
|
const { done, value } = await reader.read();
|
|
if (done) break;
|
|
buffer += decoder.decode(value, { stream: true });
|
|
const lines = buffer.split("\n\n");
|
|
buffer = lines.pop() ?? "";
|
|
for (const line of lines) {
|
|
if (!line.startsWith("data: ")) continue;
|
|
try {
|
|
const payload = JSON.parse(line.slice(6));
|
|
if (payload.type === "token") onToken(payload.content);
|
|
else if (payload.type === "done") onDone(payload);
|
|
else if (payload.type === "error") onError?.(payload.message);
|
|
} catch { /* skip malformed */ }
|
|
}
|
|
}
|
|
}
|
|
|
|
// ── History ──────────────────────────────────────────────────
|
|
|
|
export interface PromptHistoryItem {
|
|
id: string;
|
|
noteId: string;
|
|
workspaceId: string;
|
|
toolName?: string;
|
|
state: string;
|
|
reason?: string;
|
|
afterSummary?: string;
|
|
createdAt: string;
|
|
}
|
|
|
|
export async function listPromptHistory(
|
|
workspaceId: string,
|
|
limit = 20,
|
|
): Promise<{ items: PromptHistoryItem[]; total: number }> {
|
|
const api = createNotesApiClient();
|
|
return api.fetch(`/note-prompts/history?workspaceId=${encodeURIComponent(workspaceId)}&limit=${limit}`);
|
|
}
|
|
|
|
// ── Intelligence endpoints ────────────────────────────────────
|
|
|
|
export async function suggestTags(
|
|
noteId: string,
|
|
workspaceId: string,
|
|
): Promise<string[]> {
|
|
const api = createNotesApiClient();
|
|
const res = await api.fetch<{ tags: string[] }>(
|
|
`/notes/${encodeURIComponent(noteId)}/suggest-tags`,
|
|
{ method: "POST", body: JSON.stringify({ workspaceId }) },
|
|
);
|
|
return res.tags;
|
|
}
|
|
|
|
export async function checkDuplicates(
|
|
noteId: string,
|
|
workspaceId: string,
|
|
threshold = 0.85,
|
|
): Promise<SimilarNote[]> {
|
|
const api = createNotesApiClient();
|
|
const res = await api.fetch<{ duplicates: SimilarNote[] }>(
|
|
`/notes/${encodeURIComponent(noteId)}/check-duplicates`,
|
|
{ method: "POST", body: JSON.stringify({ workspaceId, threshold }) },
|
|
);
|
|
return res.duplicates;
|
|
}
|
|
|
|
export async function suggestLinks(
|
|
noteId: string,
|
|
workspaceId: string,
|
|
threshold = 0.6,
|
|
): Promise<SimilarNote[]> {
|
|
const api = createNotesApiClient();
|
|
const res = await api.fetch<{ suggestions: SimilarNote[] }>(
|
|
`/notes/${encodeURIComponent(noteId)}/suggest-links`,
|
|
{ method: "POST", body: JSON.stringify({ workspaceId, threshold }) },
|
|
);
|
|
return res.suggestions;
|
|
}
|
|
|
|
export async function getReadingTime(
|
|
noteId: string,
|
|
workspaceId: string,
|
|
): Promise<{ wordCount: number; readingTimeMinutes: number }> {
|
|
const api = createNotesApiClient();
|
|
return api.fetch(`/notes/${encodeURIComponent(noteId)}/reading-time?workspaceId=${encodeURIComponent(workspaceId)}`);
|
|
}
|
|
|
|
export async function compareNotes(
|
|
noteIds: string[],
|
|
workspaceId: string,
|
|
): Promise<RunPromptOutput> {
|
|
const api = createNotesApiClient();
|
|
return api.fetch<RunPromptOutput>("/notes/compare", {
|
|
method: "POST",
|
|
body: JSON.stringify({ noteIds, workspaceId }),
|
|
});
|
|
}
|
|
|
|
export async function mergeNotes(
|
|
noteIds: string[],
|
|
workspaceId: string,
|
|
): Promise<RunPromptOutput> {
|
|
const api = createNotesApiClient();
|
|
return api.fetch<RunPromptOutput>("/notes/merge", {
|
|
method: "POST",
|
|
body: JSON.stringify({ noteIds, workspaceId }),
|
|
});
|
|
}
|
|
|
|
export async function getKnowledgeGaps(
|
|
workspaceId: string,
|
|
): Promise<{ gaps: KnowledgeGap[]; topicMap: Record<string, number> }> {
|
|
const api = createNotesApiClient();
|
|
return api.fetch(`/workspaces/${encodeURIComponent(workspaceId)}/knowledge-gaps`, {
|
|
method: "POST",
|
|
});
|
|
}
|