UNPKG

@genkit-ai/core

Version:

Genkit AI framework core libraries.

293 lines 9.89 kB
import { __async } from "./chunk-XEFTB2OF.mjs"; import express from "express"; import z from "zod"; import { runWithStreamingCallback, StatusCodes } from "./action.js"; import { config } from "./config.js"; import { logger } from "./logging.js"; import * as registry from "./registry.js"; import { toJsonSchema } from "./schema.js"; import { cleanUpTracing, flushTracing, newTrace, setCustomMetadataAttribute } from "./tracing.js"; const RunActionResponseSchema = z.object({ result: z.unknown().optional(), error: z.unknown().optional(), telemetry: z.object({ traceId: z.string().optional() }).optional() }); let server; const GLOBAL_REFLECTION_API_PORT_KEY = "genkit__reflectionApiPort"; function startReflectionApi(port) { return __async(this, null, function* () { if (global[GLOBAL_REFLECTION_API_PORT_KEY] !== void 0) { logger.warn( `Reflection API is already running on port ${global[GLOBAL_REFLECTION_API_PORT_KEY]}` ); return; } if (!port) { port = Number(process.env.GENKIT_REFLECTION_PORT) || 3100; } global[GLOBAL_REFLECTION_API_PORT_KEY] = port; const api = express(); api.use(express.json({ limit: "30mb" })); api.get("/api/__health", (_, response) => __async(this, null, function* () { yield registry.listActions(); response.status(200).send("OK"); })); api.get("/api/__quitquitquit", (_, response) => __async(this, null, function* () { logger.debug("Received quitquitquit"); response.status(200).send("OK"); yield stopReflectionApi(); })); api.get("/api/actions", (_, response, next) => __async(this, null, function* () { logger.debug("Fetching actions."); const actions = yield registry.listActions(); const convertedActions = {}; Object.keys(actions).forEach((key) => { const action = actions[key].__action; convertedActions[key] = { key, name: action.name, description: action.description, metadata: action.metadata }; if (action.inputSchema || action.inputJsonSchema) { convertedActions[key].inputSchema = toJsonSchema({ schema: action.inputSchema, jsonSchema: action.inputJsonSchema }); } if (action.outputSchema || action.outputJsonSchema) { convertedActions[key].outputSchema = toJsonSchema({ schema: action.outputSchema, jsonSchema: action.outputJsonSchema }); } }); try { response.send(convertedActions); } catch (err) { const { message, stack } = err; next({ message, stack }); } })); api.post("/api/runAction", (request, response, next) => __async(this, null, function* () { const { key, input } = request.body; const { stream } = request.query; logger.debug(`Running action \`${key}\`...`); let traceId; try { const action = yield registry.lookupAction(key); if (!action) { response.status(404).send(`action ${key} not found`); return; } if (stream === "true") { const result = yield newTrace( { name: "dev-run-action-wrapper" }, (_, span) => __async(this, null, function* () { setCustomMetadataAttribute("genkit-dev-internal", "true"); traceId = span.spanContext().traceId; return yield runWithStreamingCallback( (chunk) => { response.write(JSON.stringify(chunk) + "\n"); }, () => __async(this, null, function* () { return yield action(input); }) ); }) ); yield flushTracing(); response.write( JSON.stringify({ result, telemetry: traceId ? { traceId } : void 0 }) ); response.end(); } else { const result = yield newTrace( { name: "dev-run-action-wrapper" }, (_, span) => __async(this, null, function* () { setCustomMetadataAttribute("genkit-dev-internal", "true"); traceId = span.spanContext().traceId; return yield action(input); }) ); response.send({ result, telemetry: traceId ? { traceId } : void 0 }); } } catch (err) { const { message, stack } = err; next({ message, stack, traceId }); } })); api.get("/api/envs", (_, response) => __async(this, null, function* () { response.json(config.configuredEnvs); })); api.get("/api/envs/:env/traces/:traceId", (request, response) => __async(this, null, function* () { const { env, traceId } = request.params; logger.debug(`Fetching trace \`${traceId}\` for env \`${env}\`.`); const tracestore = yield registry.lookupTraceStore(env); if (!tracestore) { return response.status(500).send({ code: StatusCodes.FAILED_PRECONDITION, message: `${env} trace store not found` }); } try { const trace = yield tracestore == null ? void 0 : tracestore.load(traceId); return trace ? response.json(trace) : response.status(404).send({ code: StatusCodes.NOT_FOUND, message: `Trace with traceId=${traceId} not found.` }); } catch (err) { const error = err; const { message, stack } = error; const errorResponse = { code: StatusCodes.INTERNAL, message, details: { stack } }; return response.status(500).json(errorResponse); } })); api.get("/api/envs/:env/traces", (request, response, next) => __async(this, null, function* () { const { env } = request.params; const { limit, continuationToken } = request.query; logger.debug(`Fetching traces for env \`${env}\`.`); const tracestore = yield registry.lookupTraceStore(env); if (!tracestore) { return response.status(500).send({ code: StatusCodes.FAILED_PRECONDITION, message: `${env} trace store not found` }); } try { response.json( yield tracestore.list({ limit: limit ? parseInt(limit.toString()) : void 0, continuationToken: continuationToken ? continuationToken.toString() : void 0 }) ); } catch (err) { const { message, stack } = err; next({ message, stack }); } })); api.get( "/api/envs/:env/flowStates/:flowId", (request, response, next) => __async(this, null, function* () { const { env, flowId } = request.params; logger.debug(`Fetching flow state \`${flowId}\` for env \`${env}\`.`); const flowStateStore = yield registry.lookupFlowStateStore(env); if (!flowStateStore) { return response.status(500).send({ code: StatusCodes.FAILED_PRECONDITION, message: `${env} flow state store not found` }); } try { response.json(yield flowStateStore == null ? void 0 : flowStateStore.load(flowId)); } catch (err) { const { message, stack } = err; next({ message, stack }); } }) ); api.get("/api/envs/:env/flowStates", (request, response, next) => __async(this, null, function* () { const { env } = request.params; const { limit, continuationToken } = request.query; logger.debug(`Fetching traces for env \`${env}\`.`); const flowStateStore = yield registry.lookupFlowStateStore(env); if (!flowStateStore) { return response.status(500).send({ code: StatusCodes.FAILED_PRECONDITION, message: `${env} flow state store not found` }); } try { response.json( yield flowStateStore == null ? void 0 : flowStateStore.list({ limit: limit ? parseInt(limit.toString()) : void 0, continuationToken: continuationToken ? continuationToken.toString() : void 0 }) ); } catch (err) { const { message, stack } = err; next({ message, stack }); } })); api.use((err, req, res, next) => { logger.error(err.stack); const error = err; const { message, stack } = error; const errorResponse = { code: StatusCodes.INTERNAL, message, details: { stack } }; if (err.traceId) { errorResponse.details.traceId = err.traceId; } res.status(500).json(errorResponse); }); server = api.listen(port, () => { console.log(`Reflection API running on http://localhost:${port}`); }); server.on("error", (error) => { if (process.env.GENKIT_REFLECTION_ON_STARTUP_FAILURE === "ignore") { logger.warn( `Failed to start the Reflection API on port ${port}, ignoring the error.` ); logger.debug(error); } else { throw error; } }); process.on("SIGTERM", () => __async(this, null, function* () { return yield stopReflectionApi(); })); }); } function stopReflectionApi() { return __async(this, null, function* () { yield Promise.all([ new Promise((resolve) => { if (server) { server.close(() => { logger.info("Reflection API has succesfully shut down."); resolve(); }); } else { resolve(); } }), cleanUpTracing() ]); process.exit(0); }); } export { RunActionResponseSchema, startReflectionApi }; //# sourceMappingURL=reflectionApi.mjs.map