akm-cli 0.10.261014-beta → 0.10.261015-beta
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 +45 -0
- package/README.md +7 -8
- package/SECURITY.md +3 -3
- package/dist/cli.js +2 -2
- package/dist/commands/health/semantic-search-check.js +2 -2
- package/dist/core/npm-package.js +89 -0
- package/dist/{integrations/harnesses/opencode/runtime → core}/tar.js +25 -16
- package/dist/integrations/harnesses/opencode/runtime/binary.js +8 -75
- package/dist/integrations/harnesses/opencode/runtime/index.js +5 -1
- package/dist/llm/embedders/local.js +23 -58
- package/dist/llm/embedders/onnx-runtime.js +121 -0
- package/dist/scripts/akm-migrate-node.js +15 -28
- package/dist/scripts/akm-migrate.js +15 -28
- package/dist/setup/semantic-assets.js +9 -6
- package/dist/setup/setup.js +56 -2
- package/dist/setup/steps/embeddings.js +21 -4
- package/dist/storage/database.js +17 -57
- package/docs/architecture/akm-core-principles.md +3 -2
- package/docs/architecture/internals/health-advisories.md +1 -1
- package/docs/architecture/internals/storage-locations.md +1 -0
- package/docs/architecture/testing/testing-workflow.md +21 -12
- package/docs/guides/getting-started.md +20 -18
- package/docs/guides/recipes/headless-install.md +13 -8
- package/docs/migration/v0.9-to-v0.10.md +17 -0
- package/docs/reference/cli.md +20 -9
- package/docs/reference/configuration.md +37 -15
- package/package.json +3 -6
- package/dist/standalone/onnxruntime-library.js +0 -52
package/dist/storage/database.js
CHANGED
|
@@ -125,66 +125,32 @@ function loadBunSqlite() {
|
|
|
125
125
|
}
|
|
126
126
|
let betterSqlite3Ctor;
|
|
127
127
|
/**
|
|
128
|
-
* The
|
|
128
|
+
* The package is missing, or it carries no binding for this platform. Its N-API
|
|
129
|
+
* bindings ship prebuilt in the package (see package.json → pinNotes), so neither
|
|
130
|
+
* a build toolchain nor the Node version decides whether it loads.
|
|
129
131
|
*/
|
|
130
|
-
|
|
131
|
-
"
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
* and answer with the one command that fixes it.
|
|
138
|
-
*
|
|
139
|
-
* This is the most likely failure a real user hits, and it is not a broken
|
|
140
|
-
* install: a native addon is compiled (or a prebuilt binary is selected) for
|
|
141
|
-
* the Node major present at `npm install` time. Upgrade Node afterwards and the
|
|
142
|
-
* same file no longer loads.
|
|
143
|
-
*
|
|
144
|
-
* It is matched rather than described because the symptom text varies and the
|
|
145
|
-
* previous wording only named ONE of them. The prebuilt-binary path — which is
|
|
146
|
-
* now the normal path, since better-sqlite3 is pinned to a version publishing a
|
|
147
|
-
* prebuild for every supported Node (see package.json → pinNotes) — reports
|
|
148
|
-
* `Module did not self-register`, saying nothing about versions at all. A
|
|
149
|
-
* from-source build reports the explicit `NODE_MODULE_VERSION` mismatch. Asking
|
|
150
|
-
* the user to decide which bullet applies is the step worth deleting.
|
|
151
|
-
*/
|
|
152
|
-
export function abiMismatchRemedy(message) {
|
|
153
|
-
const ABI_MISMATCH_SHAPES = [
|
|
154
|
-
"did not self-register", // prebuilt binary for another ABI
|
|
155
|
-
"NODE_MODULE_VERSION", // explicit mismatch, from-source build
|
|
156
|
-
"was compiled against a different", // same, older phrasing
|
|
157
|
-
"invalid ELF header", // binary for another platform/arch entirely
|
|
158
|
-
];
|
|
159
|
-
if (!ABI_MISMATCH_SHAPES.some((shape) => message.includes(shape)))
|
|
160
|
-
return undefined;
|
|
161
|
-
return ("akm could not load 'better-sqlite3': its native binding was built for a different\n" +
|
|
162
|
-
`Node.js version than the one now running (this Node is ABI ${process.versions.modules}).\n` +
|
|
163
|
-
"This is what happens when Node is upgraded after akm is installed. It is NOT a\n" +
|
|
164
|
-
"broken install, and reinstalling akm is not required.\n" +
|
|
165
|
-
" Fix: npm rebuild better-sqlite3 # in akm's install directory\n" +
|
|
166
|
-
" Or: npm install -g akm-cli # reinstall, rebuilding against this Node\n" +
|
|
167
|
-
" Or: run akm under Bun, whose built-in SQLite driver needs no native binding.");
|
|
132
|
+
function missingBindingRemedy() {
|
|
133
|
+
return ("akm could not load 'better-sqlite3', the SQLite driver it needs on Node.js.\n" +
|
|
134
|
+
" • Its package carries prebuilt bindings for Linux and macOS on x64 and arm64 and for\n" +
|
|
135
|
+
` Windows on x64 and arm64; this machine is ${process.platform} ${process.arch}.\n` +
|
|
136
|
+
" • Reinstall akm (`npm install -g akm-cli`) if the package is missing (a global\n" +
|
|
137
|
+
" `npm i -g better-sqlite3` will NOT be resolved — Node loads it from akm's own node_modules).\n" +
|
|
138
|
+
" • Or run akm under Bun, which has a built-in SQLite driver and needs no native binding.");
|
|
168
139
|
}
|
|
169
140
|
function loadBetterSqlite3() {
|
|
170
141
|
if (!betterSqlite3Ctor) {
|
|
171
142
|
// Runtime-gated dynamic require: only reached when NOT on Bun, so Bun never
|
|
172
143
|
// resolves or loads the optional `better-sqlite3` native dependency.
|
|
173
144
|
// `better-sqlite3` is an optionalDependency, so `npm i` can succeed without
|
|
174
|
-
// it
|
|
175
|
-
//
|
|
145
|
+
// it. Convert the raw MODULE_NOT_FOUND into an actionable message instead of
|
|
146
|
+
// a cryptic onboarding crash.
|
|
176
147
|
let mod;
|
|
177
148
|
try {
|
|
178
149
|
mod = nodeRequire("better-sqlite3");
|
|
179
150
|
}
|
|
180
151
|
catch (err) {
|
|
181
|
-
// An ABI mismatch does NOT arrive here — `require` succeeds and the
|
|
182
|
-
// failure lands at construction (see openNodeDatabase). This path is a
|
|
183
|
-
// genuinely absent or unresolvable module. `abiMismatchRemedy` is still
|
|
184
|
-
// consulted because a from-source build CAN fail at load with the
|
|
185
|
-
// explicit NODE_MODULE_VERSION message.
|
|
186
152
|
const raw = err instanceof Error ? err.message : String(err);
|
|
187
|
-
throw new Error(`${
|
|
153
|
+
throw new Error(`${missingBindingRemedy()}\n Underlying load error: ${raw}`);
|
|
188
154
|
}
|
|
189
155
|
betterSqlite3Ctor = mod.default ?? mod;
|
|
190
156
|
}
|
|
@@ -201,23 +167,17 @@ function openNodeDatabase(path, opts) {
|
|
|
201
167
|
options.readonly = opts.readonly;
|
|
202
168
|
if (opts?.create === false)
|
|
203
169
|
options.fileMustExist = true;
|
|
204
|
-
// Construction, not `require`, is where an ABI mismatch surfaces.
|
|
205
|
-
// `require("better-sqlite3")` SUCCEEDS against a binding built for another
|
|
206
|
-
// Node ABI — the package resolves its `.node` file lazily — so the loader's
|
|
207
|
-
// catch never sees this error and cannot explain it. Verified against a real
|
|
208
|
-
// ABI-127 binding under Node 24 (ABI 137): `require()` returned a function
|
|
209
|
-
// and `new Database(...)` threw. Wrapping the require alone left the most
|
|
210
|
-
// likely real-world failure reported as a bare Node internals message.
|
|
211
170
|
let db;
|
|
212
171
|
try {
|
|
213
172
|
db = opts ? new BetterSqlite3(path, options) : new BetterSqlite3(path);
|
|
214
173
|
}
|
|
215
174
|
catch (err) {
|
|
175
|
+
// The package loads its binding at the first construction, not at `require`, so a platform it carries no
|
|
176
|
+
// binding for fails here.
|
|
216
177
|
const raw = err instanceof Error ? err.message : String(err);
|
|
217
|
-
|
|
218
|
-
if (!remedy)
|
|
178
|
+
if (!raw.includes("better_sqlite3.node"))
|
|
219
179
|
throw err;
|
|
220
|
-
throw new Error(`${
|
|
180
|
+
throw new Error(`${missingBindingRemedy()}\n Underlying error: ${raw}`);
|
|
221
181
|
}
|
|
222
182
|
return {
|
|
223
183
|
prepare: db.prepare.bind(db),
|
|
@@ -225,8 +225,9 @@ Why: an accidental API is a compatibility promise nobody agreed to make.
|
|
|
225
225
|
|
|
226
226
|
Enforced by: `tests/contracts/api-surface.test.ts` (the export list),
|
|
227
227
|
`tests/integration/install/package-exports.test.ts` (the `exports` map),
|
|
228
|
-
`package.json` (`engines.node`
|
|
229
|
-
`node-smoke` job in `.github/workflows/ci.yml` (Node 22
|
|
228
|
+
`package.json` (`engines.node`), the Node version check in the launchers and
|
|
229
|
+
`src/cli.ts`, and the `node-smoke` job in `.github/workflows/ci.yml` (Node 22
|
|
230
|
+
and 24).
|
|
230
231
|
|
|
231
232
|
### 10. Agent harnesses are thin, replaceable internals
|
|
232
233
|
|
|
@@ -26,7 +26,7 @@ changes.
|
|
|
26
26
|
| `connections-and-harnesses` | One table of every configured connection (endpoint, whether its key is held — a `$VAR` set in this shell, a `credentials.json` entry, or none — and whether the endpoint answers) and harness (platform, whether its binary is on `PATH`, and with a probe its `--version`), then the work that runs on them: improve, judges, agents, extract, enrich, index, embedding and curate rerank, each naming the connection or harness and the model it resolves to through the same resolver the calls use (`evidence.rows`, typed `connection`, `harness` or `process`). `warn` when a key variable is unset, an endpoint does not answer, a harness is not installed, several connections (or harnesses) are configured and none is called `default` (said once, with the fix: name one `default`), or a work row cannot resolve because of the config; `unknown` when neither a connection nor a harness is configured; otherwise `pass`. Endpoint reachability is one bounded `GET /models` and the version is the harness's own `--version`; with `--no-probe` neither runs and the message says so. | Correct the named connection, key or harness; run `akm setup` when nothing is configured. A work row whose parts run somewhere other than the row's own target lists them in `overrides`, each with the kind (connection or harness), name and model it runs on: that is a per-process pin, working as set. |
|
|
27
27
|
| `task-fail-rate` | ≥5% of scheduled task runs failed in the window (exit 143/70 recurring), or a single task_id fails at/above the same threshold. (#943) For `command`-kind (agent/LLM dispatch) failures specifically, `evidence.agentFailureReasonCounts` always carries a `detail.reason` breakdown (`timeout`, `non_zero_exit`, `spawn_failed`, …), and the warn message names the dominant reason — e.g. `(timeout-dominant: 9/12 command-task failures)` — when one reason is at least half of the counted command-task failures. | Triage as a bug: `akm task doctor`, inspect failing lane logs. For a native shell/script task, exit-143 = killed/timeout, exit-70 = internal error. For a `command`-kind (agent/LLM) task, read `detail.reason` from `akm task history` instead of the exit code — `timeout` means the dispatch's own deadline (not an outer process kill) expired; `non_zero_exit`/`spawn_failed`/`aborted`/etc. name the other failure shapes. |
|
|
28
28
|
| `data-dir-usage` | The data directory is more than 3× the live databases (`state.db` + `index.db` + `logs.db`), or one top-level subdirectory holds more than half of it; the message names that subdirectory with its size and share. | Look at the named subdirectory. `backups/tasks/` holds one snapshot per `akm migrate apply` run that rewrote a task file; everything under `backups/` is yours to prune. |
|
|
29
|
-
| `semantic-search` | What the last `akm index` recorded about semantic search, with the index's entry and vector counts read now; no model load, no request. `pass` when every entry has a vector (local: on `onnxruntime-node`) or `semanticSearchMode` is `off`; `warn` when vectors lag entries, local embeddings ran on another runtime, or
|
|
29
|
+
| `semantic-search` | What the last `akm index` recorded about semantic search, with the index's entry and vector counts read now; no model load, no request. `pass` when every entry has a vector (local: on `onnxruntime-node`) or `semanticSearchMode` is `off`; `warn` when vectors lag entries, local embeddings ran on another runtime, or akm offers no local embeddings on this platform (`unavailable: platform`, where keyword search or an endpoint is the default); `fail` when the last index found it `blocked` (endpoint or model download failed) or `unavailable: load` (the runtime could not be downloaded or did not load, for example from a `noexec` cache directory), with the reason; `unknown` before the first index. A hard check, so a `fail` fails `akm health`. | `fail`: fix the reason named, then run `akm index`; the check reads the next index's record. `warn` for the platform: `akm setup --embedding off` for keyword search, or `akm setup --embedding <model> --embedding-endpoint <url>` for a remote endpoint. |
|
|
30
30
|
| `stash-git-exposure` | `env/` or `secrets/` assets are git-tracked **and** a remote is set — `git push` can leak keys. | `git rm --cached` the files, add `env/`+`secrets/` to `.gitignore` (a rule alone does not untrack). |
|
|
31
31
|
| `session-extraction` | (#914) Derived from the `extract_sessions_seen` ledger for the last 7 days — not `improve_runs`, which the hook-driven `akm proposal extract --session-id ...` never writes. `unknown` when nothing was recorded; `warn` when every session in the window was skipped for an infrastructure reason (`llm_unavailable`, `read_failed`, `exception`, `locked_concurrent`), naming the reason and engine; otherwise `pass` with per-outcome counts. | An `unknown` machine may be deliberately not configured for extraction, or may have stopped harvesting — check for recent sessions. A `warn` names the broken engine/reason directly. |
|
|
32
32
|
| `auto-accept-validation` | Proposals passed the confidence gate but failed validation (bad frontmatter, truncation). | Review the affected pending proposals via `akm proposal list`; they were held, not lost. |
|
|
@@ -810,6 +810,7 @@ adapter recognizes — `schema.md` + `pages/` is the probe) contains:
|
|
|
810
810
|
| `$CACHE/tasks/logs/<task-id>/` | Per-run stdout/stderr log files (`<ISO-ts>.log`) | No cleanup |
|
|
811
811
|
| `$CACHE/bin/rg` | Auto-downloaded ripgrep binary | Permanent |
|
|
812
812
|
| `$CACHE/opencode/<version>/opencode` | The OpenCode binary akm's own runtime runs (about 240 MB), fetched from the npm registry on its first use | Permanent; safe to delete (fetched again) |
|
|
813
|
+
| `$CACHE/onnxruntime/<version>-<platform>-<arch>/` | `onnxruntime_binding.node` and the ONNX Runtime library it links, which the local embedder loads; fetched from the npm registry by `akm setup --embedding local` or the first local embedding (about 36 MB kept). Must be on a mount that allows executing files | Permanent; safe to delete (fetched again) |
|
|
813
814
|
| `$CACHE/index/unresolved-sources/<stash>/<name>` | Synthetic placeholder path for a configured source whose content root did not resolve this run; never written to disk, only reported as a `SearchSource.path`. Moved out of `$STASH/.akm/unresolved-sources/` (itlackey/akm#890). | N/A (not a real directory) |
|
|
814
815
|
|
|
815
816
|
Cache-backed bundles (`git`, `website`, `npm`) are materialised into `$CACHE`
|
|
@@ -240,19 +240,27 @@ sets the same path and restores it from a model/source-identified Actions
|
|
|
240
240
|
cache. Candidate tags and manual runs are restore-only; only the scheduled
|
|
241
241
|
default-branch run may save a cache entry.
|
|
242
242
|
|
|
243
|
-
The same gate runs real semantic index/search round-trips on `onnxruntime-node
|
|
244
|
-
asserts the `embeddingRuntime` the index reports, and compares the
|
|
245
|
-
vectors with the Transformers.js reference in
|
|
246
|
-
`tests/fixtures/embedder-reference-vectors.json`.
|
|
247
|
-
|
|
248
|
-
|
|
243
|
+
The same gate runs real semantic index/search round-trips on `onnxruntime-node`'s
|
|
244
|
+
binding, asserts the `embeddingRuntime` the index reports, and compares the
|
|
245
|
+
embedder's vectors with the Transformers.js reference in
|
|
246
|
+
`tests/fixtures/embedder-reference-vectors.json`. The binding and its library are
|
|
247
|
+
shared across runs the same way as the model: `tests/_helpers/onnx-runtime-cache.ts`
|
|
248
|
+
copies the repo-local `.ci-cache/akm/onnxruntime/` into each sandbox's akm cache
|
|
249
|
+
and keeps a folder a run fetched there, and gated CI caches that directory under
|
|
250
|
+
a key from `src/llm/embedders/onnx-runtime.ts`, which pins the ONNX Runtime
|
|
251
|
+
version. Package acceptance separately verifies
|
|
252
|
+
the ordinary npm package surface.
|
|
249
253
|
|
|
250
254
|
`tests/integration/standalone-semantic.test.ts` (the same `AKM_SEMANTIC_TESTS=1`
|
|
251
|
-
gate) builds the host's standalone binary and
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
255
|
+
gate) builds the host's standalone binary and asserts it embeds no `.node` file.
|
|
256
|
+
Where akm offers local embeddings it runs `akm setup --yes --embedding local`,
|
|
257
|
+
expects the binding and the library in the cache folder, and indexes a small
|
|
258
|
+
stash, asserting a ready status, a vector per entry and the native runtime.
|
|
259
|
+
Everywhere else it asserts the default: setup warns and saves keyword search, an
|
|
260
|
+
index with semantic search on reports it unavailable for the platform, `akm
|
|
261
|
+
health` warns, and search is keyword. Gated CI runs it in the Semantic Search job
|
|
262
|
+
(Linux) and in the Native Scheduler job on macOS (local embeddings) and Windows
|
|
263
|
+
(the default), the only places the binary runs on those platforms.
|
|
256
264
|
|
|
257
265
|
### What to test explicitly
|
|
258
266
|
|
|
@@ -282,7 +290,8 @@ This validates three deployment methods across four Linux families:
|
|
|
282
290
|
- bun-based install: Ubuntu, Debian, Alpine, Fedora
|
|
283
291
|
- compiled binary install: Ubuntu, Debian, Fedora
|
|
284
292
|
- npm install: Debian on `node:24-slim`, which has no compiler, python or make
|
|
285
|
-
(`npm install -g` of the packed package
|
|
293
|
+
(`npm install -g --ignore-scripts` of the packed package, as npm 12 installs by
|
|
294
|
+
default; the install's exit code and the smoke test are the check)
|
|
286
295
|
|
|
287
296
|
Binary validation currently excludes Alpine. The compiled Linux binary used in
|
|
288
297
|
this repo's Docker tests is not packaged for Alpine/musl compatibility, so the
|
|
@@ -34,23 +34,24 @@ Or download a standalone binary directly from the
|
|
|
34
34
|
Hitting a PowerShell execution-policy error on Windows? See
|
|
35
35
|
[Troubleshooting](#troubleshooting) at the end of this guide.
|
|
36
36
|
|
|
37
|
-
###
|
|
38
|
-
|
|
39
|
-
Local semantic search
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
37
|
+
### Local semantic search
|
|
38
|
+
|
|
39
|
+
Local semantic search runs its embedding model on ONNX Runtime, and akm offers
|
|
40
|
+
it on Linux x64 (glibc) and Apple-silicon macOS; on every other
|
|
41
|
+
platform search is keyword-only or uses an embedding endpoint you configure. Choosing the built-in embedder in
|
|
42
|
+
`akm setup` (or `akm setup --yes --embedding local`) downloads what it needs once
|
|
43
|
+
into akm's cache directory (`akm info` prints it): ONNX Runtime for your platform,
|
|
44
|
+
under `onnxruntime/<version>-<platform>-<arch>/` (about 86 MB downloaded,
|
|
45
|
+
about 36 MB kept), and the model (about 127 MB). Nothing is installed with the npm
|
|
46
|
+
package or carried in a standalone binary, and the first `akm index` downloads
|
|
47
|
+
what setup did not. Two notes:
|
|
48
|
+
|
|
49
|
+
- The cache directory must be on a mount that allows executing files: the
|
|
50
|
+
runtime is loaded from there, and on a `noexec` mount `akm index` reports
|
|
51
|
+
semantic search `blocked` (keyword search works).
|
|
52
|
+
- On a platform without local embeddings, `akm setup` offers an embedding
|
|
53
|
+
endpoint or keyword search only, and `akm setup --embedding local` warns and
|
|
54
|
+
keeps keyword search.
|
|
54
55
|
|
|
55
56
|
### akm's own agent runtime
|
|
56
57
|
|
|
@@ -60,7 +61,8 @@ is the same for the npm package and the standalone binary: nothing of OpenCode
|
|
|
60
61
|
is installed with akm, and the first time the runtime runs, akm downloads the
|
|
61
62
|
OpenCode binary for your platform from the npm registry (one package, about
|
|
62
63
|
114 MB, 240 MB on disk), checks it against the registry's integrity hash and
|
|
63
|
-
keeps it in the cache directory under `opencode/<version>/`. It is fetched once
|
|
64
|
+
keeps it in the cache directory under `opencode/<version>/`. It is fetched once;
|
|
65
|
+
the `akm setup` wizard offers to fetch it then, when agent work runs there.
|
|
64
66
|
Three limits follow:
|
|
65
67
|
|
|
66
68
|
- That step needs the npm registry. Without network access for it, enable the
|
|
@@ -54,19 +54,24 @@ it and never appears on the command line:
|
|
|
54
54
|
akm setup --yes --endpoint https://api.example.com/v1 --api-key-env EXAMPLE_API_KEY
|
|
55
55
|
```
|
|
56
56
|
|
|
57
|
-
`--no-probe` keeps the run offline
|
|
58
|
-
new connection has no model until
|
|
57
|
+
`--no-probe` keeps the run offline: nothing is contacted or downloaded (the
|
|
58
|
+
endpoint's model list is not fetched, so a new connection has no model until
|
|
59
|
+
`akm models set` names one).
|
|
59
60
|
For the full set of flags, see `akm setup --help`; for the config they write,
|
|
60
61
|
see [configuration.md](../../reference/configuration.md).
|
|
61
62
|
|
|
62
|
-
**Semantic search.**
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
63
|
+
**Semantic search.** `--embedding local` chooses the built-in embedder, offered
|
|
64
|
+
on Linux x64 (glibc) and Apple-silicon macOS; elsewhere it warns and
|
|
65
|
+
keeps keyword search. Once the config is saved, a headless setup (`--yes` or
|
|
66
|
+
`--from`) downloads the embedder's runtime and model into akm's cache and
|
|
67
|
+
reports `semanticAssets` in its result (`ready`, `blocked: <reason>`, or
|
|
68
|
+
`skipped` with `--no-probe`, which leaves the download to the first
|
|
69
|
+
`akm index`). Without the flag, semantic search stays as the config has it
|
|
70
|
+
(`off` by default):
|
|
66
71
|
|
|
67
72
|
```sh
|
|
68
|
-
akm
|
|
69
|
-
akm config set semanticSearchMode off
|
|
73
|
+
akm setup --yes --embedding local # local embeddings, downloaded now
|
|
74
|
+
akm config set semanticSearchMode off # skip embeddings entirely
|
|
70
75
|
```
|
|
71
76
|
|
|
72
77
|
For resource requirements and remote-embedding alternatives, see
|
|
@@ -609,6 +609,23 @@ yours to run it, and its runs are in your OpenCode history, which improve reads.
|
|
|
609
609
|
- **A transient reflect failure** (transport error, timeout, crash) no longer
|
|
610
610
|
uses up the feedback that planned it; the ref is retried next run.
|
|
611
611
|
|
|
612
|
+
### Local semantic search and installs
|
|
613
|
+
|
|
614
|
+
- **akm no longer installs ONNX Runtime through npm.** `akm setup` with the
|
|
615
|
+
built-in embedder (`--embedding local`), or the first `akm index` after the
|
|
616
|
+
upgrade, downloads ONNX Runtime 1.24.3 once (about 86 MB) into akm's cache.
|
|
617
|
+
The vectors are unchanged, so no re-index is needed.
|
|
618
|
+
- **Local embeddings are offered on Linux x64 (glibc) and
|
|
619
|
+
Apple-silicon macOS.** Every other platform uses keyword search or an
|
|
620
|
+
embedding endpoint, and `akm setup` offers only those there.
|
|
621
|
+
- **Standalone binaries are up to 36 MB smaller**, and a `noexec` temp directory
|
|
622
|
+
no longer matters; akm's cache directory must still allow executing files.
|
|
623
|
+
- **On Node, the SQLite driver ships prebuilt for every supported Node
|
|
624
|
+
version**, so `npm install -g akm-cli` works where npm skips install scripts
|
|
625
|
+
(npm 12 does by default), and a Node upgrade no longer needs `npm rebuild`.
|
|
626
|
+
Nothing in the package runs an install script, the Node.js version check
|
|
627
|
+
included: akm checks the version when it starts.
|
|
628
|
+
|
|
612
629
|
### The environment programs run in
|
|
613
630
|
|
|
614
631
|
A harness (agent tasks and workflow agent steps included) and an `exec` unit's
|
package/docs/reference/cli.md
CHANGED
|
@@ -218,9 +218,16 @@ The wizard asks, in order:
|
|
|
218
218
|
the config as this run will save it: a further `--name` connection does not
|
|
219
219
|
serve embeddings, its models are not offered, and with several connections
|
|
220
220
|
none called `default`, `--embedding <model>` refuses and asks you to name one
|
|
221
|
-
default or pass `--embedding-endpoint`.
|
|
221
|
+
default or pass `--embedding-endpoint`. The built-in embedder is offered on
|
|
222
|
+
Linux x64 (glibc) and Apple-silicon macOS only; elsewhere the step
|
|
223
|
+
says so in one sentence and offers an endpoint or off, and `--embedding local`
|
|
224
|
+
warns and saves off.
|
|
222
225
|
5. **Save.** The config is written, the bundle directory initialized, and a
|
|
223
|
-
summary says what runs where.
|
|
226
|
+
summary says what runs where. With the built-in embedder chosen, setup then
|
|
227
|
+
downloads its runtime (ONNX Runtime, about 86 MB) and model (about 127 MB)
|
|
228
|
+
into akm's cache and loads them; the wizard asks first. When agent work runs
|
|
229
|
+
on akm's own runtime, the wizard also offers to download its OpenCode binary
|
|
230
|
+
(about 114 MB) now rather than on the first agent run.
|
|
224
231
|
|
|
225
232
|
Flags answer one question each; `--yes` takes the detected default for every
|
|
226
233
|
question left, so nothing is prompted. Without a terminal, `akm setup` refuses
|
|
@@ -236,7 +243,7 @@ unless `--yes` or `--from` is given.
|
|
|
236
243
|
| `--embedding-endpoint <url>`, `--embedding-api-key-env <NAME>` | Another endpoint serving the embedding model |
|
|
237
244
|
| `--from <file>` | A config file (JSON or YAML) to merge |
|
|
238
245
|
| `--dir <path>`, `--no-init` | The bundle directory; skip scaffolding it |
|
|
239
|
-
| `--no-probe` | Offline:
|
|
246
|
+
| `--no-probe` | Offline: nothing is contacted or downloaded. The endpoint's models are not listed, so a connection added this way has no model until `akm models set` names one, and the built-in embedder's runtime and model are downloaded by the first `akm index` |
|
|
240
247
|
|
|
241
248
|
The detected defaults are: when no agent program is configured yet, every one
|
|
242
249
|
found on `PATH` is enabled and the first found is the default. If no connection
|
|
@@ -249,7 +256,11 @@ whose endpoint lists an embedding model.
|
|
|
249
256
|
|
|
250
257
|
The wizard also lets you review registries and add bundle sources. A scripted run
|
|
251
258
|
prints its result with a `runs` object saying what runs where: `modelCalls`,
|
|
252
|
-
`agentWork` and `embeddings`.
|
|
259
|
+
`agentWork` and `embeddings`. When the saved config uses the built-in embedder,
|
|
260
|
+
the result also has `semanticAssets`: `ready` once its runtime and model are
|
|
261
|
+
downloaded and load, `blocked: <reason>` when they do not (the config is saved
|
|
262
|
+
all the same), or `skipped` with `--no-probe`. A scripted run does not download
|
|
263
|
+
akm's own agent runtime; its first agent run does.
|
|
253
264
|
|
|
254
265
|
### index
|
|
255
266
|
|
|
@@ -464,13 +475,13 @@ search, with the index's entry and vector counts read now. It loads no model and
|
|
|
464
475
|
sends no request. It `pass`es when every entry has a vector (and a local model
|
|
465
476
|
embedded on `onnxruntime-node`) or `semanticSearchMode` is `off`; `warn`s when
|
|
466
477
|
vectors lag the entries (`akm index` embeds the rest), local embeddings ran on
|
|
467
|
-
another runtime, or
|
|
468
|
-
|
|
469
|
-
|
|
478
|
+
another runtime, or akm offers no local embeddings on this platform (keyword
|
|
479
|
+
search or an endpoint is the default there, so the message names
|
|
480
|
+
`akm setup --embedding off` and `akm setup --embedding <model> --embedding-endpoint <url>`);
|
|
470
481
|
`fail`s, with the recorded reason, when the last index found semantic search
|
|
471
482
|
`blocked` (an embedding endpoint or model download failed) or `unavailable` for
|
|
472
|
-
a cause that can be fixed (the
|
|
473
|
-
|
|
483
|
+
a cause that can be fixed (the runtime could not be downloaded or did not load,
|
|
484
|
+
for example from a `noexec` cache directory); and is `unknown` before
|
|
474
485
|
the first index. Search never reads this record: a query still
|
|
475
486
|
tries semantic search and falls back to keyword search on its own. A fix shows
|
|
476
487
|
here after the next `akm index`. `evidence` carries the recorded `status`,
|
|
@@ -690,21 +690,43 @@ semantic search is disabled or has not been built. A read-only sandbox that
|
|
|
690
690
|
cannot record best-effort usage telemetry does not by itself mark search as
|
|
691
691
|
degraded.
|
|
692
692
|
The local embedder runs its model (`Xenova/bge-small-en-v1.5` unless
|
|
693
|
-
`embedding.localModel` names another) on
|
|
694
|
-
`@huggingface/tokenizers` for the token
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
`
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
693
|
+
`embedding.localModel` names another) on ONNX Runtime, through
|
|
694
|
+
`onnxruntime-node`'s native binding, with `@huggingface/tokenizers` for the token
|
|
695
|
+
ids. akm offers local embeddings on Linux x64 (glibc) and Apple-silicon
|
|
696
|
+
macOS; on every other platform semantic search uses an embedding endpoint or
|
|
697
|
+
stays keyword-only. akm does not install `onnxruntime-node`:
|
|
698
|
+
`akm setup --embedding local` (or the wizard's built-in embedder) downloads that
|
|
699
|
+
package's binding and library for this platform once from the npm registry
|
|
700
|
+
(about 86 MB; the registry's sha512 integrity is checked before anything is
|
|
701
|
+
extracted) into `<cache dir>/onnxruntime/<version>-<platform>-<arch>/`, and the
|
|
702
|
+
first local embedding downloads them when setup did not. The model's four files
|
|
703
|
+
(about 127 MB) come from the Hugging Face Hub the same way, into
|
|
704
|
+
`$HF_HOME/<repo>/` (default `<cache dir>/models`); `HF_HUB_OFFLINE=1` forbids
|
|
705
|
+
that download. `akm index --format json` reports the runtime it embedded with as
|
|
706
|
+
`verification.embeddingRuntime`. If the runtime cannot be downloaded or does not
|
|
707
|
+
load (the cache directory is mounted `noexec`), the index reports semantic search
|
|
708
|
+
`blocked` with the reason and search stays keyword-only. On a platform without
|
|
709
|
+
local embeddings, `akm setup` offers an endpoint or keyword search,
|
|
710
|
+
`--embedding local` warns and saves keyword search, and a config that turns
|
|
711
|
+
semantic search on anyway gets it reported unavailable for the platform by the
|
|
712
|
+
index and a warning from `akm health`.
|
|
713
|
+
|
|
714
|
+
**Without network access**, fill akm's cache directory (`akm info` prints
|
|
715
|
+
`cacheDir`; `AKM_CACHE_DIR` moves it) before the first `akm index`:
|
|
716
|
+
|
|
717
|
+
- `onnxruntime/<version>-<platform>-<arch>/` (for example
|
|
718
|
+
`onnxruntime/1.24.3-linux-x64/`) holding `onnxruntime_binding.node` and the
|
|
719
|
+
library it links (`libonnxruntime.so.1` on Linux,
|
|
720
|
+
`libonnxruntime.1.24.3.dylib` on macOS). Take both from
|
|
721
|
+
`package/bin/napi-v6/<platform>/<arch>/` in the `onnxruntime-node@1.24.3`
|
|
722
|
+
tarball (`npm pack onnxruntime-node@1.24.3`), or copy the folder from a
|
|
723
|
+
connected machine of the same platform after
|
|
724
|
+
`akm setup --yes --embedding local`.
|
|
725
|
+
- `models/Xenova/bge-small-en-v1.5/` holding `tokenizer.json`,
|
|
726
|
+
`tokenizer_config.json`, `config.json` and `onnx/model.onnx`, or set `HF_HOME`
|
|
727
|
+
to a directory that holds them and `HF_HUB_OFFLINE=1`.
|
|
728
|
+
- `opencode/2.1.4/opencode` (`opencode.exe` on Windows) for akm's own agent
|
|
729
|
+
runtime.
|
|
708
730
|
The default is `"off"` so a bare or headless install (`akm bundle create`, `--yes`,
|
|
709
731
|
`--config`) never silently downloads the local embedding model on first
|
|
710
732
|
index. A config that has an `embedding` block and sets no `semanticSearchMode`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "akm-cli",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.261015-beta",
|
|
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": [
|
|
@@ -34,9 +34,8 @@
|
|
|
34
34
|
},
|
|
35
35
|
"license": "MPL-2.0",
|
|
36
36
|
"pinNotes": {
|
|
37
|
-
"better-sqlite3@
|
|
37
|
+
"better-sqlite3@13.0.3": "Exact pin. The SQLite driver akm loads on Node (src/storage/database.ts); Bun uses bun:sqlite and never loads it. 13.x is built on N-API (node-addon-api), so one binding per platform serves every Node version, and the npm tarball carries those bindings prebuilt in prebuilds/ for Linux (glibc and musl) and macOS on x64 and arm64 and for Windows on x64 and arm64. It declares no install script and sets gypfile: false, so it installs the same where npm runs install scripts and where it does not (npm 12 blocks dependency scripts by default). Not covered: 32-bit ARM Linux (linux-arm, linuxmusl-arm), which 12.x served only through its install script; akm under Node has no SQLite driver there. `bun install` tries to build it anyway (Bun ignores gypfile: false for a trusted package) and, as an optional dependency, drops it silently when that fails, which is why CI installs it with npm. This replaced 12.11.1, whose binding came per Node ABI from its install script (`prebuild-install || node-gyp rebuild`, #790); the earlier note asked for a soak before 13.x, and 13.0.3 soaks through the 0.10 betas instead. Before bumping: the tarball must still carry prebuilds/ for every platform above and declare no install script, and the CI node-smoke job, which installs this exact string read back out of this file (.github/workflows/ci.yml), must pass on every Node major in engines.",
|
|
38
38
|
"@huggingface/tokenizers@0.1.3": "Exact pin: the tokenizer of the local embedding model (src/llm/embedders/local.ts). Pure JS with no dependencies. A different release can change the token ids and with them every stored vector, so re-run the real-model semantic gate (tests/integration/semantic-search-e2e.test.ts, which compares the vectors with tests/fixtures/embedder-reference-vectors.json) before changing it.",
|
|
39
|
-
"onnxruntime-node@1.24.3": "Exact pin: the local embedding runtime. The standalone binary embeds this version's native library from node_modules/onnxruntime-node/bin/napi-v6/ (src/standalone/native/) and its addon is bound to exactly that library, so a bump moves this pin, the library file names in src/standalone/native/ (the macOS one carries the version), the list of platforms it ships a library for in src/llm/embedders/local.ts and the real-model semantic gate together.",
|
|
40
39
|
"ajv@8.20.0": "Exact pin (devDependency, used only by tests: tests/tasks-schema.test.ts validates task sources against schemas/akm-task.json, tests/contracts/config-schema-drift.test.ts checks schemas/akm-config.json). Pinned in 4d7d77992 without a recorded reason; keep exact until the pin is next reviewed.",
|
|
41
40
|
"cmd-shim@9.0.2": "Exact pin (devDependency), from cd5a3be12 \"pin cmd-shim for launcher tests\": tests/integration/install/package-launcher.test.ts writes the Windows shims npm would write with this package, where it used to load the copy inside the installed npm's own node_modules. That commit records no reason for an exact version over a range; keep exact until the pin is next reviewed."
|
|
42
41
|
},
|
|
@@ -72,7 +71,6 @@
|
|
|
72
71
|
"akm-migrate": "dist/akm-migrate"
|
|
73
72
|
},
|
|
74
73
|
"scripts": {
|
|
75
|
-
"preinstall": "node -e \"var v=(process.versions.node||'0').split('.').map(function(n){return parseInt(n,10)||0});var ok=v[0]>=22;if(ok){process.exit(0)}console.error('\\n ERROR: the akm-cli npm package requires Node.js >= 22.\\n A working Bun >= 1.0 on PATH is optional and preferred for akm and akm-migrate.\\n Upgrade Node.js (https://nodejs.org), or install the runtime-free standalone binary:\\n curl -fsSL https://github.com/itlackey/akm/releases/latest/download/install.sh | bash\\n');process.exit(1)\"",
|
|
76
74
|
"build": "rm -rf dist && bun scripts/gen-config-schema.ts &&bun run tsc --project ./tsconfig.build.json && bun scripts/copy-assets.ts && bun scripts/fix-esm-extensions.ts",
|
|
77
75
|
"check": "bun run lint && bunx tsc --noEmit && bun run test:unit && bun run test:integration",
|
|
78
76
|
"check:fast": "bun run lint && bunx tsc --noEmit && bun run test:unit",
|
|
@@ -109,7 +107,7 @@
|
|
|
109
107
|
"zod-to-json-schema": "^3.23.0"
|
|
110
108
|
},
|
|
111
109
|
"optionalDependencies": {
|
|
112
|
-
"better-sqlite3": "
|
|
110
|
+
"better-sqlite3": "13.0.3",
|
|
113
111
|
"sqlite-vec": "^0.1.9"
|
|
114
112
|
},
|
|
115
113
|
"engines": {
|
|
@@ -123,7 +121,6 @@
|
|
|
123
121
|
"fast-xml-parser": "^5.10.1",
|
|
124
122
|
"marked": "^18.1.1",
|
|
125
123
|
"node-html-parser": "^9.0.1",
|
|
126
|
-
"onnxruntime-node": "1.24.3",
|
|
127
124
|
"semver": "^7.6.0",
|
|
128
125
|
"turndown": "^7.2.4",
|
|
129
126
|
"yaml": "^2.8.4",
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
-
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
-
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
-
/**
|
|
5
|
-
* The ONNX Runtime shared library for a compiled standalone binary.
|
|
6
|
-
*
|
|
7
|
-
* `onnxruntime-node`'s addon links a shared library that sits beside it in the
|
|
8
|
-
* package. A Bun executable extracts an embedded addon at load but not the
|
|
9
|
-
* library it links, so the addon cannot start. The standalone build embeds the
|
|
10
|
-
* library for its target (`src/standalone/native/`, chosen by
|
|
11
|
-
* `scripts/build-standalone.ts`); this copies it once into akm's cache and
|
|
12
|
-
* loads it with `bun:ffi`, after which the addon's own link to it is already
|
|
13
|
-
* satisfied.
|
|
14
|
-
*
|
|
15
|
-
* Outside a standalone binary (`bun src/cli.ts`, the Node build) nothing here
|
|
16
|
-
* is defined and nothing is evaluated: the package's own files are used.
|
|
17
|
-
*/
|
|
18
|
-
import fs from "node:fs";
|
|
19
|
-
import path from "node:path";
|
|
20
|
-
import { getCacheDir } from "../core/paths.js";
|
|
21
|
-
/**
|
|
22
|
-
* Put the embedded library on disk and load it, before `onnxruntime-node` is
|
|
23
|
-
* imported. Throws when the library cannot be loaded; the caller reports that
|
|
24
|
-
* as the embedding runtime being unavailable.
|
|
25
|
-
*/
|
|
26
|
-
export async function preloadOnnxRuntimeLibrary() {
|
|
27
|
-
if (typeof AKM_STANDALONE_NATIVE_MODULE === "undefined")
|
|
28
|
-
return;
|
|
29
|
-
// The specifier is a build constant, so the standalone build bundles this one module and no other build bundles any.
|
|
30
|
-
const { embeddedPath, fileName } = (await import(AKM_STANDALONE_NATIVE_MODULE));
|
|
31
|
-
if (!embeddedPath || !fileName)
|
|
32
|
-
return;
|
|
33
|
-
const directory = path.join(getCacheDir(), "onnxruntime", `${AKM_ONNXRUNTIME_VERSION}-${process.platform}-${process.arch}`);
|
|
34
|
-
const library = path.join(directory, fileName);
|
|
35
|
-
const size = fs.statSync(embeddedPath).size;
|
|
36
|
-
if (!fs.existsSync(library) || fs.statSync(library).size !== size) {
|
|
37
|
-
fs.mkdirSync(directory, { recursive: true });
|
|
38
|
-
const partial = `${library}.${process.pid}.tmp`;
|
|
39
|
-
fs.writeFileSync(partial, fs.readFileSync(embeddedPath));
|
|
40
|
-
try {
|
|
41
|
-
fs.renameSync(partial, library);
|
|
42
|
-
}
|
|
43
|
-
catch (error) {
|
|
44
|
-
// Another akm process copied it first and has it loaded, which Windows will not replace: use that copy.
|
|
45
|
-
fs.rmSync(partial, { force: true });
|
|
46
|
-
if (!fs.existsSync(library) || fs.statSync(library).size !== size)
|
|
47
|
-
throw error;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
const { dlopen } = await import("bun:ffi");
|
|
51
|
-
dlopen(library, { OrtGetApiBase: { args: [], returns: "ptr" } });
|
|
52
|
-
}
|