akm-cli 0.9.24 → 0.9.25-alpha.1

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.
Files changed (74) hide show
  1. package/CHANGELOG.md +294 -0
  2. package/dist/commands/health/checks.js +10 -11
  3. package/dist/commands/improve/consolidate/pair-pass.js +3 -2
  4. package/dist/commands/improve/consolidate.js +3 -2
  5. package/dist/commands/improve/execution.js +4 -10
  6. package/dist/commands/improve/extract-prompt.js +4 -4
  7. package/dist/commands/improve/extract.js +10 -13
  8. package/dist/commands/improve/improve-cli.js +32 -33
  9. package/dist/commands/improve/improve-strategies.js +49 -43
  10. package/dist/commands/improve/improve-usage-report.js +8 -17
  11. package/dist/commands/improve/preparation.js +3 -1
  12. package/dist/commands/improve/reflect.js +108 -172
  13. package/dist/commands/improve/stage.js +69 -18
  14. package/dist/commands/proposal/drain.js +14 -2
  15. package/dist/commands/proposal/proposal-cli.js +1 -5
  16. package/dist/commands/proposal/propose-cli.js +2 -2
  17. package/dist/commands/proposal/propose.js +80 -83
  18. package/dist/commands/remember.js +3 -3
  19. package/dist/commands/sources/schema-repair.js +1 -1
  20. package/dist/core/config/config-schema.js +37 -60
  21. package/dist/core/config/engine-semantics.js +15 -11
  22. package/dist/core/config/schema/engines.js +33 -15
  23. package/dist/core/config/schema/improve-processes.js +2 -2
  24. package/dist/core/improve-result.js +3 -3
  25. package/dist/core/structured.js +10 -0
  26. package/dist/execution/source.js +14 -0
  27. package/dist/indexer/passes/memory-inference.js +2 -1
  28. package/dist/integrations/agent/builder-shared.js +15 -0
  29. package/dist/integrations/agent/config.js +2 -0
  30. package/dist/integrations/agent/engine-resolution.js +16 -31
  31. package/dist/integrations/agent/execution.js +46 -21
  32. package/dist/integrations/agent/index.js +1 -1
  33. package/dist/integrations/agent/model-map.js +16 -15
  34. package/dist/integrations/agent/prompts.js +53 -76
  35. package/dist/integrations/agent/request-lowering.js +20 -9
  36. package/dist/integrations/agent/runner-dispatch.js +103 -4
  37. package/dist/integrations/agent/runner.js +8 -2
  38. package/dist/integrations/harnesses/aider/agent-builder.js +11 -23
  39. package/dist/integrations/harnesses/aider/index.js +0 -5
  40. package/dist/integrations/harnesses/amazonq/agent-builder.js +10 -21
  41. package/dist/integrations/harnesses/amazonq/index.js +0 -5
  42. package/dist/integrations/harnesses/claude/agent-builder.js +61 -38
  43. package/dist/integrations/harnesses/claude/index.js +0 -14
  44. package/dist/integrations/harnesses/codex/agent-builder.js +4 -4
  45. package/dist/integrations/harnesses/codex/index.js +0 -4
  46. package/dist/integrations/harnesses/copilot/agent-builder.js +4 -13
  47. package/dist/integrations/harnesses/copilot/index.js +2 -7
  48. package/dist/integrations/harnesses/gemini/agent-builder.js +4 -13
  49. package/dist/integrations/harnesses/gemini/index.js +0 -5
  50. package/dist/integrations/harnesses/ids.js +18 -10
  51. package/dist/integrations/harnesses/opencode/agent-builder.js +52 -10
  52. package/dist/integrations/harnesses/opencode/index.js +0 -8
  53. package/dist/integrations/harnesses/opencode/model-config.js +80 -0
  54. package/dist/integrations/harnesses/opencode/model-work-agent.js +80 -0
  55. package/dist/integrations/harnesses/opencode-sdk/harness.js +6 -7
  56. package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +168 -24
  57. package/dist/integrations/harnesses/openhands/agent-builder.js +8 -21
  58. package/dist/integrations/harnesses/openhands/index.js +0 -5
  59. package/dist/integrations/harnesses/pi/agent-builder.js +8 -21
  60. package/dist/integrations/harnesses/pi/index.js +0 -5
  61. package/dist/llm/client.js +5 -0
  62. package/dist/llm/feature-gate.js +10 -4
  63. package/dist/llm/index-passes.js +3 -6
  64. package/dist/llm/memory-infer.js +6 -5
  65. package/dist/llm/structured-call.js +33 -11
  66. package/dist/scripts/akm-migrate-node.js +298 -204
  67. package/dist/scripts/akm-migrate.js +298 -204
  68. package/dist/workflows/exec/step-work.js +6 -5
  69. package/dist/workflows/freeze/step-values.js +1 -1
  70. package/docs/reference/cli.md +29 -11
  71. package/docs/reference/configuration.md +168 -11
  72. package/docs/reference/workflow-schema.md +13 -9
  73. package/package.json +1 -1
  74. package/schemas/akm-config.json +36 -0
@@ -1,8 +1,8 @@
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";
5
+ import { MODEL_WORK_TOOLS } from "../execution/source.js";
6
6
  import { buildExecution, resolveExecution } from "../integrations/agent/execution.js";
7
7
  const NO_LOWERING_NOTICES = Object.freeze([]);
