diff --git a/genkit-tools/common/src/manager/manager.ts b/genkit-tools/common/src/manager/manager.ts index 7b20698644..07e3020df1 100644 --- a/genkit-tools/common/src/manager/manager.ts +++ b/genkit-tools/common/src/manager/manager.ts @@ -198,6 +198,44 @@ export class RuntimeManager { return response.data as Record; } + /** + * Retrieves all valuess. + */ + async listValues( + input: apis.ListValuesRequest + ): Promise> { + const runtime = input.runtimeId + ? this.getRuntimeById(input.runtimeId) + : this.getMostRecentRuntime(); + if (!runtime) { + throw new Error( + input?.runtimeId + ? `No runtime found with ID ${input.runtimeId}.` + : 'No runtimes found. Make sure your app is running using `genkit start -- ...`. See getting started documentation.' + ); + } + try { + const response = await axios.get( + `${runtime.reflectionServerUrl}/api/values`, + { + params: { + type: input.type, + }, + } + ); + return response.data as Record; + } catch (err) { + if ((err as AxiosError).response?.status === 404) { + return {}; + } else if ((err as AxiosError).response?.status === 400) { + throw new GenkitToolsError( + `Bad request: ${(err as AxiosError).response?.data}` + ); + } + this.httpErrorHandler(err as AxiosError, 'Error listing values.'); + } + } + /** * Runs an action. */ diff --git a/genkit-tools/common/src/server/router.ts b/genkit-tools/common/src/server/router.ts index aa3cf30555..e85a374c07 100644 --- a/genkit-tools/common/src/server/router.ts +++ b/genkit-tools/common/src/server/router.ts @@ -134,6 +134,13 @@ export const TOOLS_SERVER_ROUTER = (manager: RuntimeManager) => return manager.listActions(input); }), + /** Retrieves all values. */ + listValues: loggedProcedure + .input(apis.ListValuesRequestSchema) + .query(async ({ input }): Promise> => { + return manager.listValues(input); + }), + /** Generate a .prompt file from messages and model config. */ createPrompt: loggedProcedure .input(apis.CreatePromptRequestSchema) diff --git a/genkit-tools/common/src/types/apis.ts b/genkit-tools/common/src/types/apis.ts index 4920f6ec65..e9e6830266 100644 --- a/genkit-tools/common/src/types/apis.ts +++ b/genkit-tools/common/src/types/apis.ts @@ -80,6 +80,22 @@ export const ListActionsRequestSchema = z export type ListActionsRequest = z.infer; +export const ListValuesRequestSchema = z.object({ + runtimeId: z + .string() + .optional() + .describe( + 'ID of the Genkit runtime to run the action on. Typically $pid-$port.' + ), + type: z + .string() + .describe( + "The type of values to fetch. Currently only supports 'defaultModel'" + ), +}); + +export type ListValuesRequest = z.infer; + export const RunActionRequestSchema = z.object({ runtimeId: z .string() diff --git a/js/core/src/reflection.ts b/js/core/src/reflection.ts index 9b9389ad9d..ec8a615811 100644 --- a/js/core/src/reflection.ts +++ b/js/core/src/reflection.ts @@ -151,6 +151,30 @@ export class ReflectionServer { await this.stop(); }); + server.get('/api/values', async (req, response, next) => { + logger.debug('Fetching values.'); + try { + const type = req.query.type; + if (!type) { + response.status(400).send('Query parameter "type" is required.'); + return; + } + if (type !== 'defaultModel') { + response + .status(400) + .send( + `'type' ${type} is not supported. Only 'defaultModel' is supported` + ); + return; + } + const values = await this.registry.listValues(type as string); + response.send(values); + } catch (err) { + const { message, stack } = err as Error; + next({ message, stack }); + } + }); + server.get('/api/actions', async (_, response, next) => { logger.debug('Fetching actions.'); try { diff --git a/js/genkit/src/genkit.ts b/js/genkit/src/genkit.ts index 2cd34a4c7a..5053f6dbfd 100644 --- a/js/genkit/src/genkit.ts +++ b/js/genkit/src/genkit.ts @@ -25,6 +25,7 @@ import { generate, generateStream, loadPromptFolder, + modelRef, prompt, rerank, retrieve, @@ -46,6 +47,7 @@ import { type GenerationCommonConfigSchema, type IndexerParams, type ModelArgument, + type ModelReference, type Part, type PromptConfig, type PromptGenerateOptions, @@ -953,7 +955,7 @@ export class Genkit implements HasRegistry { this.registry.registerValue( 'defaultModel', 'defaultModel', - this.options.model + toModelRef(this.options.model) ); } if (this.options.promptDir !== null) { @@ -1086,3 +1088,22 @@ let disableReflectionApi = false; export function __disableReflectionApi() { disableReflectionApi = true; } + +/** Helper method to map ModelArgument to ModelReference */ +function toModelRef( + modelArg: ModelArgument | undefined +): ModelReference | undefined { + if (modelArg === undefined) { + return undefined; + } + if (typeof modelArg === 'string') { + return modelRef({ name: modelArg }); + } + if ((modelArg as ModelReference).name) { + return modelArg as ModelReference; + } + const modelAction = modelArg as ModelAction; + return modelRef({ + name: modelAction.__action.name, + }); +}