akm-cli 0.9.23 → 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.
- package/CHANGELOG.md +339 -0
- package/dist/commands/health/checks.js +10 -11
- package/dist/commands/improve/consolidate/pair-pass.js +3 -2
- package/dist/commands/improve/consolidate.js +3 -2
- package/dist/commands/improve/execution.js +4 -10
- package/dist/commands/improve/extract-prompt.js +4 -4
- package/dist/commands/improve/extract.js +10 -13
- package/dist/commands/improve/improve-cli.js +32 -33
- package/dist/commands/improve/improve-strategies.js +49 -43
- package/dist/commands/improve/improve-usage-report.js +8 -17
- package/dist/commands/improve/preparation.js +3 -1
- package/dist/commands/improve/reflect.js +132 -177
- package/dist/commands/improve/stage.js +69 -18
- package/dist/commands/proposal/drain.js +19 -7
- package/dist/commands/proposal/proposal-cli.js +1 -5
- package/dist/commands/proposal/propose-cli.js +2 -2
- package/dist/commands/proposal/propose.js +80 -83
- 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/engines.js +33 -15
- package/dist/core/config/schema/improve-processes.js +2 -2
- package/dist/core/improve-result.js +3 -3
- package/dist/core/structured.js +10 -0
- package/dist/execution/source.js +14 -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 +2 -0
- package/dist/integrations/agent/engine-resolution.js +16 -31
- package/dist/integrations/agent/execution.js +46 -21
- package/dist/integrations/agent/index.js +1 -1
- package/dist/integrations/agent/model-map.js +16 -15
- package/dist/integrations/agent/prompts.js +53 -76
- package/dist/integrations/agent/request-lowering.js +20 -9
- package/dist/integrations/agent/runner-dispatch.js +103 -4
- package/dist/integrations/agent/runner.js +8 -2
- package/dist/integrations/harnesses/aider/agent-builder.js +11 -23
- package/dist/integrations/harnesses/aider/index.js +0 -5
- package/dist/integrations/harnesses/amazonq/agent-builder.js +10 -21
- package/dist/integrations/harnesses/amazonq/index.js +0 -5
- package/dist/integrations/harnesses/claude/agent-builder.js +61 -38
- package/dist/integrations/harnesses/claude/index.js +0 -14
- package/dist/integrations/harnesses/codex/agent-builder.js +4 -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 +18 -10
- package/dist/integrations/harnesses/opencode/agent-builder.js +52 -10
- package/dist/integrations/harnesses/opencode/index.js +0 -8
- package/dist/integrations/harnesses/opencode/model-config.js +80 -0
- package/dist/integrations/harnesses/opencode/model-work-agent.js +80 -0
- package/dist/integrations/harnesses/opencode-sdk/harness.js +6 -7
- package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +168 -24
- package/dist/integrations/harnesses/openhands/agent-builder.js +8 -21
- package/dist/integrations/harnesses/openhands/index.js +0 -5
- package/dist/integrations/harnesses/pi/agent-builder.js +8 -21
- package/dist/integrations/harnesses/pi/index.js +0 -5
- package/dist/llm/client.js +5 -0
- package/dist/llm/feature-gate.js +10 -4
- package/dist/llm/index-passes.js +3 -6
- package/dist/llm/memory-infer.js +6 -5
- package/dist/llm/structured-call.js +33 -11
- package/dist/scripts/akm-migrate-node.js +298 -204
- package/dist/scripts/akm-migrate.js +298 -204
- package/dist/workflows/exec/step-work.js +6 -5
- package/dist/workflows/freeze/step-values.js +1 -1
- package/docs/reference/cli.md +34 -14
- package/docs/reference/configuration.md +171 -12
- package/docs/reference/workflow-schema.md +13 -9
- package/package.json +1 -1
- package/schemas/akm-config.json +36 -0
|
@@ -15,6 +15,7 @@ import { redactSensitiveText } from "../../core/redaction.js";
|
|
|
15
15
|
import { clearLogFile, setLogFile, warn } from "../../core/warn.js";
|
|
16
16
|
import { resolveWriteTarget } from "../../core/write-source.js";
|
|
17
17
|
import { DEFAULT_LLM_TIMEOUT_MS } from "../../integrations/agent/config.js";
|
|
18
|
+
import { defaultWhich } from "../../integrations/agent/detect.js";
|
|
18
19
|
import { collectEngineCredentialValues } from "../../integrations/agent/engine-resolution.js";
|
|
19
20
|
import { probeLlmReachable } from "../../llm/client.js";
|
|
20
21
|
import { getOutputMode } from "../../output/context.js";
|
|
@@ -73,26 +74,19 @@ function assertRequiredEnginesAvailable(plan) {
|
|
|
73
74
|
const lines = plan.engineUnavailable.map((item) => ` - ${item.process} (${item.configKey}): ${item.reason}`);
|
|
74
75
|
throw new ConfigError(`--require-engines: ${plan.engineUnavailable.length} improve process${plan.engineUnavailable.length === 1 ? "" : "es"} cannot run because ${plan.engineUnavailable.length === 1 ? "its" : "their"} engine is unavailable:\n${lines.join("\n")}`, "LLM_NOT_CONFIGURED");
|
|
75
76
|
}
|
|
76
|
-
/** Every
|
|
77
|
+
/** Every engine the plan would dispatch to, triage's judgment engine included. */
|
|
77
78
|
function collectRequiredEngineTargets(plan) {
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
targets.push({
|
|
90
|
-
process: "triage.judgment",
|
|
91
|
-
engine: plan.triageJudgment.engine,
|
|
92
|
-
connection: probeConnection(plan.triageJudgment),
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
return targets;
|
|
79
|
+
const runners = Object.entries(plan.processes)
|
|
80
|
+
.flatMap(([processName, process]) => (process.runner ? [[processName, process.runner]] : []))
|
|
81
|
+
.concat(plan.triageJudgment ? [["triage.judgment", plan.triageJudgment]] : []);
|
|
82
|
+
return runners.map(([processName, runner]) => ({
|
|
83
|
+
process: processName,
|
|
84
|
+
engine: runner.engine,
|
|
85
|
+
...(runner.kind === "llm" ? { connection: probeConnection(runner) } : { bin: runner.profile.bin }),
|
|
86
|
+
...(runner.kind === "sdk" && runner.fallbackConnection
|
|
87
|
+
? { connection: probeConnection({ connection: runner.fallbackConnection, timeoutMs: runner.fallbackTimeoutMs }) }
|
|
88
|
+
: {}),
|
|
89
|
+
}));
|
|
96
90
|
}
|
|
97
91
|
/** The resolved engine keeps its request timeout beside the connection (the runtime merges it in); the probe needs it on the connection. */
|
|
98
92
|
function probeConnection(runner) {
|
|
@@ -112,37 +106,42 @@ const REQUIRED_ENGINE_PROBE_MAX_MS = 120_000;
|
|
|
112
106
|
/**
|
|
113
107
|
* `--require-engines`, live: probe each connection's real completion path
|
|
114
108
|
* (a gateway can list a model whose completion route is dead, #980), once per
|
|
115
|
-
* endpoint + model, within {@link requiredEngineProbeTimeoutMs}
|
|
116
|
-
*
|
|
109
|
+
* endpoint + model, within {@link requiredEngineProbeTimeoutMs}, and look each
|
|
110
|
+
* agent harness's binary up on PATH. Returns each target's latency for the run
|
|
111
|
+
* result (R17); an unreachable one fails the run.
|
|
117
112
|
*/
|
|
118
|
-
export async function assertRequiredEnginesReachable(plan, probeReachable = (connection) => probeLlmReachable(connection, requiredEngineProbeTimeoutMs(connection))) {
|
|
113
|
+
export async function assertRequiredEnginesReachable(plan, probeReachable = (connection) => probeLlmReachable(connection, requiredEngineProbeTimeoutMs(connection)), which = defaultWhich) {
|
|
119
114
|
const targets = collectRequiredEngineTargets(plan);
|
|
120
115
|
if (targets.length === 0)
|
|
121
116
|
return [];
|
|
122
117
|
const probesByConnection = new Map();
|
|
123
|
-
const
|
|
124
|
-
const key = `${
|
|
118
|
+
const probeConnectionOnce = (connection) => {
|
|
119
|
+
const key = `${connection.endpoint.replace(/\/+$/, "")}|${connection.model}`;
|
|
125
120
|
let pending = probesByConnection.get(key);
|
|
126
121
|
if (!pending) {
|
|
127
122
|
const probeStartedAt = Date.now();
|
|
128
|
-
pending = probeReachable(
|
|
129
|
-
reach,
|
|
130
|
-
latencyMs: Date.now() - probeStartedAt,
|
|
131
|
-
}));
|
|
123
|
+
pending = probeReachable(connection).then((reach) => ({ reach, latencyMs: Date.now() - probeStartedAt }));
|
|
132
124
|
probesByConnection.set(key, pending);
|
|
133
125
|
}
|
|
134
|
-
|
|
135
|
-
|
|
126
|
+
return pending;
|
|
127
|
+
};
|
|
128
|
+
const probed = await Promise.all(targets.map(async (target) => {
|
|
129
|
+
if (target.bin !== undefined && which(target.bin) === undefined) {
|
|
130
|
+
return { ...target, reach: { reachable: false, error: `${target.bin} is not on PATH` }, latencyMs: 0 };
|
|
131
|
+
}
|
|
132
|
+
if (!target.connection)
|
|
133
|
+
return { ...target, reach: { reachable: true }, latencyMs: 0 };
|
|
134
|
+
return { ...target, ...(await probeConnectionOnce(target.connection)) };
|
|
136
135
|
}));
|
|
137
136
|
const unreachable = probed.filter((item) => !item.reach.reachable);
|
|
138
137
|
if (unreachable.length > 0) {
|
|
139
|
-
const lines = unreachable.map((item) => ` - ${item.process} (engine "${item.engine}", ${item.connection.
|
|
140
|
-
throw new ConfigError(`--require-engines: ${unreachable.length} improve process${unreachable.length === 1 ? "" : "es"} cannot run because ${unreachable.length === 1 ? "its" : "their"} engine completion path is not reachable:\n${lines.join("\n")}`, "LLM_NOT_CONFIGURED", "Check that each listed endpoint is up and serves its model. The probe is one short completion, bounded by the engine's timeoutMs (at most two minutes).");
|
|
138
|
+
const lines = unreachable.map((item) => ` - ${item.process} (engine "${item.engine}", ${item.connection?.endpoint ?? item.bin}): ${item.reach.error ?? "did not respond"}`);
|
|
139
|
+
throw new ConfigError(`--require-engines: ${unreachable.length} improve process${unreachable.length === 1 ? "" : "es"} cannot run because ${unreachable.length === 1 ? "its" : "their"} engine completion path is not reachable:\n${lines.join("\n")}`, "LLM_NOT_CONFIGURED", "Check that each listed endpoint is up and serves its model, and that each listed agent binary is installed. The endpoint probe is one short completion, bounded by the engine's timeoutMs (at most two minutes).");
|
|
141
140
|
}
|
|
142
141
|
return probed.map((item) => ({
|
|
143
142
|
process: item.process,
|
|
144
143
|
engine: item.engine,
|
|
145
|
-
endpoint: item.connection.
|
|
144
|
+
endpoint: item.connection?.endpoint ?? item.bin,
|
|
146
145
|
reachable: item.reach.reachable,
|
|
147
146
|
latencyMs: item.latencyMs,
|
|
148
147
|
}));
|
|
@@ -11,11 +11,12 @@ import thorough from "../../assets/improve-strategies/thorough.json" with { type
|
|
|
11
11
|
import { conceptIdFromTypeName, parseRefInput } from "../../core/asset/resolve-ref.js";
|
|
12
12
|
import { ImproveProfileConfigSchema } from "../../core/config/config-schema.js";
|
|
13
13
|
import { deepMergeConfig } from "../../core/config/deep-merge.js";
|
|
14
|
-
import { BUILTIN_IMPROVE_STRATEGY_NAMES,
|
|
14
|
+
import { BUILTIN_IMPROVE_STRATEGY_NAMES, IMPROVE_ENGINE_PROCESSES, IMPROVE_PROCESS_NAMES, } from "../../core/config/engine-semantics.js";
|
|
15
15
|
import { ConfigError } from "../../core/errors.js";
|
|
16
|
-
import { describeLlmCredentialAvailability } from "../../integrations/agent/engine-resolution.js";
|
|
16
|
+
import { describeLlmCredentialAvailability, } from "../../integrations/agent/engine-resolution.js";
|
|
17
|
+
import { runnerLlmConnection } from "../../integrations/agent/runner.js";
|
|
17
18
|
import { applyAutonomyGate } from "./autonomy-gate.js";
|
|
18
|
-
import { resolveImproveExecution
|
|
19
|
+
import { resolveImproveExecution } from "./execution.js";
|
|
19
20
|
import { stripBundle } from "./ledger.js";
|
|
20
21
|
export const DEFAULT_ALLOWED_TYPES = {
|
|
21
22
|
reflect: ["agent", "command", "knowledge", "lesson", "memory", "skill", "workflow"],
|
|
@@ -113,9 +114,14 @@ export function resolveImproveStrategy(name, config) {
|
|
|
113
114
|
const resolved = deepMergeConfig(baseStrategy, (userStrategies[selectedName] ?? {}));
|
|
114
115
|
return { name: selectedName, config: ImproveProfileConfigSchema.parse(resolved) };
|
|
115
116
|
}
|
|
117
|
+
/**
|
|
118
|
+
* The processes that make their own model calls, so the plan resolves a runner
|
|
119
|
+
* for each: every engine process but triage, whose engine is its judgment's.
|
|
120
|
+
*/
|
|
121
|
+
export const MODEL_CALLING_PROCESSES = new Set(IMPROVE_ENGINE_PROCESSES.filter((name) => name !== "triage"));
|
|
116
122
|
/**
|
|
117
123
|
* Project a resolved improve plan into one routing row per
|
|
118
|
-
* {@link
|
|
124
|
+
* {@link IMPROVE_PROCESS_NAMES} name, plus a `"triage.judgment"`
|
|
119
125
|
* pseudo-row when the strategy configures a judgment engine. Pure — no I/O,
|
|
120
126
|
* no re-resolution. Shared by `improve --dry-run`'s `plan.processes` (#947)
|
|
121
127
|
* and `akm health`'s post-run reporting (#944); health's own
|
|
@@ -124,14 +130,18 @@ export function resolveImproveStrategy(name, config) {
|
|
|
124
130
|
export function projectResolvedProcessRouting(plan) {
|
|
125
131
|
const unavailableByProcess = new Map(plan.engineUnavailable.map((item) => [item.process, item]));
|
|
126
132
|
const rows = [];
|
|
127
|
-
for (const processName of
|
|
133
|
+
for (const processName of IMPROVE_PROCESS_NAMES) {
|
|
128
134
|
const process = plan.processes[processName];
|
|
129
135
|
const unavailable = unavailableByProcess.get(processName);
|
|
130
136
|
rows.push({
|
|
131
137
|
process: processName,
|
|
132
138
|
enabled: process.enabled,
|
|
133
139
|
...(process.runner
|
|
134
|
-
? {
|
|
140
|
+
? {
|
|
141
|
+
engine: process.runner.engine,
|
|
142
|
+
model: runnerLlmConnection(process.runner)?.model,
|
|
143
|
+
engineKind: process.runner.kind,
|
|
144
|
+
}
|
|
135
145
|
: // #800/#957 round 3 — a credential-unavailable process never carries a
|
|
136
146
|
// runner, but its structurally resolved engine/model is still worth
|
|
137
147
|
// showing in the routing table (dry-run preview, health probe).
|
|
@@ -192,6 +202,22 @@ export function resolveImprovePlan(name, config, options = {}) {
|
|
|
192
202
|
function credentialUnavailableReason(engineName, status) {
|
|
193
203
|
return `requires a credential that is not available in this process's environment (engine "${engineName}": ${status.reason})`;
|
|
194
204
|
}
|
|
205
|
+
/**
|
|
206
|
+
* Whether the credential akm reads for `runner` is reachable in `env`: an LLM
|
|
207
|
+
* engine's own, or an SDK engine's LLM fallback. An agent CLI reads its own.
|
|
208
|
+
*/
|
|
209
|
+
function runnerCredentialStatus(runner, env) {
|
|
210
|
+
if (runner.kind === "llm")
|
|
211
|
+
return describeLlmCredentialAvailability(runner, env);
|
|
212
|
+
if (runner.kind === "sdk") {
|
|
213
|
+
return describeLlmCredentialAvailability({
|
|
214
|
+
credential: runner.fallbackCredential,
|
|
215
|
+
apiKeyFile: runner.fallbackApiKeyFile,
|
|
216
|
+
apiKeySecretRef: runner.fallbackApiKeySecretRef,
|
|
217
|
+
}, env);
|
|
218
|
+
}
|
|
219
|
+
return { available: true };
|
|
220
|
+
}
|
|
195
221
|
function buildImprovePlan(strategy, config, options) {
|
|
196
222
|
const env = options.env ?? process.env;
|
|
197
223
|
const processes = {};
|
|
@@ -205,12 +231,12 @@ function buildImprovePlan(strategy, config, options) {
|
|
|
205
231
|
// install is not the credential-in-the-wrong-environment case this option
|
|
206
232
|
// exists for.
|
|
207
233
|
let anyEngineNotConfigured = false;
|
|
208
|
-
for (const processName of
|
|
234
|
+
for (const processName of IMPROVE_PROCESS_NAMES) {
|
|
209
235
|
const sourceProcessConfig = strategy.config.processes?.[processName] ?? {};
|
|
210
236
|
const enabled = sourceProcessConfig.enabled === true;
|
|
211
237
|
let runner = null;
|
|
212
238
|
let notices = [];
|
|
213
|
-
if (
|
|
239
|
+
if (!MODEL_CALLING_PROCESSES.has(processName) || !enabled) {
|
|
214
240
|
processes[processName] = Object.freeze({ enabled, config: cloneAndFreeze(sourceProcessConfig), runner });
|
|
215
241
|
continue;
|
|
216
242
|
}
|
|
@@ -227,7 +253,7 @@ function buildImprovePlan(strategy, config, options) {
|
|
|
227
253
|
// without the runner ever carrying a credential-less connection forward.
|
|
228
254
|
let credentialUnavailableRouting;
|
|
229
255
|
if (!skipsRepairEngine) {
|
|
230
|
-
const resolved =
|
|
256
|
+
const resolved = resolveImproveExecution({
|
|
231
257
|
config,
|
|
232
258
|
profile: strategy.config,
|
|
233
259
|
process: sourceProcessConfig,
|
|
@@ -236,15 +262,14 @@ function buildImprovePlan(strategy, config, options) {
|
|
|
236
262
|
runner = resolved?.runner ?? null;
|
|
237
263
|
notices = resolved?.notices ?? [];
|
|
238
264
|
if (runner) {
|
|
239
|
-
const credentialStatus =
|
|
265
|
+
const credentialStatus = runnerCredentialStatus(runner, env);
|
|
240
266
|
if (!credentialStatus.available) {
|
|
267
|
+
const connection = runnerLlmConnection(runner);
|
|
241
268
|
credentialUnavailableMessage = credentialUnavailableReason(runner.engine, credentialStatus);
|
|
242
269
|
credentialUnavailableRouting = {
|
|
243
270
|
engine: runner.engine,
|
|
244
|
-
...(
|
|
245
|
-
...(
|
|
246
|
-
? { contextLength: runner.connection.contextLength }
|
|
247
|
-
: {}),
|
|
271
|
+
...(connection?.model !== undefined ? { model: connection.model } : {}),
|
|
272
|
+
...(connection?.contextLength !== undefined ? { contextLength: connection.contextLength } : {}),
|
|
248
273
|
};
|
|
249
274
|
runner = null;
|
|
250
275
|
notices = [];
|
|
@@ -259,7 +284,7 @@ function buildImprovePlan(strategy, config, options) {
|
|
|
259
284
|
process: processName,
|
|
260
285
|
configKey,
|
|
261
286
|
reason: credentialUnavailableMessage ??
|
|
262
|
-
`requires an
|
|
287
|
+
`requires an engine that is not configured. Set defaults.llmEngine or ${configKey}`,
|
|
263
288
|
...credentialUnavailableRouting,
|
|
264
289
|
});
|
|
265
290
|
processes[processName] = Object.freeze({
|
|
@@ -282,7 +307,7 @@ function buildImprovePlan(strategy, config, options) {
|
|
|
282
307
|
!Object.values(processes).some((process) => process.enabled) &&
|
|
283
308
|
(!options.allowAllDisabled || anyEngineNotConfigured)) {
|
|
284
309
|
const names = engineUnavailable.map((item) => `"${item.process}"`).join(", ");
|
|
285
|
-
throw new ConfigError(`No improve process can run: ${names} ${engineUnavailable.length === 1 ? "requires" : "require"} an
|
|
310
|
+
throw new ConfigError(`No improve process can run: ${names} ${engineUnavailable.length === 1 ? "requires" : "require"} an engine that is not configured. Set defaults.llmEngine, or the per-process engine key named for each.`, "LLM_NOT_CONFIGURED");
|
|
286
311
|
}
|
|
287
312
|
const triage = strategy.config.processes?.triage;
|
|
288
313
|
const judgmentEnabled = triage?.judgment?.enabled === true;
|
|
@@ -296,10 +321,6 @@ function buildImprovePlan(strategy, config, options) {
|
|
|
296
321
|
})
|
|
297
322
|
: null;
|
|
298
323
|
let triageJudgment = triageJudgmentResolution?.runner ?? null;
|
|
299
|
-
const effectiveJudgmentLlm = triage?.judgment?.llm ?? triage?.llm ?? strategy.config.llm;
|
|
300
|
-
if (triageJudgment && triageJudgment.kind !== "llm" && effectiveJudgmentLlm) {
|
|
301
|
-
throw new ConfigError(`Triage judgment engine "${triageJudgment.engine ?? "unknown"}" is an agent engine and cannot receive llm overrides.`, "INVALID_CONFIG_FILE");
|
|
302
|
-
}
|
|
303
324
|
if (processes.triage.enabled && judgmentEnabled && !triageJudgment) {
|
|
304
325
|
throw new ConfigError(`Enabled improve triage judgment requires an engine. Set defaults.llmEngine or improve.strategies.${strategy.name}.processes.triage.judgment.engine.`, "LLM_NOT_CONFIGURED");
|
|
305
326
|
}
|
|
@@ -310,29 +331,14 @@ function buildImprovePlan(strategy, config, options) {
|
|
|
310
331
|
// `engineUnavailable` under the reserved `"triage.judgment"` process name
|
|
311
332
|
// instead of silently reaching dispatch with a doomed credential.
|
|
312
333
|
if (triageJudgment) {
|
|
313
|
-
const
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
credential: triageJudgment.fallbackCredential,
|
|
322
|
-
apiKeyFile: triageJudgment.fallbackApiKeyFile,
|
|
323
|
-
apiKeySecretRef: triageJudgment.fallbackApiKeySecretRef,
|
|
324
|
-
}
|
|
325
|
-
: undefined;
|
|
326
|
-
if (judgmentCredentialFields) {
|
|
327
|
-
const credentialStatus = describeLlmCredentialAvailability(judgmentCredentialFields, env);
|
|
328
|
-
if (!credentialStatus.available) {
|
|
329
|
-
engineUnavailable.push({
|
|
330
|
-
process: "triage.judgment",
|
|
331
|
-
configKey: `improve.strategies.${strategy.name}.processes.triage.judgment.engine`,
|
|
332
|
-
reason: credentialUnavailableReason(triageJudgment.engine, credentialStatus),
|
|
333
|
-
});
|
|
334
|
-
triageJudgment = null;
|
|
335
|
-
}
|
|
334
|
+
const credentialStatus = runnerCredentialStatus(triageJudgment, env);
|
|
335
|
+
if (!credentialStatus.available) {
|
|
336
|
+
engineUnavailable.push({
|
|
337
|
+
process: "triage.judgment",
|
|
338
|
+
configKey: `improve.strategies.${strategy.name}.processes.triage.judgment.engine`,
|
|
339
|
+
reason: credentialUnavailableReason(triageJudgment.engine, credentialStatus),
|
|
340
|
+
});
|
|
341
|
+
triageJudgment = null;
|
|
336
342
|
}
|
|
337
343
|
}
|
|
338
344
|
const frozenProcesses = Object.freeze(processes);
|
|
@@ -1,20 +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
|
-
|
|
5
|
-
|
|
6
|
-
* plus the enabled processes that made no call and why, rendered as one table
|
|
7
|
-
* for the end-of-run stderr summary and `akm improve report`.
|
|
8
|
-
*/
|
|
9
|
-
import { IMPROVE_PROCESS_ENGINE_CAPABILITIES } from "../../core/config/engine-semantics.js";
|
|
10
|
-
import { eligibleRefCount, projectResolvedProcessRouting, } from "./improve-strategies.js";
|
|
11
|
-
/**
|
|
12
|
-
* Only processes that call an LLM themselves: triage (a runner, attributed to
|
|
13
|
-
* its judgment engine) and proactive maintenance (no engine) would always read
|
|
14
|
-
* as "zero calls".
|
|
15
|
-
*/
|
|
16
|
-
const LLM_BACKED_PROCESSES = new Set(Object.keys(IMPROVE_PROCESS_ENGINE_CAPABILITIES).filter((name) => IMPROVE_PROCESS_ENGINE_CAPABILITIES[name] === "llm"));
|
|
17
|
-
/** The autonomy lane gating each LLM-backed process, if any. */
|
|
4
|
+
import { eligibleRefCount, MODEL_CALLING_PROCESSES, projectResolvedProcessRouting, } from "./improve-strategies.js";
|
|
5
|
+
/** The autonomy lane gating each model-calling process, if any. */
|
|
18
6
|
const AUTONOMY_LANE_BY_PROCESS = {
|
|
19
7
|
memoryInference: "memoryInference",
|
|
20
8
|
};
|
|
@@ -30,7 +18,7 @@ function dominantReason(counts) {
|
|
|
30
18
|
return best;
|
|
31
19
|
}
|
|
32
20
|
/**
|
|
33
|
-
* Why
|
|
21
|
+
* Why a model-calling process made no call, in priority order: its engine is
|
|
34
22
|
* unavailable; disabled — `autonomy_gated` when its lane was gated, else
|
|
35
23
|
* nothing to report; every ref strategy-filtered; its dominant skip reason;
|
|
36
24
|
* else `no_signal`. The reasons are the ones the events and results already
|
|
@@ -65,8 +53,11 @@ function countReflectSkipReasons(actions) {
|
|
|
65
53
|
}
|
|
66
54
|
/** This run's `usageReport`, or `undefined` when both halves are empty. */
|
|
67
55
|
export function buildImproveUsageReport(args) {
|
|
68
|
-
//
|
|
69
|
-
|
|
56
|
+
// Only the processes that call a model themselves, on any engine kind: triage
|
|
57
|
+
// (attributed to its judgment) and proactive maintenance (no engine) would
|
|
58
|
+
// always read as "zero calls". The "triage.judgment" row is dropped too: its
|
|
59
|
+
// calls are never attributed to it (#947).
|
|
60
|
+
const routing = projectResolvedProcessRouting(args.resolvedPlan).filter((row) => row.process !== "triage.judgment" && MODEL_CALLING_PROCESSES.has(row.process));
|
|
70
61
|
const calledProcesses = new Set(args.byProcessEngineModel.filter((row) => row.calls > 0).map((row) => row.process));
|
|
71
62
|
const reflectSkipCounts = countReflectSkipReasons(args.persistedActions);
|
|
72
63
|
const noCalls = [];
|
|
@@ -24,6 +24,7 @@ import { appendEvent, readEvents } from "../../core/events.js";
|
|
|
24
24
|
import { withStateDb } from "../../core/state-db.js";
|
|
25
25
|
import { info, warn } from "../../core/warn.js";
|
|
26
26
|
import { countUsageEventsByType, USAGE_EVENT_RETENTION_DAYS } from "../../indexer/usage/usage-events.js";
|
|
27
|
+
import { runnerLlmConnection } from "../../integrations/agent/runner.js";
|
|
27
28
|
import { getAvailableHarnesses } from "../../integrations/session-logs/index.js";
|
|
28
29
|
import { getZeroResultSearches } from "../../storage/repositories/index-entries-repository.js";
|
|
29
30
|
import { getRetrievalCounts } from "../../storage/repositories/index-utility-repository.js";
|
|
@@ -119,7 +120,8 @@ function planConsolidationPass(args) {
|
|
|
119
120
|
: { poolSize: 0, candidatePoolSize: 0, judgedUnchanged: 0 };
|
|
120
121
|
// A credential-unavailable engine still resolved its context length.
|
|
121
122
|
const unavailable = resolvedPlan.engineUnavailable.find((item) => item.process === "consolidate");
|
|
122
|
-
const chunkSize = computeSafeChunkSize(resolvedPlan.processes.consolidate.runner
|
|
123
|
+
const chunkSize = computeSafeChunkSize((resolvedPlan.processes.consolidate.runner &&
|
|
124
|
+
runnerLlmConnection(resolvedPlan.processes.consolidate.runner)?.contextLength) ??
|
|
123
125
|
unavailable?.contextLength ??
|
|
124
126
|
DEFAULT_CONTEXT_LENGTH_TOKENS, 500, processConfig?.maxChunkSize);
|
|
125
127
|
const profilePassed = processConfig?.enabled !== false;
|