@botpress/adk-cli
Version:
Command-line interface for the Botpress Agent Development Kit (ADK)
114 lines (111 loc) • 4.02 kB
JavaScript
// @bun
import {
AdkError
} from "./chunk-p0hjqn4r.js";
// src/utils/dev-server.ts
import { readFileSync, existsSync, accessSync } from "fs";
import { dirname, join, parse, resolve } from "path";
import { homedir } from "os";
var DEFAULT_DEV_SERVER_PORT = 3001;
var HEALTH_TIMEOUT_MS = 2000;
var REQUEST_TIMEOUT_MS = 5000;
var CONSOLE_PORT_FILE = join(homedir(), ".adk", "console.port");
var DEV_SERVER_DOWN_ERROR = "Dev server not running \u2014 start with `adk dev`";
function getDevServerUrl() {
if (existsSync(CONSOLE_PORT_FILE)) {
try {
const port = parseInt(readFileSync(CONSOLE_PORT_FILE, "utf-8").trim(), 10);
if (port > 0)
return `http://localhost:${port}`;
} catch {}
}
return `http://localhost:${DEFAULT_DEV_SERVER_PORT}`;
}
function resolveAgentRoot(cwd = process.cwd()) {
let currentPath = resolve(cwd);
const root = parse(currentPath).root;
while (currentPath !== root) {
try {
accessSync(join(currentPath, "agent.config.ts"));
return currentPath;
} catch {
currentPath = dirname(currentPath);
}
}
return null;
}
function buildDevServerHeaders(agentRoot) {
return agentRoot ? { "X-Agent-Path": agentRoot } : {};
}
var cachedHeaders;
function getDevServerHeaders() {
if (cachedHeaders === undefined) {
cachedHeaders = buildDevServerHeaders(resolveAgentRoot());
}
return cachedHeaders;
}
async function fetchJson(pathname, headers = getDevServerHeaders(), timeoutMs = REQUEST_TIMEOUT_MS) {
const response = await fetch(`${getDevServerUrl()}${pathname}`, {
headers,
signal: AbortSignal.timeout(timeoutMs)
});
if (!response.ok) {
throw new AdkError({
code: "DEV_SERVER_FETCH",
message: `Failed to fetch ${pathname} from dev server (${response.status} ${response.statusText})`,
expected: true,
details: { status: response.status }
});
}
return await response.json();
}
async function assertDevServerRunning(headers = getDevServerHeaders()) {
try {
const response = await fetch(`${getDevServerUrl()}/api/health`, {
headers,
signal: AbortSignal.timeout(HEALTH_TIMEOUT_MS)
});
if (!response.ok) {
throw new AdkError({ code: "DEV_SERVER_DOWN", message: DEV_SERVER_DOWN_ERROR, expected: true });
}
} catch {
throw new AdkError({ code: "DEV_SERVER_DOWN", message: DEV_SERVER_DOWN_ERROR, expected: true });
}
}
async function getDevServerConfig(headers = getDevServerHeaders()) {
await assertDevServerRunning(headers);
return fetchJson("/api/config", headers);
}
async function getDevServerAgent(headers = getDevServerHeaders()) {
await assertDevServerRunning(headers);
return fetchJson("/api/agent", headers);
}
function hasWorkflowInput(inputSchema) {
const required = Array.isArray(inputSchema.required) ? inputSchema.required.length > 0 : false;
const properties = inputSchema.properties ? Object.keys(inputSchema.properties).length > 0 : false;
return required || properties;
}
function normalizeDevServerWorkflow(workflow) {
const inputSchema = workflow.input ?? { type: "object", properties: {} };
return {
name: workflow.name,
description: workflow.description,
hasSchedule: Boolean(workflow.schedule),
hasInput: hasWorkflowInput(inputSchema),
schedule: workflow.schedule,
timeout: workflow.timeout,
inputSchema
};
}
function normalizeDevServerWorkflows(workflows) {
return (workflows ?? []).map(normalizeDevServerWorkflow);
}
async function listDevServerWorkflows(headers = getDevServerHeaders()) {
const agent = await getDevServerAgent(headers);
return normalizeDevServerWorkflows(agent.workflows);
}
async function getDevServerWorkflow(name, headers = getDevServerHeaders()) {
const workflows = await listDevServerWorkflows(headers);
return workflows.find((workflow) => workflow.name === name) ?? null;
}
export { DEV_SERVER_DOWN_ERROR, getDevServerUrl, resolveAgentRoot, buildDevServerHeaders, getDevServerConfig, listDevServerWorkflows, getDevServerWorkflow };