/**
* Debug Truncation Utility for DataAI FastMCP
* EXTREMELY aggressive truncation - max 50 lines output for debugging
*/
export interface TruncationConfig {
enabled: boolean;
maxLines: number;
showSummaryOnly: boolean;
}
// MINIMAL DEBUG CONFIG - reads from DATAI_DEBUG_TRUNCATE environment variable
export const MINIMAL_DEBUG_CONFIG: TruncationConfig = {
enabled: process.env.DATAI_DEBUG_TRUNCATE === 'true',
maxLines: 200,
showSummaryOnly: true
};
export class DataTruncator {
private config: TruncationConfig;
constructor(config: TruncationConfig = MINIMAL_DEBUG_CONFIG) {
this.config = config;
}
/**
* SUPER aggressive truncation - just show summary + first few items
*/
public truncateApiResponse(data: any): any {
if (!this.config.enabled) {
return data;
}
// Create minimal summary
const summary = this.createMinimalSummary(data);
return {
__debug_truncated: true,
__summary: summary,
__sample_data: this.getSampleData(data),
__message: "Tool working - data truncated for debugging"
};
}
private createMinimalSummary(data: any): any {
if (data == null) return { type: 'null', value: data };
if (typeof data === 'string') {
return {
type: 'string',
length: data.length,
preview: data.substring(0, 50) + (data.length > 50 ? '...' : '')
};
}
if (typeof data === 'number' || typeof data === 'boolean') {
return { type: typeof data, value: data };
}
if (Array.isArray(data)) {
return {
type: 'array',
length: data.length,
item_types: this.getArrayItemTypes(data),
first_item_keys: this.getFirstItemKeys(data)
};
}
if (typeof data === 'object') {
return {
type: 'object',
keys_count: Object.keys(data).length,
keys: Object.keys(data).slice(0, 5),
sample_values: this.getSampleObjectValues(data)
};
}
return { type: typeof data, value: 'unknown' };
}
private getSampleData(data: any): any {
if (Array.isArray(data) && data.length > 0) {
// Show first 2 items instead of 1, with more fields
const sampleItems = data.slice(0, 2);
return sampleItems.map(item => {
if (typeof item === 'object' && item != null) {
const keys = Object.keys(item).slice(0, 8);
const sample: any = {};
for (const key of keys) {
const value = item[key];
if (typeof value === 'string') {
sample[key] = value.substring(0, 50) + (value.length > 50 ? '...' : '');
} else if (typeof value === 'object' && value != null) {
if (Array.isArray(value)) {
sample[key] = `[array:${value.length}]`;
} else {
const objKeys = Object.keys(value).slice(0, 3);
sample[key] = `{${objKeys.join(', ')}}`;
}
} else {
sample[key] = value;
}
}
return sample;
}
return item;
});
}
if (typeof data === 'object' && data != null) {
const keys = Object.keys(data).slice(0, 8);
const sample: any = {};
for (const key of keys) {
const value = data[key];
if (typeof value === 'string') {
sample[key] = value.substring(0, 50) + (value.length > 50 ? '...' : '');
} else if (Array.isArray(value)) {
sample[key] = `[array:${value.length}]`;
} else if (typeof value === 'object' && value != null) {
const objKeys = Object.keys(value).slice(0, 3);
sample[key] = `{${objKeys.join(', ')}}`;
} else {
sample[key] = value;
}
}
return sample;
}
return data;
}
private getArrayItemTypes(arr: any[]): string[] {
const types = new Set<string>();
for (let i = 0; i < Math.min(arr.length, 3); i++) {
types.add(typeof arr[i]);
}
return Array.from(types);
}
private getFirstItemKeys(arr: any[]): string[] {
if (arr.length > 0 && typeof arr[0] === 'object' && arr[0] != null) {
return Object.keys(arr[0]).slice(0, 10);
}
return [];
}
private getSampleObjectValues(obj: any): any {
const sample: any = {};
const keys = Object.keys(obj).slice(0, 6);
for (const key of keys) {
const value = obj[key];
if (typeof value === 'string') {
sample[key] = value.substring(0, 30) + '...';
} else if (Array.isArray(value)) {
sample[key] = `[${value.length} items]`;
} else if (typeof value === 'object' && value != null) {
const objKeys = Object.keys(value).slice(0, 2);
sample[key] = `{${objKeys.join(', ')}}`;
} else {
sample[key] = value;
}
}
return sample;
}
public getStats() {
return {
enabled: this.config.enabled,
maxLines: this.config.maxLines,
config: this.config
};
}
}
// Export singleton instance
export const debugTruncator = new DataTruncator(MINIMAL_DEBUG_CONFIG);
export default debugTruncator;
/**
* Quick utility function for common use cases
*/
export function truncateForDebug<T>(data: T): T {
return debugTruncator.truncateApiResponse(data);
}