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
93 lines (92 loc) • 4.37 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/.
import { dispatchPreparedCommandInvocation } from "../../commands/command/command-execution.js";
import { finishAttempt } from "./attempt-lifecycle.js";
import { appendHistory } from "./task-history.js";
import { persistRunLog, scrubTaskOutput, streamLines } from "./task-log.js";
export async function runPreparedCommandTask(input) {
const { task, logPath, startedAt, now, agentOptions, provenance } = input;
const dispatchOptions = {
...(input.runAgentImpl ? { runAgent: input.runAgentImpl } : {}),
...(input.chatCompletionImpl ? { chat: input.chatCompletionImpl } : {}),
...(agentOptions ? { runOptions: agentOptions } : {}),
// F-1 (R-07 fix, spec §5.2 point 3): threads the resolved event source
// into the dispatched engine's child env and the recorded usage events.
eventSource: provenance.eventSource,
};
const result = await dispatchPreparedCommandInvocation(task.invocation, dispatchOptions);
const engineName = result.engine;
const finishedAt = finishAttempt(startedAt, now());
const log = renderPromptLog({ task, engineName, result, notices: result.notices, warnings: result.warnings });
persistRunLog({
taskId: task.taskId,
startedAtIso: startedAt.toISOString(),
finishedAtIso: finishedAt.toISOString(),
logPath,
fileText: log.fileText,
dbLines: log.dbLines,
redactNames: task.redact,
environment: task.environment,
});
const status = result.ok ? "completed" : "failed";
const out = {
id: task.taskId,
status,
startedAt: startedAt.toISOString(),
finishedAt: finishedAt.toISOString(),
durationMs: finishedAt.getTime() - startedAt.getTime(),
log: logPath,
target: { kind: "command", engine: engineName },
detail: result.ok
? { exitCode: result.exitCode }
: {
reason: result.reason === undefined ? undefined : scrubTaskOutput(task, result.reason),
error: result.error === undefined ? undefined : scrubTaskOutput(task, result.error),
exitCode: result.exitCode,
},
...(result.notices && result.notices.length > 0
? {
notices: result.notices.map((notice) => ({
...notice,
message: scrubTaskOutput(task, notice.message),
})),
}
: {}),
};
appendHistory(out, input.historyReserved);
return out;
}
function renderPromptLog(input) {
const lines = [];
const dbLines = [];
const header = `[akm task] task=${input.task.taskId} kind=prompt engine=${input.engineName}`;
const summary = `ok=${input.result.ok} exit_code=${input.result.exitCode ?? "null"} duration_ms=${input.result.durationMs}${input.result.sessionId ? ` session_id=${input.result.sessionId}` : ""}`;
lines.push(header, summary);
dbLines.push({ line: header }, { level: input.result.ok ? "info" : "error", line: summary });
for (const warning of input.warnings ?? []) {
lines.push(warning);
dbLines.push({ level: "warn", line: warning });
}
for (const notice of input.notices ?? []) {
const line = `lowering_notice=${notice.code} adapter=${notice.adapter} field=${notice.field ?? ""} message=${notice.message}`;
lines.push(line);
dbLines.push({ level: notice.severity === "warning" ? "warn" : "info", line });
}
if (!input.result.ok) {
const failure = `reason=${input.result.reason ?? ""} error=${input.result.error ?? ""}`;
lines.push(failure);
dbLines.push({ level: "error", line: failure });
}
if (input.result.stdout) {
lines.push("--- agent stdout ---");
lines.push(input.result.stdout);
dbLines.push(...streamLines(input.result.stdout, "stdout", "info"));
}
if (input.result.stderr) {
lines.push("--- agent stderr ---");
lines.push(input.result.stderr);
dbLines.push(...streamLines(input.result.stderr, "stderr", "error"));
}
return { fileText: `${lines.join("\n")}\n`, dbLines };
}