Forked from npacker/web-tools
Project Files
src / tools-provider.ts
/**
* Wires shared caches, HTTP client, and rate limiter, then registers the four plugin tools
* with the LM Studio SDK.
*/
import path from "node:path"
import { TTLCache } from "./cache"
import { resolveBrowser, resolveTimingConfig } from "./config/resolve-config"
import { createMetascraper } from "./enrichment"
import { findLMStudioHome } from "./fs"
import { createImpit } from "./http"
import { PerHostRateLimiter, RateLimiter } from "./timing"
import { createFetchImagesTool } from "./tools/fetch-images-tool"
import { createImageSearchTool } from "./tools/image-search-tool"
import { createVisitWebsiteTool } from "./tools/visit-website-tool"
import { createWebSearchTool } from "./tools/web-search-tool"
import type { ImageSearchResultsPayload, WebSearchResultsPayload } from "./cache"
import type { FetchedPage } from "./page"
import type { Tool, ToolsProviderController } from "@lmstudio/sdk"
/**
* Root directory name used for the plugin's on-disk `cacache` store.
*/
const CACHE_DIRECTORY_NAME = "lms-plugin-duckduckgo-cache"
/** Cache subdirectory for web search results. */
const SEARCH_CACHE_SUBDIR = "search-enriched"
/** Maximum web search result entries retained in the search cache. */
const SEARCH_CACHE_MAX_SIZE = 100
/** Cache subdirectory for image search results. */
const IMAGE_SEARCH_CACHE_SUBDIR = "image-search"
/** Maximum image search result entries retained in the image search cache. */
const IMAGE_SEARCH_CACHE_MAX_SIZE = 100
/** Cache subdirectory for fetched page HTML payloads. */
const PAGE_CACHE_SUBDIR = "website"
/** Maximum fetched-page HTML payloads retained in the page cache. */
const PAGE_CACHE_MAX_SIZE = 50
/** Maximum concurrent image downloads permitted across the plugin. */
const MAX_IMAGE_CONCURRENCY = 6
/**
* Register the plugin's four tools with the LM Studio SDK controller.
*
* Caches and the rate limiter are constructed per-session, so plugin-setting changes take
* effect on plugin reload.
*
* @param ctl - Tools provider controller supplied by the LM Studio SDK.
* @returns The registered Web Search, Image Search, Visit Website, and Fetch Images tools.
*/
export async function toolsProvider(ctl: ToolsProviderController): Promise<Tool[]> {
const timing = resolveTimingConfig(ctl)
const impit = createImpit(resolveBrowser(ctl))
const cacheRoot = path.join(findLMStudioHome(), "plugin-data", CACHE_DIRECTORY_NAME)
const rateLimiter = new RateLimiter({ minIntervalMs: timing.requestIntervalMs })
const hostLimiter = new PerHostRateLimiter({ minIntervalMs: timing.requestIntervalMs })
const imageLimiter = new RateLimiter({ maxConcurrent: MAX_IMAGE_CONCURRENCY })
const searchCache = new TTLCache<WebSearchResultsPayload>(
path.join(cacheRoot, SEARCH_CACHE_SUBDIR),
timing.searchCacheTtlMs,
SEARCH_CACHE_MAX_SIZE
)
const imageSearchCache = new TTLCache<ImageSearchResultsPayload>(
path.join(cacheRoot, IMAGE_SEARCH_CACHE_SUBDIR),
timing.searchCacheTtlMs,
IMAGE_SEARCH_CACHE_MAX_SIZE
)
const pageCache = new TTLCache<FetchedPage>(
path.join(cacheRoot, PAGE_CACHE_SUBDIR),
timing.pageCacheTtlMs,
PAGE_CACHE_MAX_SIZE
)
const scraper = createMetascraper()
const retry = timing.retryPolicy
return [
createWebSearchTool(ctl, impit, searchCache, pageCache, rateLimiter, hostLimiter, scraper, retry),
createImageSearchTool(ctl, impit, imageSearchCache, rateLimiter, retry),
createVisitWebsiteTool(ctl, impit, pageCache, rateLimiter, retry),
createFetchImagesTool(ctl, impit, pageCache, rateLimiter, imageLimiter, retry),
]
}