feat(cli): auto-configure Athena councils

This commit is contained in:
YeonGyu-Kim
2026-03-26 12:59:44 +09:00
parent 1c125ec3ef
commit 4a14bd6d68
8 changed files with 446 additions and 50 deletions
+14 -48
View File
@@ -1,6 +1,7 @@
import * as fs from "fs";
import * as path from "path";
import { OhMyOpenCodeConfigSchema, type OhMyOpenCodeConfig } from "./config";
import { parseConfigPartiallyWithIssues } from "./plugin-config-partial";
import {
log,
deepMerge,
@@ -11,57 +12,16 @@ import {
migrateConfigFile,
} from "./shared";
const PARTIAL_STRING_ARRAY_KEYS = new Set([
"disabled_mcps",
"disabled_agents",
"disabled_skills",
"disabled_hooks",
"disabled_commands",
"disabled_tools",
]);
export function parseConfigPartially(
rawConfig: Record<string, unknown>
): OhMyOpenCodeConfig | null {
const fullResult = OhMyOpenCodeConfigSchema.safeParse(rawConfig);
if (fullResult.success) {
return fullResult.data;
}
const partialConfig: Record<string, unknown> = {};
const invalidSections: string[] = [];
for (const key of Object.keys(rawConfig)) {
if (PARTIAL_STRING_ARRAY_KEYS.has(key)) {
const sectionValue = rawConfig[key];
if (Array.isArray(sectionValue) && sectionValue.every((value) => typeof value === "string")) {
partialConfig[key] = sectionValue;
}
continue;
}
const sectionResult = OhMyOpenCodeConfigSchema.safeParse({ [key]: rawConfig[key] });
if (sectionResult.success) {
const parsed = sectionResult.data as Record<string, unknown>;
if (parsed[key] !== undefined) {
partialConfig[key] = parsed[key];
}
} else {
const sectionErrors = sectionResult.error.issues
.filter((i) => i.path[0] === key)
.map((i) => `${i.path.join(".")}: ${i.message}`)
.join(", ");
if (sectionErrors) {
invalidSections.push(`${key}: ${sectionErrors}`);
}
}
}
const { config, invalidSections } = parseConfigPartiallyWithIssues(rawConfig);
if (invalidSections.length > 0) {
log("Partial config loaded — invalid sections skipped:", invalidSections);
}
return partialConfig as OhMyOpenCodeConfig;
return config;
}
export function loadConfigFromPath(
@@ -86,15 +46,21 @@ export function loadConfigFromPath(
.map((i) => `${i.path.join(".")}: ${i.message}`)
.join(", ");
log(`Config validation error in ${configPath}:`, result.error.issues);
const partialResult = parseConfigPartiallyWithIssues(rawConfig);
const partialErrorDetails =
partialResult.invalidSections.length > 0
? partialResult.invalidSections.join("; ")
: errorMsg;
addConfigLoadError({
path: configPath,
error: `Partial config loaded — invalid sections skipped: ${errorMsg}`,
error: `Config validation failed. Loaded valid sections only. Invalid sections: ${partialErrorDetails}`,
});
const partialResult = parseConfigPartially(rawConfig);
if (partialResult) {
log(`Partial config loaded from ${configPath}`, { agents: partialResult.agents });
return partialResult;
if (partialResult.config) {
log(`Partial config loaded from ${configPath}`, { agents: partialResult.config.agents });
return partialResult.config;
}
return null;