UNPKG

@genkit-ai/core

Version:

Genkit AI framework core libraries.

1 lines 20.4 kB
{"version":3,"sources":["../src/reflection.ts"],"sourcesContent":["/**\n * Copyright 2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport express from 'express';\nimport fs from 'fs/promises';\nimport getPort, { makeRange } from 'get-port';\nimport type { Server } from 'http';\nimport path from 'path';\nimport * as z from 'zod';\nimport { StatusCodes, type Status } from './action.js';\nimport { GENKIT_REFLECTION_API_SPEC_VERSION, GENKIT_VERSION } from './index.js';\nimport { logger } from './logging.js';\nimport type { Registry } from './registry.js';\nimport { toJsonSchema } from './schema.js';\nimport { flushTracing, setTelemetryServerUrl } from './tracing.js';\n\n// TODO: Move this to common location for schemas.\nexport const RunActionResponseSchema = z.object({\n result: z.unknown().optional(),\n error: z.unknown().optional(),\n telemetry: z\n .object({\n traceId: z.string().optional(),\n })\n .optional(),\n});\nexport type RunActionResponse = z.infer<typeof RunActionResponseSchema>;\n\nexport interface ReflectionServerOptions {\n /** Port to run the server on. Actual port may be different if chosen port is occupied. Defaults to 3100. */\n port?: number;\n /** Body size limit for the server. Defaults to `30mb`. */\n bodyLimit?: string;\n /** Configured environments. Defaults to `dev`. */\n configuredEnvs?: string[];\n /** Display name that will be shown in developer tooling. */\n name?: string;\n}\n\n/**\n * Reflection server exposes an API for inspecting and interacting with Genkit in development.\n *\n * This is for use in development environments.\n *\n * @hidden\n */\nexport class ReflectionServer {\n /** List of all running servers needed to be cleaned up on process exit. */\n private static RUNNING_SERVERS: ReflectionServer[] = [];\n\n /** Registry instance to be used for API calls. */\n private registry: Registry;\n /** Options for the reflection server. */\n private options: ReflectionServerOptions;\n /** Port the server is actually running on. This may differ from `options.port` if the original was occupied. Null if server is not running. */\n private port: number | null = null;\n /** Express server instance. Null if server is not running. */\n private server: Server | null = null;\n /** Path to the runtime file. Null if server is not running. */\n private runtimeFilePath: string | null = null;\n\n constructor(registry: Registry, options?: ReflectionServerOptions) {\n this.registry = registry;\n this.options = {\n port: 3100,\n bodyLimit: '30mb',\n configuredEnvs: ['dev'],\n ...options,\n };\n }\n\n /**\n * Finds a free port to run the server on based on the original chosen port and environment.\n */\n async findPort(): Promise<number> {\n const chosenPort = this.options.port!;\n const freePort = await getPort({\n port: makeRange(chosenPort, chosenPort + 100),\n });\n if (freePort !== chosenPort) {\n logger.warn(\n `Port ${chosenPort} is already in use, using next available port ${freePort} instead.`\n );\n }\n return freePort;\n }\n\n /**\n * Starts the server.\n *\n * The server will be registered to be shut down on process exit.\n */\n async start() {\n const server = express();\n\n server.use(express.json({ limit: this.options.bodyLimit }));\n server.use((req, res, next) => {\n res.header('x-genkit-version', GENKIT_VERSION);\n next();\n });\n\n server.get('/api/__health', async (_, response) => {\n await this.registry.listActions();\n response.status(200).send('OK');\n });\n\n server.get('/api/__quitquitquit', async (_, response) => {\n logger.debug('Received quitquitquit');\n response.status(200).send('OK');\n await this.stop();\n });\n\n server.get('/api/actions', async (_, response, next) => {\n logger.debug('Fetching actions.');\n try {\n const actions = await this.registry.listResolvableActions();\n const convertedActions = {};\n Object.keys(actions).forEach((key) => {\n const action = actions[key];\n convertedActions[key] = {\n key,\n name: action.name,\n description: action.description,\n metadata: action.metadata,\n };\n if (action.inputSchema || action.inputJsonSchema) {\n convertedActions[key].inputSchema = toJsonSchema({\n schema: action.inputSchema,\n jsonSchema: action.inputJsonSchema,\n });\n }\n if (action.outputSchema || action.outputJsonSchema) {\n convertedActions[key].outputSchema = toJsonSchema({\n schema: action.outputSchema,\n jsonSchema: action.outputJsonSchema,\n });\n }\n });\n response.send(convertedActions);\n } catch (err) {\n const { message, stack } = err as Error;\n next({ message, stack });\n }\n });\n\n server.post('/api/runAction', async (request, response, next) => {\n const { key, input, context, telemetryLabels } = request.body;\n const { stream } = request.query;\n logger.debug(`Running action \\`${key}\\` with stream=${stream}...`);\n try {\n const action = await this.registry.lookupAction(key);\n if (!action) {\n response.status(404).send(`action ${key} not found`);\n return;\n }\n if (stream === 'true') {\n try {\n const callback = (chunk) => {\n response.write(JSON.stringify(chunk) + '\\n');\n };\n const result = await action.run(input, {\n context,\n onChunk: callback,\n telemetryLabels,\n });\n await flushTracing();\n response.write(\n JSON.stringify({\n result: result.result,\n telemetry: {\n traceId: result.telemetry.traceId,\n },\n } as RunActionResponse)\n );\n response.end();\n } catch (err) {\n const { message, stack } = err as Error;\n // since we're streaming, we must do special error handling here -- the headers are already sent.\n const errorResponse: Status = {\n code: StatusCodes.INTERNAL,\n message,\n details: {\n stack,\n },\n };\n if ((err as any).traceId) {\n errorResponse.details.traceId = (err as any).traceId;\n }\n response.write(\n JSON.stringify({\n error: errorResponse,\n } as RunActionResponse)\n );\n response.end();\n }\n } else {\n const result = await action.run(input, { context, telemetryLabels });\n await flushTracing();\n response.send({\n result: result.result,\n telemetry: {\n traceId: result.telemetry.traceId,\n },\n } as RunActionResponse);\n }\n } catch (err) {\n const { message, stack, traceId } = err as any;\n next({ message, stack, traceId });\n }\n });\n\n server.get('/api/envs', async (_, response) => {\n response.json(this.options.configuredEnvs);\n });\n\n server.post('/api/notify', async (request, response) => {\n const { telemetryServerUrl, reflectionApiSpecVersion } = request.body;\n if (!process.env.GENKIT_TELEMETRY_SERVER) {\n if (typeof telemetryServerUrl === 'string') {\n setTelemetryServerUrl(telemetryServerUrl);\n logger.debug(\n `Connected to telemetry server on ${telemetryServerUrl}`\n );\n }\n }\n if (reflectionApiSpecVersion !== GENKIT_REFLECTION_API_SPEC_VERSION) {\n if (\n !reflectionApiSpecVersion ||\n reflectionApiSpecVersion < GENKIT_REFLECTION_API_SPEC_VERSION\n ) {\n logger.warn(\n 'WARNING: Genkit CLI version may be outdated. Please update `genkit-cli` to the latest version.'\n );\n } else {\n logger.warn(\n 'Genkit CLI is newer than runtime library. Some feature may not be supported. ' +\n 'Consider upgrading your runtime library version (debug info: expected ' +\n `${GENKIT_REFLECTION_API_SPEC_VERSION}, got ${reflectionApiSpecVersion}).`\n );\n }\n }\n response.status(200).send('OK');\n });\n\n server.use((err, req, res, next) => {\n logger.error(err.stack);\n const error = err as Error;\n const { message, stack } = error;\n const errorResponse: Status = {\n code: StatusCodes.INTERNAL,\n message,\n details: {\n stack,\n },\n };\n if (err.traceId) {\n errorResponse.details.traceId = err.traceId;\n }\n res.status(500).json(errorResponse);\n });\n\n this.port = await this.findPort();\n this.server = server.listen(this.port, async () => {\n logger.debug(\n `Reflection server (${process.pid}) running on http://localhost:${this.port}`\n );\n ReflectionServer.RUNNING_SERVERS.push(this);\n await this.writeRuntimeFile();\n });\n }\n\n /**\n * Stops the server and removes it from the list of running servers to clean up on exit.\n */\n async stop(): Promise<void> {\n if (!this.server) {\n return;\n }\n return new Promise<void>(async (resolve, reject) => {\n await this.cleanupRuntimeFile();\n this.server!.close(async (err) => {\n if (err) {\n logger.error(\n `Error shutting down reflection server on port ${this.port}: ${err}`\n );\n reject(err);\n }\n const index = ReflectionServer.RUNNING_SERVERS.indexOf(this);\n if (index > -1) {\n ReflectionServer.RUNNING_SERVERS.splice(index, 1);\n }\n logger.debug(\n `Reflection server on port ${this.port} has successfully shut down.`\n );\n this.port = null;\n this.server = null;\n resolve();\n });\n });\n }\n\n /**\n * Writes the runtime file to the project root.\n */\n private async writeRuntimeFile() {\n try {\n const rootDir = await findProjectRoot();\n const runtimesDir = path.join(rootDir, '.genkit', 'runtimes');\n const date = new Date();\n const time = date.getTime();\n const timestamp = date.toISOString();\n const runtimeId = `${process.pid}${\n this.port !== null ? `-${this.port}` : ''\n }`;\n this.runtimeFilePath = path.join(\n runtimesDir,\n `${runtimeId}-${time}.json`\n );\n const fileContent = JSON.stringify(\n {\n id: process.env.GENKIT_RUNTIME_ID || runtimeId,\n pid: process.pid,\n name: this.options.name,\n reflectionServerUrl: `http://localhost:${this.port}`,\n timestamp,\n genkitVersion: `nodejs/${GENKIT_VERSION}`,\n reflectionApiSpecVersion: GENKIT_REFLECTION_API_SPEC_VERSION,\n },\n null,\n 2\n );\n await fs.mkdir(runtimesDir, { recursive: true });\n await fs.writeFile(this.runtimeFilePath, fileContent, 'utf8');\n logger.debug(`Runtime file written: ${this.runtimeFilePath}`);\n } catch (error) {\n logger.error(`Error writing runtime file: ${error}`);\n }\n }\n\n /**\n * Cleans up the port file.\n */\n private async cleanupRuntimeFile() {\n if (!this.runtimeFilePath) {\n return;\n }\n try {\n const fileContent = await fs.readFile(this.runtimeFilePath, 'utf8');\n const data = JSON.parse(fileContent);\n if (data.pid === process.pid) {\n await fs.unlink(this.runtimeFilePath);\n logger.debug(`Runtime file cleaned up: ${this.runtimeFilePath}`);\n }\n } catch (error) {\n logger.error(`Error cleaning up runtime file: ${error}`);\n }\n }\n\n /**\n * Stops all running reflection servers.\n */\n static async stopAll() {\n return Promise.all(\n ReflectionServer.RUNNING_SERVERS.map((server) => server.stop())\n );\n }\n}\n\n/**\n * Finds the project root by looking for a `package.json` file.\n */\nasync function findProjectRoot(): Promise<string> {\n let currentDir = process.cwd();\n while (currentDir !== path.parse(currentDir).root) {\n const packageJsonPath = path.join(currentDir, 'package.json');\n try {\n await fs.access(packageJsonPath);\n return currentDir;\n } catch {\n currentDir = path.dirname(currentDir);\n }\n }\n throw new Error('Could not find project root (package.json not found)');\n}\n\n// TODO: Verify that this works.\nif (typeof module !== 'undefined' && 'hot' in module) {\n (module as any).hot.accept();\n (module as any).hot.dispose(async () => {\n logger.debug('Cleaning up reflection server(s) before module reload...');\n await ReflectionServer.stopAll();\n });\n}\n"],"mappings":"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","names":[]}