akm-cli 0.9.24 → 0.9.25-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +173 -0
- package/dist/cli.js +1 -1
- package/dist/commands/health/checks.js +10 -11
- package/dist/commands/improve/consolidate/pair-pass.js +4 -2
- package/dist/commands/improve/consolidate.js +10 -4
- package/dist/commands/improve/execution.js +4 -11
- package/dist/commands/improve/extract-prompt.js +4 -4
- package/dist/commands/improve/extract.js +11 -13
- package/dist/commands/improve/improve-cli.js +65 -34
- package/dist/commands/improve/improve-strategies.js +49 -43
- package/dist/commands/improve/improve-usage-report.js +8 -17
- package/dist/commands/improve/loop-stages.js +3 -0
- package/dist/commands/improve/preparation.js +3 -1
- package/dist/commands/improve/reflect-noise.js +125 -0
- package/dist/commands/improve/reflect.js +105 -172
- package/dist/commands/improve/retrieval-gate.js +7 -2
- package/dist/commands/improve/stage.js +67 -24
- package/dist/commands/proposal/drain.js +11 -2
- package/dist/commands/proposal/proposal-cli.js +1 -5
- package/dist/commands/proposal/propose-cli.js +2 -2
- package/dist/commands/proposal/propose.js +72 -84
- package/dist/commands/proposal/validators/proposal-quality-validators.js +4 -2
- package/dist/commands/read/search-cli.js +0 -38
- package/dist/commands/remember.js +3 -3
- package/dist/commands/sources/schema-repair.js +1 -1
- package/dist/core/config/config-schema.js +37 -60
- package/dist/core/config/engine-semantics.js +15 -11
- package/dist/core/config/schema/improve-processes.js +18 -2
- package/dist/core/improve-result.js +3 -3
- package/dist/core/redaction.js +4 -0
- package/dist/core/spawn-env.js +25 -0
- package/dist/core/structured.js +11 -1
- package/dist/execution/source.js +10 -0
- package/dist/indexer/passes/memory-inference.js +2 -1
- package/dist/integrations/agent/builder-shared.js +15 -0
- package/dist/integrations/agent/config.js +1 -1
- package/dist/integrations/agent/engine-resolution.js +13 -31
- package/dist/integrations/agent/execution.js +48 -22
- package/dist/integrations/agent/index.js +1 -1
- package/dist/integrations/agent/profiles.js +2 -2
- package/dist/integrations/agent/prompts.js +55 -114
- package/dist/integrations/agent/request-lowering.js +21 -8
- package/dist/integrations/agent/runner-dispatch.js +96 -3
- package/dist/integrations/agent/runner.js +8 -2
- package/dist/integrations/harnesses/aider/agent-builder.js +10 -23
- package/dist/integrations/harnesses/aider/index.js +0 -5
- package/dist/integrations/harnesses/amazonq/agent-builder.js +9 -21
- package/dist/integrations/harnesses/amazonq/index.js +0 -5
- package/dist/integrations/harnesses/claude/agent-builder.js +47 -36
- package/dist/integrations/harnesses/claude/index.js +0 -14
- package/dist/integrations/harnesses/codex/agent-builder.js +3 -4
- package/dist/integrations/harnesses/codex/index.js +0 -4
- package/dist/integrations/harnesses/copilot/agent-builder.js +4 -13
- package/dist/integrations/harnesses/copilot/index.js +2 -7
- package/dist/integrations/harnesses/gemini/agent-builder.js +4 -13
- package/dist/integrations/harnesses/gemini/index.js +0 -5
- package/dist/integrations/harnesses/ids.js +12 -10
- package/dist/integrations/harnesses/opencode/agent-builder.js +41 -9
- package/dist/integrations/harnesses/opencode/index.js +0 -8
- package/dist/integrations/harnesses/opencode/model-config.js +33 -0
- package/dist/integrations/harnesses/opencode/model-work-agent.js +115 -0
- package/dist/integrations/harnesses/opencode-sdk/harness.js +2 -7
- package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +114 -28
- package/dist/integrations/harnesses/openhands/agent-builder.js +7 -21
- package/dist/integrations/harnesses/openhands/index.js +0 -5
- package/dist/integrations/harnesses/pi/agent-builder.js +7 -21
- package/dist/integrations/harnesses/pi/index.js +0 -5
- package/dist/llm/client.js +5 -0
- package/dist/llm/feature-gate.js +12 -9
- package/dist/llm/index-passes.js +2 -5
- package/dist/llm/memory-infer.js +6 -5
- package/dist/llm/structured-call.js +33 -11
- package/dist/output/shapes/passthrough.js +1 -0
- package/dist/scripts/akm-migrate-node.js +298 -228
- package/dist/scripts/akm-migrate.js +298 -228
- package/dist/workflows/exec/step-work.js +6 -5
- package/dist/workflows/exec/unit-dispatch.js +4 -13
- package/dist/workflows/freeze/step-values.js +1 -1
- package/docs/reference/cli.md +41 -18
- package/docs/reference/configuration.md +165 -12
- package/docs/reference/data-and-telemetry.md +2 -3
- package/docs/reference/workflow-schema.md +10 -9
- package/package.json +1 -1
- package/schemas/akm-config.json +108 -0
package/dist/llm/feature-gate.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
2
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
3
|
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
+
import { DEFAULT_LLM_TIMEOUT_MS } from "../integrations/agent/config.js";
|
|
4
5
|
/**
|
|
5
6
|
* For each feature key, return the effective enabled state by reading the
|
|
6
7
|
* 0.9.0 config shape.
|
|
@@ -37,14 +38,11 @@ export function isLlmFeatureEnabled(config, feature, improveEnabled) {
|
|
|
37
38
|
return false;
|
|
38
39
|
return resolver(config);
|
|
39
40
|
}
|
|
40
|
-
/**
|
|
41
|
-
* Default hard timeout for every bounded in-tree LLM call.
|
|
42
|
-
*/
|
|
43
|
-
const DEFAULT_TIMEOUT_MS = 600_000;
|
|
44
41
|
/**
|
|
45
42
|
* Run `fn()` only if `isLlmFeatureEnabled(config, feature)` is `true`. On
|
|
46
43
|
* disablement, throw, or timeout, return `fallback` (or — if it is a
|
|
47
|
-
* thunk — the value produced by calling it).
|
|
44
|
+
* thunk — the value produced by calling it). The timeout aborts the signal
|
|
45
|
+
* `fn` receives, so the work it started stops too.
|
|
48
46
|
*/
|
|
49
47
|
export async function tryLlmFeature(feature, config, fn, fallback, opts) {
|
|
50
48
|
const resolveFallback = async () => typeof fallback === "function" ? await fallback() : fallback;
|
|
@@ -52,10 +50,10 @@ export async function tryLlmFeature(feature, config, fn, fallback, opts) {
|
|
|
52
50
|
opts?.onFallback?.({ feature, reason: "disabled" });
|
|
53
51
|
return resolveFallback();
|
|
54
52
|
}
|
|
55
|
-
const timeoutMs = opts && Object.hasOwn(opts, "timeoutMs") ? (opts.timeoutMs ?? null) :
|
|
53
|
+
const timeoutMs = opts && Object.hasOwn(opts, "timeoutMs") ? (opts.timeoutMs ?? null) : DEFAULT_LLM_TIMEOUT_MS;
|
|
56
54
|
try {
|
|
57
55
|
if (timeoutMs === null || timeoutMs <= 0) {
|
|
58
|
-
return await fn();
|
|
56
|
+
return await fn(new AbortController().signal);
|
|
59
57
|
}
|
|
60
58
|
return await runWithTimeout(fn, timeoutMs, feature);
|
|
61
59
|
}
|
|
@@ -97,11 +95,16 @@ export class LlmFeatureTimeoutError extends Error {
|
|
|
97
95
|
}
|
|
98
96
|
async function runWithTimeout(fn, timeoutMs, feature) {
|
|
99
97
|
let timer;
|
|
98
|
+
const controller = new AbortController();
|
|
100
99
|
try {
|
|
101
100
|
return await new Promise((resolve, reject) => {
|
|
102
|
-
timer = setTimeout(() =>
|
|
101
|
+
timer = setTimeout(() => {
|
|
102
|
+
const timedOut = new LlmFeatureTimeoutError(feature, timeoutMs);
|
|
103
|
+
controller.abort(timedOut);
|
|
104
|
+
reject(timedOut);
|
|
105
|
+
}, timeoutMs);
|
|
103
106
|
Promise.resolve()
|
|
104
|
-
.then(() => fn())
|
|
107
|
+
.then(() => fn(controller.signal))
|
|
105
108
|
.then(resolve, reject);
|
|
106
109
|
});
|
|
107
110
|
}
|
package/dist/llm/index-passes.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
2
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
3
|
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
-
import { warn } from "../core/warn.js";
|
|
5
4
|
import { cloneExecutionJsonObject } from "../execution/json.js";
|
|
6
5
|
import { buildExecution, resolveExecution } from "../integrations/agent/execution.js";
|
|
7
6
|
const NO_LOWERING_NOTICES = Object.freeze([]);
|
|
@@ -38,16 +37,14 @@ export function resolveIndexPassExecution(passName, config) {
|
|
|
38
37
|
...indexExecutionDefaults(defaults),
|
|
39
38
|
...(!own(defaults, "engine") && fallbackLlmEngine ? { engine: fallbackLlmEngine } : {}),
|
|
40
39
|
};
|
|
40
|
+
// Under the model-work tool policy, so an engine that cannot confine it is refused here.
|
|
41
41
|
const prepared = resolveExecution({
|
|
42
42
|
content: "",
|
|
43
43
|
config,
|
|
44
44
|
invocationDefaults,
|
|
45
45
|
current: indexExecutionDefaults(pass),
|
|
46
|
+
modelWork: true,
|
|
46
47
|
});
|
|
47
48
|
const lowered = buildExecution(prepared.request, prepared.runner);
|
|
48
|
-
if (lowered.runner.kind !== "llm") {
|
|
49
|
-
warn("[akm] Index pass %s requires an LLM engine; %s is not one. Skipping this pass.", passName, selectedEngine);
|
|
50
|
-
return Object.freeze({ runner: undefined, notices: NO_LOWERING_NOTICES });
|
|
51
|
-
}
|
|
52
49
|
return Object.freeze({ runner: lowered.runner, notices: lowered.notices });
|
|
53
50
|
}
|
package/dist/llm/memory-infer.js
CHANGED
|
@@ -21,6 +21,7 @@ import memoryInferUserPrompt from "../assets/prompts/memory-infer-user.md" with
|
|
|
21
21
|
import { toErrorMessage } from "../core/common.js";
|
|
22
22
|
import { parseEmbeddedJsonResponse } from "../core/parse.js";
|
|
23
23
|
import { warn } from "../core/warn.js";
|
|
24
|
+
import { runnerLlmConnection } from "../integrations/agent/runner.js";
|
|
24
25
|
import { callStructured } from "./structured-call.js";
|
|
25
26
|
const SYSTEM_PROMPT = memoryInferSystemPrompt;
|
|
26
27
|
const USER_PROMPT_PREFIX = memoryInferUserPrompt;
|
|
@@ -34,9 +35,9 @@ const PROMPT_PLACEHOLDERS = new Set([
|
|
|
34
35
|
"2-3 sentence compressed body preserving key facts verbatim",
|
|
35
36
|
]);
|
|
36
37
|
/**
|
|
37
|
-
* Strict JSON Schema for the derived-memory payload. Sent
|
|
38
|
-
*
|
|
39
|
-
*
|
|
38
|
+
* Strict JSON Schema for the derived-memory payload. Sent as `response_format`
|
|
39
|
+
* unless the engine sets `supportsJsonSchema: false`; the client drops it once
|
|
40
|
+
* for a provider that rejects it.
|
|
40
41
|
*
|
|
41
42
|
* Extends the responseSchema lift (PR 1, asset-writers-investigation §5) to
|
|
42
43
|
* the memory-inference path. Mirrors the validation gate below
|
|
@@ -89,8 +90,8 @@ export async function compressMemoryToDerivedMemory(llmRunner, body, signal, akm
|
|
|
89
90
|
],
|
|
90
91
|
request: {
|
|
91
92
|
// The engine's or the process's configured temperature; 0.1 only when neither sets one.
|
|
92
|
-
temperature: llmRunner
|
|
93
|
-
timeoutMs: llmRunner.timeoutMs,
|
|
93
|
+
temperature: runnerLlmConnection(llmRunner)?.temperature ?? 0.1,
|
|
94
|
+
...(Object.hasOwn(llmRunner, "timeoutMs") ? { timeoutMs: llmRunner.timeoutMs } : {}),
|
|
94
95
|
signal,
|
|
95
96
|
responseSchema: DERIVED_MEMORY_JSON_SCHEMA,
|
|
96
97
|
onRetryAttempt,
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
3
|
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
4
|
import { ConfigError } from "../core/errors.js";
|
|
5
|
+
import { DEFAULT_LLM_TIMEOUT_MS } from "../integrations/agent/config.js";
|
|
5
6
|
import { buildExecution, resolveExecution } from "../integrations/agent/execution.js";
|
|
6
7
|
import { runExecution } from "../integrations/agent/runner-dispatch.js";
|
|
7
8
|
import { isContextSizeError, LlmCallError } from "./client.js";
|
|
@@ -22,8 +23,12 @@ export function classifyLlmError(err) {
|
|
|
22
23
|
function own(value, key) {
|
|
23
24
|
return value !== undefined && Object.hasOwn(value, key);
|
|
24
25
|
}
|
|
25
|
-
/**
|
|
26
|
-
|
|
26
|
+
/**
|
|
27
|
+
* @internal Exact request-to-cascade projection, exported for presence-semantics contracts.
|
|
28
|
+
* Model work is bounded: with no timeout from the request or the runner, it
|
|
29
|
+
* gets {@link DEFAULT_LLM_TIMEOUT_MS} on every runner kind.
|
|
30
|
+
*/
|
|
31
|
+
export function resolveStructuredCurrent(current, request, runner) {
|
|
27
32
|
const out = current ? { ...current } : {};
|
|
28
33
|
const requestHasInference = own(request, "temperature") || own(request, "maxTokens") || own(request, "enableThinking");
|
|
29
34
|
const baseInference = current?.inference && typeof current.inference === "object" && !Array.isArray(current.inference)
|
|
@@ -46,6 +51,9 @@ export function resolveStructuredCurrent(current, request) {
|
|
|
46
51
|
}
|
|
47
52
|
if (own(request, "timeoutMs"))
|
|
48
53
|
out.timeout = request?.timeoutMs ?? null;
|
|
54
|
+
else if (runner && !Object.hasOwn(runner, "timeoutMs") && !own(current, "timeout")) {
|
|
55
|
+
out.timeout = DEFAULT_LLM_TIMEOUT_MS;
|
|
56
|
+
}
|
|
49
57
|
return Object.keys(out).length > 0 ? out : undefined;
|
|
50
58
|
}
|
|
51
59
|
function requireTerminalUserMessage(messages) {
|
|
@@ -59,8 +67,17 @@ function requireTerminalUserMessage(messages) {
|
|
|
59
67
|
};
|
|
60
68
|
}
|
|
61
69
|
function dispatchFailure(result) {
|
|
62
|
-
const message = result.error ?? result.stderr ?? result.reason ?? "
|
|
63
|
-
|
|
70
|
+
const message = result.error ?? result.stderr ?? result.reason ?? "dispatch failed";
|
|
71
|
+
const error = result.llmErrorCode ? new LlmCallError(message, result.llmErrorCode) : new Error(message);
|
|
72
|
+
return Object.assign(error, { reason: result.reason, result });
|
|
73
|
+
}
|
|
74
|
+
/** The runner's failure reason (`timeout`, `aborted`, …) a failed dispatch threw with, whatever its kind. */
|
|
75
|
+
export function dispatchFailureReason(err) {
|
|
76
|
+
return err instanceof Error ? err.reason : undefined;
|
|
77
|
+
}
|
|
78
|
+
/** The failed dispatch's own result (an agent's exit code and stderr, say), whatever its kind. */
|
|
79
|
+
export function dispatchFailureResult(err) {
|
|
80
|
+
return err instanceof Error ? err.result : undefined;
|
|
64
81
|
}
|
|
65
82
|
export async function callStructured(opts) {
|
|
66
83
|
const { feature, akmConfig, enabled, messages, request, parse, onError, fallback, onFallback } = opts;
|
|
@@ -77,23 +94,28 @@ export async function callStructured(opts) {
|
|
|
77
94
|
}
|
|
78
95
|
const runner = opts.runner;
|
|
79
96
|
if (!runner)
|
|
80
|
-
throw new TypeError("callStructured requires a resolved
|
|
97
|
+
throw new TypeError("callStructured requires a resolved runner");
|
|
81
98
|
const terminal = requireTerminalUserMessage(messages);
|
|
99
|
+
// `gateSignal` aborts when the feature gate's timeout fires, so the dispatch stops with it.
|
|
100
|
+
// Every structured call is unattended model work, so it runs under the model-work tool policy.
|
|
82
101
|
const prepareInvocation = () => {
|
|
83
|
-
const current = resolveStructuredCurrent(opts.current, request);
|
|
84
102
|
const prepared = resolveExecution({
|
|
85
103
|
content: terminal.content,
|
|
86
104
|
conversation: terminal.conversation,
|
|
87
105
|
runner,
|
|
88
|
-
|
|
106
|
+
current: resolveStructuredCurrent(opts.current, request, runner),
|
|
107
|
+
modelWork: true,
|
|
89
108
|
});
|
|
90
109
|
const lowered = buildExecution(prepared.request, prepared.runner);
|
|
91
110
|
opts.onNotices?.(lowered.notices);
|
|
92
|
-
return async () => {
|
|
111
|
+
return async (gateSignal) => {
|
|
112
|
+
const signal = request?.signal && gateSignal ? AbortSignal.any([request.signal, gateSignal]) : (request?.signal ?? gateSignal);
|
|
113
|
+
const runOptions = { ...request?.runOptions, ...(signal ? { signal } : {}) };
|
|
93
114
|
const result = await runExecution(lowered, {
|
|
94
115
|
...(request?.chat ? { chat: request.chat } : {}),
|
|
116
|
+
...(request?.runSdk ? { runSdk: request.runSdk } : {}),
|
|
95
117
|
...(request?.onRetryAttempt ? { onRetryAttempt: request.onRetryAttempt } : {}),
|
|
96
|
-
...(
|
|
118
|
+
...(Object.keys(runOptions).length > 0 ? { runOptions } : {}),
|
|
97
119
|
});
|
|
98
120
|
if (!result.ok)
|
|
99
121
|
throw dispatchFailure(result);
|
|
@@ -111,9 +133,9 @@ export async function callStructured(opts) {
|
|
|
111
133
|
const invoke = prepareInvocation();
|
|
112
134
|
// GATED: run through `tryLlmFeature`. A throw inside is classified ONCE and
|
|
113
135
|
// routed to `onError`; `tryLlmFeature` returns `fallback` on disablement/timeout.
|
|
114
|
-
const outcome = await tryLlmFeature(feature, akmConfig, async () => {
|
|
136
|
+
const outcome = await tryLlmFeature(feature, akmConfig, async (gateSignal) => {
|
|
115
137
|
try {
|
|
116
|
-
return { kind: "value", value: await invoke() };
|
|
138
|
+
return { kind: "value", value: await invoke(gateSignal) };
|
|
117
139
|
}
|
|
118
140
|
catch (err) {
|
|
119
141
|
// Credential materialization remains dispatch-owned, so a missing
|