{"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.mjs';\nimport { getGenkitRuntimeConfig } from './config.mjs';\nimport { GENKIT_REFLECTION_API_SPEC_VERSION, GENKIT_VERSION } from './index.mjs';\nimport { logger } from './logging.mjs';\nimport type { Registry } from './registry.mjs';\nimport { toJsonSchema } from './schema.mjs';\nimport { flushTracing, setTelemetryServerUrl } from './tracing.mjs';\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  private v2Server: any | 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  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    if (getGenkitRuntimeConfig().sandboxedRuntime) {\n      logger.debug(\n        'Skipping ReflectionServer start: not supported in sandboxed runtime.'\n      );\n      return;\n    }\n    if (process.env.GENKIT_REFLECTION_V2_SERVER) {\n      const { ReflectionServerV2 } = await import('./reflection-v2.mjs');\n      this.v2Server = new ReflectionServerV2(this.registry, {\n        configuredEnvs: this.options.configuredEnvs,\n        name: this.options.name,\n        url: process.env.GENKIT_REFLECTION_V2_SERVER,\n      });\n      await this.v2Server.start();\n      ReflectionServer.RUNNING_SERVERS.push(this);\n      return;\n    }\n\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/values', async (req, response, next) => {\n      logger.debug('Fetching values.');\n      try {\n        const type = req.query.type;\n        if (!type) {\n          response.status(400).send('Query parameter \"type\" is required.');\n          return;\n        }\n        if (type !== 'defaultModel' && type !== 'middleware') {\n          response\n            .status(400)\n            .send(\n              `'type' ${type} is not supported. Only 'defaultModel' and 'middleware' are supported`\n            );\n          return;\n        }\n        const values = await this.registry.listValues(type as string);\n        const mappedValues: Record<string, any> = {};\n        for (const [key, value] of Object.entries(values)) {\n          mappedValues[key] =\n            value &&\n            (value as any).toJson &&\n            typeof (value as any).toJson === 'function'\n              ? (value as any).toJson()\n              : value;\n        }\n        response.send(mappedValues);\n      } catch (err) {\n        const { message, stack } = err as Error;\n        next({ message, stack });\n      }\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: 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: 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\n      try {\n        await this.registry.listActions();\n        await this.writeRuntimeFile();\n      } catch (e) {\n        logger.error(`Error initializing plugins: ${e}`);\n        try {\n          await this.stop();\n        } catch (err) {\n          logger.error(`Failed to stop server gracefully: ${err}`);\n        }\n      }\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.v2Server) {\n      await this.v2Server.stop();\n      const index = ReflectionServer.RUNNING_SERVERS.indexOf(this);\n      if (index > -1) {\n        ReflectionServer.RUNNING_SERVERS.splice(index, 1);\n      }\n      return;\n    }\n\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":[]}