@copilotkit/runtime
Version:
<img src="https://github.com/user-attachments/assets/0a6b64d9-e193-4940-a3f6-60334ac34084" alt="banner" style="border-radius: 12px; border: 2px solid #d6d4fa;" />
87 lines (85 loc) • 4.12 kB
JavaScript
import "reflect-metadata";
import { createCopilotEndpointSingleRoute } from "../../../v2/runtime/endpoints/hono-single.mjs";
import telemetryClient, { getRuntimeInstanceTelemetryInfo } from "../../telemetry-client.mjs";
import { getCommonConfig } from "../shared.mjs";
import { getFullUrl, isDisturbedOrLockedError, isStreamConsumed, nodeStreamToReadableStream, readableStreamToNodeStream, synthesizeBodyFromParsedBody, toHeaders } from "./request-handler.mjs";
//#region src/lib/integrations/node-http/index.ts
function copilotRuntimeNodeHttpEndpoint(options) {
const commonConfig = getCommonConfig(options);
telemetryClient.setGlobalProperties({ runtime: { framework: "node-http" } });
if (options.properties?._copilotkit) telemetryClient.setGlobalProperties({ _copilotkit: options.properties._copilotkit });
telemetryClient.capture("oss.runtime.instance_created", getRuntimeInstanceTelemetryInfo(options));
const logger = commonConfig.logging;
logger.debug("Creating Node HTTP endpoint");
const serviceAdapter = options.serviceAdapter;
if (serviceAdapter) options.runtime.handleServiceAdapter(serviceAdapter);
const honoApp = createCopilotEndpointSingleRoute({
runtime: options.runtime.instance,
basePath: options.baseUrl ?? options.endpoint,
...options.cors && { cors: options.cors }
});
const handle = async function handler(req, res) {
const url = getFullUrl(req);
const hasBody = req.method !== "GET" && req.method !== "HEAD";
const baseHeaders = toHeaders(req.headers);
const parsedBody = req.body;
const streamConsumed = isStreamConsumed(req) || parsedBody !== void 0;
const canStream = hasBody && !streamConsumed;
let requestBody = void 0;
let useDuplex = false;
if (hasBody && canStream) {
requestBody = nodeStreamToReadableStream(req);
useDuplex = true;
}
if (hasBody && streamConsumed) if (parsedBody !== void 0) {
const synthesized = synthesizeBodyFromParsedBody(parsedBody, baseHeaders);
requestBody = synthesized.body ?? void 0;
baseHeaders.delete("content-length");
if (synthesized.contentType) baseHeaders.set("content-type", synthesized.contentType);
logger.debug("Request stream already consumed; using parsed req.body to rebuild request.");
} else {
logger.warn("Request stream consumed with no available body; sending empty payload.");
requestBody = void 0;
}
const buildRequest = (body, headers, duplex) => new Request(url, {
method: req.method,
headers,
body,
duplex: duplex ? "half" : void 0
});
let response;
try {
response = await honoApp.fetch(buildRequest(requestBody, baseHeaders, useDuplex));
} catch (error) {
if (isDisturbedOrLockedError(error) && hasBody) {
logger.warn("Encountered disturbed/locked request body; rebuilding request using parsed body or empty payload.");
const fallbackHeaders = new Headers(baseHeaders);
let fallbackBody;
if (parsedBody !== void 0) {
const synthesized = synthesizeBodyFromParsedBody(parsedBody, fallbackHeaders);
fallbackBody = synthesized.body ?? void 0;
fallbackHeaders.delete("content-length");
if (synthesized.contentType) fallbackHeaders.set("content-type", synthesized.contentType);
} else fallbackBody = void 0;
response = await honoApp.fetch(buildRequest(fallbackBody, fallbackHeaders, false));
} else throw error;
}
res.statusCode = response.status;
response.headers.forEach((value, key) => {
res.setHeader(key, value);
});
if (response.body) readableStreamToNodeStream(response.body).pipe(res);
else res.end();
};
function isRequestLike(obj) {
return obj instanceof Request || typeof obj === "object" && obj !== null && "url" in obj && "method" in obj && "headers" in obj && typeof obj.url === "string" && typeof obj.method === "string";
}
return function(reqOrRequest, res) {
if (isRequestLike(reqOrRequest) && !res) return honoApp.fetch(reqOrRequest);
if (!res) throw new TypeError("ServerResponse is required for Node HTTP requests");
return handle(reqOrRequest, res);
};
}
//#endregion
export { copilotRuntimeNodeHttpEndpoint };
//# sourceMappingURL=index.mjs.map