UNPKG

akm-cli

Version:

akm (Agent Knowledge Manager) — a portable, local-first capability library for AI agents. Discover, load, share, and improve reusable skills, scripts, workflows, and knowledge across any shell-capable coding agent, including Claude Code, OpenCode, and Cur

109 lines (108 loc) • 4.49 kB
// This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. /** * `index` config: reserved feature sections + arbitrary per-pass entries. * Extracted verbatim from the former `config-schema.ts` monolith — no behavior * change. */ import { z } from "zod"; import { warnOnce } from "../../warn.js"; import { engineName, LlmInvocationOverridesSchema, nonEmptyString, positiveInt } from "./primitives.js"; // ── Index / per-pass ──────────────────────────────────────────────────────── const INDEX_PASS_RETIRED_KEYS = new Set([ "endpoint", "provider", "apiKey", "baseUrl", "temperature", "maxTokens", "capabilities", ]); /** * Per-pass `index.<pass>` entry. The preprocess names and drops the retired * engine settings above with a targeted message. Any other unknown key is kept * and named once by the config loader's schema walk, like an unknown key * anywhere else in config. */ export const IndexPassConfigSchema = z.preprocess((raw, ctx) => { if (typeof raw !== "object" || raw === null || Array.isArray(raw)) { return raw; // let z.object below produce the type error } const obj = raw; let cleaned; for (const key of Object.keys(obj)) { const dotted = [...(ctx.path ?? []), key].join("."); if (INDEX_PASS_RETIRED_KEYS.has(key)) { warnOnce(`index-pass:retired:${dotted}`, `\`${dotted}\` is a retired engine setting and is ignored; select a named engine and use typed invocation fields instead.`); cleaned ??= { ...obj }; delete cleaned[key]; } } return cleaned ?? raw; }, z .object({ engine: engineName.optional(), model: nonEmptyString.optional(), timeoutMs: z.union([positiveInt, z.null()]).optional(), enabled: z.boolean().optional(), llm: LlmInvocationOverridesSchema.optional(), }) .passthrough()); const IndexDefaultsSchema = z .object({ engine: engineName.optional(), model: nonEmptyString.optional(), timeoutMs: z.union([positiveInt, z.null()]).optional(), llm: LlmInvocationOverridesSchema.optional(), }) .passthrough(); /** * Index config is a union of reserved feature sections and per-pass entries. * Passthrough so per-pass entries (keyed by arbitrary pass names like * `memory`, or a retired one like `graph`) can live next to the reserved keys. * The outer preprocess emits the legacy parser's actionable error messages * for the two most common type-shape mistakes: * - An array at the `index` block. * - A non-object at `index.<passName>`. * Inner field validation (invocation overrides, provider-key rejection) is * delegated to {@link IndexPassConfigSchema}. */ const IndexConfigRuntimeSchema = z.preprocess((raw, ctx) => { if (raw === undefined || raw === null) return raw; if (Array.isArray(raw)) { ctx.addIssue({ code: z.ZodIssueCode.custom, message: 'Invalid `index` config: expected an object keyed by pass name (e.g. `{ "memory": { "enabled": false } }`).', }); return raw; } if (typeof raw !== "object") return raw; let cleaned; for (const [passName, value] of Object.entries(raw)) { if (passName === "stalenessDetection") { warnOnce("index:stalenessDetection", "`index.stalenessDetection` is a retired pass and is ignored."); cleaned ??= { ...raw }; delete cleaned.stalenessDetection; continue; } if (typeof value !== "object" || value === null || Array.isArray(value)) { ctx.addIssue({ code: z.ZodIssueCode.custom, message: `Invalid \`index.${passName}\` config: expected an object like \`{ "enabled": false }\`.`, }); return raw; } } return cleaned ?? raw; }, z .object({ defaults: IndexDefaultsSchema.optional(), }) .catchall(IndexPassConfigSchema)); // The runtime catchall correctly validates arbitrary pass objects, but its // inferred string index signature also covers reserved scalar keys. Publish a // precise output type while retaining the stricter runtime and JSON schemas. export const IndexConfigSchema = IndexConfigRuntimeSchema;