@genkit-ai/core
Version:
Genkit AI framework core libraries.
1 lines • 25.9 kB
Source Map (JSON)
{"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 * Checks if an error is an AbortError (from AbortController.abort()).\n */\nfunction isAbortError(err: any): boolean {\n return (\n err?.name === 'AbortError' ||\n (typeof DOMException !== 'undefined' &&\n err instanceof DOMException &&\n err.name === 'AbortError')\n );\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 /** Map of active actions indexed by trace ID for cancellation support. */\n private activeActions = new Map<\n string,\n {\n abortController: AbortController;\n startTime: Date;\n }\n >();\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 get runtimeId() {\n return `${process.pid}${this.port !== null ? `-${this.port}` : ''}`;\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 (req, response) => {\n if (req.query['id'] && req.query['id'] !== this.runtimeId) {\n response.status(503).send('Invalid runtime ID');\n return;\n }\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 const abortController = new AbortController();\n let traceId: string | undefined;\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 // Set up onTraceStart callback to send trace ID in headers early.\n // This fires once for the root action span, before any streaming chunks\n // or final result are returned.\n const onTraceStartCallback = ({\n traceId: tid,\n spanId,\n }: {\n traceId: string;\n spanId: string;\n }) => {\n traceId = tid; // Update traceId for cleanup later\n this.activeActions.set(tid, {\n abortController,\n startTime: new Date(),\n });\n response.setHeader('X-Genkit-Trace-Id', tid);\n response.setHeader('X-Genkit-Span-Id', spanId);\n response.setHeader('X-Genkit-Version', GENKIT_VERSION);\n if (stream === 'true') {\n response.setHeader('Content-Type', 'text/plain');\n response.setHeader('Transfer-Encoding', 'chunked');\n } else {\n response.setHeader('Content-Type', 'application/json');\n // Force chunked encoding so we can flush headers early\n response.setHeader('Transfer-Encoding', 'chunked');\n }\n response.statusCode = 200;\n response.flushHeaders();\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 onTraceStart: onTraceStartCallback,\n abortSignal: abortController.signal,\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: isAbortError(err)\n ? StatusCodes.CANCELLED\n : StatusCodes.INTERNAL,\n message: isAbortError(err) ? 'Action was cancelled' : 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 // Non-streaming: send JSON response\n const result = await action.run(input, {\n context,\n telemetryLabels,\n onTraceStart: onTraceStartCallback,\n abortSignal: abortController.signal,\n });\n await flushTracing();\n response.end(\n JSON.stringify({\n result: result.result,\n telemetry: {\n traceId: result.telemetry.traceId,\n },\n } as RunActionResponse)\n );\n }\n } catch (err) {\n const { message, stack } = err as Error;\n const errorResponse: Status = {\n code: isAbortError(err)\n ? StatusCodes.CANCELLED\n : StatusCodes.INTERNAL,\n message: isAbortError(err) ? 'Action was cancelled' : message,\n details: { stack, traceId: (err as any).traceId || traceId },\n };\n if (response.headersSent) {\n // Headers already sent via onTraceStart, must send error in response body\n response.end(\n JSON.stringify({ error: errorResponse } as RunActionResponse)\n );\n } else {\n // Headers not sent yet, use standard error handling\n next({ message, stack });\n }\n } finally {\n if (traceId) {\n this.activeActions.delete(traceId);\n }\n }\n });\n\n server.post('/api/cancelAction', async (request, response) => {\n const { traceId } = request.body;\n\n if (!traceId || typeof traceId !== 'string') {\n response.status(400).json({ error: 'traceId is required' });\n return;\n }\n\n const activeAction = this.activeActions.get(traceId);\n\n if (activeAction) {\n activeAction.abortController.abort();\n this.activeActions.delete(traceId);\n response.status(200).json({ message: 'Action cancelled' });\n } else {\n response.status(404).json({\n message: 'Action not found or already completed',\n });\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\n // Headers may have been sent already (via onTraceStart), so check before setting status\n res.status(200).end(JSON.stringify({ error: 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 this.runtimeFilePath = path.join(\n runtimesDir,\n `${this.runtimeId}-${time}.json`\n );\n const fileContent = JSON.stringify(\n {\n id: process.env.GENKIT_RUNTIME_ID || this.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":[]}