akm-cli 0.9.14 → 0.9.15-beta.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 +559 -0
- package/STABILITY.md +6 -3
- package/dist/akm +54 -1
- package/dist/akm-migrate +34 -1
- 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 +40 -3
- 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 +28 -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/installed-stashes.js +58 -16
- package/dist/commands/sources/self-update.js +2 -2
- package/dist/commands/sources/stash-cli.js +48 -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/config/schema/embedding.js +41 -0
- package/dist/core/env-secret-ref.js +58 -5
- package/dist/core/errors.js +30 -0
- package/dist/core/file-lock.js +49 -15
- package/dist/core/improve-result.js +51 -0
- package/dist/core/loopback.js +17 -0
- package/dist/core/parent-watchdog.js +64 -0
- package/dist/core/paths.js +11 -0
- package/dist/core/run-lock.js +107 -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 +29 -1
- package/dist/indexer/indexer.js +93 -29
- package/dist/indexer/materialize-embeddings.js +564 -48
- package/dist/indexer/search/db-search.js +49 -2
- package/dist/indexer/search/search-source.js +23 -1
- 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 +497 -32
- 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 +25146 -21759
- package/dist/scripts/akm-migrate.js +24271 -20885
- package/dist/storage/repositories/embedding-salvage-repository.js +184 -0
- 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-schema.js +16 -0
- 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-native-task.js +23 -1
- 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 +133 -0
- package/docs/migration/release-notes/README.md +5 -0
- package/docs/reference/cli.md +271 -30
- package/docs/reference/configuration.md +234 -21
- 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 +47 -0
|
@@ -3,7 +3,10 @@
|
|
|
3
3
|
AKM reads one user configuration file: `$XDG_CONFIG_HOME/akm/config.json`
|
|
4
4
|
(normally `~/.config/akm/config.json` on Linux and macOS, or
|
|
5
5
|
`%APPDATA%\akm\config.json` on Windows). Set `AKM_CONFIG_DIR` to override the
|
|
6
|
-
directory. Project `.akm/config.json` files are not merged.
|
|
6
|
+
directory. Project `.akm/config.json` files are not merged. A config file may
|
|
7
|
+
optionally extend one other config via `extends` (see "Sharing configuration
|
|
8
|
+
across installs" below) — this is a single, explicit, user-opted-in key, not
|
|
9
|
+
automatic project-config discovery.
|
|
7
10
|
|
|
8
11
|
## Version 0.9
|
|
9
12
|
|
|
@@ -89,14 +92,21 @@ LLM endpoints must be complete `http://` or `https://` chat-completions URLs
|
|
|
89
92
|
ending in `/chat/completions`, without userinfo, query, or fragment. API keys
|
|
90
93
|
are symbolic only: `$VAR` or `${VAR}`. AKM resolves them only at dispatch.
|
|
91
94
|
|
|
92
|
-
An LLM engine may set `
|
|
93
|
-
value such as `"none"`, `"low"`, or `"high"`. AKM sends
|
|
94
|
-
|
|
95
|
-
`
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
`
|
|
99
|
-
|
|
95
|
+
An LLM engine may set `enableThinking: false` to turn thinking off and
|
|
96
|
+
`reasoningEffort` to a value such as `"none"`, `"low"`, or `"high"`. AKM sends
|
|
97
|
+
**both** wire forms — `chat_template_kwargs.enable_thinking` and top-level
|
|
98
|
+
`enable_thinking` — whenever `enableThinking` resolves, from engine config
|
|
99
|
+
or a calling process (improve's `consolidate`/`reflect` and the distill
|
|
100
|
+
quality gate always request `enableThinking: false` for a machine-readable
|
|
101
|
+
payload); `reasoningEffort` is always sent as top-level `reasoning_effort`
|
|
102
|
+
when set. Backend support: llama.cpp direct honors both forms
|
|
103
|
+
(`reasoning_effort` from build ≥ b10644); vLLM honors
|
|
104
|
+
`chat_template_kwargs`; Bifrost drops `chat_template_kwargs` and passes
|
|
105
|
+
`reasoning_effort` through, so also set `reasoningEffort: "none"` behind it; a
|
|
106
|
+
strict hosted API may 400 on unrecognized keys. Both fields are AKM-owned, not
|
|
107
|
+
settable via `extraParams`. A response with reasoning tokens despite
|
|
108
|
+
`enableThinking: false` triggers a runtime warning and the `akm health`
|
|
109
|
+
`thinking-control` advisory.
|
|
100
110
|
|
|
101
111
|
An agent engine may set `bin`, `args`, `workspace`, `model`, and `timeoutMs`.
|
|
102
112
|
Only `platform: "opencode-sdk"` may set `llmEngine`; it names
|
|
@@ -147,19 +157,54 @@ the same version-1 schema as the installed file:
|
|
|
147
157
|
```
|
|
148
158
|
|
|
149
159
|
Each engine mapping is either a non-empty exact model string or a structured
|
|
150
|
-
profile with the documented fields `model` and `
|
|
151
|
-
omit `model` when the installed layer already supplies it, as the
|
|
152
|
-
Claude override above does. After overlay, every alias/engine entry
|
|
153
|
-
usable model. Unknown profile fields are rejected; JSON-safe
|
|
154
|
-
`inference` are preserved for engine adapters to lower
|
|
160
|
+
profile with the documented fields `model`, `inference`, and `engine`. A user
|
|
161
|
+
profile may omit `model` when the installed layer already supplies it, as the
|
|
162
|
+
partial Claude override above does. After overlay, every alias/engine entry
|
|
163
|
+
must have a usable model. Unknown profile fields are rejected; JSON-safe
|
|
164
|
+
fields inside `inference` are preserved for engine adapters to lower
|
|
165
|
+
optimistically.
|
|
166
|
+
|
|
167
|
+
A profile's `engine` field (0.9.15, #946) borrows a column's `model` (and, for
|
|
168
|
+
an `llm`-kind engine, its inference defaults) from a configured
|
|
169
|
+
`engines.<name>` connection instead of hand-typing a literal model a second
|
|
170
|
+
time:
|
|
171
|
+
|
|
172
|
+
```json
|
|
173
|
+
{
|
|
174
|
+
"version": 1,
|
|
175
|
+
"aliases": {
|
|
176
|
+
"fast": {
|
|
177
|
+
"opencode": { "engine": "local-fast" }
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
With `engines.local-fast` configured (agent-kind or llm-kind), this column
|
|
184
|
+
resolves to that engine's own `model` string. `model` and `engine` are
|
|
185
|
+
mutually exclusive on the same profile — `engine` is an indirection for the
|
|
186
|
+
model value, never an engine-selection override; which engine `akm agent`
|
|
187
|
+
dispatches to is still decided entirely by `--engine`/`defaults.engine` (see
|
|
188
|
+
[Engine selection](#engines)). The referenced engine's `model` must itself be
|
|
189
|
+
literal, not another alias, and akm copies it verbatim: it does not translate
|
|
190
|
+
between an engine's connection and an agent platform's own provider registry,
|
|
191
|
+
so the value must already be meaningful for the column's platform (e.g. a
|
|
192
|
+
`kind: "agent", platform: "opencode"` engine's `model` should already be a
|
|
193
|
+
string opencode itself understands, such as `krang/qwen3.5-9b`). Run
|
|
194
|
+
`akm models list` to see, for every alias/column, the resolved model and
|
|
195
|
+
whether it came from the installed defaults, the user overlay, and a literal
|
|
196
|
+
value or an `engine` reference.
|
|
155
197
|
|
|
156
198
|
The user file overlays the installed file by alias, engine, and nested object
|
|
157
199
|
field. Objects merge recursively. Arrays, scalars, and explicit `null` replace
|
|
158
|
-
the lower value; omitted fields preserve it.
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
200
|
+
the lower value; omitted fields preserve it. A layer setting a literal `model`
|
|
201
|
+
clears any `engine` inherited from a farther layer, and vice versa — the
|
|
202
|
+
nearer layer's choice of literal-vs-engine always wins outright rather than
|
|
203
|
+
merging. Alias and engine keys are case-normalized, and case-colliding
|
|
204
|
+
definitions are rejected. Unknown model inputs still pass through
|
|
205
|
+
byte-for-byte as exact identifiers. Once a name is a known merged alias,
|
|
206
|
+
selecting an engine with no mapping is an actionable configuration error
|
|
207
|
+
rather than silently sending the alias as a model ID.
|
|
163
208
|
|
|
164
209
|
The common execution cascade reads these files for current direct command and
|
|
165
210
|
non-interactive agent calls, task source v4 runs, and improve/proposal/index
|
|
@@ -351,8 +396,62 @@ unless a remote `embedding` config is provided.
|
|
|
351
396
|
`akm improve`'s memory-inference/consolidate passes when they call an
|
|
352
397
|
embedding model: `provider`, `endpoint`, `model`, `apiKey` (symbolic
|
|
353
398
|
reference, same rules as engine `apiKey`), `dimension`, `localModel`,
|
|
354
|
-
`maxTokens`, `batchSize`, `chunkSize`, `contextLength`,
|
|
355
|
-
`ollamaOptions.num_ctx`.
|
|
399
|
+
`maxInputTokens`, `maxTokens`, `batchSize`, `chunkSize`, `contextLength`,
|
|
400
|
+
`timeoutMs`, `concurrency`, and `ollamaOptions.num_ctx`.
|
|
401
|
+
|
|
402
|
+
The knobs that bound request/document size and rate, all optional (defaults
|
|
403
|
+
apply when unset), for a remote endpoint (`src/llm/embedders/remote.ts`):
|
|
404
|
+
|
|
405
|
+
| Key | Default | Bounds |
|
|
406
|
+
| --- | --- | --- |
|
|
407
|
+
| `embedding.maxInputTokens` | `512` | Per-DOCUMENT cap, applied before batching (#956). A document's embedded text is truncated to its head (unicode-safe) at this many estimated tokens instead of ever being skipped for size alone — a document is skipped only when its truncated head is empty. |
|
|
408
|
+
| `embedding.maxTokens` | `8000` (`DEFAULT_TOKEN_BUDGET`) | Per-REQUEST token budget: how many (already-capped) documents' estimated tokens fit in one HTTP request. With the 512-token default document cap, a request carries about 16 documents by default. |
|
|
409
|
+
| `embedding.batchSize` | `100` | Per-REQUEST document-COUNT safety cap, independent of the token budget — guards against many tiny documents packing an oversized request. |
|
|
410
|
+
| `embedding.contextLength` | unset | Ollama's `num_ctx` ONLY, forwarded verbatim as `options.num_ctx` on the native `/api/embed` request. Does **not** feed the request token budget above (#956) — the two used to share this one field, so setting it for the server's context window silently changed request batching too. |
|
|
411
|
+
| `embedding.timeoutMs` | `120000` (120s) | Per-request wall timeout — see below. |
|
|
412
|
+
| `embedding.concurrency` | `1` loopback / `2` remote | In-flight request window — see below. |
|
|
413
|
+
|
|
414
|
+
`embedding.timeoutMs` (positive integer, default `120000` — 120s) is the
|
|
415
|
+
budget for a request at the FULL token budget (`embedding.maxTokens`); a
|
|
416
|
+
local model server on a large, token-budget-bounded batch legitimately takes
|
|
417
|
+
longer than the prior fixed 30s cut off. A smaller request gets a
|
|
418
|
+
proportionally smaller timeout —
|
|
419
|
+
`clamp(timeoutMs × requestTokens / tokenBudget, 30000, timeoutMs)` — so a
|
|
420
|
+
dead endpoint is still detected in seconds on the common case of small
|
|
421
|
+
documents. Set `embedding.timeoutMs` lower to fail fast against a
|
|
422
|
+
known-fast endpoint, or higher for a slow local server on large batches.
|
|
423
|
+
|
|
424
|
+
A request TIMEOUT (not a rejection for exceeding the context window) never
|
|
425
|
+
drops its batch immediately: field confirmation showed that once akm
|
|
426
|
+
abandons a timed-out request, the endpoint (e.g. llama-server) keeps
|
|
427
|
+
computing it anyway, so dropping it right away just grows the provider's
|
|
428
|
+
queue while every following batch dies the same way. Instead akm backs off
|
|
429
|
+
(5s, doubling, capped at 60s) and retries the same request once; a second
|
|
430
|
+
timeout splits it in half and retries each half the same way, down to
|
|
431
|
+
individual documents, and a single document that still times out is finally
|
|
432
|
+
skipped (logged at the default `warn` level). After 3 consecutive failures
|
|
433
|
+
at single-document size (timeout or network error), or 3 consecutive
|
|
434
|
+
network errors at any size, the embedding phase stops dispatching further
|
|
435
|
+
requests and reports failure — batches already committed are kept; rerun
|
|
436
|
+
`akm index` once the endpoint is healthy.
|
|
437
|
+
|
|
438
|
+
`akm index` keeps a small number of `/v1/embeddings` requests in flight at
|
|
439
|
+
once (a remote endpoint only; the local transformer path is unaffected):
|
|
440
|
+
`1` for a loopback endpoint (`localhost`, `127.0.0.0/8`, etc. — a local
|
|
441
|
+
model server serves one inference at a time, and parallel requests thrash
|
|
442
|
+
it) and `2` for a remote one, unless `embedding.concurrency` (positive
|
|
443
|
+
integer, 1-16) overrides it. This default holds for the overwhelming
|
|
444
|
+
majority of setups; set the override only for an endpoint that genuinely
|
|
445
|
+
serves parallel requests — a local server started with a multi-slot flag
|
|
446
|
+
(llama.cpp's `--parallel N`, vLLM) — not to "speed up" an ordinary
|
|
447
|
+
single-slot model server, which the default already protects from
|
|
448
|
+
reload-thrash. Request SIZE remains the first throughput lever regardless:
|
|
449
|
+
`embedding.batchSize` (a document-count cap, default 100) together with
|
|
450
|
+
`embedding.maxTokens` (an estimated token budget per request, default 8000
|
|
451
|
+
— NOT `embedding.contextLength`, see the table above) control how many
|
|
452
|
+
documents land in one request — with the default 512-token
|
|
453
|
+
`embedding.maxInputTokens` document cap, that is about 16-32 documents,
|
|
454
|
+
taking about the same wall time as a single one against a healthy endpoint.
|
|
356
455
|
|
|
357
456
|
## Search tuning
|
|
358
457
|
|
|
@@ -484,6 +583,94 @@ Arrays replace, `null` is only valid for nullable fields, and `config unset` is
|
|
|
484
583
|
the only deletion operation. `configVersion` cannot be set or unset with the
|
|
485
584
|
generic walker.
|
|
486
585
|
|
|
586
|
+
`config get <key> --show-source` wraps the (redacted) value as
|
|
587
|
+
`{ value, source }`, where `source` is `"local"` when the local file's own
|
|
588
|
+
JSON sets the key, `"extends:<ref>"` for the nearest `extends` chain member
|
|
589
|
+
that sets it, or `"default"` when neither does. It is opt-in — plain
|
|
590
|
+
`config get` keeps its Stable, script-safe bare-value shape.
|
|
591
|
+
|
|
592
|
+
### Sharing configuration across installs
|
|
593
|
+
|
|
594
|
+
Five hosts running the same fleet often carry an identical `engines` map and
|
|
595
|
+
`improve.strategies` block, differing only in credential delivery (`apiKey`
|
|
596
|
+
vs `apiKeyFile`), bundle paths, and cron offsets. Hand-syncing that block
|
|
597
|
+
across hosts drifts silently. `extends` fixes this: put the shared block in
|
|
598
|
+
one file, and have each host's local config extend it.
|
|
599
|
+
|
|
600
|
+
```jsonc
|
|
601
|
+
// bundles/fleet/config/shared.json — versioned with the bundle, shared by every host
|
|
602
|
+
{
|
|
603
|
+
"configVersion": "0.9.0",
|
|
604
|
+
"engines": {
|
|
605
|
+
"fast": { "kind": "llm", "endpoint": "https://api.example.test/v1/chat/completions", "model": "qwen3" }
|
|
606
|
+
},
|
|
607
|
+
"improve": { "strategies": { "nightly": { "engine": "fast" } } }
|
|
608
|
+
}
|
|
609
|
+
```
|
|
610
|
+
|
|
611
|
+
```jsonc
|
|
612
|
+
// ~/.config/akm/config.json — this host's local file, under 20 lines
|
|
613
|
+
{
|
|
614
|
+
"configVersion": "0.9.0",
|
|
615
|
+
"extends": "fleet//config/shared.json",
|
|
616
|
+
"bundles": {
|
|
617
|
+
"fleet": { "git": "https://github.com/example/fleet-bundle.git" },
|
|
618
|
+
"stash": { "path": "~/akm-stash", "writable": true }
|
|
619
|
+
},
|
|
620
|
+
"defaultBundle": "stash",
|
|
621
|
+
"engines": { "fast": { "apiKeyFile": "/run/secrets/fast-api-key" } }
|
|
622
|
+
}
|
|
623
|
+
```
|
|
624
|
+
|
|
625
|
+
`extends` accepts either form:
|
|
626
|
+
|
|
627
|
+
- A filesystem path — relative paths resolve against the directory of the
|
|
628
|
+
config file that declares them; a leading `~` expands.
|
|
629
|
+
- A `bundle//<path>` ref — a plain file path *relative to that bundle's
|
|
630
|
+
content root* (e.g. `config/shared.json`), resolved through the bundle's
|
|
631
|
+
configured `path`, not the search index — so it never needs `akm index` to
|
|
632
|
+
have run. This is not an asset ref: the path after `//` needs no asset type
|
|
633
|
+
(`scripts/`, `knowledge/`, …) and the shared file is never indexed; it can
|
|
634
|
+
live anywhere under the bundle. An empty, absolute, or content-root-escaping
|
|
635
|
+
path is rejected. Only a filesystem bundle (`bundles.<id>.path`) can host an
|
|
636
|
+
`extends` source; sync a `git`/`website` bundle with `akm bundle
|
|
637
|
+
add`/`akm sync` first so the file is materialized locally, then point
|
|
638
|
+
`extends` at it.
|
|
639
|
+
|
|
640
|
+
There is no `extends: <url>` form: config load is synchronous and runs on
|
|
641
|
+
every invocation, and akm deliberately does not fetch network resources at
|
|
642
|
+
load time (the same reason `registries` is never fetched until a
|
|
643
|
+
registry-touching command runs). A URL-backed shared config should be synced
|
|
644
|
+
as a `git`/`website` bundle and referenced as `extends: bundle//<path>`
|
|
645
|
+
once materialized, reusing the sync machinery akm already has instead of a
|
|
646
|
+
second one inside config load.
|
|
647
|
+
|
|
648
|
+
The base config runs through the exact same load pipeline as the local
|
|
649
|
+
file — its own version shim, its own legacy-shape shim — so it can carry an
|
|
650
|
+
older `configVersion` independently, and it may itself set `extends`
|
|
651
|
+
(chained). Cycle detection (`ConfigError`, "extends cycle detected") stops A
|
|
652
|
+
extends B extends A instead of recursing forever. Merge order is
|
|
653
|
+
`DEFAULT_CONFIG` (outermost) → the resolved `extends` chain → the local
|
|
654
|
+
file's own keys (local always wins) — the same `deepMergeConfig` "override
|
|
655
|
+
wins" semantics `config set` already uses. A referenced file/bundle that does
|
|
656
|
+
not already exist locally is a load-time `ConfigError` naming the ref — akm
|
|
657
|
+
never fetches or syncs one on your behalf.
|
|
658
|
+
|
|
659
|
+
`akm config diff <path|bundle//path>` compares this host's EFFECTIVE
|
|
660
|
+
config (its own `extends` already applied) against another config file or
|
|
661
|
+
bundle-relative file (loaded through the same loader, so ITS `extends` is
|
|
662
|
+
honoured too), printing sorted `{ path, local, other }` rows for every leaf
|
|
663
|
+
that differs. Both sides are redacted the same way `config get`/`list` are
|
|
664
|
+
before comparison, so a differing secret never round-trips into the diff
|
|
665
|
+
output. Cross-host comparison (`ssh host2 akm config diff ...` in a loop) is
|
|
666
|
+
left to the operator; akm has no concept of a networked fleet to compare
|
|
667
|
+
against directly.
|
|
668
|
+
|
|
669
|
+
```sh
|
|
670
|
+
akm config diff ~/other-host/config.json
|
|
671
|
+
akm config diff fleet//config/shared.json
|
|
672
|
+
```
|
|
673
|
+
|
|
487
674
|
## Environment
|
|
488
675
|
|
|
489
676
|
| Variable | Purpose |
|
|
@@ -513,6 +700,32 @@ not itself a secret. Setting both `apiKey` and `apiKeyFile` on the same
|
|
|
513
700
|
engine is rejected. A missing, unreadable, or empty file fails the call
|
|
514
701
|
closed, naming the engine and path but never the file's content.
|
|
515
702
|
|
|
703
|
+
`engines.<name>.apiKey` also accepts `secret://<name>`, a reference into
|
|
704
|
+
AKM's own secret store (`akm secret set <name> --from-file <file>`), for a
|
|
705
|
+
launch context where the credential's environment variable is deliberately
|
|
706
|
+
not sourced into the process — a scheduled task's crontab preamble, or a
|
|
707
|
+
container entrypoint that keeps the user's env out on purpose — and a
|
|
708
|
+
file-backed credential is not an option. Like `apiKeyFile`, only the
|
|
709
|
+
reference is kept in `config.json`; the store lookup happens at dispatch
|
|
710
|
+
time, and an unresolved reference fails the call closed, naming the
|
|
711
|
+
reference but never the value. `akm improve`, workflow LLM steps, and `akm
|
|
712
|
+
health`'s engine probes all resolve `secret://` the same way direct LLM and
|
|
713
|
+
embedding calls have since 0.9.13 (#917); resolution order for a single
|
|
714
|
+
`apiKey` field is: an env reference (`$VAR`/`${VAR}`) first, then
|
|
715
|
+
`apiKeyFile`, then `secret://<name>` — though in practice a config sets only
|
|
716
|
+
one of the three per engine.
|
|
717
|
+
|
|
718
|
+
`embedding.apiKey` accepts the same three forms and resolves `secret://` the
|
|
719
|
+
same way, on every path that sends an embedding request: `akm index`
|
|
720
|
+
(including its `bundle update` post-commit embedding pass and the targeted
|
|
721
|
+
re-embed a write command like `akm remember` triggers), `akm improve`'s
|
|
722
|
+
consolidate pass (memory dedup and similarity clustering), and the
|
|
723
|
+
fingerprint-rename canary `akm index` runs when the embedding config
|
|
724
|
+
changes. All of them build the
|
|
725
|
+
provider request through the same `RemoteEmbedder`/`resolveSecret` boundary,
|
|
726
|
+
so a `secret://` reference resolves identically regardless of which command
|
|
727
|
+
triggered the request (#953).
|
|
728
|
+
|
|
516
729
|
Use `AKM_SQLITE_JOURNAL_MODE=DELETE` or `TRUNCATE` when WAL is unavailable,
|
|
517
730
|
such as on some NFS/SMB mounts. With the default `WAL` setting, AKM detects a
|
|
518
731
|
network filesystem for the data directory and falls back to `DELETE`.
|
|
@@ -230,6 +230,14 @@ the set of types the code actually emits at HEAD (verified against every
|
|
|
230
230
|
| `llm_usage_summary` | The owning LLM telemetry sink's terminal-record count marker | `expectedTerminalRecords` |
|
|
231
231
|
| `health_probe` | `akm health`'s state.db round-trip write/read probe. **Not durably retained**: the row is inserted then deleted within the same connection once the round trip is confirmed, so the net effect on the `events` table is always zero rows | n/a (ephemeral) |
|
|
232
232
|
|
|
233
|
+
`llm_usage` rows also carry `process`/`engine`/`stage` (each optional; a call
|
|
234
|
+
made outside any attributed scope carries none of them). `akm improve`
|
|
235
|
+
(#944) aggregates a run's own `llm_usage` events into a process x engine x
|
|
236
|
+
model cross-tab — `summarizeLlmUsageCrossTab` in `src/commands/health/llm-usage.ts`
|
|
237
|
+
— persisted on the run result as `usageReport.byProcessEngineModel` and
|
|
238
|
+
queryable per-run or aggregated with `akm improve report`; see
|
|
239
|
+
`docs/reference/cli.md`'s `#### improve report` section.
|
|
240
|
+
|
|
233
241
|
### 2. Usage Events Table
|
|
234
242
|
|
|
235
243
|
`usage_events` is the local analytical record behind utility ranking,
|
package/docs/reference/tasks.md
CHANGED
|
@@ -121,6 +121,20 @@ key in task source v4: `agent`, `engine`, `model`, `inference`, `tools`,
|
|
|
121
121
|
number, or boolean values. Keep credentials out of task source; `redact`
|
|
122
122
|
contains environment variable names, never secret values.
|
|
123
123
|
|
|
124
|
+
`timeout:` (milliseconds) means a different mechanism depending on the
|
|
125
|
+
target. For `run:` (native shell/script) and `workflows/<name>` targets it is
|
|
126
|
+
an outer supervisory deadline: the runner kills the child process, or aborts
|
|
127
|
+
the workflow run at its next step boundary, when it fires. For `uses:
|
|
128
|
+
akm/command`, `commands/<name>`, and any other agent/LLM dispatch target
|
|
129
|
+
there is no outer process kill — `timeout:` instead resolves through the
|
|
130
|
+
execution cascade (config/persona/command/task layers) into the dispatch's
|
|
131
|
+
own deadline, and the SDK/CLI runner races each phase against it internally.
|
|
132
|
+
Either way, a dispatch that times out is recorded as `status: failed` with
|
|
133
|
+
`detail.reason: "timeout"` in `task_history` — not a silent `completed` — and
|
|
134
|
+
`akm task run` exits non-zero for it; see [health-advisories.md's
|
|
135
|
+
`task-fail-rate` row](https://github.com/itlackey/akm/blob/main/docs/architecture/internals/health-advisories.md)
|
|
136
|
+
for how `akm health` surfaces a timeout-dominant failure pattern.
|
|
137
|
+
|
|
124
138
|
## Scheduling
|
|
125
139
|
|
|
126
140
|
Scheduling is **optional**. Omit `schedule:` entirely for a manual-only
|
|
@@ -381,7 +395,8 @@ for full before/after examples and recovery guidance.
|
|
|
381
395
|
|
|
382
396
|
## Operations
|
|
383
397
|
|
|
384
|
-
- `akm search --type task`
|
|
398
|
+
- `akm search --type task` (or its alias `akm task list`) and
|
|
399
|
+
`akm show tasks/<id>` inspect task assets.
|
|
385
400
|
- `akm task explain <ref>` prints a task's declared inputs, resolved target,
|
|
386
401
|
effective execution settings, and schedule bindings without running
|
|
387
402
|
anything — see [`akm task explain`](#akm-task-explain) above.
|
|
@@ -1352,7 +1352,11 @@ optional user `models.json` files:
|
|
|
1352
1352
|
|
|
1353
1353
|
Resolution checks the selected engine name or canonical harness column. A
|
|
1354
1354
|
known alias without that column fails rather than guessing a provider model;
|
|
1355
|
-
an unknown string is treated as an exact model selector.
|
|
1355
|
+
an unknown string is treated as an exact model selector. A column may itself
|
|
1356
|
+
be an `engine`-backed indirection (0.9.15) rather than a literal model string
|
|
1357
|
+
— see [Model-map files](configuration.md#model-map-files) — so a step naming
|
|
1358
|
+
`model: fast` also benefits from whatever engine-backed mapping the operator
|
|
1359
|
+
configured for the selected engine, with no workflow-authored change. See the [Author's Guide](https://github.com/itlackey/akm/blob/main/docs/guides/author-workflows.md#choosing-engines-and-models)
|
|
1356
1360
|
for guidance on which tier to pick per step.
|
|
1357
1361
|
|
|
1358
1362
|
## See also
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "akm-cli",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.15-beta.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "akm (Agent Knowledge Manager) — a portable, local-first capability library for AI agents. Discover, load, share, and improve reusable skills, scripts, workflows, and knowledge across any shell-capable coding agent, including Claude Code, OpenCode, and Cursor.",
|
|
6
6
|
"keywords": [
|
package/schemas/akm-config.json
CHANGED
|
@@ -9,6 +9,10 @@
|
|
|
9
9
|
"type": "string",
|
|
10
10
|
"const": "0.9.0"
|
|
11
11
|
},
|
|
12
|
+
"extends": {
|
|
13
|
+
"type": "string",
|
|
14
|
+
"minLength": 1
|
|
15
|
+
},
|
|
12
16
|
"engines": {
|
|
13
17
|
"type": "object",
|
|
14
18
|
"additionalProperties": {
|
|
@@ -207,6 +211,10 @@
|
|
|
207
211
|
"type": "string",
|
|
208
212
|
"minLength": 1
|
|
209
213
|
},
|
|
214
|
+
"maxInputTokens": {
|
|
215
|
+
"type": "integer",
|
|
216
|
+
"exclusiveMinimum": 0
|
|
217
|
+
},
|
|
210
218
|
"maxTokens": {
|
|
211
219
|
"type": "integer",
|
|
212
220
|
"exclusiveMinimum": 0
|
|
@@ -232,6 +240,15 @@
|
|
|
232
240
|
}
|
|
233
241
|
},
|
|
234
242
|
"additionalProperties": true
|
|
243
|
+
},
|
|
244
|
+
"timeoutMs": {
|
|
245
|
+
"type": "integer",
|
|
246
|
+
"exclusiveMinimum": 0
|
|
247
|
+
},
|
|
248
|
+
"concurrency": {
|
|
249
|
+
"type": "integer",
|
|
250
|
+
"exclusiveMinimum": 0,
|
|
251
|
+
"maximum": 16
|
|
235
252
|
}
|
|
236
253
|
},
|
|
237
254
|
"additionalProperties": true
|
|
@@ -1696,6 +1713,10 @@
|
|
|
1696
1713
|
"type": "string",
|
|
1697
1714
|
"const": "0.9.0"
|
|
1698
1715
|
},
|
|
1716
|
+
"extends": {
|
|
1717
|
+
"type": "string",
|
|
1718
|
+
"minLength": 1
|
|
1719
|
+
},
|
|
1699
1720
|
"engines": {
|
|
1700
1721
|
"type": "object",
|
|
1701
1722
|
"additionalProperties": {
|
|
@@ -1894,6 +1915,10 @@
|
|
|
1894
1915
|
"type": "string",
|
|
1895
1916
|
"minLength": 1
|
|
1896
1917
|
},
|
|
1918
|
+
"maxInputTokens": {
|
|
1919
|
+
"type": "integer",
|
|
1920
|
+
"exclusiveMinimum": 0
|
|
1921
|
+
},
|
|
1897
1922
|
"maxTokens": {
|
|
1898
1923
|
"type": "integer",
|
|
1899
1924
|
"exclusiveMinimum": 0
|
|
@@ -1919,6 +1944,15 @@
|
|
|
1919
1944
|
}
|
|
1920
1945
|
},
|
|
1921
1946
|
"additionalProperties": true
|
|
1947
|
+
},
|
|
1948
|
+
"timeoutMs": {
|
|
1949
|
+
"type": "integer",
|
|
1950
|
+
"exclusiveMinimum": 0
|
|
1951
|
+
},
|
|
1952
|
+
"concurrency": {
|
|
1953
|
+
"type": "integer",
|
|
1954
|
+
"exclusiveMinimum": 0,
|
|
1955
|
+
"maximum": 16
|
|
1922
1956
|
}
|
|
1923
1957
|
},
|
|
1924
1958
|
"additionalProperties": true
|
|
@@ -3463,6 +3497,10 @@
|
|
|
3463
3497
|
"type": "string",
|
|
3464
3498
|
"minLength": 1
|
|
3465
3499
|
},
|
|
3500
|
+
"maxInputTokens": {
|
|
3501
|
+
"type": "integer",
|
|
3502
|
+
"exclusiveMinimum": 0
|
|
3503
|
+
},
|
|
3466
3504
|
"maxTokens": {
|
|
3467
3505
|
"type": "integer",
|
|
3468
3506
|
"exclusiveMinimum": 0
|
|
@@ -3488,6 +3526,15 @@
|
|
|
3488
3526
|
}
|
|
3489
3527
|
},
|
|
3490
3528
|
"additionalProperties": true
|
|
3529
|
+
},
|
|
3530
|
+
"timeoutMs": {
|
|
3531
|
+
"type": "integer",
|
|
3532
|
+
"exclusiveMinimum": 0
|
|
3533
|
+
},
|
|
3534
|
+
"concurrency": {
|
|
3535
|
+
"type": "integer",
|
|
3536
|
+
"exclusiveMinimum": 0,
|
|
3537
|
+
"maximum": 16
|
|
3491
3538
|
}
|
|
3492
3539
|
},
|
|
3493
3540
|
"additionalProperties": true
|