Commit Graph

556 Commits

Author SHA1 Message Date
b19f486d50
Merge branch 'main' into feat-nvidia-embedding-remote-sync 2026-06-12 07:38:27 +08:00
6021ea34ac
Merge pull request #1 from ai-workspace-services/codex-feat-nvidia-embedding-remote-sync
Codex feat nvidia embedding remote sync
2026-06-12 07:34:39 +08:00
Haitao Pan
77024f7904 feat: add NVIDIA embedding API support and QMD remote sync 2026-06-12 07:32:43 +08:00
Tobias Lütke
636602409c
Merge pull request #715 from rymalia/docs/qmd-reference-phase-1
docs: CLI reference, collection-flag semantics, MCP params, bench, new commands
2026-06-08 18:50:52 +02:00
Ryan Malia
7488fe8094 docs: CLI reference, collection-flag semantics, MCP params, bench, new commands
Documents previously-undocumented surface area surfaced by onboarding feedback
and the bench discoverability report:

- README: collection filtering (-c semantics), collection show/include/exclude/
  update-cmd, --intent/--no-rerank/-C/--full-path, --format <kind> (legacy
  output booleans noted as aliases), vector-search/deep-search aliases, embed
  memory flags, a sample --explain trace, MCP tool parameter reference, qmd
  doctor/init, get :from:count + --no-line-numbers, and a Benchmarking section
  for qmd bench.
- README: removed the misleading `qmd update --pull` example; --pull is parsed
  but never consumed, so it points to `qmd collection update-cmd` (the real
  per-collection pre-reindex mechanism) instead.
- docs/SYNTAX.md: drop the non-existent `q` MCP parameter (the query tool/REST
  endpoint accept only `searches`); add a Scoping section.
- server.ts: buildInstructions now advertises the plural `collections` parameter
  to match the schema (singular was silently stripped, yielding unscoped
  results), and the `get` instruction documents the full file.md:from:count
  range suffix instead of only file.md:100.

