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

49 lines (48 loc) • 2.26 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/. const ESC = "\u001B"; const BEL = "\u0007"; /** * Matches ANSI CSI sequences (colors, cursor movement, erase-line) and OSC * sequences (title, hyperlink) terminated by BEL or ST. Built via the RegExp * constructor so the control characters live in named string constants * instead of regex-literal escapes. */ const ANSI_SEQUENCE = new RegExp(`${ESC}\\[[0-9;?]*[ -/]*[@-~]` + `|${ESC}\\][^${BEL}${ESC}]*(?:${BEL}|${ESC}\\\\)`, "g"); /** * Resolve carriage-return overwrites within one physical line: a terminal * would redraw from column 0 at each `\r`, so only the segment after the last * `\r` survives (spinner frames like "⠋ Thinking..." disappear exactly as * they do on screen). A trailing bare `\r` (CRLF line endings) is handled by * splitting on `\r?\n` before this runs. */ function resolveCarriageReturns(line) { const lastCr = line.lastIndexOf("\r"); return lastCr === -1 ? line : line.slice(lastCr + 1); } /** Strip terminal framing from raw captured stdout. See module doc, rule 1. */ export function stripTerminalFraming(raw) { const lines = raw.split(/\r?\n/).map((line) => resolveCarriageReturns(line).replace(ANSI_SEQUENCE, "")); // Drop Q's "> " response marker from the first non-empty line only — deeper // occurrences may be legitimate content (markdown blockquotes). for (let i = 0; i < lines.length; i++) { const line = lines[i] ?? ""; if (line.trim().length === 0) continue; if (line.startsWith("> ")) lines[i] = line.slice(2); break; } return lines.join("\n").trim(); } /** * Normalize a raw Amazon Q run result into `{ text, sessionId? }`. * See the module doc for the rules. */ export const amazonqResultExtractor = (result) => { const sessionId = result.sessionId; // Rule 2: a pre-parsed whole-stdout JSON *string* is the answer itself. const text = typeof result.parsed === "string" ? result.parsed.trim() : stripTerminalFraming(result.stdout); return { text, ...(sessionId ? { sessionId } : {}) }; };