akm-cli 0.9.14 → 0.9.15-beta.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 +397 -0
- package/STABILITY.md +6 -3
- package/dist/assets/prompts/reflect-feedback-framing.md +1 -0
- package/dist/assets/prompts/reflect-llm-framed-contract.md +2 -0
- package/dist/assets/prompts/reflect-llm-schema-contract.md +2 -0
- package/dist/assets/tasks/core/improve.yml +1 -1
- package/dist/assets/tasks/core/index-refresh.yml +1 -1
- package/dist/assets/tasks/improve/akm-graph-refresh-weekly.yml +1 -1
- package/dist/assets/tasks/improve/akm-improve-catchup.yml +1 -1
- package/dist/assets/tasks/improve/akm-improve-consolidate.yml +1 -1
- package/dist/assets/tasks/improve/akm-improve-frequent.yml +1 -1
- package/dist/assets/tasks/improve/akm-improve-nightly.yml +1 -1
- package/dist/cli/retired-commands.js +0 -1
- package/dist/cli/shared.js +9 -0
- package/dist/cli/unknown-flags.js +1 -0
- package/dist/cli.js +3 -2
- package/dist/commands/config-cli.js +85 -3
- package/dist/commands/env/env-cli.js +1 -42
- package/dist/commands/env/env.js +1 -1
- package/dist/commands/env/secret-cli.js +1 -2
- package/dist/commands/health/checks.js +357 -63
- package/dist/commands/health/engine-usage.js +45 -0
- package/dist/commands/health/improve-metrics.js +18 -0
- package/dist/commands/health/llm-usage.js +41 -1
- package/dist/commands/health/plugin-staleness.js +7 -3
- package/dist/commands/health/version-drift.js +93 -0
- package/dist/commands/health/windows.js +3 -1
- package/dist/commands/health.js +44 -9
- package/dist/commands/improve/consolidate/chunking.js +4 -2
- package/dist/commands/improve/improve-cli.js +99 -5
- package/dist/commands/improve/improve-report.js +154 -0
- package/dist/commands/improve/improve-result-file.js +45 -33
- package/dist/commands/improve/improve-strategies.js +133 -3
- package/dist/commands/improve/improve-usage-report.js +182 -0
- package/dist/commands/improve/improve.js +40 -3
- package/dist/commands/improve/locks.js +27 -78
- package/dist/commands/improve/planner.js +1 -0
- package/dist/commands/improve/preparation.js +9 -1
- package/dist/commands/improve/reflect.js +44 -4
- package/dist/commands/models-cli.js +50 -1
- package/dist/commands/proposal/repository.js +8 -3
- package/dist/commands/proposal/validators/proposal-quality-validators.js +41 -6
- package/dist/commands/proposal/validators/proposal-validators.js +24 -0
- package/dist/commands/read/search-cli.js +38 -2
- package/dist/commands/read/show.js +103 -4
- package/dist/commands/sources/info.js +5 -1
- package/dist/commands/sources/self-update.js +2 -2
- package/dist/commands/sources/stash-cli.js +31 -0
- package/dist/commands/tasks/tasks-cli.js +49 -2
- package/dist/commands/workflow-cli.js +86 -12
- package/dist/core/asset/markdown-fragments.js +35 -0
- package/dist/core/config/config-schema.js +14 -0
- package/dist/core/config/config.js +302 -24
- package/dist/core/env-secret-ref.js +58 -5
- package/dist/core/errors.js +30 -0
- package/dist/core/improve-result.js +51 -0
- package/dist/core/loopback.js +17 -0
- package/dist/core/paths.js +11 -0
- package/dist/core/run-lock.js +96 -0
- package/dist/core/sensitive-marker-path.js +19 -0
- package/dist/core/state-db.js +74 -14
- package/dist/indexer/index-rebuild-lock.js +73 -0
- package/dist/indexer/index-writer-lock.js +40 -1
- package/dist/indexer/index-written-assets.js +21 -1
- package/dist/indexer/indexer.js +18 -17
- package/dist/indexer/materialize-embeddings.js +282 -32
- package/dist/indexer/search/db-search.js +49 -2
- package/dist/integrations/agent/engine-resolution.js +96 -6
- package/dist/integrations/agent/execution-definitions.js +6 -15
- package/dist/integrations/agent/execution-lowering.js +6 -1
- package/dist/integrations/agent/execution-preparation.js +1 -1
- package/dist/integrations/agent/model-map.js +123 -20
- package/dist/integrations/agent/prompts.js +40 -8
- package/dist/integrations/agent/runner-dispatch.js +9 -3
- package/dist/integrations/agent/runner.js +2 -0
- package/dist/llm/client.js +8 -3
- package/dist/llm/embedder.js +20 -8
- package/dist/llm/embedders/local.js +10 -2
- package/dist/llm/embedders/remote.js +188 -21
- package/dist/output/shapes/helpers.js +38 -2
- package/dist/output/shapes/models-list.js +16 -0
- package/dist/output/shapes/passthrough.js +2 -0
- package/dist/output/shapes.js +4 -0
- package/dist/output/text/command-format.js +29 -0
- package/dist/output/text/helpers.js +1 -1
- package/dist/output/text/improve-report.js +27 -0
- package/dist/{commands/env/marker-path.js → output/text/models.js} +4 -3
- package/dist/output/text/show-format.js +4 -0
- package/dist/output/text.js +4 -0
- package/dist/scripts/akm-migrate-node.js +24798 -21732
- package/dist/scripts/akm-migrate.js +23408 -20343
- package/dist/storage/repositories/improve-runs-repository.js +34 -0
- package/dist/storage/repositories/index-fts-repository.js +49 -6
- package/dist/storage/repositories/index-vec-repository.js +30 -0
- package/dist/storage/repositories/workflow-runs-repository.js +55 -18
- package/dist/tasks/backends/cron.js +14 -7
- package/dist/tasks/run/run-workflow-task.js +16 -0
- package/dist/workflows/exec/child-workflow.js +2 -2
- package/dist/workflows/exec/dispatch-redaction.js +21 -9
- package/dist/workflows/exec/run-workflow.js +6 -5
- package/dist/workflows/runtime/runs.js +33 -5
- package/docs/migration/release-notes/0.9.15.md +52 -0
- package/docs/migration/release-notes/README.md +4 -0
- package/docs/reference/cli.md +245 -29
- package/docs/reference/configuration.md +180 -19
- package/docs/reference/data-and-telemetry.md +8 -0
- package/docs/reference/tasks.md +16 -1
- package/docs/reference/workflow-schema.md +5 -1
- package/package.json +1 -1
- package/schemas/akm-config.json +8 -0
|
@@ -12,10 +12,12 @@
|
|
|
12
12
|
* settings use their canonical engine/strategy paths; retired aliases are not
|
|
13
13
|
* rewritten at this boundary.
|
|
14
14
|
*/
|
|
15
|
+
import { isDeepStrictEqual } from "node:util";
|
|
15
16
|
import { defineGroupCommand, defineJsonCommand, output } from "../cli/shared.js";
|
|
16
|
-
import { resolveStashDir } from "../core/common.js";
|
|
17
|
-
import { DEFAULT_CONFIG, loadConfig, mutateConfig } from "../core/config/config.js";
|
|
17
|
+
import { isRecord, resolveStashDir } from "../core/common.js";
|
|
18
|
+
import { DEFAULT_CONFIG, getConfigValueSource, loadConfig, mutateConfig, parseAndValidateConfigText, resolveConfigRefSource, } from "../core/config/config.js";
|
|
18
19
|
import { configGet, configSet, configUnset, unknownKeyHint } from "../core/config/config-walker.js";
|
|
20
|
+
import { UsageError } from "../core/errors.js";
|
|
19
21
|
import { getCacheDir, getConfigPath, getDbPath, getDefaultStashDir } from "../core/paths.js";
|
|
20
22
|
import { formatRegistryUrl } from "../core/registry-url.js";
|
|
21
23
|
// ── Public API ──────────────────────────────────────────────────────────────
|
|
@@ -53,6 +55,55 @@ function isRegistryUrlPath(path) {
|
|
|
53
55
|
return path[0] === "registries" && path.at(-1) === "url";
|
|
54
56
|
}
|
|
55
57
|
export { unknownKeyHint };
|
|
58
|
+
/**
|
|
59
|
+
* Flatten a (redacted) config object down to `{dottedPath: leafValue}`
|
|
60
|
+
* entries. A plain object descends; an array or scalar is a leaf — matching
|
|
61
|
+
* `deepMergeConfig`'s own "objects merge, arrays replace wholesale" rule, so
|
|
62
|
+
* an array difference reports as one row rather than per-index noise.
|
|
63
|
+
*/
|
|
64
|
+
function flattenConfigLeaves(value, prefix, out) {
|
|
65
|
+
if (isRecord(value) && Object.keys(value).length > 0) {
|
|
66
|
+
for (const [key, child] of Object.entries(value))
|
|
67
|
+
flattenConfigLeaves(child, [...prefix, key], out);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
out.set(prefix.join("."), value);
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Diff two (already redacted) effective config objects into sorted
|
|
74
|
+
* `{path, local, other}` rows for every leaf that differs — including a leaf
|
|
75
|
+
* present on only one side (the other's value reads `undefined`).
|
|
76
|
+
*/
|
|
77
|
+
function diffConfigs(local, other) {
|
|
78
|
+
const localLeaves = new Map();
|
|
79
|
+
const otherLeaves = new Map();
|
|
80
|
+
flattenConfigLeaves(local, [], localLeaves);
|
|
81
|
+
flattenConfigLeaves(other, [], otherLeaves);
|
|
82
|
+
const paths = new Set([...localLeaves.keys(), ...otherLeaves.keys()]);
|
|
83
|
+
const rows = [];
|
|
84
|
+
for (const path of paths) {
|
|
85
|
+
const localValue = localLeaves.get(path);
|
|
86
|
+
const otherValue = otherLeaves.get(path);
|
|
87
|
+
if (!isDeepStrictEqual(localValue, otherValue))
|
|
88
|
+
rows.push({ path, local: localValue, other: otherValue });
|
|
89
|
+
}
|
|
90
|
+
rows.sort((a, b) => a.path.localeCompare(b.path));
|
|
91
|
+
return rows;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* `akm config diff <path|bundle//path>`: the current effective config
|
|
95
|
+
* (this instance's `extends` already applied) against another config file or
|
|
96
|
+
* bundle-relative file (loaded through the same loader, its own `extends`
|
|
97
|
+
* honoured), secrets redacted on both sides before comparison so a differing
|
|
98
|
+
* secret never round-trips into the diff.
|
|
99
|
+
*/
|
|
100
|
+
export function akmConfigDiff(ref) {
|
|
101
|
+
const current = loadConfig();
|
|
102
|
+
const { text, resolvedPath } = resolveConfigRefSource(ref, current, getConfigPath());
|
|
103
|
+
const other = parseAndValidateConfigText(text, resolvedPath);
|
|
104
|
+
const rows = diffConfigs(redactConfigValue(current), redactConfigValue(other));
|
|
105
|
+
return { rows };
|
|
106
|
+
}
|
|
56
107
|
// ── `akm config` command surface ────────────────────────────────────────────
|
|
57
108
|
// Extracted verbatim from src/cli.ts (WS6). The `main.subCommands.config` key
|
|
58
109
|
// and every config subcommand's args/output shape are byte-identical. Leaf
|
|
@@ -105,9 +156,16 @@ export const configCommand = defineGroupCommand({
|
|
|
105
156
|
meta: { name: "get", description: "Get a configuration value by key" },
|
|
106
157
|
args: {
|
|
107
158
|
key: { type: "positional", required: true, description: "Config key (for example: embedding, defaultBundle)" },
|
|
159
|
+
"show-source": {
|
|
160
|
+
type: "boolean",
|
|
161
|
+
description: 'Wrap the value as { value, source }, where source is "local", "extends:<ref>" (the nearest ' +
|
|
162
|
+
'extends chain member that sets it), or "default".',
|
|
163
|
+
default: false,
|
|
164
|
+
},
|
|
108
165
|
},
|
|
109
166
|
run({ args }) {
|
|
110
|
-
|
|
167
|
+
const value = getConfigValue(loadConfig(), args.key);
|
|
168
|
+
output("config", args["show-source"] ? { value, source: getConfigValueSource(args.key) } : value);
|
|
111
169
|
},
|
|
112
170
|
}),
|
|
113
171
|
set: defineJsonCommand({
|
|
@@ -152,6 +210,14 @@ export const configCommand = defineGroupCommand({
|
|
|
152
210
|
},
|
|
153
211
|
},
|
|
154
212
|
run({ args }) {
|
|
213
|
+
// A key only an `extends` base supplies has nothing local to remove:
|
|
214
|
+
// `unsetConfigValue` would silently no-op and the value comes right
|
|
215
|
+
// back on the next load. Refuse before mutating rather than pretend
|
|
216
|
+
// it worked.
|
|
217
|
+
const source = getConfigValueSource(args.key);
|
|
218
|
+
if (source.startsWith("extends:")) {
|
|
219
|
+
throw new UsageError(`Config key "${args.key}" is inherited from ${source} and cannot be unset here.`, "TARGET_NOT_UPDATABLE", `Override it locally with "akm config set ${args.key} <value>", or edit the base file directly.`);
|
|
220
|
+
}
|
|
155
221
|
const result = mutateConfig((current) => unsetConfigValue(current, args.key), { absentNoop: true });
|
|
156
222
|
const updated = result.config;
|
|
157
223
|
if (!args.silent) {
|
|
@@ -159,6 +225,22 @@ export const configCommand = defineGroupCommand({
|
|
|
159
225
|
}
|
|
160
226
|
},
|
|
161
227
|
}),
|
|
228
|
+
diff: defineJsonCommand({
|
|
229
|
+
meta: {
|
|
230
|
+
name: "diff",
|
|
231
|
+
description: "Show effective-config differences against another config file or bundle-relative file, secrets redacted",
|
|
232
|
+
},
|
|
233
|
+
args: {
|
|
234
|
+
ref: {
|
|
235
|
+
type: "positional",
|
|
236
|
+
required: true,
|
|
237
|
+
description: "Other config: a file path or bundle//path (relative to the bundle's content root)",
|
|
238
|
+
},
|
|
239
|
+
},
|
|
240
|
+
run({ args }) {
|
|
241
|
+
output("config-diff", akmConfigDiff(args.ref));
|
|
242
|
+
},
|
|
243
|
+
}),
|
|
162
244
|
},
|
|
163
245
|
// The bare `akm config` invocation (and `akm config --list`) dumps the
|
|
164
246
|
// current config. defineGroupCommand short-circuits this body when a
|
|
@@ -22,52 +22,11 @@ import path from "node:path";
|
|
|
22
22
|
import { getParsedInvocation } from "../../cli/invocation.js";
|
|
23
23
|
import { getStringArg } from "../../cli/parse-args.js";
|
|
24
24
|
import { defineGroupCommand, defineJsonCommand, output } from "../../cli/shared.js";
|
|
25
|
-
import { deriveCanonicalAssetName } from "../../core/asset/asset-placement.js";
|
|
26
25
|
import { writeFileAtomic } from "../../core/common.js";
|
|
27
|
-
import {
|
|
28
|
-
import { makeEnvRef, resolveEnvPath, resolveEnvWriteTarget, withEnvSecretWrite } from "../../core/env-secret-ref.js";
|
|
26
|
+
import { listEnvsRecursive, makeEnvRef, resolveEnvPath, resolveEnvWriteTarget, sensitiveMarkerPath, withEnvSecretWrite, } from "../../core/env-secret-ref.js";
|
|
29
27
|
import { ConfigError, NotFoundError, UsageError } from "../../core/errors.js";
|
|
30
|
-
import { resolveSourceEntries } from "../../indexer/search/search-source.js";
|
|
31
28
|
import { readStdin } from "../../runtime.js";
|
|
32
29
|
import { buildChildEnv } from "./child-env.js";
|
|
33
|
-
import { sensitiveMarkerPath } from "./marker-path.js";
|
|
34
|
-
/**
|
|
35
|
-
* Walk each stash's env files and return one entry per `.env` file, using the
|
|
36
|
-
* env asset spec's canonical-name logic (e.g. `env/team/prod.env` →
|
|
37
|
-
* `env/team/prod`, `env/team/.env` → `env/team/default`).
|
|
38
|
-
*/
|
|
39
|
-
function listEnvsRecursive(listKeysFn) {
|
|
40
|
-
const result = [];
|
|
41
|
-
for (const source of resolveSourceEntries(undefined, loadConfig())) {
|
|
42
|
-
const root = path.join(source.path, "env");
|
|
43
|
-
if (!fs.existsSync(root))
|
|
44
|
-
continue;
|
|
45
|
-
const walk = (dir) => {
|
|
46
|
-
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
47
|
-
const full = path.join(dir, entry.name);
|
|
48
|
-
if (entry.isDirectory()) {
|
|
49
|
-
walk(full);
|
|
50
|
-
continue;
|
|
51
|
-
}
|
|
52
|
-
if (!entry.isFile())
|
|
53
|
-
continue;
|
|
54
|
-
if (entry.name !== ".env" && !entry.name.endsWith(".env"))
|
|
55
|
-
continue;
|
|
56
|
-
const canonical = deriveCanonicalAssetName("env", root, full);
|
|
57
|
-
if (!canonical)
|
|
58
|
-
continue;
|
|
59
|
-
// Skip sensitive envs: a sibling .sensitive marker file suppresses listing.
|
|
60
|
-
const markerPath = sensitiveMarkerPath(full, "env");
|
|
61
|
-
if (fs.existsSync(markerPath))
|
|
62
|
-
continue;
|
|
63
|
-
const { keys } = listKeysFn(full);
|
|
64
|
-
result.push({ ref: makeEnvRef(canonical, source), path: full, keys });
|
|
65
|
-
}
|
|
66
|
-
};
|
|
67
|
-
walk(root);
|
|
68
|
-
}
|
|
69
|
-
return result;
|
|
70
|
-
}
|
|
71
30
|
const envListCommand = defineJsonCommand({
|
|
72
31
|
meta: { name: "list", description: "List all env files across all bundles with their key names (no values)" },
|
|
73
32
|
async run() {
|
package/dist/commands/env/env.js
CHANGED
|
@@ -49,7 +49,7 @@ import fs from "node:fs";
|
|
|
49
49
|
import path from "node:path";
|
|
50
50
|
import dotenv from "dotenv";
|
|
51
51
|
import { scanEnvKeyNames, writeFileAtomic } from "../../core/common.js";
|
|
52
|
-
import { sensitiveMarkerPath } from "
|
|
52
|
+
import { sensitiveMarkerPath } from "../../core/sensitive-marker-path.js";
|
|
53
53
|
export { scanEnvKeyNames };
|
|
54
54
|
/**
|
|
55
55
|
* Read and return ONLY non-secret metadata: key names.
|
|
@@ -35,14 +35,13 @@ import { defineGroupCommand, defineJsonCommand, output } from "../../cli/shared.
|
|
|
35
35
|
import { decideDangerousEnvInjection } from "../../core/activation-policy.js";
|
|
36
36
|
import { deriveCanonicalAssetName } from "../../core/asset/asset-placement.js";
|
|
37
37
|
import { loadConfig } from "../../core/config/config.js";
|
|
38
|
-
import { makeSecretRef, resolveSecretPath, resolveSecretWriteTarget, withEnvSecretWrite, } from "../../core/env-secret-ref.js";
|
|
38
|
+
import { makeSecretRef, resolveSecretPath, resolveSecretWriteTarget, sensitiveMarkerPath, withEnvSecretWrite, } from "../../core/env-secret-ref.js";
|
|
39
39
|
import { ConfigError, NotFoundError, UsageError } from "../../core/errors.js";
|
|
40
40
|
import { appendEvent } from "../../core/events.js";
|
|
41
41
|
import { warn } from "../../core/warn.js";
|
|
42
42
|
import { resolveSourceEntries } from "../../indexer/search/search-source.js";
|
|
43
43
|
import { readStdin } from "../../runtime.js";
|
|
44
44
|
import { buildChildEnv } from "./child-env.js";
|
|
45
|
-
import { sensitiveMarkerPath } from "./marker-path.js";
|
|
46
45
|
function parseKeyListFlag(raw) {
|
|
47
46
|
if (raw === undefined)
|
|
48
47
|
return undefined;
|