@genkit-ai/core
Version:
Genkit AI framework core libraries.
293 lines • 9.89 kB
JavaScript
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