diff --git a/packages/kbot/dist-in/iterator-cache.d.ts b/packages/kbot/dist-in/iterator-cache.d.ts new file mode 100644 index 00000000..165d77b2 --- /dev/null +++ b/packages/kbot/dist-in/iterator-cache.d.ts @@ -0,0 +1,16 @@ +export interface CacheProvider { + get(key: object, namespace: string): Promise; + set(key: object, namespace: string, value: any, options?: { + expiration?: number; + }): Promise; + delete(key: object, namespace: string): Promise; +} +export interface CacheConfig { + enabled?: boolean; + provider?: 'default' | 'redis'; + namespace?: string; + expiration?: number; + redisUrl?: string; +} +export declare const DEFAULT_CACHE_CONFIG: Required>; +export declare function createCacheProvider(config?: CacheConfig): CacheProvider; diff --git a/packages/kbot/dist-in/iterator-cache.js b/packages/kbot/dist-in/iterator-cache.js new file mode 100644 index 00000000..6fd4a60d --- /dev/null +++ b/packages/kbot/dist-in/iterator-cache.js @@ -0,0 +1,114 @@ +import { get_cached_object, set_cached_object, rm_cached_object } from "@polymech/cache"; +import { Redis } from 'ioredis'; +export const DEFAULT_CACHE_CONFIG = { + enabled: true, + provider: 'default', + namespace: 'default-cache', + expiration: 7 * 24 * 60 * 60 // 7 days in seconds +}; +// --- Default Cache Provider (using @polymech/cache) --- +class DefaultCacheProvider { + async get(key, namespace) { + try { + return await get_cached_object({ ca_options: key }, namespace); + } + catch (error) { + console.error(`DefaultCache: Error getting cache for key ${JSON.stringify(key)} in namespace ${namespace}:`, error); + return null; + } + } + async set(key, namespace, value, options) { + try { + await set_cached_object({ ca_options: key }, namespace, value, options); + } + catch (error) { + console.error(`DefaultCache: Error setting cache for key ${JSON.stringify(key)} in namespace ${namespace}:`, error); + } + } + async delete(key, namespace) { + try { + await rm_cached_object({ ca_options: key }, namespace); + } + catch (error) { + console.error(`DefaultCache: Error deleting cache for key ${JSON.stringify(key)} in namespace ${namespace}:`, error); + } + } +} +// --- Redis Cache Provider --- +class RedisCacheProvider { + redis; + constructor(redisUrl) { + // Default to local instance if no URL is provided + this.redis = new Redis(redisUrl || 'redis://localhost:6379'); + this.redis.on('error', (err) => console.error('Redis Client Error', err)); + } + generateKey(key, namespace) { + // Simple serialization; consider a more robust hashing function for complex keys + return `${namespace}:${JSON.stringify(key)}`; + } + async get(key, namespace) { + const redisKey = this.generateKey(key, namespace); + try { + const data = await this.redis.get(redisKey); + return data ? JSON.parse(data) : null; + } + catch (error) { + console.error(`RedisCache: Error getting cache for key ${redisKey}:`, error); + return null; + } + } + async set(key, namespace, value, options) { + const redisKey = this.generateKey(key, namespace); + try { + const stringValue = JSON.stringify(value); + if (options?.expiration) { + await this.redis.set(redisKey, stringValue, 'EX', options.expiration); + } + else { + await this.redis.set(redisKey, stringValue); + } + } + catch (error) { + console.error(`RedisCache: Error setting cache for key ${redisKey}:`, error); + } + } + async delete(key, namespace) { + const redisKey = this.generateKey(key, namespace); + try { + await this.redis.del(redisKey); + } + catch (error) { + console.error(`RedisCache: Error deleting cache for key ${redisKey}:`, error); + } + } + async disconnect() { + await this.redis.quit(); + } +} +// --- Factory Function --- +let defaultCacheProviderInstance = null; +let redisCacheProviderInstance = null; +export function createCacheProvider(config) { + const mergedConfig = { ...DEFAULT_CACHE_CONFIG, ...config }; + if (!mergedConfig.enabled) { + // Return a dummy provider if caching is disabled + return { + get: async () => null, + set: async () => { }, + delete: async () => { }, + }; + } + if (mergedConfig.provider === 'redis') { + if (!redisCacheProviderInstance) { + // Pass redisUrl if provided in config + redisCacheProviderInstance = new RedisCacheProvider(config?.redisUrl); + } + return redisCacheProviderInstance; + } + // Default provider + if (!defaultCacheProviderInstance) { + defaultCacheProviderInstance = new DefaultCacheProvider(); + } + return defaultCacheProviderInstance; +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaXRlcmF0b3ItY2FjaGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaXRlcmF0b3ItY2FjaGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLGlCQUFpQixFQUFFLGlCQUFpQixFQUFFLGdCQUFnQixFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDekYsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLFNBQVMsQ0FBQztBQWdCaEMsTUFBTSxDQUFDLE1BQU0sb0JBQW9CLEdBQTRDO0lBQ3pFLE9BQU8sRUFBRSxJQUFJO0lBQ2IsUUFBUSxFQUFFLFNBQVM7SUFDbkIsU0FBUyxFQUFFLGVBQWU7SUFDMUIsVUFBVSxFQUFFLENBQUMsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsQ0FBQyxvQkFBb0I7Q0FDcEQsQ0FBQztBQUVGLHlEQUF5RDtBQUV6RCxNQUFNLG9CQUFvQjtJQUN0QixLQUFLLENBQUMsR0FBRyxDQUFDLEdBQVcsRUFBRSxTQUFpQjtRQUNwQyxJQUFJLENBQUM7WUFDRCxPQUFPLE1BQU0saUJBQWlCLENBQUMsRUFBRSxVQUFVLEVBQUUsR0FBRyxFQUFFLEVBQUUsU0FBUyxDQUFDLENBQUM7UUFDbkUsQ0FBQztRQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7WUFDYixPQUFPLENBQUMsS0FBSyxDQUFDLDZDQUE2QyxJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsU0FBUyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFDcEgsT0FBTyxJQUFJLENBQUM7UUFDaEIsQ0FBQztJQUNMLENBQUM7SUFFRCxLQUFLLENBQUMsR0FBRyxDQUFDLEdBQVcsRUFBRSxTQUFpQixFQUFFLEtBQVUsRUFBRSxPQUFpQztRQUNuRixJQUFJLENBQUM7WUFDRCxNQUFNLGlCQUFpQixDQUFDLEVBQUUsVUFBVSxFQUFFLEdBQUcsRUFBRSxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsT0FBTyxDQUFDLENBQUM7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 \ No newline at end of file diff --git a/packages/kbot/dist-in/iterator.d.ts b/packages/kbot/dist-in/iterator.d.ts index 99e3b2aa..7439e03d 100644 --- a/packages/kbot/dist-in/iterator.d.ts +++ b/packages/kbot/dist-in/iterator.d.ts @@ -1,5 +1,6 @@ import { IKBotTask } from '@polymech/ai-tools'; import { AsyncTransformer, ErrorCallback, FilterCallback, OnTransformCallback, OnTransformedCallback, INetworkOptions } from './async-iterator.js'; +import { CacheConfig } from './iterator-cache.js'; /** * Notes for LLM modifications * @@ -22,11 +23,6 @@ export interface IteratorFactory { transform: (mappings: FieldMapping[]) => Promise; createTransformer: (options: IKBotTask) => AsyncTransformer; } -export interface CacheConfig { - enabled?: boolean; - namespace?: string; - expiration?: number; -} export interface IOptions { network?: INetworkOptions; errorCallback?: ErrorCallback; @@ -38,6 +34,7 @@ export interface IOptions { onTransformed?: OnTransformedCallback; } export { INetworkOptions }; +export { CacheConfig }; export declare function createLLMTransformer(options: IKBotTask, logger?: ILogger, cacheConfig?: CacheConfig): AsyncTransformer; export declare function createIterator(obj: Record, optionsMixin: Partial, globalOptions?: IOptions): IteratorFactory; export declare function transformWithMappings(obj: Record, createTransformer: (options: IKBotTask) => AsyncTransformer, mappings: FieldMapping[], globalOptions?: IOptions): Promise; diff --git a/packages/kbot/dist-in/iterator.js b/packages/kbot/dist-in/iterator.js index 2971064c..b0999ceb 100644 --- a/packages/kbot/dist-in/iterator.js +++ b/packages/kbot/dist-in/iterator.js @@ -1,6 +1,6 @@ import { defaultError, defaultFilters, testFilters, transformObjectWithOptions, DEFAULT_NETWORK_OPTIONS } from './async-iterator.js'; import { run } from './commands/run.js'; -import { get_cached_object, set_cached_object } from "@polymech/cache"; +import { createCacheProvider, DEFAULT_CACHE_CONFIG } from './iterator-cache.js'; const dummyLogger = { info: () => { }, warn: () => { }, @@ -23,13 +23,9 @@ export const removeEmptyObjects = (obj) => { } return obj; }; -const DEFAULT_CACHE_CONFIG = { - enabled: true, - namespace: 'llm-responses', - expiration: 7 * 24 * 60 * 60 // 7 days in seconds -}; export function createLLMTransformer(options, logger = dummyLogger, cacheConfig) { - const config = { ...DEFAULT_CACHE_CONFIG, ...cacheConfig }; + const mergedCacheConfig = { ...DEFAULT_CACHE_CONFIG, ...cacheConfig }; + const cacheProvider = createCacheProvider(mergedCacheConfig); return async (input, jsonPath) => { logger.info(`Transforming field at path: ${jsonPath}`); logger.info(`Input: ${input}`); @@ -47,8 +43,8 @@ export function createLLMTransformer(options, logger = dummyLogger, cacheConfig) tools: [] }); try { - if (config.enabled) { - const cachedResponse = await get_cached_object({ ca_options: cacheKeyObj }, config.namespace); + if (mergedCacheConfig.enabled) { + const cachedResponse = await cacheProvider.get(cacheKeyObj, 'llm-responses'); if (cachedResponse?.content) { logger.info(`Using cached LLM response for prompt: ${kbotTask.prompt.substring(0, 100)}...`); return cachedResponse.content; @@ -57,8 +53,8 @@ export function createLLMTransformer(options, logger = dummyLogger, cacheConfig) const results = await run(kbotTask); if (results && results.length > 0 && typeof results[0] === 'string') { const result = results[0].trim(); - if (config.enabled) { - await set_cached_object({ ca_options: cacheKeyObj }, config.namespace, { content: result }, { expiration: config.expiration }); + if (mergedCacheConfig.enabled) { + await cacheProvider.set(cacheKeyObj, 'llm-responses', { content: result }, { expiration: mergedCacheConfig.expiration }); logger.info(`Cached LLM response for prompt: ${kbotTask.prompt.substring(0, 100)}...`); } logger.info(`Result: ${result}`); @@ -79,7 +75,9 @@ export function createIterator(obj, optionsMixin, globalOptions = {}) { ...DEFAULT_NETWORK_OPTIONS, ...network }; - const config = { ...DEFAULT_CACHE_CONFIG, ...cacheConfig }; + const mergedCacheConfig = { ...DEFAULT_CACHE_CONFIG, ...cacheConfig }; + const cacheProvider = createCacheProvider(mergedCacheConfig); + const objCacheNamespace = 'transformed-objects'; const defaultTransformerFactory = (options) => { return async (input) => input; }; @@ -116,27 +114,22 @@ export function createIterator(obj, optionsMixin, globalOptions = {}) { transform: async (mappings) => { // *** Object Cache Check (Start) *** let objectCacheKey; - if (config.enabled) { - objectCacheKey = createObjectCacheKey(obj, mappings); // Key based on initial state - const cachedObject = await get_cached_object({ ca_options: objectCacheKey }, 'transformed-objects'); + if (mergedCacheConfig.enabled) { + objectCacheKey = createObjectCacheKey(obj, mappings); + const cachedObject = await cacheProvider.get(objectCacheKey, objCacheNamespace); if (cachedObject?.content) { logger.info('Using cached transformed object'); - // Clear the original object before merging cache to avoid partial states Object.keys(obj).forEach(key => delete obj[key]); deepMerge(obj, cachedObject.content); return; } } // *** Object Cache Check (End) *** - // If no cache hit or caching disabled, perform the transformations directly on 'obj' - // REMOVED: const transformedObj = JSON.parse(JSON.stringify(obj)); for (const mapping of mappings) { const mergedOptions = { ...optionsMixin, ...mapping.options }; const { jsonPath, targetPath = null } = mapping; const transformer = createTransformer(mergedOptions); - // Call transformObjectWithOptions directly on the original 'obj' - await transformObjectWithOptions(obj, // <<< Operate directly on obj - transformer, { + await transformObjectWithOptions(obj, transformer, { jsonPath, targetPath, network: networkOptions, @@ -148,19 +141,15 @@ export function createIterator(obj, optionsMixin, globalOptions = {}) { }); } // *** Object Cache Setting (Start) *** - // Cache the final state of the modified 'obj' - if (config.enabled && objectCacheKey) { // Ensure key was generated - await set_cached_object({ ca_options: objectCacheKey }, 'transformed-objects', { content: obj }, // <<< Cache the final obj - { expiration: config.expiration }); + if (mergedCacheConfig.enabled && objectCacheKey) { + await cacheProvider.set(objectCacheKey, objCacheNamespace, { content: obj }, { expiration: mergedCacheConfig.expiration }); logger.info('Cached transformed object'); } // *** Object Cache Setting (End) *** - // REMOVED: deepMerge(obj, transformedObj); } }; } export async function transformWithMappings(obj, createTransformer, mappings, globalOptions = {}) { - // Pass the provided createTransformer as the transformerFactory in options const optionsWithTransformer = { ...globalOptions, transformerFactory: createTransformer @@ -183,4 +172,4 @@ export async function transform(obj, mappings, optionsMixin = {}, options = {}) await iterator.transform(mappings); return obj; } -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaXRlcmF0b3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaXRlcmF0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQU1ILFlBQVksRUFDWixjQUFjLEVBQ2QsV0FBVyxFQUNYLDBCQUEwQixFQUUxQix1QkFBdUIsRUFDMUIsTUFBTSxxQkFBcUIsQ0FBQTtBQUM1QixPQUFPLEVBQUUsR0FBRyxFQUFFLE1BQU0sbUJBQW1CLENBQUE7QUFDdkMsT0FBTyxFQUFFLGlCQUFpQixFQUFFLGlCQUFpQixFQUFvQixNQUFNLGlCQUFpQixDQUFBO0FBaUJ4RixNQUFNLFdBQVcsR0FBWTtJQUN6QixJQUFJLEVBQUUsR0FBRyxFQUFFLEdBQUUsQ0FBQztJQUNkLElBQUksRUFBRSxHQUFHLEVBQUUsR0FBRSxDQUFDO0lBQ2QsS0FBSyxFQUFFLEdBQUcsRUFBRSxHQUFFLENBQUM7Q0FDbEIsQ0FBQztBQUVGLE1BQU0sQ0FBQyxNQUFNLGtCQUFrQixHQUFHLENBQUMsR0FBUSxFQUFPLEVBQUU7SUFDaEQsSUFBSSxHQUFHLEtBQUssSUFBSSxJQUFJLEdBQUcsS0FBSyxTQUFTO1FBQUUsT0FBTyxHQUFHLENBQUM7SUFDbEQsS0FBSyxNQUFNLEdBQUcsSUFBSSxHQUFHLEVBQUUsQ0FBQztRQUNwQixNQUFNLEdBQUcsR0FBRyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUE7UUFDcEIsSUFBSSxHQUFHLEtBQUssSUFBSSxJQUFJLEdBQUcsS0FBSyxTQUFTO1lBQUUsU0FBUztRQUNoRCxJQUFJLE9BQU8sR0FBRyxLQUFLLFFBQVE7WUFDdkIsQ0FBQyxHQUFHLElBQUksT0FBTyxJQUFJLE9BQU8sR0FBRyxLQUFLLFFBQVEsSUFBSSxHQUFHLEtBQUssQ0FBQyxJQUFJLEdBQUcsSUFBSSxRQUFRLENBQUMsRUFDN0UsQ0FBQztZQUNDLEdBQUcsQ0FBQyxHQUFHLENBQUMsR0FBRyxrQkFBa0IsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMs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 \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaXRlcmF0b3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaXRlcmF0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQU1ILFlBQVksRUFDWixjQUFjLEVBQ2QsV0FBVyxFQUNYLDBCQUEwQixFQUUxQix1QkFBdUIsRUFDMUIsTUFBTSxxQkFBcUIsQ0FBQTtBQUM1QixPQUFPLEVBQUUsR0FBRyxFQUFFLE1BQU0sbUJBQW1CLENBQUE7QUFFdkMsT0FBTyxFQUFlLG1CQUFtQixFQUFpQixvQkFBb0IsRUFBRSxNQUFNLHFCQUFxQixDQUFBO0FBZ0IzRyxNQUFNLFdBQVcsR0FBWTtJQUN6QixJQUFJLEVBQUUsR0FBRyxFQUFFLEdBQUUsQ0FBQztJQUNkLElBQUksRUFBRSxHQUFHLEVBQUUsR0FBRSxDQUFDO0lBQ2QsS0FBSyxFQUFFLEdBQUcsRUFBRSxHQUFFLENBQUM7Q0FDbEIsQ0FBQztBQUVGLE1BQU0sQ0FBQyxNQUFNLGtCQUFrQixHQUFHLENBQUMsR0FBUSxFQUFPLEVBQUU7SUFDaEQsSUFBSSxHQUFHLEtBQUssSUFBSSxJQUFJLEdBQUcsS0FBSyxTQUFTO1FBQUUsT0FBTyxHQUFHLENBQUM7SUFDbEQsS0FBSyxNQUFNLEdBQUcsSUFBSSxHQUFHLEVBQUUsQ0FBQztRQUNwQixNQUFNLEdBQUcsR0FBRyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUE7UUFDcEIsSUFBSSxHQUFHLEtBQUssSUFBSSxJQUFJLEdBQUcsS0FBSyxTQUFTO1lBQUUsU0FBUztRQUNoRCxJQUFJLE9BQU8sR0FBRyxLQUFLLFFBQVE7WUFDdkIsQ0FBQyxHQUFHLElBQUksT0FBTyxJQUFJLE9BQU8sR0FBRyxLQUFLLFFBQVEsSUFBSSxHQUFHLEtBQUssQ0FBQyxJQUFJLEdBQUcsSUFBSSxRQUFRLENBQUMsRUFDN0UsQ0FBQztZQUNDLEdBQUcsQ0FBQyxHQUFHLENBQUMsR0FBRyxrQkFBa0IsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMs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 \ No newline at end of file diff --git a/packages/kbot/dist-in/prompt.js b/packages/kbot/dist-in/prompt.js index 9622b6ce..1fec1568 100644 --- a/packages/kbot/dist-in/prompt.js +++ b/packages/kbot/dist-in/prompt.js @@ -17,12 +17,15 @@ export const preferences = async (opts) => { let preferencesPath = path.resolve(path.join(process.cwd(), PREFERENCES_FILE_NAME)); if (!exists(preferencesPath)) { // Fall back to specified preferences path if local file doesn't exist - preferencesPath = path.resolve(resolve(opts.preferences, false, env_vars())); + // Only resolve if opts.preferences is actually defined + preferencesPath = opts.preferences ? path.resolve(resolve(opts.preferences, false, env_vars())) : ''; } - const preferences = read(preferencesPath, 'string'); + // Only read if preferencesPath is valid and exists + const preferencesContent = preferencesPath && exists(preferencesPath) ? read(preferencesPath, 'string') : ''; return { role: "user", - content: `USER Preferences : ${preferences}` || '' + // Only include content if preferences were actually loaded + content: preferencesContent ? `USER Preferences : ${preferencesContent}` : '' }; }; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvbXB0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL3Byb21wdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFJQSxPQUFPLEVBQUUsSUFBSSxJQUFJLElBQUksRUFBRSxNQUFNLG1CQUFtQixDQUFBO0FBQ2hELE9BQU8sRUFBRSxJQUFJLElBQUksTUFBTSxFQUFFLE1BQU0scUJBQXFCLENBQUE7QUFDcEQsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLG1CQUFtQixDQUFBO0FBQzNDLE9BQU8sS0FBSyxJQUFJLE1BQU0sV0FBVyxDQUFBO0FBRWpDLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQTtBQUMvQyxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sZ0JBQWdCLENBQUE7QUFDekMsT0FBTyxFQUFFLHFCQUFxQixFQUFFLE1BQU0sZ0JBQWdCLENBQUE7QUFFdEQsTUFBTSxDQUFDLE1BQU0sTUFBTSxHQUFHLEtBQUssRUFBRSxJQUFlLEVBQW1ELEVBQUU7SUFDN0YsTUFBTSxLQUFLLEdBQUcsTUFBTSxZQUFZLENBQUMsSUFBSSxDQUFDLENBQUE7SUFDdEMsT0FBTztRQUNILElBQUksRUFBRSxNQUFNO1FBQ1osT0FBTyxFQUFFLEtBQUssSUFBSSxFQUFFO0tBQ3ZCLENBQUE7QUFDTCxDQUFDLENBQUE7QUFFRCxNQUFNLENBQUMsTUFBTSxXQUFXLEdBQUcsS0FBSyxFQUFFLElBQWUsRUFBbUQsRUFBRTtJQUNsRyw4QkFBOEI7SUFDOUIsSUFBSSxlQUFlLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUUsRUFBRSxxQkFBcUIsQ0FBQyxDQUFDLENBQUE7SUFDbkYsSUFBSSxDQUFDLE1BQU0sQ0FBQyxlQUFlLENBQUMsRUFBRSxDQUFDO1FBQzNCLHNFQUFzRTtRQUN0RSxlQUFlLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFLENBQUMsQ0FBQyxDQUFBO0lBQ2hGLENBQUM7SUFDRCxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsZUFBZSxFQUFFLFFBQVEsQ0FBVyxDQUFBO0lBQzdELE9BQU87UUFDSCxJQUFJLEVBQUUsTUFBTTtRQUNaLE9BQU8sRUFBRSxzQkFBc0IsV0FBVyxFQUFFLElBQUksRUFBRTtLQUNyRCxDQUFBO0FBQ0wsQ0FBQyxDQUFBIn0= \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvbXB0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL3Byb21wdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFJQSxPQUFPLEVBQUUsSUFBSSxJQUFJLElBQUksRUFBRSxNQUFNLG1CQUFtQixDQUFBO0FBQ2hELE9BQU8sRUFBRSxJQUFJLElBQUksTUFBTSxFQUFFLE1BQU0scUJBQXFCLENBQUE7QUFDcEQsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLG1CQUFtQixDQUFBO0FBQzNDLE9BQU8sS0FBSyxJQUFJLE1BQU0sV0FBVyxDQUFBO0FBRWpDLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQTtBQUMvQyxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sZ0JBQWdCLENBQUE7QUFDekMsT0FBTyxFQUFFLHFCQUFxQixFQUFFLE1BQU0sZ0JBQWdCLENBQUE7QUFFdEQsTUFBTSxDQUFDLE1BQU0sTUFBTSxHQUFHLEtBQUssRUFBRSxJQUFlLEVBQW1ELEVBQUU7SUFDN0YsTUFBTSxLQUFLLEdBQUcsTUFBTSxZQUFZLENBQUMsSUFBSSxDQUFDLENBQUE7SUFDdEMsT0FBTztRQUNILElBQUksRUFBRSxNQUFNO1FBQ1osT0FBTyxFQUFFLEtBQUssSUFBSSxFQUFFO0tBQ3ZCLENBQUE7QUFDTCxDQUFDLENBQUE7QUFFRCxNQUFNLENBQUMsTUFBTSxXQUFXLEdBQUcsS0FBSyxFQUFFLElBQWUsRUFBbUQsRUFBRTtJQUNsRyw4QkFBOEI7SUFDOUIsSUFBSSxlQUFlLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUUsRUFBRSxxQkFBcUIsQ0FBQyxDQUFDLENBQUE7SUFDbkYsSUFBSSxDQUFDLE1BQU0sQ0FBQyxlQUFlLENBQUMsRUFBRSxDQUFDO1FBQzNCLHNFQUFzRTtRQUN0RSx1REFBdUQ7UUFDdkQsZUFBZSxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFBO0lBQ3hHLENBQUM7SUFDRCxtREFBbUQ7SUFDbkQsTUFBTSxrQkFBa0IsR0FBRyxlQUFlLElBQUksTUFBTSxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsZUFBZSxFQUFFLFFBQVEsQ0FBVyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUE7SUFDdEgsT0FBTztRQUNILElBQUksRUFBRSxNQUFNO1FBQ1osMkRBQTJEO1FBQzNELE9BQU8sRUFBRSxrQkFBa0IsQ0FBQyxDQUFDLENBQUMsc0JBQXNCLGtCQUFrQixFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUU7S0FDaEYsQ0FBQTtBQUNMLENBQUMsQ0FBQSJ9 \ No newline at end of file diff --git a/packages/kbot/logs/params.json b/packages/kbot/logs/params.json index 995d91d0..0d22092a 100644 --- a/packages/kbot/logs/params.json +++ b/packages/kbot/logs/params.json @@ -1,13 +1,13 @@ { - "model": "mistralai/mistral-tiny", + "model": "openai/chatgpt-4o-latest", "messages": [ { "role": "user", - "content": "Generate a random number" + "content": "Analyze this product review and extract key information\n\nText to transform: \"Great selection of fruits with good prices and quality. Some items were out of stock.\"" }, { "role": "user", - "content": "USER Preferences : undefined" + "content": "" } ], "tools": [] diff --git a/packages/kbot/package-lock.json b/packages/kbot/package-lock.json index d1fdfdad..0828ee33 100644 --- a/packages/kbot/package-lock.json +++ b/packages/kbot/package-lock.json @@ -7,6 +7,7 @@ "": { "name": "@polymech/kbot-d", "version": "0.3.5", + "license": "MIT", "dependencies": { "@polymech/ai-tools": "file:../ai-tools", "@polymech/cache": "file:../cache", @@ -22,6 +23,7 @@ "emojilib": "4.0.1", "env-var": "7.5.0", "glob": "11.0.1", + "ioredis": "^5.4.1", "json-schema-to-zod": "2.6.0", "jsonpath-plus": "10.3.0", "marked": "14.1.4", @@ -1085,6 +1087,12 @@ } } }, + "node_modules/@ioredis/commands": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz", + "integrity": "sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==", + "license": "MIT" + }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -3128,6 +3136,15 @@ "node": ">=6" } }, + "node_modules/cluster-key-slot": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", + "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -3287,6 +3304,15 @@ "node": ">=0.4.0" } }, + "node_modules/denque": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.10" + } + }, "node_modules/dequal": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", @@ -4435,6 +4461,30 @@ "node": ">=10.13.0" } }, + "node_modules/ioredis": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.6.0.tgz", + "integrity": "sha512-tBZlIIWbndeWBWCXWZiqtOF/yxf6yZX3tAlTJ7nfo5jhd6dctNxF7QnYlZLZ1a0o0pDoen7CgZqO+zjNaFbJAg==", + "license": "MIT", + "dependencies": { + "@ioredis/commands": "^1.1.1", + "cluster-key-slot": "^1.1.0", + "debug": "^4.3.4", + "denque": "^2.1.0", + "lodash.defaults": "^4.2.0", + "lodash.isarguments": "^3.1.0", + "redis-errors": "^1.2.0", + "redis-parser": "^3.0.0", + "standard-as-callback": "^2.1.0" + }, + "engines": { + "node": ">=12.22.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ioredis" + } + }, "node_modules/is-core-module": { "version": "2.16.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", @@ -4817,6 +4867,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==", + "license": "MIT" + }, + "node_modules/lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==", + "license": "MIT" + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -6347,6 +6409,27 @@ "node": ">= 10.13.0" } }, + "node_modules/redis-errors": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", + "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/redis-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", + "integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==", + "license": "MIT", + "dependencies": { + "redis-errors": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/remark-parse": { "version": "11.0.0", "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", @@ -6766,6 +6849,12 @@ "dev": true, "license": "MIT" }, + "node_modules/standard-as-callback": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz", + "integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==", + "license": "MIT" + }, "node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", diff --git a/packages/kbot/package.json b/packages/kbot/package.json index 7e2a01bb..4d5c866b 100644 --- a/packages/kbot/package.json +++ b/packages/kbot/package.json @@ -63,6 +63,7 @@ "emojilib": "4.0.1", "env-var": "7.5.0", "glob": "11.0.1", + "ioredis": "^5.4.1", "json-schema-to-zod": "2.6.0", "jsonpath-plus": "10.3.0", "marked": "14.1.4", diff --git a/packages/kbot/src/iterator-cache.ts b/packages/kbot/src/iterator-cache.ts new file mode 100644 index 00000000..16e39189 --- /dev/null +++ b/packages/kbot/src/iterator-cache.ts @@ -0,0 +1,139 @@ +import { get_cached_object, set_cached_object, rm_cached_object } from "@polymech/cache"; +import { Redis } from 'ioredis'; + +export interface CacheProvider { + get(key: object, namespace: string): Promise; + set(key: object, namespace: string, value: any, options?: { expiration?: number }): Promise; + delete(key: object, namespace: string): Promise; +} + +export interface CacheConfig { + enabled?: boolean; + provider?: 'default' | 'redis'; + namespace?: string; + expiration?: number; // in seconds + redisUrl?: string; // e.g., 'redis://localhost:6379' +} + +export const DEFAULT_CACHE_CONFIG: Required> = { + enabled: true, + provider: 'default', + namespace: 'default-cache', + expiration: 7 * 24 * 60 * 60 // 7 days in seconds +}; + +// --- Default Cache Provider (using @polymech/cache) --- + +class DefaultCacheProvider implements CacheProvider { + async get(key: object, namespace: string): Promise { + try { + return await get_cached_object({ ca_options: key }, namespace); + } catch (error) { + console.error(`DefaultCache: Error getting cache for key ${JSON.stringify(key)} in namespace ${namespace}:`, error); + return null; + } + } + + async set(key: object, namespace: string, value: any, options?: { expiration?: number }): Promise { + try { + await set_cached_object({ ca_options: key }, namespace, value, options); + } catch (error) { + console.error(`DefaultCache: Error setting cache for key ${JSON.stringify(key)} in namespace ${namespace}:`, error); + } + } + + async delete(key: object, namespace: string): Promise { + try { + await rm_cached_object({ ca_options: key }, namespace); + } catch (error) { + console.error(`DefaultCache: Error deleting cache for key ${JSON.stringify(key)} in namespace ${namespace}:`, error); + } + } +} + +// --- Redis Cache Provider --- + +class RedisCacheProvider implements CacheProvider { + private redis: Redis; + + constructor(redisUrl?: string) { + // Default to local instance if no URL is provided + this.redis = new Redis(redisUrl || 'redis://localhost:6379'); + this.redis.on('error', (err) => console.error('Redis Client Error', err)); + } + + private generateKey(key: object, namespace: string): string { + // Simple serialization; consider a more robust hashing function for complex keys + return `${namespace}:${JSON.stringify(key)}`; + } + + async get(key: object, namespace: string): Promise { + const redisKey = this.generateKey(key, namespace); + try { + const data = await this.redis.get(redisKey); + return data ? JSON.parse(data) : null; + } catch (error) { + console.error(`RedisCache: Error getting cache for key ${redisKey}:`, error); + return null; + } + } + + async set(key: object, namespace: string, value: any, options?: { expiration?: number }): Promise { + const redisKey = this.generateKey(key, namespace); + try { + const stringValue = JSON.stringify(value); + if (options?.expiration) { + await this.redis.set(redisKey, stringValue, 'EX', options.expiration); + } else { + await this.redis.set(redisKey, stringValue); + } + } catch (error) { + console.error(`RedisCache: Error setting cache for key ${redisKey}:`, error); + } + } + + async delete(key: object, namespace: string): Promise { + const redisKey = this.generateKey(key, namespace); + try { + await this.redis.del(redisKey); + } catch (error) { + console.error(`RedisCache: Error deleting cache for key ${redisKey}:`, error); + } + } + + async disconnect(): Promise { + await this.redis.quit(); + } +} + +// --- Factory Function --- + +let defaultCacheProviderInstance: CacheProvider | null = null; +let redisCacheProviderInstance: CacheProvider | null = null; + +export function createCacheProvider(config?: CacheConfig): CacheProvider { + const mergedConfig = { ...DEFAULT_CACHE_CONFIG, ...config }; + + if (!mergedConfig.enabled) { + // Return a dummy provider if caching is disabled + return { + get: async () => null, + set: async () => {}, + delete: async () => {}, + }; + } + + if (mergedConfig.provider === 'redis') { + if (!redisCacheProviderInstance) { + // Pass redisUrl if provided in config + redisCacheProviderInstance = new RedisCacheProvider(config?.redisUrl); + } + return redisCacheProviderInstance; + } + + // Default provider + if (!defaultCacheProviderInstance) { + defaultCacheProviderInstance = new DefaultCacheProvider(); + } + return defaultCacheProviderInstance; +} \ No newline at end of file diff --git a/packages/kbot/src/iterator.ts b/packages/kbot/src/iterator.ts index a534d0df..dd08dc16 100644 --- a/packages/kbot/src/iterator.ts +++ b/packages/kbot/src/iterator.ts @@ -13,8 +13,8 @@ import { DEFAULT_NETWORK_OPTIONS } from './async-iterator.js' import { run } from './commands/run.js' -import { get_cached_object, set_cached_object, rm_cached_object } from "@polymech/cache" import { deepClone } from "@polymech/core/objects" +import { CacheConfig, createCacheProvider, CacheProvider, DEFAULT_CACHE_CONFIG } from './iterator-cache.js' /** * Notes for LLM modifications @@ -64,12 +64,6 @@ export interface IteratorFactory { createTransformer: (options: IKBotTask) => AsyncTransformer } -export interface CacheConfig { - enabled?: boolean; - namespace?: string; - expiration?: number; // in seconds -} - export interface IOptions { network?: INetworkOptions; errorCallback?: ErrorCallback; @@ -81,21 +75,18 @@ export interface IOptions { onTransformed?: OnTransformedCallback; } -const DEFAULT_CACHE_CONFIG: Required = { - enabled: true, - namespace: 'llm-responses', - expiration: 7 * 24 * 60 * 60 // 7 days in seconds -}; - // Re-export INetworkOptions for other modules to use export { INetworkOptions }; +// Re-export CacheConfig as well +export { CacheConfig }; export function createLLMTransformer( options: IKBotTask, logger: ILogger = dummyLogger, cacheConfig?: CacheConfig ): AsyncTransformer { - const config: Required = { ...DEFAULT_CACHE_CONFIG, ...cacheConfig }; + const mergedCacheConfig = { ...DEFAULT_CACHE_CONFIG, ...cacheConfig }; + const cacheProvider = createCacheProvider(mergedCacheConfig); return async (input: string, jsonPath: string): Promise => { logger.info(`Transforming field at path: ${jsonPath}`); @@ -117,8 +108,8 @@ export function createLLMTransformer( }); try { - if (config.enabled) { - const cachedResponse = await get_cached_object({ ca_options: cacheKeyObj }, config.namespace) as { content: string }; + if (mergedCacheConfig.enabled) { + const cachedResponse = await cacheProvider.get(cacheKeyObj, 'llm-responses') as { content: string }; if (cachedResponse?.content) { logger.info(`Using cached LLM response for prompt: ${kbotTask.prompt.substring(0, 100)}...`); return cachedResponse.content; @@ -129,12 +120,12 @@ export function createLLMTransformer( if (results && results.length > 0 && typeof results[0] === 'string') { const result = results[0].trim(); - if (config.enabled) { - await set_cached_object( - { ca_options: cacheKeyObj }, - config.namespace, + if (mergedCacheConfig.enabled) { + await cacheProvider.set( + cacheKeyObj, + 'llm-responses', { content: result }, - { expiration: config.expiration } + { expiration: mergedCacheConfig.expiration } ); logger.info(`Cached LLM response for prompt: ${kbotTask.prompt.substring(0, 100)}...`); } @@ -173,7 +164,9 @@ export function createIterator( ...network }; - const config: Required = { ...DEFAULT_CACHE_CONFIG, ...cacheConfig }; + const mergedCacheConfig = { ...DEFAULT_CACHE_CONFIG, ...cacheConfig }; + const cacheProvider = createCacheProvider(mergedCacheConfig); + const objCacheNamespace = 'transformed-objects'; const defaultTransformerFactory = (options: IKBotTask): AsyncTransformer => { return async (input: string): Promise => input; @@ -213,16 +206,15 @@ export function createIterator( transform: async (mappings: FieldMapping[]): Promise => { // *** Object Cache Check (Start) *** let objectCacheKey: any; - if (config.enabled) { - objectCacheKey = createObjectCacheKey(obj, mappings); // Key based on initial state - const cachedObject = await get_cached_object( - { ca_options: objectCacheKey }, - 'transformed-objects' + if (mergedCacheConfig.enabled) { + objectCacheKey = createObjectCacheKey(obj, mappings); + const cachedObject = await cacheProvider.get( + objectCacheKey, + objCacheNamespace ) as { content: Record }; if (cachedObject?.content) { logger.info('Using cached transformed object'); - // Clear the original object before merging cache to avoid partial states Object.keys(obj).forEach(key => delete obj[key]); deepMerge(obj, cachedObject.content); return; @@ -230,16 +222,13 @@ export function createIterator( } // *** Object Cache Check (End) *** - // If no cache hit or caching disabled, perform the transformations directly on 'obj' - // REMOVED: const transformedObj = JSON.parse(JSON.stringify(obj)); for (const mapping of mappings) { const mergedOptions = { ...optionsMixin, ...mapping.options } as IKBotTask; const { jsonPath, targetPath = null } = mapping; const transformer = createTransformer(mergedOptions); - // Call transformObjectWithOptions directly on the original 'obj' await transformObjectWithOptions( - obj, // <<< Operate directly on obj + obj, transformer, { jsonPath, @@ -255,19 +244,16 @@ export function createIterator( } // *** Object Cache Setting (Start) *** - // Cache the final state of the modified 'obj' - if (config.enabled && objectCacheKey) { // Ensure key was generated - await set_cached_object( - { ca_options: objectCacheKey }, - 'transformed-objects', - { content: obj }, // <<< Cache the final obj - { expiration: config.expiration } + if (mergedCacheConfig.enabled && objectCacheKey) { + await cacheProvider.set( + objectCacheKey, + objCacheNamespace, + { content: obj }, + { expiration: mergedCacheConfig.expiration } ); logger.info('Cached transformed object'); } // *** Object Cache Setting (End) *** - - // REMOVED: deepMerge(obj, transformedObj); } }; } @@ -278,7 +264,6 @@ export async function transformWithMappings( mappings: FieldMapping[], globalOptions: IOptions = {} ): Promise { - // Pass the provided createTransformer as the transformerFactory in options const optionsWithTransformer: IOptions = { ...globalOptions, transformerFactory: createTransformer diff --git a/packages/kbot/src/prompt.ts b/packages/kbot/src/prompt.ts index 8fbab641..40d1bb5f 100644 --- a/packages/kbot/src/prompt.ts +++ b/packages/kbot/src/prompt.ts @@ -24,11 +24,14 @@ export const preferences = async (opts: IKBotTask): Promise