// @bun
import {
  isFeatureEnabled
} from "./chunk-sb6ft3r2.js";
import {
  createCliLogger
} from "./chunk-t993tmz7.js";
import {
  AdkError,
  ConfigManager,
  ConfigWriter,
  DEPLOYED_AGENT_MANIFEST_FILE_KEY,
  DEPLOYED_AGENT_MANIFEST_TAGS,
  deployedAgentManifestSchema,
  getProjectClient
} from "./chunk-7krp2mgz.js";
import {
  ne
} from "./chunk-6w0knnta.js";
import {
  Uk
} from "./chunk-3xrpxgq4.js";

// src/server/utils/cors.ts
var LOCALHOST_PATTERN = /^https?:\/\/(localhost|127\.0\.0\.1|\[::1\])(:\d+)?$/;
function isAllowedOrigin(origin) {
  if (!origin)
    return false;
  return LOCALHOST_PATTERN.test(origin);
}
function getCorsHeaders(req) {
  const origin = req.headers.get("origin");
  if (!isAllowedOrigin(origin))
    return {};
  return {
    "Access-Control-Allow-Origin": origin,
    "Access-Control-Allow-Methods": "GET, POST, PUT, PATCH, DELETE, OPTIONS",
    "Access-Control-Allow-Headers": "Content-Type",
    "Access-Control-Expose-Headers": "X-ADK-DevConsole",
    Vary: "Origin"
  };
}
function handleCorsPreflightResponse(req) {
  return new Response(null, {
    headers: getCorsHeaders(req),
    status: 204
  });
}

// src/server/utils/timing.ts
var timingLogger = createCliLogger({ tag: "timing" });
var eventLoopLogger = createCliLogger({ tag: "event-loop" });
var DEFAULT_SLOW_REQUEST_MS = 1000;
var DEFAULT_EVENT_LOOP_LAG_MS = 500;
var EVENT_LOOP_SAMPLE_MS = 1000;
function thresholdFromEnv(name, fallback) {
  const raw = process.env[name];
  if (!raw)
    return fallback;
  const value = Number(raw);
  return Number.isFinite(value) && value >= 0 ? value : fallback;
}
var slowRequestThresholdMs = thresholdFromEnv("ADK_DEV_SLOW_REQUEST_MS", DEFAULT_SLOW_REQUEST_MS);
var eventLoopLagThresholdMs = thresholdFromEnv("ADK_DEV_EVENT_LOOP_LAG_MS", DEFAULT_EVENT_LOOP_LAG_MS);
async function withRequestTiming(label, operation) {
  const start = performance.now();
  try {
    return await operation();
  } finally {
    const duration = performance.now() - start;
    if (duration >= slowRequestThresholdMs) {
      timingLogger.warn(`${label} took ${Math.round(duration)}ms`);
    }
  }
}
function startEventLoopLagMonitor(label) {
  let previous = performance.now();
  const interval = setInterval(() => {
    const now = performance.now();
    const lag = now - previous - EVENT_LOOP_SAMPLE_MS;
    previous = now;
    if (lag >= eventLoopLagThresholdMs) {
      eventLoopLogger.warn(`${label} blocked for ${Math.round(lag)}ms`);
    }
  }, EVENT_LOOP_SAMPLE_MS);
  interval.unref?.();
  return () => clearInterval(interval);
}

