2
import path from 'path';
4
import cacheManager from 'cache-manager';
5
import fsStore from 'cache-manager-fs-hash';
7
import logger from './logger';
8
import { fetchWithRetries } from './fetch';
9
import { getConfigDirectoryPath } from './util';
11
import type { Cache } from 'cache-manager';
12
import type { RequestInfo, RequestInit } from 'node-fetch';
14
let cacheInstance: Cache | undefined;
17
typeof process.env.PROMPTFOO_CACHE_ENABLED === 'undefined'
19
: process.env.PROMPTFOO_CACHE_ENABLED === '1' ||
20
process.env.PROMPTFOO_CACHE_ENABLED === 'true' ||
21
process.env.PROMPTFOO_CACHE_ENABLED === 'yes';
24
process.env.PROMPTFOO_CACHE_TYPE || (process.env.NODE_ENV === 'test' ? 'memory' : 'disk');
26
export function getCache() {
29
process.env.PROMPTFOO_CACHE_PATH || path.join(getConfigDirectoryPath(), 'cache');
30
if (!fs.existsSync(cachePath)) {
31
logger.info(`Creating cache folder at ${cachePath}.`);
32
fs.mkdirSync(cachePath, { recursive: true });
34
cacheInstance = cacheManager.caching({
35
store: cacheType === 'disk' ? fsStore : 'memory',
37
max: process.env.PROMPTFOO_CACHE_MAX_FILE_COUNT || 10_000,
39
ttl: process.env.PROMPTFOO_CACHE_TTL || 60 * 60 * 24 * 14,
40
maxsize: process.env.PROMPTFOO_CACHE_MAX_SIZE || 1e7,
48
export async function fetchWithCache(
50
options: RequestInit = {},
52
format: 'json' | 'text' = 'json',
53
bust: boolean = false,
54
): Promise<{ data: any; cached: boolean }> {
55
if (!enabled || bust) {
56
const resp = await fetchWithRetries(url, options, timeout);
57
const respText = await resp.text();
61
data: format === 'json' ? JSON.parse(respText) : respText,
64
throw new Error(`Error parsing response as JSON: ${respText}`);
68
const cache = await getCache();
70
const copy = Object.assign({}, options);
72
const cacheKey = `fetch:${url}:${JSON.stringify(copy)}`;
75
const cachedResponse = await cache.get(cacheKey);
78
logger.debug(`Returning cached response for ${url}: ${cachedResponse}`);
81
data: JSON.parse(cachedResponse as string),
86
const response = await fetchWithRetries(url, options, timeout);
87
const responseText = await response.text();
89
const data = format === 'json' ? JSON.parse(responseText) : responseText;
91
logger.debug(`Storing ${url} response in cache: ${JSON.stringify(data)}`);
92
await cache.set(cacheKey, JSON.stringify(data));
100
`Error parsing response from ${url}: ${
101
(err as Error).message
102
}. Received text: ${responseText}`,
107
export function enableCache() {
111
export function disableCache() {
115
export async function clearCache() {
116
return getCache().reset();
119
export function isCacheEnabled() {