UNPKG

@genkit-ai/core

Version:

Genkit AI framework core libraries.

154 lines 4.44 kB
import * as z from "zod"; import { ActionMetadataSchema, defineAction } from "./action.mjs"; import { GenkitError } from "./error.mjs"; class SimpleCache { value; expiresAt; ttlMillis; dap; dapFn; fetchPromise = null; constructor(config, dapFn) { this.dapFn = dapFn; this.ttlMillis = !config.cacheConfig?.ttlMillis ? 3 * 1e3 : config.cacheConfig?.ttlMillis; } setDap(dap) { this.dap = dap; } setValue(value) { const dapId = this.dap?.__action?.name; if (dapId) { Object.entries(value).forEach(([actionType, actionList]) => { actionList?.forEach((action) => { action.__action.key = `/dynamic-action-provider/${dapId}:${actionType}/${action.__action.name}`; }); }); } this.value = value; this.expiresAt = Date.now() + this.ttlMillis; } /** * Gets or fetches the DAP data. * @param skipTrace Don't run the action. i.e. don't create a trace log. * @returns The DAP data */ async getOrFetch(params) { const isStale = !this.value || !this.expiresAt || this.ttlMillis < 0 || Date.now() > this.expiresAt; if (!isStale) { return this.value; } if (!this.fetchPromise) { this.fetchPromise = (async () => { try { if (this.dap && !params?.skipTrace) { await this.dap.run(); } else { this.setValue(await this.dapFn()); } if (!this.value) { throw new Error("value is undefined"); } return this.value; } catch (error) { console.error("Error fetching Dynamic Action Provider value:", error); this.invalidate(); throw error; } finally { this.fetchPromise = null; } })(); } return await this.fetchPromise; } invalidate() { this.value = void 0; } } function isDynamicActionProvider(obj) { return obj.__action?.metadata?.type == "dynamic-action-provider"; } function transformDapValue(value) { return Object.values(value).flatMap( (actions) => actions?.map((a) => a.__action) || [] ); } function defineDynamicActionProvider(registry, config, fn) { let cfg; if (typeof config == "string") { cfg = { name: config }; } else { cfg = { ...config }; } const cache = new SimpleCache(cfg, fn); const a = defineAction( registry, { ...cfg, inputSchema: z.void(), outputSchema: z.array(ActionMetadataSchema), actionType: "dynamic-action-provider", metadata: { ...cfg.metadata || {}, type: "dynamic-action-provider" } }, async (_options) => { const dapValue = await fn(); cache.setValue(dapValue); return transformDapValue(dapValue); } ); implementDap(a, cache); return a; } function implementDap(dap, cache) { cache.setDap(dap); dap.__cache = cache; dap.invalidateCache = () => { dap.__cache.invalidate(); }; dap.getAction = async (actionType, actionName) => { const result = await dap.__cache.getOrFetch(); if (result[actionType]) { return result[actionType].find((t) => t.__action.name == actionName); } return void 0; }; dap.listActionMetadata = async (actionType, actionName) => { const result = await dap.__cache.getOrFetch(); if (!result[actionType]) { return []; } const metadata = result[actionType].map((a) => a.__action); if (actionName == "*") { return metadata; } if (actionName.endsWith("*")) { const prefix = actionName.slice(0, -1); return metadata.filter((m) => m.name.startsWith(prefix)); } return metadata.filter((m) => m.name == actionName); }; dap.getActionMetadataRecord = async (dapPrefix) => { const dapActions = {}; const result = await dap.__cache.getOrFetch({ skipTrace: true }); for (const actions of Object.values(result)) { const metadataList = actions.map((a) => a.__action); for (const metadata of metadataList) { if (!metadata.name || !metadata.key) { throw new GenkitError({ status: "INVALID_ARGUMENT", message: `Invalid metadata when listing dynamic actions from ${dapPrefix} - name required` }); } dapActions[metadata.key] = metadata; } } return dapActions; }; } export { defineDynamicActionProvider, isDynamicActionProvider }; //# sourceMappingURL=dynamic-action-provider.mjs.map