// src/server/config.ts
import { EventEmitter } from "events";
var serverConfig;
var serverStartTime;
var devCommandStatus = "building";
var latestWorkerStats = null;
var agent0RuntimeClient = null;
var devBotRuntimeState = {
  running: false,
  port: null,
  url: null,
  botId: null
};
function getServerConfig() {
  return serverConfig;
}
function setServerConfig(config) {
  serverConfig = config;
}
function getServerStartTime() {
  return serverStartTime;
}
function setServerStartTime(time) {
  serverStartTime = time;
}
function getDevCommandStatus() {
  return devCommandStatus;
}
function setDevCommandStatus(status) {
  devCommandStatus = status;
}
function getLatestWorkerStats() {
  return latestWorkerStats;
}
function updateWorkerStats(stats) {
  latestWorkerStats = stats;
}
function getAgent0RuntimeClient() {
  return agent0RuntimeClient;
}
function setAgent0RuntimeClient(client) {
  agent0RuntimeClient = client;
}
var activeEnvironment = "dev";
function getActiveEnvironment() {
  return activeEnvironment;
}
function setActiveEnvironment(env) {
  activeEnvironment = env;
}
function getDevBotRuntimeState() {
  return devBotRuntimeState;
}
function setDevBotRuntimeState(state) {
  devBotRuntimeState = {
    ...devBotRuntimeState,
    ...state
  };
}
function resetDevBotRuntimeState() {
  devBotRuntimeState = {
    running: false,
    port: null,
    url: null,
    botId: null
  };
}
var serverEvents = new EventEmitter;
function emitSecretsValuesChanged() {
  serverEvents.emit("secrets:values-changed");
}
function onSecretsValuesChanged(listener) {
  serverEvents.on("secrets:values-changed", listener);
  return () => serverEvents.off("secrets:values-changed", listener);
}
function emitProjectReloaded() {
  serverEvents.emit("project:reloaded");
}
function onProjectReloaded(listener) {
  serverEvents.on("project:reloaded", listener);
  return () => serverEvents.off("project:reloaded", listener);
}

// src/server/utils/responses.ts
var JSON_HEADERS = {
  "Content-Type": "application/json"
};
function jsonResponse(data, status = 200) {
  return new Response(JSON.stringify(data), {
    status,
    headers: JSON_HEADERS
  });
}
function errorResponse(error, message, status = 500) {
  return jsonResponse({ error, message }, status);
}
function successResponse(data) {
  return jsonResponse(data, 200);
}

// src/server/handlers/feature-flags.ts
var UI_FLAGS = ["enable_agent_0", "enable_guided_setup"];
async function handleFeatureFlags() {
  const flags = {};
  for (const name of UI_FLAGS) {
    flags[name] = isFeatureEnabled(name, { email: "" });
  }
  return successResponse({ flags });
}

// src/server/prod-agent-metadata.ts
var MANIFEST_CACHE_TTL_MS = 15000;
var AGENT_NOT_DEPLOYED_MESSAGE = "Agent has not been deployed yet. Deploy with `adk deploy` to publish the production target.";

class ProdManifestService {
  cache = new Map;
  async getManifest(target) {
    const cacheKey = this.getCacheKey(target);
    const cached = this.cache.get(cacheKey);
    if (cached && Date.now() - cached.fetchedAt < MANIFEST_CACHE_TTL_MS) {
      return cached.manifest;
    }
    const client = this.makeClient(target);
    const file = await this.findManifestFile(client);
    if (!file.url) {
      throw new AdkError({
        code: "PROD_METADATA_INVALID",
        message: "Deployed ADK metadata file does not have a download URL."
      });
    }
    const response = await fetch(file.url);
    if (!response.ok) {
      throw new AdkError({
        code: "PROD_METADATA_INVALID",
        message: `Failed to download deployed ADK metadata: ${response.status} ${response.statusText}`
      });
    }
    const manifest = parseDeployedAgentManifest(await response.text());
    this.cache.set(cacheKey, { fetchedAt: Date.now(), manifest });
    return manifest;
  }
  clear(target) {
    if (!target) {
      this.cache.clear();
      return;
    }
    this.cache.delete(this.getCacheKey(target));
  }
  async findManifestFile(client) {
    try {
      const { file: file2 } = await client.getFile({ id: DEPLOYED_AGENT_MANIFEST_FILE_KEY });
      return file2;
    } catch {}
    const { files } = await client.listFiles({ tags: { ...DEPLOYED_AGENT_MANIFEST_TAGS } });
    const file = files.find((candidate) => candidate.key === DEPLOYED_AGENT_MANIFEST_FILE_KEY) ?? files[0];
    if (!file) {
      throw new AdkError({
        code: "AGENT_NOT_DEPLOYED",
        message: AGENT_NOT_DEPLOYED_MESSAGE,
        expected: true
      });
    }
    return file;
  }
  makeClient(target) {
    return new Uk({
      token: target.token,
      apiUrl: target.apiUrl,
      workspaceId: target.workspaceId,
      botId: target.botId,
      headers: { "x-multiple-integrations": "true" }
    });
  }
  getCacheKey(target) {
    return `${target.apiUrl}:${target.workspaceId}:${target.botId}`;
  }
}

