import * as fs from "node:fs"; import * as path from "node:path"; import { CONFIG_DIR_NAME, getAgentDir } from "@earendil-works/pi-coding-agent"; import { createDefaultClusterConfig, parseClusterConfig } from "./config-core.ts"; import type { ClusterConfig } from "./types.ts"; export { createDefaultClusterConfig, workerLevelConfigSignature } from "./config-core.ts"; export interface LoadedClusterConfig { config: ClusterConfig; path: string; } export function getGlobalConfigPath(): string { return path.join(getAgentDir(), "subagent-cluster.json"); } export function getConfigCandidates(cwd: string): string[] { const candidates: string[] = []; let current = path.resolve(cwd); while (true) { candidates.push(path.join(current, CONFIG_DIR_NAME, "subagent-cluster.json")); const parent = path.dirname(current); if (parent === current) break; current = parent; } candidates.push(path.join(getAgentDir(), "subagent-cluster.json")); return candidates; } export function readClusterConfig(configPath: string): LoadedClusterConfig { let content: string; try { content = fs.readFileSync(configPath, "utf8"); } catch (error) { throw new Error(`无法读取集群配置 ${configPath}: ${error instanceof Error ? error.message : String(error)}`); } try { return { config: parseClusterConfig(JSON.parse(content)), path: configPath }; } catch (error) { throw new Error(`集群配置无效 ${configPath}: ${error instanceof Error ? error.message : String(error)}`); } } export async function readOrCreateClusterConfig(configPath: string, model: string): Promise { if (fs.existsSync(configPath)) return readClusterConfig(configPath); const config = createDefaultClusterConfig(model); await writeClusterConfig(configPath, config); return { config, path: configPath }; } export function loadClusterConfig(cwd: string): LoadedClusterConfig { const candidates = getConfigCandidates(cwd); for (const configPath of candidates) { if (fs.existsSync(configPath)) return readClusterConfig(configPath); } throw new Error( [`未找到集群配置。`, `请创建 ${candidates[0]},或使用全局配置 ${candidates[1]}。`, `配置示例见 pi-subagent-cluster 包 README.md`].join("\n"), ); } export async function writeClusterConfig(configPath: string, config: ClusterConfig): Promise { await fs.promises.mkdir(path.dirname(configPath), { recursive: true }); await fs.promises.writeFile(configPath, `${JSON.stringify(config, null, 2)}\n`, "utf8"); }