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
54 lines (53 loc) • 2.81 kB
JavaScript
// 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/.
/**
* Type-guard narrowing a harness to {@link SessionLogCapableHarness}.
*
* `Array.prototype.filter`'s type-predicate overload requires the predicate's
* inferred type to extend the array's element type — a plain
* `(h: AkmHarness) => h is SessionLogCapableHarness` predicate fails that
* constraint against `HARNESS_REGISTRY`'s element type (the union of the ten
* concrete harness classes, each with literal `id`s narrower than
* `SessionLogCapableHarness`'s `id: string`), so `.filter` would silently fall
* back to its non-narrowing overload. Generic over the input `H` and
* intersecting it into the predicate (`H & SessionLogCapableHarness`) keeps
* the result always a subtype of `H`, so the constraint holds regardless of
* what concrete harness type(s) `H` resolves to — this is what lets
* `HARNESS_REGISTRY.filter(isSessionLogHarness)` (in `./index.ts`) actually
* narrow to a type where `sessionLogProvider` is known-present, retiring the
* load-time throw that used to guard this in `session-logs/index.ts`.
*/
export function isSessionLogHarness(h) {
return h.capabilities.sessionLogs;
}
/**
* Shared base for harness descriptors (#566).
*
* Provides shared optional descriptor fields for concrete harnesses.
*
* Deliberately implements {@link AkmHarnessCommon}, NOT the discriminated
* `AkmHarness` union (WI-9.7, H1): `AkmHarnessCommon` excludes `capabilities`
* and `sessionLogProvider`, the two fields whose pairing the union enforces.
* A base class shared by both branches cannot itself satisfy either specific
* union member — `capabilities` stays declared `abstract` at the (widened)
* `HarnessCapabilities` union type here, and each subclass narrows it to a
* literal `sessionLogs: true`/`false` variant via `caps({...})`.
* `sessionLogProvider` is intentionally NOT declared here at all (not even
* optional): the 7 non-session-log subclasses simply never declare it, which
* satisfies `NonSessionLogHarness`'s `sessionLogProvider?: undefined` (an
* absent optional property satisfies an `undefined`-typed optional); had this
* class declared it as `sessionLogProvider?: () => SessionLogHarness`
* instead, every non-session-log subclass would inherit that (function |
* undefined) type and fail to satisfy `NonSessionLogHarness` at the
* `HARNESS_REGISTRY` `satisfies` check. The three session-log subclasses
* (Claude, Codex, OpenCode) declare their own required `sessionLogProvider`.
*/
export class BaseHarness {
setupDetectionDir;
agentBuilder;
executionLowerer;
identityEnv;
presenceEnv;
resultExtractor;
}