class ProdAgentMetadataService {
  manifestService;
  constructor(manifestService = new ProdManifestService) {
    this.manifestService = manifestService;
  }
  async getAgentDefinition(target) {
    const manifest = await this.manifestService.getManifest(target);
    return manifestToAgentDefinition(manifest, target);
  }
}
var prodAgentMetadataService = new ProdAgentMetadataService;
function getLocalProdMetadataTarget(config) {
  const token = config.credentials.token;
  const apiUrl = config.credentials.apiUrl;
  const workspaceId = config.project?.agentInfo?.workspaceId ?? config.credentials.workspaceId;
  const botId = config.project?.agentInfo?.botId ?? config.credentials.prodBotId;
  if (!token || !apiUrl || !workspaceId || !botId) {
    return null;
  }
  return {
    token,
    apiUrl,
    workspaceId,
    botId,
    botName: config.project?.config?.name,
    agentPath: config.agentPath,
    devBotId: config.project?.agentInfo?.devId ?? config.credentials.devBotId
  };
}
function manifestToAgentDefinition(manifest, target) {
  return {
    name: manifest.agent.name ?? target.botName ?? "unknown",
    version: "0.0.0",
    description: manifest.agent.description,
    path: target.agentPath,
    agentInfo: {
      botId: target.botId,
      workspaceId: target.workspaceId,
      apiUrl: target.apiUrl,
      ...target.devBotId ? { devId: target.devBotId } : {}
    },
    workflows: manifest.primitives.workflows.map(toWorkflowDefinition),
    actions: manifest.primitives.actions.map(toDefinition),
    tables: manifest.primitives.tables.map(toDefinition),
    triggers: manifest.primitives.triggers.map(toDefinition),
    conversations: manifest.primitives.conversations.map(toDefinition),
    knowledge: manifest.primitives.knowledge.map(toDefinition)
  };
}
function toWorkflowDefinition(primitive) {
  return {
    ...primitive.definition,
    path: primitive.source.path,
    export: primitive.source.exportName
  };
}
function toDefinition(primitive) {
  return primitive.definition;
}
function parseDeployedAgentManifest(content) {
  let value;
  try {
    value = JSON.parse(content);
  } catch {
    throw new AdkError({
      code: "PROD_METADATA_INVALID",
      message: "Deployed ADK metadata is not valid JSON."
    });
  }
  const result = deployedAgentManifestSchema.safeParse(value);
  if (!result.success) {
    throw new AdkError({
      code: "PROD_METADATA_INVALID",
      message: `Invalid deployed ADK metadata: ${result.error.errors.map((e) => e.message).join(", ")}`
    });
  }
  return result.data;
}

// src/server/utils/validation.ts
function parseEnv(req) {
  const raw = new URL(req.url).searchParams.get("env");
  if (raw !== "dev" && raw !== "prod")
    return null;
  return raw;
}
function validateProject() {
  const serverConfig2 = getServerConfig();
  if (!serverConfig2.project) {
    return errorResponse("No project loaded", "Agent project not available", 500);
  }
  return null;
}
function validateCredentials() {
  const serverConfig2 = getServerConfig();
  if (!serverConfig2.credentials?.token) {
    return errorResponse("No credentials configured", "Bot credentials are required", 401);
  }
  return null;
}
function validateBotId(environment) {
  const environment_ = environment ?? getActiveEnvironment();
  const serverConfig2 = getServerConfig();
  const devId = serverConfig2.project?.agentInfo?.devId;
  const prodBotId = serverConfig2.project?.agentInfo?.botId;
  const targetBotId = environment_ === "prod" ? prodBotId : devId;
  if (!targetBotId) {
    return errorResponse("No bot ID configured", `No ${environment_ === "prod" ? "production" : "development"} bot ID found in agent.json`, 400);
  }
  return null;
}
function validateMethod(req, allowedMethod) {
  if (req.method !== allowedMethod) {
    return errorResponse("Method not allowed", `Only ${allowedMethod} requests are allowed`, 405);
  }
  return null;
}
function validateProjectAndCredentials() {
  return validateProject() || validateCredentials();
}
function getTargetBotId(environment) {
  const environment_ = environment ?? getActiveEnvironment();
  const serverConfig2 = getServerConfig();
  const devId = serverConfig2.project?.agentInfo?.devId;
  const prodBotId = serverConfig2.project?.agentInfo?.botId;
  return environment_ === "prod" ? prodBotId || null : devId || null;
}
function getScopedServerCredentials(botId) {
  const credentials = getServerConfig().credentials;
  return {
    token: credentials.token,
    apiUrl: credentials.apiUrl || "https://api.botpress.cloud",
    ...credentials.workspaceId ? { workspaceId: credentials.workspaceId } : {},
    botId
  };
}

