deep-research / src /store /debug.ts
Leon4gr45's picture
Deploy app
c16e487 verified
import { create } from "zustand";
import { persist } from "zustand/middleware";
interface LogEntry {
timestamp: string;
level: "info" | "warn" | "error";
message: string;
data?: any[];
}
interface DebugStore {
logs: LogEntry[];
addLog: (level: "info" | "warn" | "error", message: string, ...data: any[]) => void;
clearLogs: () => void;
exportLogs: () => string;
}
// Intercept console methods to capture logs
const originalConsoleLog = console.log;
const originalConsoleWarn = console.warn;
const originalConsoleError = console.error;
export const useDebugStore = create<DebugStore>()(
persist(
(set, get) => ({
logs: [],
addLog: (level, message, ...data) => {
const serialize = (obj: any, depth = 0): any => {
if (depth > 3) return "[Max Depth Reached]";
if (obj === null || obj === undefined) return obj;
if (obj instanceof Error || (obj && typeof obj.message === 'string' && typeof obj.name === 'string')) {
return {
name: obj.name,
message: obj.message,
stack: obj.stack,
cause: obj.cause ? serialize(obj.cause, depth + 1) : undefined,
// Some APIs return error data in custom properties
...(Object.getOwnPropertyNames(obj).reduce((acc, key) => {
if (!['name', 'message', 'stack', 'cause'].includes(key)) {
acc[key] = serialize((obj as any)[key], depth + 1);
}
return acc;
}, {} as any))
};
}
if (typeof obj === "object") {
try {
if (Array.isArray(obj)) {
return obj.map(item => serialize(item, depth + 1));
}
const result: any = {};
for (const key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
result[key] = serialize(obj[key], depth + 1);
}
}
return result;
} catch {
return "[Unserializable Object]";
}
}
return obj;
};
const parsedMessage =
typeof message === "string" ? message : JSON.stringify(serialize(message));
const entry: LogEntry = {
timestamp: new Date().toISOString(),
level,
message: parsedMessage,
data: data.length > 0 ? data.map(serialize) : undefined,
};
// Limit logs to last 1000 entries to prevent memory issues
set((state) => ({
logs: [...state.logs.slice(-999), entry],
}));
},
clearLogs: () => set({ logs: [] }),
exportLogs: () => {
const { logs } = get();
return JSON.stringify(logs, null, 2);
},
}),
{
name: "deep-research-debug-store",
}
)
);
// Function to initialize log interception
export function initLogInterception() {
if (typeof window === "undefined") return; // Client-side only
console.log = (...args) => {
originalConsoleLog(...args);
useDebugStore.getState().addLog("info", args[0], ...args.slice(1));
};
console.warn = (...args) => {
originalConsoleWarn(...args);
useDebugStore.getState().addLog("warn", args[0], ...args.slice(1));
};
console.error = (...args) => {
originalConsoleError(...args);
useDebugStore.getState().addLog("error", args[0], ...args.slice(1));
};
}