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
90 lines (89 loc) • 4.18 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/.
/**
* Pi coding-agent CLI command builder (P2, plan §"The adapter contract"
* step 2 / §"Capability matrix").
*
* Translates a platform-agnostic {@link AgentDispatchRequest} into the exact
* headless argv the `pi` CLI expects. Per the capability matrix the headless
* invocation is:
*
* pi -p "<prompt>"
*
* with `--mode json` for structured (JSONL) output, `--model <m>` for model
* selection, and `-c`/`-r`/`--session <id>` for resume — not built here
* because `AgentDispatchRequest` carries no session id (akm's
* `workflow_run_units` is the durable resume source of truth).
*
* Platform-specific mapping decisions (all localized here, per the adapter
* contract):
*
* - **prompt** — `-p` is Pi's non-interactive print mode (same convention as
* Claude Code's `--print`); the prompt is the trailing positional message.
* The `--` end-of-options separator precedes it, mirroring the claude/codex
* builders, so a prompt whose text begins with `-`/`--` can never be parsed
* as flags.
* - **systemPrompt** — passed via `--system-prompt` (Pi follows the Claude
* Code flag conventions).
* - **schema** — the matrix places Pi in the "via prompt+validate" tier (no
* native `--output-schema` equivalent, unlike Codex), so the JSON Schema
* reaches it as the instruction the shared request lowering appends to the
* prompt, and `--mode json` is emitted so stdout is the documented JSONL
* event stream that `./result-extractor.ts` normalizes. The engine's shared
* retry-until-valid loop performs the actual validation. Without a schema
* the argv matches the matrix's bare headless shape (`pi -p "<p>"`) and the
* extractor's plain-text path applies.
* - **tools** — deliberately unconsumed. Pi manages tool access through its
* own config/extension system (the matrix lists MCP as "extensions only");
* there is no documented per-tool allowlist flag, and inventing one would
* produce a silently broken command. A restrictive policy is therefore
* dropped rather than approximated — never silently widened.
* - **inference** — not translated: the shared lowering reports each field of
* the request's inference as untranslated.
*
* Registered: `piBuilder` is `PiHarness.agentBuilder` (`./index.ts`), one of
* the ten harnesses `HARNESS_REGISTRY` constructs (`harnesses/index.ts`);
* `agent/builders.ts` derives `BUILTIN_BUILDERS` from that registry, so this
* builder is reachable under the `"pi"` platform name without any further
* wiring. The `PI_SESSION_ID` identity-env marker is declared alongside it
* (`./index.ts`).
*/
import { resolveDispatchModel } from "../../agent/builder-shared.js";
import { createAgentRequestLowerer } from "../../agent/request-lowering.js";
/** Canonical harness/platform id used for model-alias resolution. */
export const PI_PLATFORM = "pi";
/**
* Pi builder.
* Command shape:
* pi [--system-prompt "..."] [--model <m>] [--mode json] -p -- "<prompt>"
*/
export const piBuilder = {
platform: PI_PLATFORM,
personaChannel: "native",
lower: createAgentRequestLowerer({
adapter: PI_PLATFORM,
personaChannel: "native",
tools: "none",
}),
build(profile, req) {
const args = [...profile.args];
if (req.systemPrompt) {
args.push("--system-prompt", req.systemPrompt);
}
if (req.model) {
const resolved = resolveDispatchModel(req, profile, PI_PLATFORM);
args.push("--model", resolved);
}
if (req.schema) {
// Structured unit: JSONL event stream on stdout — the pi result
// extractor's documented input (prompt+validate tier).
args.push("--mode", "json");
}
// -p = non-interactive print mode; prompt is the trailing positional.
args.push("-p");
args.push("--");
args.push(req.prompt);
return { argv: [profile.bin, ...args] };
},
};