#!/usr/bin/env node
import {
  atomicWriteFileSync
} from "./chunk-NQDJ6QAM.js";
import {
  VALID_LOG_LEVELS,
  loadProxyRuntimeEnv,
  serviceLogger
} from "./chunk-LWDOXOWY.js";
import {
  CONFIG_PATH,
  PROFILE_NAME,
  defaultHookPortForProfile
} from "./chunk-7RSBFN2G.js";

// src/common/config.ts
import { existsSync, mkdirSync, readFileSync } from "fs";
import { dirname, isAbsolute } from "path";
import { z } from "zod";
var LogLevelSchema = z.enum(VALID_LOG_LEVELS);
var RelayTargetSchema = z.object({
  url: z.string().optional(),
  proxyToken: z.string().optional()
}).strict();
var ProxyProfileSchema = z.object({
  relay: z.string().optional()
}).strict();
var AgentCliSchema = z.object({
  claudeBin: z.string().optional(),
  codexBin: z.string().optional(),
  claudeBinHistory: z.array(z.string()).optional(),
  codexBinHistory: z.array(z.string()).optional()
}).strict();
var ProxyConfigFileSchema = z.object({
  defaultProfile: z.string().optional(),
  profiles: z.record(z.string(), ProxyProfileSchema),
  relays: z.record(z.string(), RelayTargetSchema),
  agentCli: AgentCliSchema.optional(),
  previewRoots: z.array(z.string()).optional(),
  logLevel: LogLevelSchema.optional()
}).strict();
function readConfigFile() {
  if (!existsSync(CONFIG_PATH)) {
    throw new Error(`Dev Anywhere config not found at ${CONFIG_PATH}. Run "dev-anywhere init".`);
  }
  let raw;
  try {
    raw = JSON.parse(readFileSync(CONFIG_PATH, "utf-8"));
  } catch (err) {
    throw new Error(
      `${CONFIG_PATH} is not valid JSON: ${err instanceof Error ? err.message : String(err)}`,
      { cause: err }
    );
  }
  const parsed = ProxyConfigFileSchema.safeParse(raw);
  if (!parsed.success) {
    const issues = parsed.error.issues.map(
      (issue) => `  ${issue.path.length > 0 ? issue.path.join(".") : "(root)"}: ${issue.message}`
    ).join("\n");
    throw new Error(`Invalid config at ${CONFIG_PATH}:
${issues}`);
  }
  return parsed.data;
}
function agentCliField(provider) {
  return provider === "claude" ? "claudeBin" : "codexBin";
}
function agentCliHistoryField(provider) {
  return provider === "claude" ? "claudeBinHistory" : "codexBinHistory";
}
function validateAgentCliPath(path) {
  const normalized = path.trim();
  if (!normalized) throw new Error("\u8BF7\u8F93\u5165 CLI \u8DEF\u5F84");
  if (!isAbsolute(normalized)) throw new Error("CLI \u8DEF\u5F84\u5FC5\u987B\u662F\u7EDD\u5BF9\u8DEF\u5F84");
  return normalized;
}
function uniqueAbsolutePaths(paths) {
  const seen = /* @__PURE__ */ new Set();
  const result = [];
  for (const path of paths) {
    const normalized = path?.trim();
    if (!normalized || !isAbsolute(normalized) || seen.has(normalized)) continue;
    seen.add(normalized);
    result.push(normalized);
  }
  return result;
}
function resolveRelayConfig(fromFile, requestedRelayName) {
  const profile = fromFile.profiles[PROFILE_NAME];
  if (!profile) {
    const available = Object.keys(fromFile.profiles).sort();
    throw new Error(
      `Unknown profile "${PROFILE_NAME}". Available profiles: ${available.length > 0 ? available.join(", ") : "(none)"}`
    );
  }
  const relayName = requestedRelayName?.trim() || profile.relay?.trim();
  if (!relayName) {
    throw new Error(`Profile "${PROFILE_NAME}" must specify a relay.`);
  }
  const relay = fromFile.relays[relayName];
  if (!relay) {
    const available = Object.keys(fromFile.relays).sort();
    throw new Error(
      `Unknown relay "${relayName}". Available relays: ${available.length > 0 ? available.join(", ") : "(none)"}`
    );
  }
  return {
    relayName,
    relayNameSource: requestedRelayName?.trim() ? "cli" : "profile",
    relay
  };
}
function loadConfig(options) {
  const env = loadProxyRuntimeEnv();
  const fromFile = readConfigFile();
  const agentCli = fromFile.agentCli ?? {};
  const resolved = resolveRelayConfig(fromFile, options?.relayName);
  const claudeBin = env.claudeBin ?? agentCli.claudeBin;
  const codexBin = env.codexBin ?? agentCli.codexBin;
  const config = {
    profileName: PROFILE_NAME,
    relayName: resolved.relayName,
    relayUrl: env.relayUrl ?? resolved.relay.url,
    relayToken: env.relayProxyToken ?? resolved.relay.proxyToken,
    hookPort: env.hookPort ?? defaultHookPortForProfile(PROFILE_NAME),
    claudeBin,
    codexBin,
    previewRoots: uniqueAbsolutePaths(fromFile.previewRoots ?? []),
    agentCliSuggestions: {
      claude: uniqueAbsolutePaths([
        env.claudeBin,
        agentCli.claudeBin,
        ...agentCli.claudeBinHistory ?? []
      ]),
      codex: uniqueAbsolutePaths([
        env.codexBin,
        agentCli.codexBin,
        ...agentCli.codexBinHistory ?? []
      ])
    },
    sources: {
      relayName: resolved.relayNameSource,
      relayUrl: env.relayUrl ? "env" : resolved.relay.url ? "file" : "none",
      relayToken: env.relayProxyToken ? "env" : resolved.relay.proxyToken ? "file" : "none",
      hookPort: env.hookPort !== void 0 ? "env" : "default",
      claudeBin: env.claudeBin ? "env" : agentCli.claudeBin ? "file" : "none",
      codexBin: env.codexBin ? "env" : agentCli.codexBin ? "file" : "none"
    }
  };
  serviceLogger.info(
    {
      profile: config.profileName,
      relayName: config.relayName,
      relayNameSource: config.sources.relayName,
      relayUrl: config.relayUrl ?? "(unset)",
      relayUrlSource: config.sources.relayUrl,
      relayTokenSource: config.sources.relayToken,
      hookPort: config.hookPort,
      hookPortSource: config.sources.hookPort,
      claudeBinSource: config.sources.claudeBin,
      codexBinSource: config.sources.codexBin
    },
    "Config loaded"
  );
  return config;
}
function buildProviderEnv(config, baseEnv = process.env) {
  return {
    ...baseEnv,
    ...config.claudeBin ? { CLAUDE_BIN: config.claudeBin } : {},
    ...config.codexBin ? { CODEX_BIN: config.codexBin } : {}
  };
}
function updateAgentCliConfig(config, provider, path) {
  const field = agentCliField(provider);
  const historyField = agentCliHistoryField(provider);
  const history = uniqueAbsolutePaths([path, ...config[historyField] ?? []]).slice(0, 8);
  return {
    ...config,
    [field]: path,
    [historyField]: history
  };
}
function saveAgentCliPath(provider, path) {
  const normalized = validateAgentCliPath(path);
  const fromFile = readConfigFile();
  fromFile.agentCli = updateAgentCliConfig(fromFile.agentCli ?? {}, provider, normalized);
  mkdirSync(dirname(CONFIG_PATH), { recursive: true });
  atomicWriteFileSync(CONFIG_PATH, `${JSON.stringify(fromFile, null, 2)}
`, { mode: 384 });
}

export {
  loadConfig,
  buildProviderEnv,
  saveAgentCliPath
};
//# sourceMappingURL=chunk-4543KN27.js.map