/**
* search_objects tool implementation
* Search objects in a bucket with various filter criteria
*/
import { z } from "zod";
import { ProviderManager } from "../providers/manager.js";
import { createToolSuccessResponse, createToolErrorResponse } from "../utils/response-formatter.js";
import type { SearchFilter } from "../types/storage.js";
/**
* Schema for search_objects tool
*/
export const searchObjectsSchema = {
bucket: z.string().describe("The name of the bucket to search in"),
prefix: z.string().optional().describe("Filter objects by key prefix"),
suffix: z.string().optional().describe("Filter objects by key suffix"),
extensions: z.array(z.string()).optional().describe("Filter by file extensions (e.g., ['.jpg', '.png'])"),
pattern: z.string().optional().describe("Glob pattern to match object keys (e.g., '*.txt', 'folder/**/file.json')"),
min_size: z.number().optional().describe("Minimum file size in bytes"),
max_size: z.number().optional().describe("Maximum file size in bytes"),
modified_after: z.string().optional().describe("Filter objects modified after this date (ISO 8601 format)"),
modified_before: z.string().optional().describe("Filter objects modified before this date (ISO 8601 format)"),
max_results: z.number().optional().describe("Maximum number of results to return (default: 100)"),
};
/**
* Get metadata for search_objects tool
*/
export function getSearchObjectsMetadata(sourceId: string, maxResults?: number) {
const toolName = sourceId === "default" ? "search_objects" : `search_objects_${sourceId}`;
return {
name: toolName,
title: `Search Objects (${sourceId})`,
description: `Search for objects in a bucket from the '${sourceId}' source. Supports filtering by prefix, suffix, extensions, glob patterns, file size, and modification date.${maxResults ? ` Default max_results: ${maxResults}` : ""}`,
schema: searchObjectsSchema,
annotations: {
title: `search_objects (${sourceId})`,
readOnlyHint: true,
destructiveHint: false,
idempotentHint: true,
openWorldHint: false,
},
};
}
/**
* Create search_objects tool handler for a specific source
*/
export function createSearchObjectsToolHandler(sourceId?: string, defaultMaxResults?: number) {
return async (args: any, _extra: any) => {
const {
bucket,
prefix,
suffix,
extensions,
pattern,
min_size,
max_size,
modified_after,
modified_before,
max_results,
} = args as {
bucket: string;
prefix?: string;
suffix?: string;
extensions?: string[];
pattern?: string;
min_size?: number;
max_size?: number;
modified_after?: string;
modified_before?: string;
max_results?: number;
};
try {
const provider = ProviderManager.getCurrentProvider(sourceId);
const filter: SearchFilter = {
prefix,
suffix,
extensions,
pattern,
minSize: min_size,
maxSize: max_size,
modifiedAfter: modified_after,
modifiedBefore: modified_before,
maxResults: max_results || defaultMaxResults || 100,
};
const result = await provider.searchObjects(bucket, filter);
return createToolSuccessResponse({
...result,
source_id: sourceId || "default",
});
} catch (error) {
return createToolErrorResponse((error as Error).message, "SEARCH_OBJECTS_ERROR");
}
};
}