8
8
  function own(value, key) {
@@ -38,16 +38,13 @@ export function resolveIndexPassExecution(passName, config) {
38
38
  ...indexExecutionDefaults(defaults),
39
39
  ...(!own(defaults, "engine") && fallbackLlmEngine ? { engine: fallbackLlmEngine } : {}),
40
40
  };
41
+ // Under the model-work tool policy, so an engine that cannot confine it is refused here.
41
42
  const prepared = resolveExecution({
42
43
  content: "",
43
44
  config,
44
45
  invocationDefaults,
45
- current: indexExecutionDefaults(pass),
46
+ current: { ...indexExecutionDefaults(pass), tools: MODEL_WORK_TOOLS },
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
  }
@@ -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 to providers that
38
- * opt in via `runner.connection.supportsJsonSchema = true`; the client
39
- * silently drops the schema for providers that don't.
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.connection.temperature ?? 0.1,
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,8 @@
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 { MODEL_WORK_TOOLS } from "../execution/source.js";
6
+ import { DEFAULT_MODEL_WORK_TIMEOUT_MS } from "../integrations/agent/config.js";
5
7
  import { buildExecution, resolveExecution } from "../integrations/agent/execution.js";
6
8
  import { runExecution } from "../integrations/agent/runner-dispatch.js";
7
9
  import { isContextSizeError, LlmCallError } from "./client.js";
@@ -22,8 +24,12 @@ export function classifyLlmError(err) {
22
24
  function own(value, key) {
23
25
  return value !== undefined && Object.hasOwn(value, key);
24
26
  }
25
- /** @internal Exact request-to-cascade projection, exported for presence-semantics contracts. */
26
- export function resolveStructuredCurrent(current, request) {
27
+ /**
28
+ * @internal Exact request-to-cascade projection, exported for presence-semantics contracts.
29
+ * Model work is bounded: with no timeout from the request or the runner, it
30
+ * gets {@link DEFAULT_MODEL_WORK_TIMEOUT_MS} on every runner kind.
31
+ */
32
+ export function resolveStructuredCurrent(current, request, runner) {
27
33
  const out = current ? { ...current } : {};
28
34
  const requestHasInference = own(request, "temperature") || own(request, "maxTokens") || own(request, "enableThinking");
29
35
  const baseInference = current?.inference && typeof current.inference === "object" && !Array.isArray(current.inference)
@@ -46,6 +52,9 @@ export function resolveStructuredCurrent(current, request) {
46
52
  }
47
53
  if (own(request, "timeoutMs"))
48
54
  out.timeout = request?.timeoutMs ?? null;
55
+ else if (runner && !Object.hasOwn(runner, "timeoutMs") && !own(current, "timeout")) {
56
+ out.timeout = DEFAULT_MODEL_WORK_TIMEOUT_MS;
57
+ }
49
58
  return Object.keys(out).length > 0 ? out : undefined;
50
59
  }
51
60
  function requireTerminalUserMessage(messages) {
@@ -59,8 +68,17 @@ function requireTerminalUserMessage(messages) {
59
68
  };
60
69
  }
61
70
  function dispatchFailure(result) {
62
- const message = result.error ?? result.stderr ?? result.reason ?? "LLM dispatch failed";
63
- return result.llmErrorCode ? new LlmCallError(message, result.llmErrorCode) : new Error(message);
71
+ const message = result.error ?? result.stderr ?? result.reason ?? "dispatch failed";
72
+ const error = result.llmErrorCode ? new LlmCallError(message, result.llmErrorCode) : new Error(message);
73
+ return Object.assign(error, { reason: result.reason, result });
74
+ }
75
+ /** The runner's failure reason (`timeout`, `aborted`, …) a failed dispatch threw with, whatever its kind. */
76
+ export function dispatchFailureReason(err) {
77
+ return err instanceof Error ? err.reason : undefined;
78
+ }
79
+ /** The failed dispatch's own result (an agent's exit code and stderr, say), whatever its kind. */
80
+ export function dispatchFailureResult(err) {
81
+ return err instanceof Error ? err.result : undefined;
64
82
  }
65
83
  export async function callStructured(opts) {
66
84
  const { feature, akmConfig, enabled, messages, request, parse, onError, fallback, onFallback } = opts;
@@ -77,23 +95,27 @@ export async function callStructured(opts) {
77
95
  }
78
96
  const runner = opts.runner;
79
97
  if (!runner)
80
- throw new TypeError("callStructured requires a resolved LLM runner");
98
+ throw new TypeError("callStructured requires a resolved runner");
81
99
  const terminal = requireTerminalUserMessage(messages);
100
+ // `gateSignal` aborts when the feature gate's timeout fires, so the dispatch stops with it.
101
+ // Every structured call is unattended model work, so it runs under the model-work tool policy.
82
102
  const prepareInvocation = () => {
83
- const current = resolveStructuredCurrent(opts.current, request);
84
103
  const prepared = resolveExecution({
85
104
  content: terminal.content,
86
105
  conversation: terminal.conversation,
87
106
  runner,
88
- ...(current ? { current } : {}),
107
+ current: { ...resolveStructuredCurrent(opts.current, request, runner), tools: MODEL_WORK_TOOLS },
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
- ...(own(request, "signal") ? { runOptions: { signal: request?.signal } } : {}),
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