MCPcopy Create free account
hub / github.com/cortexkit/magic-context / parsePluginConfig

Function parsePluginConfig

packages/plugin/src/config/index.ts:216–376  ·  view source on GitHub ↗
(
    rawConfig: Record<string, unknown>,
    recoveredTopLevelKeys: string[] = [],
)

Source from the content-addressed store, hash-verified

214}
215
216function parsePluginConfig(
217 rawConfig: Record<string, unknown>,
218 recoveredTopLevelKeys: string[] = [],
219): MagicContextPluginConfig & { configWarnings?: string[] } {
220 // Pre-Zod shim: reshape legacy experimental.* graduated keys so the user's
221 // opt-in/out state survives upgrades even when they never run `doctor`.
222 const preMigrationWarnings: string[] = [];
223 const migratedExperimental = migrateLegacyExperimental(rawConfig, preMigrationWarnings);
224 // Dreamer v2: convert the legacy v1 dreamer shape (window schedule, tasks
225 // array, user_memories/pin_key_files blocks) into the per-task `tasks` record.
226 // Runs AFTER migrate-experimental so experimental.user_memories (already
227 // relocated to dreamer.user_memories above) is folded into the v2 tasks here.
228 const migratedDreamer = migrateDreamerV2(migratedExperimental, preMigrationWarnings);
229 const migrated = migrateLegacyAgentEnabledInMemory(migratedDreamer, preMigrationWarnings);
230 const parsed = MagicContextConfigSchema.safeParse(migrated);
231 const disabledHooks = Array.isArray(rawConfig.disabled_hooks)
232 ? rawConfig.disabled_hooks.filter((value): value is string => typeof value === "string")
233 : undefined;
234 const command =
235 typeof rawConfig.command === "object" && rawConfig.command !== null
236 ? (rawConfig.command as MagicContextPluginConfig["command"])
237 : undefined;
238
239 if (parsed.success) {
240 return {
241 ...parsed.data,
242 disabled_hooks: disabledHooks,
243 command,
244 ...(preMigrationWarnings.length > 0 ? { configWarnings: preMigrationWarnings } : {}),
245 };
246 }
247
248 // Full parse failed — recover field-by-field using defaults for invalid fields.
249 // Agent configs (historian, dreamer, sidekick) are dropped on error rather than defaulted
250 // because wrong model config could run expensive models or fail silently.
251 const defaults = MagicContextConfigSchema.parse({});
252 const warnings: string[] = [];
253
254 // Build a patched copy of rawConfig, replacing invalid fields with undefined
255 // so Zod fills in defaults on the second parse.
256 const errorPaths = new Set<string>();
257 // Collect any custom Zod messages per top-level key so a field with an
258 // explanatory `.max(..., "why")` / `.refine(..., "why")` message surfaces the
259 // reason to the user instead of a bare "invalid value" (e.g. issue #111's
260 // execute_threshold cache-safety explanation). Only non-default Zod messages
261 // are kept — the generic "Too big"/"Invalid input" boilerplate adds nothing.
262 const customMessagesByKey = new Map<string, string>();
263 // Per top-level key, the set of FULL error paths (e.g. ["memory","auto_search"]).
264 // Used to prune only the invalid nested leaf instead of the whole block.
265 const issuePathsByKey = new Map<string, PropertyKey[][]>();
266 const GENERIC_ZOD_PREFIXES = ["Too big", "Too small", "Invalid input", "Invalid", "Expected"];
267 for (const issue of parsed.error.issues) {
268 const topKey = issue.path[0];
269 if (topKey !== undefined) {
270 const key = String(topKey);
271 errorPaths.add(key);
272 const paths = issuePathsByKey.get(key) ?? [];
273 paths.push([...issue.path]);

Callers 1

loadPluginConfigDetailedFunction · 0.85

Calls 8

migrateDreamerV2Function · 0.90
pruneNestedConfigLeafFunction · 0.90
getMethod · 0.80
setMethod · 0.80
hasMethod · 0.80
redactConfigValueFunction · 0.70

Tested by

no test coverage detected