Skip to main content
Glama
batch-format.tsβ€’9.52 kB
import { BatchOperationType, UniversalResourceType, } from '@handlers/tool-configs/universal/types.js'; import { formatResourceType } from '@handlers/tool-configs/universal/shared-handlers.js'; import { safeExtractRecordValues, safeExtractFirstValue, } from '@handlers/tool-configs/shared/type-utils.js'; import type { JsonObject } from '@shared-types/attio.js'; import type { UniversalBatchSearchResult } from '@api/operations/batch.js'; function isJsonObject(value: unknown): value is JsonObject { return typeof value === 'object' && value !== null && !Array.isArray(value); } function isJsonObjectArray(value: unknown): value is JsonObject[] { return Array.isArray(value) && value.every(isJsonObject); } function isUniversalBatchSearchResultArray( value: unknown ): value is UniversalBatchSearchResult[] { return ( Array.isArray(value) && value.every( (item) => isJsonObject(item) && 'success' in item && typeof item.success === 'boolean' && ('query' in item ? typeof item.query === 'string' : true) ) ); } function isRecordId( value: unknown ): value is JsonObject & { record_id: string } { return ( isJsonObject(value) && 'record_id' in value && typeof value.record_id === 'string' ); } function isOperationResult( value: unknown ): value is JsonObject & { result?: JsonObject } { return ( isJsonObject(value) && (!('result' in value) || isJsonObject(value.result)) ); } function isOperationData( value: unknown ): value is JsonObject & { data?: JsonObject } { return ( isJsonObject(value) && (!('data' in value) || isJsonObject(value.data)) ); } function coerceDisplayValue(value: unknown): string | undefined { if (value == null) return undefined; if (typeof value === 'string') return value; if (Array.isArray(value)) { const first = value[0]; if (typeof first === 'string') return first; if (first && typeof first === 'object' && 'value' in first) return String((first as JsonObject).value); } if (typeof value === 'object' && value && 'value' in value) return String((value as JsonObject).value); return undefined; } function extractDisplayName( values: JsonObject | undefined, fallback?: string ): string { if (!values) return fallback ?? 'Unknown'; const name = coerceDisplayValue(values.name); const title = coerceDisplayValue(values.title); return name ?? title ?? fallback ?? 'Unknown'; } function formatBatchSearchResults( batchResults: UniversalBatchSearchResult[], resourceTypeName: string ): string { const successCount = batchResults.filter((r) => r.success).length; const failureCount = batchResults.length - successCount; let summary = `Batch search completed: ${successCount} successful, ${failureCount} failed\n\n`; const successful = batchResults.filter((r) => r.success); if (successful.length > 0) { summary += 'Successful searches:\n'; successful.forEach((searchResult, index) => { const records = searchResult.result ?? []; const resourceLabel = pluralizeResource(resourceTypeName, records.length); summary += `\n${index + 1}. Query: "${searchResult.query}" - Found ${records.length} ${resourceLabel}\n`; if (records.length > 0) { records.slice(0, 3).forEach((record: unknown, recordIndex: number) => { if (!isJsonObject(record)) { summary += ` ${recordIndex + 1}. Invalid record format\n`; return; } const values = safeExtractRecordValues(record); const recordId = isJsonObject(record.id) ? record.id : undefined; const name = safeExtractFirstValue(values?.name) ?? safeExtractFirstValue(values?.title, 'Unnamed'); const id = isRecordId(recordId) ? recordId.record_id : 'unknown'; summary += ` ${recordIndex + 1}. ${name} (ID: ${id})\n`; }); if (records.length > 3) { summary += ` ... and ${records.length - 3} more\n`; } } }); } const failed = batchResults.filter((r) => !r.success); if (failed.length > 0) { summary += '\nFailed searches:\n'; failed.forEach((searchResult, index) => { summary += `${index + 1}. Query: "${searchResult.query}" - Error: ${searchResult.error}\n`; }); } return summary; } function pluralizeResource(resourceTypeName: string, count: number): string { const base = resourceTypeName || 'record'; if (count === 1) { return base; } if (base.endsWith('y')) { return `${base.slice(0, -1)}ies`; } if (base.endsWith('s')) { return base; } return `${base}s`; } function formatSuccessfulOperations( operations: JsonObject[], resourceTypeName: string ): string { if (!operations.length) { return ''; } const header = 'Successful operations:'; const lines = operations.map((op: JsonObject, index: number) => { if (!isOperationResult(op)) { return `${index + 1}. Invalid operation format`; } const opResult = op.result; const values = isJsonObject(opResult?.values) ? opResult.values : undefined; const fallbackId = (typeof opResult?.record_id === 'string' ? opResult.record_id : undefined) ?? 'Unknown'; const name = extractDisplayName(values, fallbackId); const descriptor = resourceTypeName ? `${name}` : name; return `${index + 1}. ${descriptor}`; }); return `${header}\n${lines.join('\n')}`; } function formatFailedOperations(operations: JsonObject[]): string { if (!operations.length) { return ''; } const header = 'Failed operations:'; const lines = operations.map((op: JsonObject, index: number) => { if (!isOperationData(op)) { return `${index + 1}. Invalid operation format: Unknown error`; } const opData = op.data; const identifier = (typeof op.record_id === 'string' ? op.record_id : undefined) ?? (typeof opData?.name === 'string' ? opData.name : undefined) ?? 'Unknown'; const error = op.error ?? 'Unknown error'; return `${index + 1}. ${identifier}: ${error}`; }); return `${header}\n${lines.join('\n')}`; } function formatSearchRecords( records: JsonObject[], resourceTypeName: string ): string { if (!records.length) { return `Batch search found 0 ${pluralizeResource(resourceTypeName, 0)}`; } const lines = records.map((record: JsonObject, index: number) => { const values = safeExtractRecordValues(record); const recordId = isJsonObject(record.id) ? record.id : undefined; const name = extractDisplayName(values, 'Unnamed'); const id = isRecordId(recordId) ? recordId.record_id : 'unknown'; return `${index + 1}. ${name} (ID: ${id})`; }); return `Batch search found ${records.length} ${pluralizeResource(resourceTypeName, records.length)}:\n${lines.join('\n')}`; } export function formatBatchResult( results: JsonObject | JsonObject[] | undefined, operationType?: BatchOperationType, resourceType?: UniversalResourceType ): string { if (!results) { return 'Batch operation failed'; } const operationName = operationType ?? 'operation'; const resourceTypeName = resourceType ? formatResourceType(resourceType) : 'record'; if (!isJsonObjectArray(results)) { return formatInvalidResultsStructure(operationName, results); } if (operationType === BatchOperationType.SEARCH) { return formatSearchOperationResults(results, resourceTypeName); } return formatStandardOperationResults( results, operationName, resourceTypeName ); } /** * Formats results when structure is invalid (not an array) */ function formatInvalidResultsStructure( operationName: string, results: JsonObject | JsonObject[] ): string { return `Batch ${operationName} result: ${JSON.stringify(results)}`; } /** * Formats search operation results (handles both batch search and simple search) */ function formatSearchOperationResults( results: JsonObject[], resourceTypeName: string ): string { if (isUniversalBatchSearchResultArray(results)) { return formatBatchSearchResults(results, resourceTypeName); } return formatSearchRecords(results, resourceTypeName); } /** * Formats standard CRUD operation results with success/failure summary */ function formatStandardOperationResults( results: JsonObject[], operationName: string, resourceTypeName: string ): string { const { successful, failed } = categorizeOperationResults(results); const summary = buildResultSummary( operationName, successful.length, failed.length ); const sections = [summary]; const successSection = formatSuccessfulOperations( successful, resourceTypeName ); if (successSection) { sections.push(successSection); } const failedSection = formatFailedOperations(failed); if (failedSection) { sections.push(failedSection); } return sections.join('\n\n'); } /** * Categorizes operation results into successful and failed */ function categorizeOperationResults(results: JsonObject[]): { successful: JsonObject[]; failed: JsonObject[]; } { return { successful: results.filter((r) => r.success), failed: results.filter((r) => !r.success), }; } /** * Builds a summary line for batch operation results */ function buildResultSummary( operationName: string, successCount: number, failureCount: number ): string { return `Batch ${operationName} completed: ${successCount} successful, ${failureCount} failed`; }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/kesslerio/attio-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server