mirror of
https://github.com/tiennm99/litellm.git
synced 2026-08-12 06:22:25 +00:00
new utils
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
import { message } from "antd";
|
||||
import { MESSAGE_COPY_SUCCESS } from "./constants";
|
||||
|
||||
/**
|
||||
* Copies text to clipboard with fallback for non-secure contexts.
|
||||
* Shows success/error message to user.
|
||||
*
|
||||
* @param text - Text to copy to clipboard
|
||||
* @param label - Label for the copied content (e.g., "Request", "Metadata")
|
||||
* @returns Promise<boolean> - true if copy succeeded, false otherwise
|
||||
*/
|
||||
export async function copyToClipboard(text: string, label: string): Promise<boolean> {
|
||||
try {
|
||||
// Try modern clipboard API first
|
||||
if (navigator.clipboard && window.isSecureContext) {
|
||||
await navigator.clipboard.writeText(text);
|
||||
message.success(`${label} ${MESSAGE_COPY_SUCCESS}`);
|
||||
return true;
|
||||
} else {
|
||||
// Fallback for non-secure contexts (like 0.0.0.0)
|
||||
const textArea = document.createElement("textarea");
|
||||
textArea.value = text;
|
||||
textArea.style.position = "fixed";
|
||||
textArea.style.opacity = "0";
|
||||
document.body.appendChild(textArea);
|
||||
textArea.focus();
|
||||
textArea.select();
|
||||
|
||||
const successful = document.execCommand("copy");
|
||||
document.body.removeChild(textArea);
|
||||
|
||||
if (!successful) {
|
||||
throw new Error("execCommand failed");
|
||||
}
|
||||
message.success(`${label} ${MESSAGE_COPY_SUCCESS}`);
|
||||
return true;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Copy failed:", error);
|
||||
message.error(`Failed to copy ${label}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
// Drawer configuration constants
|
||||
export const DRAWER_WIDTH = "60%";
|
||||
export const DRAWER_HEADER_PADDING = "16px 24px";
|
||||
export const DRAWER_CONTENT_PADDING = "24px";
|
||||
|
||||
// Truncation and display limits
|
||||
export const DEFAULT_MAX_WIDTH = 180;
|
||||
export const API_BASE_MAX_WIDTH = 200;
|
||||
export const JSON_MAX_HEIGHT = 400;
|
||||
export const METADATA_MAX_HEIGHT = 300;
|
||||
|
||||
// Tab keys (kept for backwards compatibility if needed)
|
||||
export const TAB_REQUEST = "request" as const;
|
||||
export const TAB_RESPONSE = "response" as const;
|
||||
|
||||
// Keyboard shortcuts
|
||||
export const KEY_ESCAPE = "Escape";
|
||||
export const KEY_J_LOWER = "j";
|
||||
export const KEY_J_UPPER = "J";
|
||||
export const KEY_K_LOWER = "k";
|
||||
export const KEY_K_UPPER = "K";
|
||||
|
||||
// Typography
|
||||
export const FONT_FAMILY_MONO = "monospace";
|
||||
export const FONT_SIZE_SMALL = 12;
|
||||
export const FONT_SIZE_MEDIUM = 13;
|
||||
export const FONT_SIZE_HEADER = 16;
|
||||
|
||||
// Colors
|
||||
export const COLOR_BORDER = "#f0f0f0";
|
||||
export const COLOR_BACKGROUND = "#fff";
|
||||
export const COLOR_SECONDARY = "#8c8c8c";
|
||||
export const COLOR_BG_LIGHT = "#fafafa";
|
||||
|
||||
// Spacing
|
||||
export const SPACING_SMALL = 4;
|
||||
export const SPACING_MEDIUM = 8;
|
||||
export const SPACING_LARGE = 12;
|
||||
export const SPACING_XLARGE = 16;
|
||||
export const SPACING_XXLARGE = 24;
|
||||
|
||||
// Messages
|
||||
export const MESSAGE_COPY_SUCCESS = "copied to clipboard";
|
||||
export const MESSAGE_REQUEST_ID_COPIED = "Request ID copied to clipboard";
|
||||
@@ -0,0 +1,93 @@
|
||||
/**
|
||||
* Utility functions for LogDetailsDrawer component.
|
||||
* These functions handle data formatting, validation, and guardrail calculations.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Formats data for display. If input is a string, attempts to parse as JSON.
|
||||
* @param input - Data to format (string or object)
|
||||
* @returns Parsed JSON object or original input
|
||||
*/
|
||||
export function formatData(input: any) {
|
||||
if (typeof input === "string") {
|
||||
try {
|
||||
return JSON.parse(input);
|
||||
} catch {
|
||||
return input;
|
||||
}
|
||||
}
|
||||
return input;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if messages array/object contains data.
|
||||
* @param messages - Messages to check
|
||||
* @returns True if messages exist and have content
|
||||
*/
|
||||
export function checkHasMessages(messages: any): boolean {
|
||||
if (!messages) return false;
|
||||
if (Array.isArray(messages)) return messages.length > 0;
|
||||
if (typeof messages === "object") return Object.keys(messages).length > 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if response object contains data.
|
||||
* @param response - Response to check
|
||||
* @returns True if response exists and has content
|
||||
*/
|
||||
export function checkHasResponse(response: any): boolean {
|
||||
if (!response) return false;
|
||||
return Object.keys(formatData(response)).length > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes guardrail information into an array.
|
||||
* @param guardrailInfo - Guardrail data (may be array, object, or null)
|
||||
* @returns Array of guardrail entries
|
||||
*/
|
||||
export function normalizeGuardrailEntries(guardrailInfo: any): any[] {
|
||||
if (Array.isArray(guardrailInfo)) return guardrailInfo;
|
||||
if (guardrailInfo) return [guardrailInfo];
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates total number of masked entities across all guardrail entries.
|
||||
* @param entries - Array of guardrail entries
|
||||
* @returns Total count of masked entities
|
||||
*/
|
||||
export function calculateTotalMaskedEntities(entries: any[]): number {
|
||||
return entries.reduce((sum, entry) => {
|
||||
const maskedCounts = entry?.masked_entity_count;
|
||||
if (!maskedCounts) return sum;
|
||||
return (
|
||||
sum +
|
||||
Object.values(maskedCounts).reduce<number>((acc, count) => (typeof count === "number" ? acc + count : acc), 0)
|
||||
);
|
||||
}, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a display label for guardrail(s).
|
||||
* @param entries - Array of guardrail entries
|
||||
* @returns Display string for guardrail label
|
||||
*/
|
||||
export function getGuardrailLabel(entries: any[]): string {
|
||||
if (entries.length === 0) return "-";
|
||||
if (entries.length === 1) return entries[0]?.guardrail_name ?? "-";
|
||||
return `${entries.length} guardrails`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if vector store data exists in metadata.
|
||||
* @param metadata - Metadata object to check
|
||||
* @returns True if vector store data exists and is non-empty
|
||||
*/
|
||||
export function checkHasVectorStoreData(metadata: Record<string, any>): boolean {
|
||||
return (
|
||||
metadata.vector_store_request_metadata &&
|
||||
Array.isArray(metadata.vector_store_request_metadata) &&
|
||||
metadata.vector_store_request_metadata.length > 0
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user