// src/server/handlers/config-vars.ts
var { transforms } = ne;
var logger = createCliLogger({ tag: "config-vars" });
function getJsonSchemaType(prop) {
  if (typeof prop !== "object")
    return;
  return Array.isArray(prop.type) ? prop.type[0] : prop.type;
}
function getDevContext() {
  const serverConfig2 = getServerConfig();
  const project = serverConfig2.project;
  if (!project)
    return null;
  const schema = project.config?.configuration?.schema;
  if (!schema)
    return null;
  const botId = getTargetBotId("dev");
  if (!botId)
    return null;
  return { botId, schema };
}
async function fetchCloudConfiguration(botId, target) {
  const creds = target ?? getServerConfig().credentials;
  if (!creds?.token || !creds.apiUrl || !creds.workspaceId)
    return null;
  const client = await getProjectClient({
    credentials: {
      token: creds.token,
      apiUrl: creds.apiUrl,
      workspaceId: creds.workspaceId,
      botId
    },
    botId
  });
  const { bot } = await client.getBot({ id: botId });
  return {
    schema: bot.configuration?.schema,
    data: bot.configuration?.data ?? {}
  };
}
function createConfigManager(botId, target) {
  const creds = target ?? getServerConfig().credentials;
  if (!creds?.token || !creds.apiUrl) {
    return new ConfigManager(botId);
  }
  return new ConfigManager(botId, {
    credentials: {
      token: creds.token,
      apiUrl: creds.apiUrl,
      ...creds.workspaceId ? { workspaceId: creds.workspaceId } : {},
      botId
    }
  });
}
function getServerProdConfigTarget(prodBotId) {
  const creds = getServerConfig().credentials;
  if (!creds?.token || !creds.apiUrl || !creds.workspaceId)
    return null;
  return {
    token: creds.token,
    apiUrl: creds.apiUrl,
    workspaceId: creds.workspaceId,
    botId: prodBotId
  };
}
function hasCloudConfigurationSchema(schema) {
  return !!schema && Object.keys(schema).length > 0;
}
function reconstructZodFromCloud(cloudSchema) {
  try {
    const reconstructed = transforms.fromJSONSchema(cloudSchema);
    return reconstructed;
  } catch (error) {
    logger.warn(`Failed to reconstruct Zod schema from cloud JSON schema: ${error instanceof Error ? error.message : String(error)}`);
    return null;
  }
}
async function handleGetConfigVariables(req) {
  const env = parseEnv(req);
  if (!env) {
    return errorResponse("Invalid environment", 'env query param must be "dev" or "prod"', 400);
  }
  if (env === "dev") {
    const ctx = getDevContext();
    if (!ctx) {
      return successResponse({
        fields: [],
        valid: true,
        missing: [],
        source: "local"
      });
    }
    const configManager = createConfigManager(ctx.botId);
    const [fields, validation] = await Promise.all([
      configManager.describeSchema(ctx.schema),
      configManager.validate(ctx.schema)
    ]);
    return successResponse({
      fields,
      valid: validation.valid,
      missing: validation.missing,
      source: "local"
    });
  }
  const prodBotId = getTargetBotId("prod");
  if (!prodBotId) {
    return errorResponse("No bot ID configured", "No production bot ID found in agent.json", 400);
  }
  const target = getServerProdConfigTarget(prodBotId);
  if (!target) {
    return errorResponse("No credentials configured", "Bot credentials are required", 401);
  }
  return handleGetProdConfigVariables(target);
}
async function handlePutConfigVariables(req) {
  const env = parseEnv(req);
  if (!env) {
    return errorResponse("Invalid environment", 'env query param must be "dev" or "prod"', 400);
  }
  let body;
  try {
    body = await req.json();
  } catch {
    return errorResponse("Invalid JSON", "Request body must be valid JSON", 400);
  }
  if (env === "dev") {
    const ctx = getDevContext();
    if (!ctx) {
      return errorResponse("No configuration schema", "No configuration schema defined in agent.config.ts", 400);
    }
    const configManager = createConfigManager(ctx.botId);
    const results = {};
    for (const [key, value] of Object.entries(body)) {
      results[key] = await configManager.setWithValidation(key, value, ctx.schema);
    }
    return successResponse({ results, env });
  }
  const prodBotId = getTargetBotId("prod");
  if (!prodBotId) {
    return errorResponse("No bot ID configured", "No production bot ID found in agent.json", 400);
  }
  const target = getServerProdConfigTarget(prodBotId);
  if (!target) {
    return errorResponse("No credentials configured", "Bot credentials are required", 401);
  }
  return setProdConfigVariables(target, body);
}
async function handleGetProdConfigVariables(target) {
  try {
    const cloud = await fetchCloudConfiguration(target.botId, target);
    if (!cloud) {
      return errorResponse("No credentials configured", "Bot credentials are required", 401);
    }
    if (!hasCloudConfigurationSchema(cloud.schema)) {
      return successResponse({
        fields: [],
        valid: true,
        missing: [],
        source: "cloud",
        deployed: true,
        schemaMissing: true
      });
    }
    const zodSchema = reconstructZodFromCloud(cloud.schema);
    if (!zodSchema) {
      return errorResponse("Failed to parse deployed schema", "Deployed configuration schema could not be reconstructed", 500);
    }
    const configManager = createConfigManager(target.botId, target);
    const [fields, validation] = await Promise.all([
      configManager.describeSchema(zodSchema),
      configManager.validate(zodSchema)
    ]);
    return successResponse({
      fields,
      valid: validation.valid,
      missing: validation.missing,
      source: "cloud",
      deployed: true
    });
  } catch (error) {
    return errorResponse("Failed to load prod configuration", error instanceof Error ? error.message : "Unknown error", 500);
  }
}
async function handlePutProdConfigVariables(req, target) {
  let body;
  try {
    body = await req.json();
  } catch {
    return errorResponse("Invalid JSON", "Request body must be valid JSON", 400);
  }
  return setProdConfigVariables(target, body);
}
async function setProdConfigVariables(target, body) {
  let cloud;
  try {
    cloud = await fetchCloudConfiguration(target.botId, target);
  } catch (error) {
    return errorResponse("Failed to load prod configuration", error instanceof Error ? error.message : "Unknown error", 500);
  }
  if (!cloud) {
    return errorResponse("No credentials configured", "Bot credentials are required", 401);
  }
  if (!hasCloudConfigurationSchema(cloud.schema)) {
    return errorResponse("Deployed configuration has no schema", "Run `adk deploy` to publish a configuration schema first.", 400);
  }
  const zodSchema = reconstructZodFromCloud(cloud.schema);
  if (!zodSchema) {
    return errorResponse("Failed to parse deployed schema", "Deployed configuration schema could not be reconstructed", 500);
  }
  const configManager = createConfigManager(target.botId, target);
  const results = {};
  for (const [key, value] of Object.entries(body)) {
    results[key] = await configManager.setWithValidation(key, value, zodSchema);
  }
  return successResponse({ results, env: "prod" });
}
async function handlePatchConfigSchema(req) {
  const env = parseEnv(req);
  if (!env) {
    return errorResponse("Invalid environment", 'env query param must be "dev" or "prod"', 400);
  }
  if (env === "prod") {
    return errorResponse("schema_mutation_requires_deploy", "Prod schema changes must go through `adk deploy`.", 409);
  }
  const serverConfig2 = getServerConfig();
  if (!serverConfig2.agentPath) {
    return errorResponse("No agent path", "Agent path not configured", 400);
  }
  let updates;
  try {
    updates = await req.json();
  } catch {
    return errorResponse("Invalid JSON", "Request body must be valid JSON array", 400);
  }
  if (!Array.isArray(updates)) {
    return errorResponse("Invalid body", "Request body must be an array", 400);
  }
  try {
    const configWriter = new ConfigWriter(serverConfig2.agentPath);
    await configWriter.updateConfiguration(updates);
    return successResponse({ success: true });
  } catch (error) {
    return errorResponse("Update failed", error instanceof Error ? error.message : "Unknown error", 500);
  }
}
async function handleGetConfigSchemaDiff() {
  const serverConfig2 = getServerConfig();
  const devZod = serverConfig2.project?.config?.configuration?.schema;
  const prodBotId = getTargetBotId("prod");
  if (!prodBotId) {
    return successResponse({
      deployed: false,
      schemaMissing: false,
      onlyInDev: [],
      onlyInProd: [],
      typeMismatches: []
    });
  }
  let devSchema = { type: "object", properties: {}, required: [] };
  if (devZod) {
    try {
      devSchema = devZod.toJSONSchema();
    } catch (error) {
      return errorResponse("Failed to serialise dev configuration schema", error instanceof Error ? error.message : "Unknown error", 500);
    }
  }
  let cloud;
  try {
    cloud = await fetchCloudConfiguration(prodBotId);
  } catch (error) {
    return errorResponse("Failed to load prod configuration", error instanceof Error ? error.message : "Unknown error", 500);
  }
  if (!cloud) {
    return errorResponse("No credentials configured", "Bot credentials are required", 401);
  }
  const prodSchema = hasCloudConfigurationSchema(cloud.schema) ? cloud.schema : undefined;
  const devProps = devSchema.properties ?? {};
  const prodProps = prodSchema?.properties ?? {};
  const devKeys = new Set(Object.keys(devProps));
  const prodKeys = new Set(Object.keys(prodProps));
  const onlyInDev = [...devKeys].filter((k) => !prodKeys.has(k));
  const onlyInProd = [...prodKeys].filter((k) => !devKeys.has(k));
  const typeMismatches = [];
  for (const key of devKeys) {
    if (!prodKeys.has(key))
      continue;
    const d = getJsonSchemaType(devProps[key]);
    const p = getJsonSchemaType(prodProps[key]);
    if (d !== p) {
      typeMismatches.push({ key, devType: d, prodType: p });
    }
  }
  return successResponse({
    deployed: true,
    schemaMissing: !prodSchema,
    onlyInDev,
    onlyInProd,
    typeMismatches
  });
}

export { getCorsHeaders, handleCorsPreflightResponse, withRequestTiming, startEventLoopLagMonitor, jsonResponse, errorResponse, successResponse, prodAgentMetadataService, getLocalProdMetadataTarget, getServerConfig, setServerConfig, getServerStartTime, setServerStartTime, getDevCommandStatus, setDevCommandStatus, getLatestWorkerStats, updateWorkerStats, getAgent0RuntimeClient, setAgent0RuntimeClient, getActiveEnvironment, setActiveEnvironment, getDevBotRuntimeState, setDevBotRuntimeState, resetDevBotRuntimeState, emitSecretsValuesChanged, onSecretsValuesChanged, emitProjectReloaded, onProjectReloaded, parseEnv, validateCredentials, validateBotId, validateMethod, validateProjectAndCredentials, getTargetBotId, getScopedServerCredentials, handleGetConfigVariables, handlePutConfigVariables, handleGetProdConfigVariables, handlePutProdConfigVariables, handlePatchConfigSchema, handleGetConfigSchemaDiff, handleFeatureFlags };
