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

60 lines (59 loc) • 3.19 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/. import { defaultWhich } from "./detect.js"; import { OPENCODE_SDK_SERVER_BIN } from "./profiles.js"; /** Engine name used for the synthesized entry; matches the platform id. */ export const FALLBACK_ENGINE_NAME = "opencode-sdk"; /** Announcement text, surfaced once per run/dispatch. */ export const FALLBACK_ANNOUNCEMENT = `No engine is configured; falling back to \`${FALLBACK_ENGINE_NAME}\` via the ` + `\`${OPENCODE_SDK_SERVER_BIN}\` binary on PATH — provider, model, and auth come ` + "from opencode's own configuration. " + "Run `akm setup`, or set `defaults.engine`, to choose explicitly."; /** Failure suffix for every surface that needs an engine and found none. */ export const NO_ENGINE_MESSAGE_SUFFIX = `has no selected engine, and no usable \`${OPENCODE_SDK_SERVER_BIN}\` binary was found to fall back to.`; /** Guidance used when the fallback itself is unavailable. */ export const NO_ENGINE_REMEDY = "Run `akm setup` to detect an installed agent, or set one explicitly: " + '`akm config set engines.claude \'{"kind":"agent","platform":"claude"}\'` ' + "then `akm config set defaults.engine claude`. " + `Installing the \`${OPENCODE_SDK_SERVER_BIN}\` binary also works ` + "(`npm i -g opencode-ai`) — akm falls back to it automatically."; /** * The fallback engine when its `opencode` binary is present: an * operator-configured `opencode-sdk` entry (whose pinned `bin`, possibly * outside PATH, is what gets probed), else a bare opencode-sdk agent engine. */ export function fallbackEngineConfig(config, whichFn = defaultWhich) { const existing = config.engines?.[FALLBACK_ENGINE_NAME]; const bin = existing?.kind === "agent" ? existing.bin : undefined; if (!whichFn(bin ?? OPENCODE_SDK_SERVER_BIN)) return undefined; return existing ?? { kind: "agent", platform: "opencode-sdk" }; } /** * For diagnostics that report the effective engine: a config whose * `defaults.engine` resolves, with the implicit `opencode-sdk` fallback when it * does not and an opencode binary is present. Never mutates `config`; returns * the same object when no fallback is needed. */ export function withEngineFallback(config, whichFn = defaultWhich) { if (config.defaults?.engine) return { config }; const engine = fallbackEngineConfig(config, whichFn); if (!engine) return { config }; return { config: { ...config, engines: { ...(config.engines ?? {}), [FALLBACK_ENGINE_NAME]: engine }, defaults: { ...(config.defaults ?? {}), engine: FALLBACK_ENGINE_NAME }, }, fallbackEngineName: FALLBACK_ENGINE_NAME, }; } /** The announcement, but only when the fallback candidate is the engine that actually won selection. */ export function fallbackAnnouncement(fallbackEngineName, selectedEngineName) { if (!fallbackEngineName || selectedEngineName !== fallbackEngineName) return undefined; return FALLBACK_ANNOUNCEMENT; }