Refs #25, #181, #217, #372, #520, #576
2026-06-07 13:37:41 -07:00
Tobias Lütke
3f751cd0f0
Merge pull request #698 from tobi/feat/literal-path-storage
fix: store literal filesystem paths, drop handelize() at index time
2026-06-01 18:49:02 -04:00
Tobias Lütke
5528b14abe test: normalize collectionDir with realpathSync for macOS compat
On macOS /tmp is a symlink to /private/tmp. mkdtemp returns /tmp/...
but getRealPath(resolve(pwd)) in collectionAdd resolves symlinks and
stores /private/tmp/... in the DB. toVirtualPath and --full-path
resolution then fail because the test-side collectionDir path doesn't
match the DB-side path. Fix by calling realpathSync on the test
collectionDir before passing it to CLI commands and assertions.
2026-06-01 20:25:28 +00:00
Tobias Lütke
070147d8ab fix: store literal filesystem paths, drop handelize() at index time
Filenames with special characters (#, &, spaces, [], (), etc.) now
round-trip correctly through index → search → get → full-path.

Root cause: reindexCollection() called handelize() on the relative path
before storing it in documents.path, turning
  '# Meeting - 234232 3432 __ 5.md' → 'Meeting-234232-3432-5.md'
This broke all downstream operations that needed to reconstruct the
real filesystem path from the DB record.

Changes:
- Remove handelize() from reindexCollection() in store.ts (index time)
- Remove handelize() from update command path in cli/qmd.ts
- findOrMigrateLegacyDocument now tries both raw path and handalized
  variant so existing indexes auto-migrate on next qmd update
- resolveVirtualPath, toVirtualPath, detectCollectionFromPath all work
  correctly once the DB stores literal paths

Tests (test/path-fidelity.test.ts — 10/10):
- Store level: DB contains literal paths, not handalized slugs
- toVirtualPath returns non-null for crazy-named files
- (1) search --json file field shows literal path
- (2) get --full-path resolves to a real on-disk path
- (3) get <actual-fs-path> finds the document
- (3b) subdir file with crazy name also works
- (4) ls shows literal paths
- (5) search docid can be fetched back
- Normal filenames still work (regression)
- Migration: qmd update on handalized index rewrites paths to literal
2026-06-01 20:20:50 +00:00
Tobias Lütke
f9d414c931 fix(search): split dotted tokens in FTS5 so version strings like 2026.4.10 match (#563)
fix(http): return qmd:// URIs from REST /query endpoint to match CLI output (#576)
2026-05-31 23:15:37 +00:00
Tobi Lutke
5323277086
release: v2.5.3 2026-05-28 19:53:26 -07:00
Tobi Lutke
c5f4217a6f
fix(cli): exit naturally so node-llama-cpp's beforeExit fires
The libggml-metal static destructor asserts on a non-empty residency-set
collection during __cxa_finalize_ranges, dumping a multi-kB GGML backtrace
after successful output (ggml-org/llama.cpp#22593, one-line fix open as
PR #22595). The assertion only trips when process.exit() skips Node's
beforeExit hook — which is exactly the hook node-llama-cpp registers to
auto-dispose its native handles.

Primary fix: finishSuccessfulCliCommand now sets process.exitCode = 0
and returns instead of calling process.exit(0). The event loop drains,
beforeExit fires, native Metal resources tear down in order, and the
process exits cleanly even without the workaround env var.

Defense-in-depth retained: bin/qmd and scripts/test-all.mjs still export
GGML_METAL_NO_RESIDENCY=1 on darwin for error paths and tests that
terminate via process.exit(). Opt back in with QMD_METAL_KEEP_RESIDENCY=1.

Also: correct upstream issue refs (was #17869 → now #22593/#22595).
Add scripts/repro-metal-rsets-crash.mjs minimal reproduction.
2026-05-28 17:23:31 -07:00
Tobi Lutke
c162ed1319
fix: disable libggml-metal residency sets on darwin
The libggml-metal static device destructor asserts on a non-empty
residency set during libc `exit()` → `__cxa_finalize_ranges`
(ggml-org/llama.cpp#17869). The residency set's 180 s keep_alive timer
hasn't expired by exit, so `GGML_ASSERT([rsets->data count] == 0)`
fails and `ggml_abort` dumps a multi-kB backtrace to stderr after the
user-visible output. Every llama-using CLI command (`query`,
`vsearch`, `embed`) was affected, plus the `bun test` runner.

No JS-side dispose path can prevent it: the static destructor runs
after every JS-reachable cleanup, and Node's `reallyExit` calls libc
`exit()` not `_exit()` (verified in node/src/api/environment.cc),
so it does NOT skip C++ static destructors as we'd assumed.

The actual fix is to disable residency sets via
`GGML_METAL_NO_RESIDENCY=1` before the native binding loads. For
QMD's short-lived CLI workflow there's no measurable cost
(benchmarked: identical wall time with and without on M3 Pro).

Three propagation points are needed:
- `bin/qmd` exports the env var before spawning node/bun. This
  covers all production CLI invocations.
- `src/test-preload.ts` mirrors the launcher for `bun test` runs.
  Bun does NOT sync `process.env` mutations to libc `setenv()`
  (verified empirically — Node does, via uv_os_setenv), so on Bun we
  reach for `bun:ffi` to call `setenv()` directly. vitest forks
  per-test-file so its parent never loads the binding.
- `qmd doctor` reports the mitigation state via the new
  `isDarwinMetalMitigationActive()` predicate so users can verify it
  in their environment.

Opt back in with `QMD_METAL_KEEP_RESIDENCY=1` (long-lived qmd
processes, MCP daemon hot reload, upstream fix triage). The old
`QMD_DISABLE_DARWIN_QUERY_JSON_SAFE_EXIT` is removed — its per-command
bypass mechanism didn't actually work on Node (it called
`process.reallyExit` which goes through libc exit) and is fully
replaced by the launcher env var.

Removed the old broken `installDarwinExitGuard()` mechanism from
LlamaCpp; kept the function name as a no-op shim for back-compat.
2026-05-28 13:40:14 -07:00
Tobi Lutke
0d7fdb7589
fix(launcher): prefer Node+tsx over Bun in source mode when both lockfiles exist
Source-mode runner selection now mirrors the dist-mode 'npm priority' rule:
if both package-lock.json and bun.lock are present in the package root,
use Node + tsx instead of Bun. pnpm/npm installs ship Node-ABI native
modules (better-sqlite3, sqlite-vec), and routing through Bun produces
ABI mismatches.

This also fixes pnpm-global installs, which copy the entire working tree
(including .git and bun.lock) into <prefix>/node_modules/@tobilu/qmd/.
The old logic saw .git + bun.lock + bun-on-PATH and routed to Bun
against the Node-installed native modules.

Adds a regression test covering the both-lockfiles source-checkout case.
2026-05-28 11:57:30 -07:00
Tobi Lutke
3de3162e1a
feat(cli): ./-prefix $PWD-relative --full-path; add --format <kind>
--full-path now ./-prefixes any path that resolves under $PWD, both for
search/query results and for get/multi-get headers. This makes the
output unambiguously a filesystem path — a bare 'notes/foo.md' could be
misread as a collection-relative qmd:// fragment, but './notes/foo.md'
cannot. Absolute realpaths (when the file is outside $PWD) are
unchanged. Extracted as renderFullPath() and reused across the three
call sites so the policy stays consistent.

New --format <kind> flag selects output format for search/query and
multi-get (cli|json|csv|md|xml|files). The legacy boolean aliases
(--json/--csv/--md/--xml/--files) still work for back-compat but are
removed from --help; the skill is updated to use --format.

ANSI colors and OSC 8 hyperlinks are already gated on process.stdout
.isTTY, so piped/agentic invocations get clean plain-text output with
no escape sequences. Verified via od -c on a piped 'qmd search' run.
2026-05-28 11:35:21 -07:00
Tobi Lutke
436420e927
feat(search,query): --full-path swaps qmd:// for on-disk paths
`qmd://` URIs remain the default identifier in search and query output
(across all formats: cli, --json, --md, --csv, --xml, --files). The
default CLI view now consistently prints the full qmd:// URI as the
visible label so it can be piped straight into `qmd get`, and --md
output gains a **file:** line for the same reason.

--full-path (already on get/multi-get) now also applies to search and
query: the per-result label becomes the file's on-disk path — relative
to $PWD when the file is in a subfolder of the current directory,
absolute realpath otherwise — and the per-result #docid is dropped
because the path is the identifier. Falls back to qmd:// when the file
is no longer resolvable on disk.

Also locks in @@ -line,count @@ header arithmetic with a regression test
that mirrors the user-reported 77-line / '1 before, 72 after' scenario.
2026-05-28 11:18:03 -07:00
Tobi Lutke
fa8f904a9d
docs(qmd-skill): structured-query-first; cite docid + lines; no sed
- Make structured `qmd query` with intent:/lex:/vec:/hyde: the default
  search mode, and emphasize that the caller authors the expansion
  rather than leaning on the built-in query-expansion model.
- Tell the caller to cite the #docid and exact line numbers now
  printed by get/multi-get, and to slice files with the :from:count
  suffix or --from/-l instead of piping through sed/head/tail.
- Document --full-path for handing the on-disk path to editor tools.
- Bump skill version to 2.2.0 and record the behavior changes under
  ## [Unreleased] in CHANGELOG.md.
- Update the package smoke test that pinned the old 'structured
  queries' wording to match the new, more specific intro phrasing.
2026-05-28 10:56:13 -07:00
Tobi Lutke
41bc3a27d8
feat(get,multi-get): line-numbered + docid output, line ranges, --full-path
Redesign the get/multi-get retrieval surface so callers can cite what
they retrieved and request follow-up slices without piping through sed:

- Output is line-numbered by default; opt out with --no-line-numbers.
- Header always identifies the document by qmd:// path + #docid. The
  MCP get/multi_get tools default lineNumbers=true to match.
- qmd get and the MCP get tool accept a :from:count suffix on a path
  or docid (e.g. '#abc123:120:40' reads 40 lines from line 120).
  Explicit --from/-l flags still override the suffix.
- qmd multi-get now includes #docid in every output format (--md,
  --json, --csv, --xml, --files, default CLI), matching qmd search.
- New --full-path flag swaps the qmd:// + docid header for the
  document's on-disk path (handy for piping into Read/Edit/editors);
  falls back to the canonical header when the file no longer exists.
2026-05-28 10:55:55 -07:00
Haitao Pan
e3711767c6 fix: disable local qmd models by default 2026-05-23 11:04:48 +08:00
Tobi Lütke
443760f4d5
release: v2.5.2 2026-05-22 20:24:08 +00:00
Tobi Lütke
f72f6dcc6c
Update CHANGELOG.md and remove autoresearch.jsonl 2026-05-22 20:24:01 +00:00
Tobi Lütke
65e517f783
Enhance launcher shebang polyglot to fall back to Bun if Node is missing on the system
Result: {"status":"keep","test_status":0}
2026-05-22 20:21:12 +00:00
Tobi Lütke
7a5d8f5574
Make bin/qmd launcher a shebang polyglot to support both Windows cmd/ps1 native wrappers and sh-invoked smoke tests
Result: {"status":"keep","test_status":0}
2026-05-22 20:08:49 +00:00
Tobi Lütke
65b813d737
Rewrite launcher in Node.js to fix Windows execution and keep tests passing
Result: {"status":"keep","test_status":0}
2026-05-22 20:03:44 +00:00
Tobi Lütke
ba6538090f
release: v2.5.1 2026-05-20 00:24:59 +00:00
Tobi Lütke
96ab7787f8
Use npm trusted publishing 2026-05-20 00:19:46 +00:00
Tobi Lütke
a8a314b802
Stabilize doctor CLI tests 2026-05-19 23:34:06 +00:00
Tobi Lütke
1926412f29
release: v2.5.0 2026-05-19 23:08:39 +00:00
Tobi Lütke
e3a9c5d02b
Make release script portable 2026-05-19 23:08:30 +00:00
Tobi Lütke
a3f0b9423f
Expand install smoke harness 2026-05-19 23:05:49 +00:00
Tobi Lütke
b5f156c313
Improve qmd diagnostics and embed resilience 2026-05-19 21:39:48 +00:00
Tobi Lutke
105c577b3b
docs: improve qmd skill guidance 2026-05-19 15:22:14 -04:00
Tobi Lutke
2b250f3dca
fix: run qmd from unbuilt checkouts 2026-05-19 15:22:13 -04:00
Tobi Lutke
632c34d120
chore: strengthen package test task 2026-05-19 14:27:38 -04:00
Tobi Lutke
d9348f43a0
feat: add local init and doctor diagnostics 2026-05-19 14:27:33 -04:00
Tobi Lutke
5cda3cf54c
Improve qmd doctor diagnostics 2026-05-19 12:48:16 -04:00
Tobi Lütke
596198c2ba
fix: update nix module hashes 2026-05-18 02:59:20 +00:00
Tobi Lütke
6ea0544e76
chore: update core runtime dependencies 2026-05-18 02:54:03 +00:00
Tobi Lütke
ac6b154f0c
feat: add qmd doctor vector diagnostics 2026-05-18 01:52:05 +00:00
Tobias Lütke
ddbd6bd8be
Merge pull request #656 from tobi/fix/gpu-status-warning
Fix GPU status guidance and benchmark warnings
2026-05-16 19:55:39 -04:00
Tobi Lütke
ad8a371be2
Fix QMD CI test runtime assumptions 2026-05-16 23:52:53 +00:00
Tobi Lütke
028e8fc86f
Improve packaged QMD skill 2026-05-16 23:46:40 +00:00
Tobi Lütke
15a711d729
Run local tests on Node and Bun 2026-05-16 23:46:22 +00:00
Tobi Lütke
da184e58e9
Unify QMD model resolution 2026-05-16 23:46:22 +00:00
Tobi Lütke
1f757379e2
Fix GPU status guidance and benchmark warnings 2026-05-16 23:45:58 +00:00
Tobias Lütke
cdf3bc0712
Merge pull request #657 from tobi/feat/cli-served-skills
Serve QMD skill instructions from the CLI
2026-05-16 19:40:10 -04:00
Tobi Lütke
c18c74a134
Serve QMD skill instructions from CLI 2026-05-16 22:43:33 +00:00
Tobias Lütke
17aa34d753
Merge pull request #655 from tobi/feat/local-qmd-index-bench
feat: support project-local QMD indexes
2026-05-16 14:31:05 -04:00
Tobi Lütke
b2550d273a
Merge remote-tracking branch 'origin/main' into feat/local-qmd-index-bench
# Conflicts:
#	src/cli/qmd.ts
2026-05-16 18:27:49 +00:00
Tobi Lütke
2e0c74310c
feat: support project-local indexes in bench 2026-05-16 18:22:04 +00:00
Tobias Lütke
87520252a5
Merge pull request #654 from tobi/workoff/t_657414dc-dev-review
fix: keep partial embeddings pending
2026-05-16 13:52:49 -04:00