UNPKG

@genkit-ai/core

Version:

Genkit AI framework core libraries.

446 lines 14.3 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var registry_exports = {}; __export(registry_exports, { Registry: () => Registry, isActionType: () => isActionType, parseRegistryKey: () => parseRegistryKey }); module.exports = __toCommonJS(registry_exports); var import_dotprompt = require("dotprompt"); var import_action = require("./action.js"); var import_background_action = require("./background-action.js"); var import_dynamic_action_provider = require("./dynamic-action-provider.js"); var import_error = require("./error.js"); var import_logging = require("./logging.js"); var import_schema = require("./schema.js"); const ACTION_TYPES = [ "custom", "dynamic-action-provider", "embedder", "evaluator", "executable-prompt", "flow", "indexer", "model", "background-model", "check-operation", "cancel-operation", "prompt", "reranker", "retriever", "tool", "tool.v2", "util", "resource" ]; function isActionType(value) { return ACTION_TYPES.includes(value); } function parsePluginName(registryKey) { const tokens = registryKey.split("/"); if (tokens.length >= 4) { return tokens[2]; } return void 0; } function parseRegistryKey(registryKey) { if (registryKey.startsWith("/dynamic-action-provider")) { const keyTokens = registryKey.split(":"); const hostTokens = keyTokens[0].split("/"); if (hostTokens.length < 3) { return void 0; } if (keyTokens.length < 2) { return { actionType: "dynamic-action-provider", actionName: hostTokens[2] }; } const tokens2 = keyTokens[1].split("/"); if (tokens2.length < 2 || !isActionType(tokens2[0])) { return void 0; } return { dynamicActionHost: hostTokens[2], actionType: tokens2[0], actionName: tokens2.slice(1).join("/") }; } const tokens = registryKey.split("/"); if (tokens.length < 3) { return void 0; } if (tokens.length >= 4) { return { actionType: tokens[1], pluginName: tokens[2], actionName: tokens.slice(3).join("/") }; } return { actionType: tokens[1], actionName: tokens[2] }; } class Registry { actionsById = {}; pluginsByName = {}; schemasByName = {}; valueByTypeAndName = {}; allPluginsInitialized = false; apiStability = "stable"; dotprompt; parent; /** Additional runtime context data for flows and tools. */ context; constructor(parent) { if (parent) { this.parent = parent; this.apiStability = parent?.apiStability; this.dotprompt = parent.dotprompt; } else { this.dotprompt = new import_dotprompt.Dotprompt({ schemaResolver: async (name) => { const resolvedSchema = await this.lookupSchema(name); if (!resolvedSchema) { throw new import_error.GenkitError({ message: `Schema '${name}' not found`, status: "NOT_FOUND" }); } return (0, import_schema.toJsonSchema)(resolvedSchema); } }); } } /** * Creates a new registry overlaid onto the provided registry. * @param parent The parent registry. * @returns The new overlaid registry. */ static withParent(parent) { return new Registry(parent); } async resolveActionNames(key) { const parsedKey = parseRegistryKey(key); if (parsedKey?.dynamicActionHost) { const hostId = `/dynamic-action-provider/${parsedKey.dynamicActionHost}`; const dap = await this.actionsById[hostId]; if (!dap || !(0, import_dynamic_action_provider.isDynamicActionProvider)(dap)) { return []; } return (await dap.listActionMetadata(parsedKey.actionType, parsedKey.actionName)).map((m) => `${hostId}:${parsedKey.actionType}/${m.name}`); } if (await this.lookupAction(key)) { return [key]; } return []; } /** * Looks up an action in the registry. * @param key The key of the action to lookup. * @returns The action. */ async lookupAction(key) { const parsedKey = parseRegistryKey(key); if (parsedKey?.dynamicActionHost && this.actionsById[`/dynamic-action-provider/${parsedKey.dynamicActionHost}`]) { const action = await this.getDynamicAction(parsedKey); if (action) { return action; } } if (parsedKey?.pluginName && this.pluginsByName[parsedKey.pluginName]) { await this.initializePlugin(parsedKey.pluginName); if (!this.actionsById[key]) { await this.resolvePluginAction( parsedKey.pluginName, parsedKey.actionType, parsedKey.actionName ); } } return await this.actionsById[key] || this.parent?.lookupAction(key); } /** * Looks up a background action from the registry. * @param key The key of the action to lookup. * @returns The action. */ async lookupBackgroundAction(key) { return (0, import_background_action.lookupBackgroundAction)(this, key); } /** * Registers an action in the registry. * @param type The type of the action to register. * @param action The action to register. */ registerAction(type, action, opts) { if (type !== action.__action.actionType) { throw new import_error.GenkitError({ status: "INVALID_ARGUMENT", message: `action type (${type}) does not match type on action (${action.__action.actionType})` }); } if (opts?.namespace && !action.__action.name.startsWith(`${opts.namespace}/`)) { action.__action.name = `${opts.namespace}/${action.__action.name}`; } const key = `/${type}/${action.__action.name}`; import_logging.logger.debug(`registering ${key}`); if (this.actionsById.hasOwnProperty(key)) { import_logging.logger.error( `ERROR: ${key} already has an entry in the registry. Overwriting.` ); } this.actionsById[key] = action; if (action.__registry) { import_logging.logger.error(`ERROR: ${key} already registered.`); } action.__registry = this; } /** * Registers an action promise in the registry. */ registerActionAsync(type, name, action, opts) { if (opts?.namespace && !name.startsWith(`${opts.namespace}/`)) { name = `${opts.namespace}/${name}`; } const key = `/${type}/${name}`; import_logging.logger.debug(`registering ${key} (async)`); if (this.actionsById.hasOwnProperty(key)) { import_logging.logger.error( `ERROR: ${key} already has an entry in the registry. Overwriting.` ); } this.actionsById[key] = action; } /** * Returns all actions that have been registered in the registry. * @returns All actions in the registry as a map of <key, action>. */ async listActions() { await this.initializeAllPlugins(); const actions = {}; await Promise.all( Object.entries(this.actionsById).map(async ([key, action]) => { actions[key] = await action; }) ); return { ...await this.parent?.listActions(), ...actions }; } /** * Returns all actions that are resolvable by plugins as well as those that are already * in the registry. * * NOTE: this method should not be used in latency sensitive code paths. * It may rely on "admin" API calls such as "list models", which may cause increased cold start latency. * * @returns All resolvable action metadata as a map of <key, action metadata>. */ async listResolvableActions() { let resolvableActions = {}; await Promise.all( Object.entries(this.pluginsByName).map(async ([pluginName, plugin]) => { if (plugin.listActions) { try { (await plugin.listActions()).forEach((meta) => { if (!meta.name) { throw new import_error.GenkitError({ status: "INVALID_ARGUMENT", message: `Invalid metadata when listing actions from ${pluginName} - name required` }); } if (!meta.actionType) { throw new import_error.GenkitError({ status: "INVALID_ARGUMENT", message: `Invalid metadata when listing actions from ${pluginName} - actionType required` }); } resolvableActions[`/${meta.actionType}/${meta.name}`] = meta; }); } catch (e) { import_logging.logger.error(`Error listing actions for ${pluginName} `, e); } } }) ); for (const [key, action] of Object.entries(await this.listActions())) { resolvableActions[key] = action.__action; if ((0, import_dynamic_action_provider.isDynamicActionProvider)(action)) { try { const dapPrefix = `/${action.__action.actionType}/${action.__action.name}`; const dapMetadataRecord = await action.getActionMetadataRecord(dapPrefix); resolvableActions = { ...resolvableActions, ...dapMetadataRecord }; } catch (e) { import_logging.logger.error( `Error listing actions for Dynamic Action Provider ${action.__action.name}` ); } } } return { ...await this.parent?.listResolvableActions(), ...resolvableActions }; } /** * Initializes all plugins in the registry. */ async initializeAllPlugins() { if (this.allPluginsInitialized) { return; } for (const pluginName of Object.keys(this.pluginsByName)) { await this.initializePlugin(pluginName); } this.allPluginsInitialized = true; } /** * Registers a plugin provider. This plugin must be initialized before it can be used by calling {@link initializePlugin} or {@link initializeAllPlugins}. * @param name The name of the plugin to register. * @param provider The plugin provider. */ registerPluginProvider(name, provider) { if (this.pluginsByName[name]) { throw new Error(`Plugin ${name} already registered`); } this.allPluginsInitialized = false; let cached; let isInitialized = false; this.pluginsByName[name] = { name: provider.name, initializer: () => { if (!isInitialized) { cached = provider.initializer(); isInitialized = true; } return cached; }, resolver: async (actionType, actionName) => { if (provider.resolver) { await provider.resolver(actionType, actionName); } }, listActions: async () => { if (provider.listActions) { return await provider.listActions(); } return []; } }; } /** * Looks up a plugin. * @param name The name of the plugin to lookup. * @returns The plugin provider. */ lookupPlugin(name) { return this.pluginsByName[name] || this.parent?.lookupPlugin(name); } /** * Resolves a new Action dynamically by registering it. * @param pluginName The name of the plugin * @param actionType The type of the action * @param actionName The name of the action * @returns */ async resolvePluginAction(pluginName, actionType, actionName) { const plugin = this.pluginsByName[pluginName]; if (plugin) { return await (0, import_action.runOutsideActionRuntimeContext)(async () => { if (plugin.resolver) { await plugin.resolver(actionType, actionName); } }); } } async getDynamicAction(key) { if (key.actionName.includes("*")) { return void 0; } const actionId = `/dynamic-action-provider/${key.dynamicActionHost}`; const dap = await this.actionsById[actionId]; if (!dap || !(0, import_dynamic_action_provider.isDynamicActionProvider)(dap)) { return void 0; } return await dap.getAction(key.actionType, key.actionName); } /** * Initializes a plugin already registered with {@link registerPluginProvider}. * @param name The name of the plugin to initialize. * @returns The plugin. */ async initializePlugin(name) { if (this.pluginsByName[name]) { return await (0, import_action.runOutsideActionRuntimeContext)( () => this.pluginsByName[name].initializer() ); } } /** * Registers a schema. * @param name The name of the schema to register. * @param data The schema to register (either a Zod schema or a JSON schema). */ registerSchema(name, data) { if (this.schemasByName[name]) { throw new Error(`Schema ${name} already registered`); } this.schemasByName[name] = data; } registerValue(type, name, value) { if (!this.valueByTypeAndName[type]) { this.valueByTypeAndName[type] = {}; } this.valueByTypeAndName[type][name] = value; } async lookupValue(type, key) { const pluginName = parsePluginName(key); if (!this.valueByTypeAndName[type]?.[key] && pluginName) { await this.initializePlugin(pluginName); } return this.valueByTypeAndName[type]?.[key] || this.parent?.lookupValue(type, key); } async listValues(type) { await this.initializeAllPlugins(); return { ...await this.parent?.listValues(type) || {}, ...this.valueByTypeAndName[type] || {} }; } /** * Looks up a schema. * @param name The name of the schema to lookup. * @returns The schema. */ lookupSchema(name) { return this.schemasByName[name] || this.parent?.lookupSchema(name); } } // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { Registry, isActionType, parseRegistryKey }); //# sourceMappingURL=registry.js.map