AgentGraph / frontend /src /hooks /useContextDocuments.ts
wu981526092's picture
🚀 Deploy AgentGraph: Complete agent monitoring and knowledge graph system
c2ea5ed
/**
* Hook for managing context documents with basic fetch operations
*/
import { useState, useCallback } from "react";
import {
ContextDocument,
CreateContextRequest,
UpdateContextRequest,
ContextDocumentResponse,
ContextDocumentType,
} from "@/types/context";
interface UseContextDocumentsReturn {
documents: ContextDocument[];
loading: boolean;
error: string | null;
createDocument: (
traceId: string,
request: CreateContextRequest
) => Promise<ContextDocument | null>;
updateDocument: (
traceId: string,
contextId: string,
updates: UpdateContextRequest
) => Promise<ContextDocument | null>;
deleteDocument: (traceId: string, contextId: string) => Promise<boolean>;
uploadFile: (
traceId: string,
file: File,
title: string,
documentType: ContextDocumentType
) => Promise<ContextDocument | null>;
loadDocuments: (traceId: string) => Promise<void>;
refreshDocuments: (traceId: string) => Promise<void>;
}
const API_BASE = "/api";
async function fetchApi<T>(
endpoint: string,
options?: RequestInit
): Promise<T> {
const url = `${API_BASE}${endpoint}`;
const response = await fetch(url, {
headers: {
"Content-Type": "application/json",
...options?.headers,
},
...options,
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(`API Error: ${response.statusText} - ${errorText}`);
}
const data = await response.json();
return data;
}
export function useContextDocuments(): UseContextDocumentsReturn {
const [documents, setDocuments] = useState<ContextDocument[]>([]);
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const handleError = useCallback((err: any, defaultMessage: string) => {
const message = err?.message || defaultMessage;
setError(message);
console.error(defaultMessage, err);
return null;
}, []);
const loadDocuments = useCallback(
async (traceId: string) => {
setLoading(true);
setError(null);
try {
const documents = await fetchApi<ContextDocument[]>(
`/traces/${traceId}/context`
);
setDocuments(documents || []);
} catch (err) {
handleError(err, "Failed to load context documents");
} finally {
setLoading(false);
}
},
[handleError]
);
const refreshDocuments = useCallback(
async (traceId: string) => {
await loadDocuments(traceId);
},
[loadDocuments]
);
const createDocument = useCallback(
async (
traceId: string,
request: CreateContextRequest
): Promise<ContextDocument | null> => {
setLoading(true);
setError(null);
try {
const response = await fetchApi<ContextDocumentResponse>(
`/traces/${traceId}/context`,
{
method: "POST",
body: JSON.stringify(request),
}
);
if (response.success && response.data) {
setDocuments((prev) => [...prev, response.data!]);
return response.data;
} else {
throw new Error(response.message || "Failed to create document");
}
} catch (err) {
return handleError(err, "Failed to create context document");
} finally {
setLoading(false);
}
},
[handleError]
);
const updateDocument = useCallback(
async (
traceId: string,
contextId: string,
updates: UpdateContextRequest
): Promise<ContextDocument | null> => {
setLoading(true);
setError(null);
try {
const response = await fetchApi<ContextDocumentResponse>(
`/traces/${traceId}/context/${contextId}`,
{
method: "PUT",
body: JSON.stringify(updates),
}
);
if (response.success && response.data) {
setDocuments((prev) =>
prev.map((doc) => (doc.id === contextId ? response.data! : doc))
);
return response.data;
} else {
throw new Error(response.message || "Failed to update document");
}
} catch (err) {
return handleError(err, "Failed to update context document");
} finally {
setLoading(false);
}
},
[handleError]
);
const deleteDocument = useCallback(
async (traceId: string, contextId: string): Promise<boolean> => {
setLoading(true);
setError(null);
try {
const response = await fetchApi<ContextDocumentResponse>(
`/traces/${traceId}/context/${contextId}`,
{
method: "DELETE",
}
);
if (response.success) {
setDocuments((prev) => prev.filter((doc) => doc.id !== contextId));
return true;
} else {
throw new Error(response.message || "Failed to delete document");
}
} catch (err) {
handleError(err, "Failed to delete context document");
return false;
} finally {
setLoading(false);
}
},
[handleError]
);
const uploadFile = useCallback(
async (
traceId: string,
file: File,
title: string,
documentType: ContextDocumentType
): Promise<ContextDocument | null> => {
setLoading(true);
setError(null);
try {
const formData = new FormData();
formData.append("file", file);
formData.append("title", title);
formData.append("document_type", documentType);
const response = await fetch(
`${API_BASE}/traces/${traceId}/context/upload`,
{
method: "POST",
body: formData,
}
);
if (!response.ok) {
throw new Error(`Upload failed: ${response.statusText}`);
}
const result = (await response.json()) as ContextDocumentResponse;
if (result.success && result.data) {
setDocuments((prev) => [...prev, result.data!]);
return result.data;
} else {
throw new Error(result.message || "Failed to upload file");
}
} catch (err) {
return handleError(err, "Failed to upload context file");
} finally {
setLoading(false);
}
},
[handleError]
);
return {
documents,
loading,
error,
createDocument,
updateDocument,
deleteDocument,
uploadFile,
loadDocuments,
refreshDocuments,
};
}