feat(web): enrich note detail with extraction
This commit is contained in:
parent
d44763dfe7
commit
a7c362a9fc
56
web/src/lib/extraction-client.ts
Normal file
56
web/src/lib/extraction-client.ts
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { createApiClient } from "@bytelyst/api-client";
|
||||||
|
import { EXTRACTION_SERVICE_URL, PRODUCT_ID } from "@/lib/product-config";
|
||||||
|
import type { NoteTask } from "@/lib/types";
|
||||||
|
|
||||||
|
type ExtractionEntity = {
|
||||||
|
extraction_class: string;
|
||||||
|
extraction_text: string;
|
||||||
|
attributes?: Record<string, string>;
|
||||||
|
};
|
||||||
|
|
||||||
|
type ExtractResponse = {
|
||||||
|
extractions: ExtractionEntity[];
|
||||||
|
};
|
||||||
|
|
||||||
|
function getAccessToken(): string | null {
|
||||||
|
if (typeof window === "undefined") {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return localStorage.getItem(`${PRODUCT_ID}_access_token`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const extractionApi = createApiClient({
|
||||||
|
baseUrl: EXTRACTION_SERVICE_URL,
|
||||||
|
getToken: getAccessToken,
|
||||||
|
});
|
||||||
|
|
||||||
|
function slugify(value: string): string {
|
||||||
|
return value
|
||||||
|
.toLowerCase()
|
||||||
|
.replace(/[^a-z0-9]+/g, "-")
|
||||||
|
.replace(/^-+|-+$/g, "")
|
||||||
|
.slice(0, 64);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function extractSuggestedTasks(text: string): Promise<NoteTask[]> {
|
||||||
|
const response = await extractionApi.fetch<ExtractResponse>("/api/extract", {
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify({
|
||||||
|
text,
|
||||||
|
taskId: "transcript-extraction",
|
||||||
|
productId: PRODUCT_ID,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
return response.extractions
|
||||||
|
.filter((item) => item.extraction_class === "action_item" || item.extraction_class === "deadline")
|
||||||
|
.map((item, index) => ({
|
||||||
|
id: `extract-${slugify(item.extraction_text)}-${index}`,
|
||||||
|
title: item.extraction_text,
|
||||||
|
status: "todo",
|
||||||
|
source: "agent",
|
||||||
|
}));
|
||||||
|
}
|
||||||
@ -1,4 +1,5 @@
|
|||||||
import { createApiClient } from "@bytelyst/api-client";
|
import { createApiClient } from "@bytelyst/api-client";
|
||||||
|
import { extractSuggestedTasks } from "@/lib/extraction-client";
|
||||||
import { NOTES_API_URL, PRODUCT_ID } from "@/lib/product-config";
|
import { NOTES_API_URL, PRODUCT_ID } from "@/lib/product-config";
|
||||||
import type { AgentTimelineItem, ArtifactSummary, NoteDetail, NoteSummary, NoteTask, WorkspaceSummary } from "@/lib/types";
|
import type { AgentTimelineItem, ArtifactSummary, NoteDetail, NoteSummary, NoteTask, WorkspaceSummary } from "@/lib/types";
|
||||||
|
|
||||||
@ -223,7 +224,12 @@ export async function getNoteDetail(noteId: string): Promise<NoteDetail | null>
|
|||||||
),
|
),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const tasks = taskResponse.items.map(toNoteTask);
|
const extractedTasks = await extractSuggestedTasks(note.body).catch(() => []);
|
||||||
|
const existingTaskTitles = new Set(taskResponse.items.map((task) => task.title.trim().toLowerCase()));
|
||||||
|
const tasks = [
|
||||||
|
...taskResponse.items.map(toNoteTask),
|
||||||
|
...extractedTasks.filter((task) => !existingTaskTitles.has(task.title.trim().toLowerCase())),
|
||||||
|
];
|
||||||
const artifacts = artifactResponse.items.map(toArtifactSummary);
|
const artifacts = artifactResponse.items.map(toArtifactSummary);
|
||||||
const timeline = actionResponse.items
|
const timeline = actionResponse.items
|
||||||
.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt))
|
.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt))
|
||||||
|
|||||||
@ -8,6 +8,7 @@ export const PLATFORM_SERVICE_ORIGIN =
|
|||||||
process.env.NEXT_PUBLIC_PLATFORM_SERVICE_ORIGIN ??
|
process.env.NEXT_PUBLIC_PLATFORM_SERVICE_ORIGIN ??
|
||||||
PLATFORM_SERVICE_URL.replace(/\/api\/?$/, "");
|
PLATFORM_SERVICE_URL.replace(/\/api\/?$/, "");
|
||||||
export const NOTES_API_URL = process.env.NEXT_PUBLIC_NOTES_API_URL ?? "http://localhost:4016/api";
|
export const NOTES_API_URL = process.env.NEXT_PUBLIC_NOTES_API_URL ?? "http://localhost:4016/api";
|
||||||
|
export const EXTRACTION_SERVICE_URL = process.env.NEXT_PUBLIC_EXTRACTION_SERVICE_URL ?? "http://localhost:4005";
|
||||||
export const DIAGNOSTICS_URL = process.env.NEXT_PUBLIC_DIAGNOSTICS_URL ?? PLATFORM_SERVICE_ORIGIN;
|
export const DIAGNOSTICS_URL = process.env.NEXT_PUBLIC_DIAGNOSTICS_URL ?? PLATFORM_SERVICE_ORIGIN;
|
||||||
export const TELEMETRY_TRANSPORT =
|
export const TELEMETRY_TRANSPORT =
|
||||||
process.env.NEXT_PUBLIC_TELEMETRY_TRANSPORT === "beacon" ? "beacon" : "fetch";
|
process.env.NEXT_PUBLIC_TELEMETRY_TRANSPORT === "beacon" ? "beacon" : "fetch";
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user