akm-cli 0.9.0-beta.52 → 0.9.0-beta.54
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/dist/assets/hints/cli-hints-full.md +6 -5
- package/dist/cli/clack.js +56 -0
- package/dist/cli/confirm.js +1 -1
- package/dist/cli.js +0 -7
- package/dist/commands/env/env-cli.js +3 -2
- package/dist/commands/env/env.js +14 -67
- package/dist/commands/health/checks.js +28 -15
- package/dist/commands/health/html-report.js +33 -10
- package/dist/commands/health.js +222 -22
- package/dist/commands/improve/collapse-detector.js +419 -0
- package/dist/commands/improve/consolidate.js +72 -54
- package/dist/commands/improve/distill.js +79 -13
- package/dist/commands/improve/extract.js +13 -6
- package/dist/commands/improve/homeostatic.js +109 -79
- package/dist/commands/improve/improve-cli.js +67 -1
- package/dist/commands/improve/improve.js +10 -0
- package/dist/commands/improve/loop-stages.js +39 -1
- package/dist/commands/improve/outcome-loop.js +33 -19
- package/dist/commands/improve/preparation.js +36 -11
- package/dist/commands/improve/salience.js +49 -32
- package/dist/commands/read/curate.js +9 -13
- package/dist/commands/read/knowledge.js +4 -0
- package/dist/commands/read/search-cli.js +6 -4
- package/dist/commands/read/search.js +12 -5
- package/dist/commands/read/show.js +6 -8
- package/dist/commands/sources/add-cli.js +1 -1
- package/dist/commands/sources/init.js +12 -0
- package/dist/commands/sources/stash-cli.js +1 -1
- package/dist/commands/tasks/default-tasks.js +12 -0
- package/dist/core/asset/asset-spec.js +3 -2
- package/dist/core/config/config-schema.js +39 -17
- package/dist/core/config/config.js +12 -0
- package/dist/core/eval/rank-metrics.js +113 -0
- package/dist/core/state/migrations.js +56 -0
- package/dist/core/state-db.js +146 -19
- package/dist/core/warn.js +21 -0
- package/dist/indexer/db/db.js +6 -0
- package/dist/indexer/ensure-index.js +36 -92
- package/dist/indexer/index-writer-lock.js +9 -11
- package/dist/indexer/index-written-assets.js +105 -0
- package/dist/indexer/indexer.js +16 -4
- package/dist/indexer/passes/metadata.js +20 -0
- package/dist/indexer/read-preflight.js +23 -0
- package/dist/indexer/search/db-search.js +29 -1
- package/dist/indexer/search/ranking-contributors.js +33 -1
- package/dist/indexer/search/ranking.js +66 -0
- package/dist/indexer/search/search-fields.js +6 -0
- package/dist/indexer/walk/walker.js +21 -13
- package/dist/integrations/agent/detect.js +9 -0
- package/dist/integrations/agent/index.js +1 -1
- package/dist/llm/client.js +12 -0
- package/dist/llm/embedder.js +26 -2
- package/dist/llm/embedders/local.js +7 -1
- package/dist/llm/feature-gate.js +6 -2
- package/dist/output/renderers.js +8 -13
- package/dist/output/shapes/helpers.js +0 -3
- package/dist/output/shapes/passthrough.js +1 -0
- package/dist/scripts/migrate-storage.js +178 -35
- package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +46 -19
- package/dist/setup/detect.js +9 -0
- package/dist/setup/registry-stash-loader.js +12 -0
- package/dist/setup/setup.js +1 -1
- package/dist/storage/repositories/index-db.js +10 -1
- package/dist/tasks/backends/index.js +9 -0
- package/dist/tasks/runner.js +9 -0
- package/package.json +2 -4
|
@@ -148,20 +148,28 @@ function isInsideGitRepo(dir) {
|
|
|
148
148
|
* read (e.g. permission errors).
|
|
149
149
|
*/
|
|
150
150
|
export function* walkMarkdownFiles(root) {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
const full = path.join(root, entry.name);
|
|
160
|
-
if (entry.isDirectory()) {
|
|
161
|
-
yield* walkMarkdownFiles(full);
|
|
151
|
+
const stack = [root];
|
|
152
|
+
while (stack.length > 0) {
|
|
153
|
+
const current = stack.pop();
|
|
154
|
+
if (!current)
|
|
155
|
+
continue;
|
|
156
|
+
let entries;
|
|
157
|
+
try {
|
|
158
|
+
entries = fs.readdirSync(current, { withFileTypes: true });
|
|
162
159
|
}
|
|
163
|
-
|
|
164
|
-
|
|
160
|
+
catch {
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
for (const entry of entries) {
|
|
164
|
+
const full = path.join(current, entry.name);
|
|
165
|
+
if (entry.isSymbolicLink())
|
|
166
|
+
continue;
|
|
167
|
+
if (entry.isDirectory()) {
|
|
168
|
+
stack.push(full);
|
|
169
|
+
}
|
|
170
|
+
else if (entry.isFile() && entry.name.toLowerCase().endsWith(".md")) {
|
|
171
|
+
yield full;
|
|
172
|
+
}
|
|
165
173
|
}
|
|
166
174
|
}
|
|
167
175
|
}
|
|
@@ -55,6 +55,11 @@ export function defaultWhich(bin, envSource = process.env) {
|
|
|
55
55
|
}
|
|
56
56
|
return undefined;
|
|
57
57
|
}
|
|
58
|
+
let detectOverrides;
|
|
59
|
+
/** TEST-ONLY. Swap the detection implementations; pass undefined to restore. */
|
|
60
|
+
export function _setAgentDetectForTests(fakes) {
|
|
61
|
+
detectOverrides = fakes;
|
|
62
|
+
}
|
|
58
63
|
/**
|
|
59
64
|
* Probe every resolvable agent profile (built-ins plus user overrides)
|
|
60
65
|
* for an installed CLI.
|
|
@@ -64,6 +69,8 @@ export function defaultWhich(bin, envSource = process.env) {
|
|
|
64
69
|
* @param whichFn Binary lookup. Tests should inject a stub.
|
|
65
70
|
*/
|
|
66
71
|
export function detectAgentCliProfiles(agent, whichFn = defaultWhich) {
|
|
72
|
+
if (detectOverrides?.detectAgentCliProfiles)
|
|
73
|
+
return detectOverrides.detectAgentCliProfiles(agent, whichFn);
|
|
67
74
|
const profiles = listResolvedAgentProfiles(agent);
|
|
68
75
|
return profiles.map((profile) => probeProfile(profile, whichFn));
|
|
69
76
|
}
|
|
@@ -87,6 +94,8 @@ function probeProfile(profile, whichFn) {
|
|
|
87
94
|
* writing `agent.default`.
|
|
88
95
|
*/
|
|
89
96
|
export function pickDefaultAgentProfile(results, existingDefault) {
|
|
97
|
+
if (detectOverrides?.pickDefaultAgentProfile)
|
|
98
|
+
return detectOverrides.pickDefaultAgentProfile(results, existingDefault);
|
|
90
99
|
if (existingDefault) {
|
|
91
100
|
const match = results.find((r) => r.name === existingDefault && r.available);
|
|
92
101
|
if (match)
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
4
|
export { getCommandBuilder } from "./builders.js";
|
|
5
5
|
export { DEFAULT_AGENT_TIMEOUT_MS, listAgentProfileNames, listResolvedAgentProfiles, requireAgentProfile, resolveAgentProfile, resolveDefaultProfileName, resolveProfileFromConfig, } from "./config.js";
|
|
6
|
-
export { defaultWhich, detectAgentCliProfiles, pickDefaultAgentProfile } from "./detect.js";
|
|
6
|
+
export { _setAgentDetectForTests, defaultWhich, detectAgentCliProfiles, pickDefaultAgentProfile } from "./detect.js";
|
|
7
7
|
export { listBuiltinModelAliases, resolveModel } from "./model-aliases.js";
|
|
8
8
|
export { BUILTIN_AGENT_PROFILE_NAMES, getBuiltinAgentProfile, listBuiltinAgentProfiles, } from "./profiles.js";
|
|
9
9
|
export { buildProposePrompt, buildReflectPrompt, buildSchemaRepairPrompt, extractDraftConfidence, parseAgentProposalPayload, } from "./prompts.js";
|
package/dist/llm/client.js
CHANGED
|
@@ -165,7 +165,19 @@ function isRetryable(err) {
|
|
|
165
165
|
}
|
|
166
166
|
return false;
|
|
167
167
|
}
|
|
168
|
+
// ── Test seam ────────────────────────────────────────────────────────────────
|
|
169
|
+
// Swap-and-restore override. Inert in production; only tests call the setter.
|
|
170
|
+
let chatCompletionOverride;
|
|
171
|
+
/** TEST-ONLY. Swap the implementation of `chatCompletion`; pass undefined to restore. */
|
|
172
|
+
export function _setChatCompletionForTests(fake) {
|
|
173
|
+
chatCompletionOverride = fake;
|
|
174
|
+
}
|
|
168
175
|
export async function chatCompletion(config, messages, options) {
|
|
176
|
+
if (chatCompletionOverride)
|
|
177
|
+
return chatCompletionOverride(config, messages, options);
|
|
178
|
+
return chatCompletionReal(config, messages, options);
|
|
179
|
+
}
|
|
180
|
+
async function chatCompletionReal(config, messages, options) {
|
|
169
181
|
const effectiveTimeoutMs = options?.timeoutMs ?? config.timeoutMs ?? 120_000;
|
|
170
182
|
const started = Date.now();
|
|
171
183
|
try {
|
package/dist/llm/embedder.js
CHANGED
|
@@ -3,11 +3,26 @@
|
|
|
3
3
|
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
4
|
import { embedCacheKey, getCachedEmbedding, setCachedEmbedding } from "./embedders/cache.js";
|
|
5
5
|
import { DETERMINISTIC_EMBED_MODEL_ID, deterministicEmbed, isDeterministicEmbedEnabled, } from "./embedders/deterministic.js";
|
|
6
|
-
import { DEFAULT_LOCAL_MODEL, isTransformersAvailable, LocalEmbedder } from "./embedders/local.js";
|
|
6
|
+
import { DEFAULT_LOCAL_MODEL, isTransformersAvailable as isTransformersAvailableReal, LocalEmbedder, } from "./embedders/local.js";
|
|
7
7
|
import { hasRemoteEndpoint, RemoteEmbedder } from "./embedders/remote.js";
|
|
8
8
|
// ── Re-exports (public API) ─────────────────────────────────────────────────
|
|
9
9
|
export { clearEmbeddingCache } from "./embedders/cache.js";
|
|
10
|
-
export {
|
|
10
|
+
export { _setTransformersLoaderForTests, DEFAULT_LOCAL_MODEL } from "./embedders/local.js";
|
|
11
|
+
let embedderOverrides;
|
|
12
|
+
/** TEST-ONLY. Swap embedder implementations; pass undefined to restore. */
|
|
13
|
+
export function _setEmbedderForTests(fakes) {
|
|
14
|
+
embedderOverrides = fakes;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Check whether the @huggingface/transformers package is importable.
|
|
18
|
+
* Delegating wrapper around `./embedders/local`'s probe so tests can swap it
|
|
19
|
+
* via {@link _setEmbedderForTests}.
|
|
20
|
+
*/
|
|
21
|
+
export function isTransformersAvailable() {
|
|
22
|
+
if (embedderOverrides?.isTransformersAvailable)
|
|
23
|
+
return embedderOverrides.isTransformersAvailable();
|
|
24
|
+
return isTransformersAvailableReal();
|
|
25
|
+
}
|
|
11
26
|
// ── Singleton local embedder ────────────────────────────────────────────────
|
|
12
27
|
// `_localEmbedder` is an intentional module-level singleton but constructed
|
|
13
28
|
// lazily on first use. The underlying @huggingface/transformers pipeline is
|
|
@@ -40,6 +55,8 @@ export function resetLocalEmbedder() {
|
|
|
40
55
|
* and embedding config. Repeated identical queries return the cached vector.
|
|
41
56
|
*/
|
|
42
57
|
export async function embed(text, embeddingConfig, signal) {
|
|
58
|
+
if (embedderOverrides?.embed)
|
|
59
|
+
return embedderOverrides.embed(text, embeddingConfig, signal);
|
|
43
60
|
// Deterministic mode (env-gated, test/bench only): model-free, stable.
|
|
44
61
|
if (isDeterministicEmbedEnabled()) {
|
|
45
62
|
return deterministicEmbed(text);
|
|
@@ -61,6 +78,8 @@ export async function embed(text, embeddingConfig, signal) {
|
|
|
61
78
|
* which processes texts in chunks of 32 for genuine batched inference.
|
|
62
79
|
*/
|
|
63
80
|
export async function embedBatch(texts, embeddingConfig, signal) {
|
|
81
|
+
if (embedderOverrides?.embedBatch)
|
|
82
|
+
return embedderOverrides.embedBatch(texts, embeddingConfig, signal);
|
|
64
83
|
if (texts.length === 0)
|
|
65
84
|
return [];
|
|
66
85
|
// Deterministic mode (env-gated, test/bench only): model-free, stable.
|
|
@@ -104,6 +123,8 @@ export { cosineSimilarity } from "./embedders/types.js";
|
|
|
104
123
|
* - No config: use `DEFAULT_LOCAL_MODEL` (the shared singleton model).
|
|
105
124
|
*/
|
|
106
125
|
export function resolveEmbeddingModelId(embeddingConfig) {
|
|
126
|
+
if (embedderOverrides?.resolveEmbeddingModelId)
|
|
127
|
+
return embedderOverrides.resolveEmbeddingModelId(embeddingConfig);
|
|
107
128
|
if (isDeterministicEmbedEnabled())
|
|
108
129
|
return DETERMINISTIC_EMBED_MODEL_ID;
|
|
109
130
|
if (!embeddingConfig)
|
|
@@ -117,6 +138,9 @@ export function resolveEmbeddingModelId(embeddingConfig) {
|
|
|
117
138
|
* Check whether embedding is available with a detailed reason on failure.
|
|
118
139
|
*/
|
|
119
140
|
export async function checkEmbeddingAvailability(embeddingConfig) {
|
|
141
|
+
if (embedderOverrides?.checkEmbeddingAvailability) {
|
|
142
|
+
return embedderOverrides.checkEmbeddingAvailability(embeddingConfig);
|
|
143
|
+
}
|
|
120
144
|
// Deterministic mode (env-gated): always available — no model, no network.
|
|
121
145
|
if (isDeterministicEmbedEnabled()) {
|
|
122
146
|
return { available: true };
|
|
@@ -28,6 +28,12 @@ function isBatchTensor(v) {
|
|
|
28
28
|
Array.isArray(v.dims) &&
|
|
29
29
|
v.dims.length >= 2);
|
|
30
30
|
}
|
|
31
|
+
const realTransformersLoader = () => import("@huggingface/transformers");
|
|
32
|
+
let transformersLoader = realTransformersLoader;
|
|
33
|
+
/** TEST-ONLY. Swap the transformers module loader; pass undefined to restore. */
|
|
34
|
+
export function _setTransformersLoaderForTests(fake) {
|
|
35
|
+
transformersLoader = fake ?? realTransformersLoader;
|
|
36
|
+
}
|
|
31
37
|
const LOCAL_EMBEDDER_DTYPE = "fp32";
|
|
32
38
|
const LOCAL_EMBEDDER_FALLBACK_DTYPE = "auto";
|
|
33
39
|
/**
|
|
@@ -180,7 +186,7 @@ export class LocalEmbedder {
|
|
|
180
186
|
}
|
|
181
187
|
let pipeline;
|
|
182
188
|
try {
|
|
183
|
-
const mod = await
|
|
189
|
+
const mod = await transformersLoader();
|
|
184
190
|
pipeline = mod.pipeline;
|
|
185
191
|
}
|
|
186
192
|
catch (importError) {
|
package/dist/llm/feature-gate.js
CHANGED
|
@@ -24,8 +24,12 @@ const FEATURE_LOCATION = {
|
|
|
24
24
|
metadata_enhance: (cfg) => cfg.index?.metadataEnhance?.enabled ?? false,
|
|
25
25
|
// Legacy default: false
|
|
26
26
|
curate_rerank: (cfg) => cfg.search?.curateRerank?.enabled ?? false,
|
|
27
|
-
//
|
|
28
|
-
|
|
27
|
+
// Default ON since R3 (docs/design/improve-self-learning-analysis.md G5):
|
|
28
|
+
// distill is a primary acquisition path and the judge fails open (no LLM /
|
|
29
|
+
// timeout / parse failure all pass through), so the gate only ever filters
|
|
30
|
+
// when a judge verdict actually exists. Opt out via
|
|
31
|
+
// profiles.improve.default.processes.distill.qualityGate.enabled: false.
|
|
32
|
+
lesson_quality_gate: (cfg) => cfg.profiles?.improve?.default?.processes?.distill?.qualityGate?.enabled ?? true,
|
|
29
33
|
// Legacy default: false
|
|
30
34
|
proposal_quality_gate: (cfg) => cfg.profiles?.improve?.default?.processes?.reflect?.qualityGate?.enabled ?? false,
|
|
31
35
|
// Legacy default: false
|
package/dist/output/renderers.js
CHANGED
|
@@ -364,23 +364,21 @@ const scriptSourceRenderer = {
|
|
|
364
364
|
};
|
|
365
365
|
// ── 8. env-file ───────────────────────────────────────────────────────────────
|
|
366
366
|
/**
|
|
367
|
-
* Env renderer. Returns ONLY key names
|
|
368
|
-
*
|
|
369
|
-
* through `akm show`.
|
|
367
|
+
* Env renderer. Returns ONLY key names — never values, and never comment
|
|
368
|
+
* text (comments routinely contain commented-out credentials). Deliberately
|
|
369
|
+
* omits content/template/prompt so env values cannot leak through `akm show`.
|
|
370
370
|
*/
|
|
371
371
|
const envFileRenderer = {
|
|
372
372
|
name: "env-file",
|
|
373
373
|
buildShowResponse(ctx) {
|
|
374
374
|
const name = deriveName(ctx);
|
|
375
|
-
const { keys
|
|
375
|
+
const { keys } = listVaultKeys(ctx.absPath);
|
|
376
376
|
return {
|
|
377
377
|
type: "env",
|
|
378
378
|
name,
|
|
379
379
|
path: ctx.absPath,
|
|
380
|
-
action: "Environment —
|
|
381
|
-
description: comments.length > 0 ? comments.join("\n") : undefined,
|
|
380
|
+
action: "Environment — key names only. Use `akm env run <ref> -- <command>` to run with the whole .env injected; prefer `--clean` to minimize inherited parent env. AKM itself does not print values, but child stdout/stderr is not redacted. `akm env export <ref> --out <file>` writes a sourceable script to a file. Never `source` the raw file. Values stay on disk and are never written to akm's stdout.",
|
|
382
381
|
keys,
|
|
383
|
-
comments,
|
|
384
382
|
};
|
|
385
383
|
},
|
|
386
384
|
enrichSearchHit(hit, _stashDir) {
|
|
@@ -647,12 +645,9 @@ function applyScriptMetadata(entry, ctx) {
|
|
|
647
645
|
}
|
|
648
646
|
}
|
|
649
647
|
function applyEnvMetadata(entry, ctx) {
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
entry.source = "comments";
|
|
654
|
-
entry.confidence = 0.7;
|
|
655
|
-
}
|
|
648
|
+
// Key names only — comment text must never reach description/search_text
|
|
649
|
+
// (comments routinely contain commented-out credentials).
|
|
650
|
+
const { keys } = listVaultKeys(ctx.absPath);
|
|
656
651
|
if (keys.length > 0) {
|
|
657
652
|
entry.searchHints = keys;
|
|
658
653
|
}
|
|
@@ -369,7 +369,6 @@ export function shapeShowOutput(result, detail, shape = "human") {
|
|
|
369
369
|
"workflowParameters",
|
|
370
370
|
"steps",
|
|
371
371
|
"keys",
|
|
372
|
-
"comments",
|
|
373
372
|
"related",
|
|
374
373
|
]);
|
|
375
374
|
}
|
|
@@ -385,7 +384,6 @@ export function shapeShowOutput(result, detail, shape = "human") {
|
|
|
385
384
|
"run",
|
|
386
385
|
"origin",
|
|
387
386
|
"keys",
|
|
388
|
-
"comments",
|
|
389
387
|
"related",
|
|
390
388
|
]);
|
|
391
389
|
}
|
|
@@ -411,7 +409,6 @@ export function shapeShowOutput(result, detail, shape = "human") {
|
|
|
411
409
|
"cwd",
|
|
412
410
|
"activeRun",
|
|
413
411
|
"keys",
|
|
414
|
-
"comments",
|
|
415
412
|
"related",
|
|
416
413
|
// path and editable are always projected so JSON consumers can locate and
|
|
417
414
|
// edit the asset without needing --detail full (QA #7).
|