@tobilu/qmd 2.0.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/README.md +1 -1
- package/bin/qmd +13 -2
- package/dist/cli/qmd.js +167 -12
- package/dist/embedded-skills.d.ts +6 -0
- package/dist/embedded-skills.js +14 -0
- package/dist/llm.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [2.0.1] - 2026-03-10
|
|
6
|
+
|
|
7
|
+
### Changes
|
|
8
|
+
|
|
9
|
+
- `qmd skill install` copies the packaged QMD skill into
|
|
10
|
+
`~/.claude/commands/` for one-command setup. #355 (thanks @nibzard)
|
|
11
|
+
|
|
12
|
+
### Fixes
|
|
13
|
+
|
|
14
|
+
- Fix Qwen3-Embedding GGUF filename case — HuggingFace filenames are
|
|
15
|
+
case-sensitive, the lowercase variant returned 404. #349 (thanks @byheaven)
|
|
16
|
+
- Resolve symlinked global launcher path so `qmd` works correctly when
|
|
17
|
+
installed via `npm i -g`. #352 (thanks @nibzard)
|
|
18
|
+
|
|
5
19
|
## [2.0.0] - 2026-03-10
|
|
6
20
|
|
|
7
21
|
QMD 2.0 declares a stable library API. The SDK is now the primary interface —
|
package/README.md
CHANGED
|
@@ -500,7 +500,7 @@ This is useful for multilingual corpora (e.g. Chinese, Japanese, Korean) where
|
|
|
500
500
|
|
|
501
501
|
```sh
|
|
502
502
|
# Use Qwen3-Embedding-0.6B for better multilingual (CJK) support
|
|
503
|
-
export QMD_EMBED_MODEL="hf:Qwen/Qwen3-Embedding-0.6B-GGUF/
|
|
503
|
+
export QMD_EMBED_MODEL="hf:Qwen/Qwen3-Embedding-0.6B-GGUF/Qwen3-Embedding-0.6B-Q8_0.gguf"
|
|
504
504
|
|
|
505
505
|
# After changing the model, re-embed all collections:
|
|
506
506
|
qmd embed -f
|
package/bin/qmd
CHANGED
|
@@ -1,8 +1,19 @@
|
|
|
1
1
|
#!/bin/sh
|
|
2
|
+
# Resolve symlinks so global installs (npm link / npm install -g) can find the
|
|
3
|
+
# actual package directory instead of the global bin directory.
|
|
4
|
+
SOURCE="$0"
|
|
5
|
+
while [ -L "$SOURCE" ]; do
|
|
6
|
+
SOURCE_DIR="$(cd -P "$(dirname "$SOURCE")" && pwd)"
|
|
7
|
+
TARGET="$(readlink "$SOURCE")"
|
|
8
|
+
case "$TARGET" in
|
|
9
|
+
/*) SOURCE="$TARGET" ;;
|
|
10
|
+
*) SOURCE="$SOURCE_DIR/$TARGET" ;;
|
|
11
|
+
esac
|
|
12
|
+
done
|
|
13
|
+
|
|
2
14
|
# Detect the runtime used to install this package and use the matching one
|
|
3
15
|
# to avoid native module ABI mismatches (e.g., better-sqlite3 compiled for bun vs node)
|
|
4
|
-
|
|
5
|
-
DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
|
16
|
+
DIR="$(cd -P "$(dirname "$SOURCE")/.." && pwd)"
|
|
6
17
|
|
|
7
18
|
# Check if we were installed with bun (look for bun.lock or bun-lockb)
|
|
8
19
|
if [ -f "$DIR/bun.lock" ] || [ -f "$DIR/bun.lockb" ] || [ -n "$BUN_INSTALL" ]; then
|
package/dist/cli/qmd.js
CHANGED
|
@@ -3,13 +3,15 @@ import { openDatabase } from "../db.js";
|
|
|
3
3
|
import fastGlob from "fast-glob";
|
|
4
4
|
import { execSync, spawn as nodeSpawn } from "child_process";
|
|
5
5
|
import { fileURLToPath } from "url";
|
|
6
|
-
import { dirname, join as pathJoin } from "path";
|
|
6
|
+
import { dirname, join as pathJoin, relative as relativePath } from "path";
|
|
7
7
|
import { parseArgs } from "util";
|
|
8
|
-
import { readFileSync, realpathSync, statSync, existsSync, unlinkSync, writeFileSync, openSync, closeSync, mkdirSync } from "fs";
|
|
8
|
+
import { readFileSync, realpathSync, statSync, existsSync, unlinkSync, writeFileSync, openSync, closeSync, mkdirSync, lstatSync, rmSync, symlinkSync, readlinkSync } from "fs";
|
|
9
|
+
import { createInterface } from "readline/promises";
|
|
9
10
|
import { getPwd, getRealPath, homedir, resolve, enableProductionMode, searchFTS, extractSnippet, getContextForFile, getContextForPath, listCollections, removeCollection, renameCollection, findSimilarFiles, findDocumentByDocid, isDocid, matchFilesByGlob, getHashesNeedingEmbedding, getHashesForEmbedding, clearAllEmbeddings, insertEmbedding, getStatus, hashContent, extractTitle, formatDocForEmbedding, chunkDocumentByTokens, clearCache, getCacheKey, getCachedResult, setCachedResult, getIndexHealth, parseVirtualPath, buildVirtualPath, isVirtualPath, resolveVirtualPath, toVirtualPath, insertContent, insertDocument, findActiveDocument, updateDocumentTitle, updateDocument, deactivateDocument, getActiveDocumentPaths, cleanupOrphanedContent, deleteLLMCache, deleteInactiveDocuments, cleanupOrphanedVectors, vacuumDatabase, getCollectionsWithoutContext, getTopLevelPathsWithoutContext, handelize, hybridQuery, vectorSearchQuery, structuredSearch, addLineNumbers, DEFAULT_EMBED_MODEL, DEFAULT_RERANK_MODEL, DEFAULT_GLOB, DEFAULT_MULTI_GET_MAX_BYTES, createStore, getDefaultDbPath, reindexCollection, generateEmbeddings, syncConfigToDb, } from "../store.js";
|
|
10
11
|
import { disposeDefaultLlamaCpp, getDefaultLlamaCpp, withLLMSession, pullModels, DEFAULT_EMBED_MODEL_URI, DEFAULT_GENERATE_MODEL_URI, DEFAULT_RERANK_MODEL_URI, DEFAULT_MODEL_CACHE_DIR } from "../llm.js";
|
|
11
12
|
import { formatSearchResults, formatDocuments, escapeXml, escapeCSV, } from "./formatter.js";
|
|
12
13
|
import { getCollection as getCollectionFromYaml, listCollections as yamlListCollections, getDefaultCollectionNames, addContext as yamlAddContext, removeContext as yamlRemoveContext, removeCollection as yamlRemoveCollectionFn, renameCollection as yamlRenameCollectionFn, setGlobalContext, listAllContexts, setConfigIndexName, loadConfig, } from "../collections.js";
|
|
14
|
+
import { getEmbeddedQmdSkillContent, getEmbeddedQmdSkillFiles } from "../embedded-skills.js";
|
|
13
15
|
// Enable production mode - allows using default database path
|
|
14
16
|
// Tests must set INDEX_PATH or use createStore() with explicit path
|
|
15
17
|
enableProductionMode();
|
|
@@ -1969,6 +1971,8 @@ function parseCLI() {
|
|
|
1969
1971
|
help: { type: "boolean", short: "h" },
|
|
1970
1972
|
version: { type: "boolean", short: "v" },
|
|
1971
1973
|
skill: { type: "boolean" },
|
|
1974
|
+
global: { type: "boolean" },
|
|
1975
|
+
yes: { type: "boolean" },
|
|
1972
1976
|
// Search options
|
|
1973
1977
|
n: { type: "string" },
|
|
1974
1978
|
"min-score": { type: "string" },
|
|
@@ -2047,19 +2051,116 @@ function parseCLI() {
|
|
|
2047
2051
|
values,
|
|
2048
2052
|
};
|
|
2049
2053
|
}
|
|
2054
|
+
function getSkillInstallDir(globalInstall) {
|
|
2055
|
+
return globalInstall
|
|
2056
|
+
? resolve(homedir(), ".agents", "skills", "qmd")
|
|
2057
|
+
: resolve(getPwd(), ".agents", "skills", "qmd");
|
|
2058
|
+
}
|
|
2059
|
+
function getClaudeSkillLinkPath(globalInstall) {
|
|
2060
|
+
return globalInstall
|
|
2061
|
+
? resolve(homedir(), ".claude", "skills", "qmd")
|
|
2062
|
+
: resolve(getPwd(), ".claude", "skills", "qmd");
|
|
2063
|
+
}
|
|
2064
|
+
function pathExists(path) {
|
|
2065
|
+
try {
|
|
2066
|
+
lstatSync(path);
|
|
2067
|
+
return true;
|
|
2068
|
+
}
|
|
2069
|
+
catch {
|
|
2070
|
+
return false;
|
|
2071
|
+
}
|
|
2072
|
+
}
|
|
2073
|
+
function removePath(path) {
|
|
2074
|
+
const stat = lstatSync(path);
|
|
2075
|
+
if (stat.isDirectory() && !stat.isSymbolicLink()) {
|
|
2076
|
+
rmSync(path, { recursive: true, force: true });
|
|
2077
|
+
}
|
|
2078
|
+
else {
|
|
2079
|
+
unlinkSync(path);
|
|
2080
|
+
}
|
|
2081
|
+
}
|
|
2050
2082
|
function showSkill() {
|
|
2051
|
-
|
|
2052
|
-
const relativePath = pathJoin("skills", "qmd", "SKILL.md");
|
|
2053
|
-
const skillPath = pathJoin(scriptDir, "..", "..", relativePath);
|
|
2054
|
-
console.log(`QMD Skill (${relativePath})`);
|
|
2055
|
-
console.log(`Location: ${skillPath}`);
|
|
2083
|
+
console.log("QMD Skill (embedded)");
|
|
2056
2084
|
console.log("");
|
|
2057
|
-
|
|
2058
|
-
|
|
2085
|
+
const content = getEmbeddedQmdSkillContent();
|
|
2086
|
+
process.stdout.write(content.endsWith("\n") ? content : content + "\n");
|
|
2087
|
+
}
|
|
2088
|
+
function writeEmbeddedSkill(targetDir, force) {
|
|
2089
|
+
if (pathExists(targetDir)) {
|
|
2090
|
+
if (!force) {
|
|
2091
|
+
throw new Error(`Skill already exists: ${targetDir} (use --force to replace it)`);
|
|
2092
|
+
}
|
|
2093
|
+
removePath(targetDir);
|
|
2094
|
+
}
|
|
2095
|
+
mkdirSync(targetDir, { recursive: true });
|
|
2096
|
+
for (const file of getEmbeddedQmdSkillFiles()) {
|
|
2097
|
+
const destination = resolve(targetDir, file.relativePath);
|
|
2098
|
+
mkdirSync(dirname(destination), { recursive: true });
|
|
2099
|
+
writeFileSync(destination, file.content, "utf-8");
|
|
2100
|
+
}
|
|
2101
|
+
}
|
|
2102
|
+
function ensureClaudeSymlink(linkPath, targetDir, force) {
|
|
2103
|
+
const parentDir = dirname(linkPath);
|
|
2104
|
+
if (pathExists(parentDir)) {
|
|
2105
|
+
const resolvedTargetDir = realpathSync(dirname(targetDir));
|
|
2106
|
+
const resolvedLinkParent = realpathSync(parentDir);
|
|
2107
|
+
// If .claude/skills already resolves to the same directory as .agents/skills,
|
|
2108
|
+
// the skill is already visible to Claude and creating qmd -> qmd would loop.
|
|
2109
|
+
if (resolvedTargetDir === resolvedLinkParent) {
|
|
2110
|
+
return false;
|
|
2111
|
+
}
|
|
2112
|
+
}
|
|
2113
|
+
const linkTarget = relativePath(parentDir, targetDir) || ".";
|
|
2114
|
+
mkdirSync(parentDir, { recursive: true });
|
|
2115
|
+
if (pathExists(linkPath)) {
|
|
2116
|
+
const stat = lstatSync(linkPath);
|
|
2117
|
+
if (stat.isSymbolicLink() && readlinkSync(linkPath) === linkTarget) {
|
|
2118
|
+
return true;
|
|
2119
|
+
}
|
|
2120
|
+
if (!force) {
|
|
2121
|
+
throw new Error(`Claude skill path already exists: ${linkPath} (use --force to replace it)`);
|
|
2122
|
+
}
|
|
2123
|
+
removePath(linkPath);
|
|
2124
|
+
}
|
|
2125
|
+
symlinkSync(linkTarget, linkPath, "dir");
|
|
2126
|
+
return true;
|
|
2127
|
+
}
|
|
2128
|
+
async function shouldCreateClaudeSymlink(linkPath, autoYes) {
|
|
2129
|
+
if (autoYes) {
|
|
2130
|
+
return true;
|
|
2131
|
+
}
|
|
2132
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
2133
|
+
console.log(`Tip: create a Claude symlink manually at ${linkPath}`);
|
|
2134
|
+
return false;
|
|
2135
|
+
}
|
|
2136
|
+
const rl = createInterface({
|
|
2137
|
+
input: process.stdin,
|
|
2138
|
+
output: process.stdout,
|
|
2139
|
+
});
|
|
2140
|
+
try {
|
|
2141
|
+
const answer = await rl.question(`Create a symlink in ${linkPath}? [y/N] `);
|
|
2142
|
+
const normalized = answer.trim().toLowerCase();
|
|
2143
|
+
return normalized === "y" || normalized === "yes";
|
|
2144
|
+
}
|
|
2145
|
+
finally {
|
|
2146
|
+
rl.close();
|
|
2147
|
+
}
|
|
2148
|
+
}
|
|
2149
|
+
async function installSkill(globalInstall, force, autoYes) {
|
|
2150
|
+
const installDir = getSkillInstallDir(globalInstall);
|
|
2151
|
+
writeEmbeddedSkill(installDir, force);
|
|
2152
|
+
console.log(`✓ Installed QMD skill to ${installDir}`);
|
|
2153
|
+
const claudeLinkPath = getClaudeSkillLinkPath(globalInstall);
|
|
2154
|
+
if (!(await shouldCreateClaudeSymlink(claudeLinkPath, autoYes))) {
|
|
2059
2155
|
return;
|
|
2060
2156
|
}
|
|
2061
|
-
const
|
|
2062
|
-
|
|
2157
|
+
const linked = ensureClaudeSymlink(claudeLinkPath, installDir, force);
|
|
2158
|
+
if (linked) {
|
|
2159
|
+
console.log(`✓ Linked Claude skill at ${claudeLinkPath}`);
|
|
2160
|
+
}
|
|
2161
|
+
else {
|
|
2162
|
+
console.log(`✓ Claude already sees the skill via ${dirname(claudeLinkPath)}`);
|
|
2163
|
+
}
|
|
2063
2164
|
}
|
|
2064
2165
|
function showHelp() {
|
|
2065
2166
|
console.log("qmd — Quick Markdown Search");
|
|
@@ -2074,6 +2175,7 @@ function showHelp() {
|
|
|
2074
2175
|
console.log(" qmd vsearch <query> - Vector similarity only");
|
|
2075
2176
|
console.log(" qmd get <file>[:line] [-l N] - Show a single document, optional line slice");
|
|
2076
2177
|
console.log(" qmd multi-get <pattern> - Batch fetch via glob or comma-separated list");
|
|
2178
|
+
console.log(" qmd skill show/install - Show or install the packaged QMD skill");
|
|
2077
2179
|
console.log(" qmd mcp - Start the MCP server (stdio transport for AI agents)");
|
|
2078
2180
|
console.log("");
|
|
2079
2181
|
console.log("Collections & context:");
|
|
@@ -2123,7 +2225,9 @@ function showHelp() {
|
|
|
2123
2225
|
console.log("");
|
|
2124
2226
|
console.log("AI agents & integrations:");
|
|
2125
2227
|
console.log(" - Run `qmd mcp` to expose the MCP server (stdio) to agents/IDEs.");
|
|
2126
|
-
console.log(" - `qmd
|
|
2228
|
+
console.log(" - `qmd skill install` installs the QMD skill into ./.agents/skills/qmd.");
|
|
2229
|
+
console.log(" - Use `qmd skill install --global` for ~/.agents/skills/qmd.");
|
|
2230
|
+
console.log(" - `qmd --skill` is kept as an alias for `qmd skill show`.");
|
|
2127
2231
|
console.log(" - Advanced: `qmd mcp --http ...` and `qmd mcp --http --daemon` are optional for custom transports.");
|
|
2128
2232
|
console.log("");
|
|
2129
2233
|
console.log("Global options:");
|
|
@@ -2178,6 +2282,19 @@ if (isMain) {
|
|
|
2178
2282
|
showSkill();
|
|
2179
2283
|
process.exit(0);
|
|
2180
2284
|
}
|
|
2285
|
+
if (cli.values.help && cli.command === "skill") {
|
|
2286
|
+
console.log("Usage: qmd skill <show|install> [options]");
|
|
2287
|
+
console.log("");
|
|
2288
|
+
console.log("Commands:");
|
|
2289
|
+
console.log(" show Print the packaged QMD skill");
|
|
2290
|
+
console.log(" install Install into ./.agents/skills/qmd");
|
|
2291
|
+
console.log("");
|
|
2292
|
+
console.log("Options:");
|
|
2293
|
+
console.log(" --global Install into ~/.agents/skills/qmd");
|
|
2294
|
+
console.log(" --yes Also create the .claude/skills/qmd symlink");
|
|
2295
|
+
console.log(" -f, --force Replace existing install or symlink");
|
|
2296
|
+
process.exit(0);
|
|
2297
|
+
}
|
|
2181
2298
|
if (!cli.command || cli.values.help) {
|
|
2182
2299
|
showHelp();
|
|
2183
2300
|
process.exit(cli.values.help ? 0 : 1);
|
|
@@ -2546,6 +2663,44 @@ if (isMain) {
|
|
|
2546
2663
|
}
|
|
2547
2664
|
break;
|
|
2548
2665
|
}
|
|
2666
|
+
case "skill": {
|
|
2667
|
+
const subcommand = cli.args[0];
|
|
2668
|
+
switch (subcommand) {
|
|
2669
|
+
case "show": {
|
|
2670
|
+
showSkill();
|
|
2671
|
+
break;
|
|
2672
|
+
}
|
|
2673
|
+
case "install": {
|
|
2674
|
+
try {
|
|
2675
|
+
await installSkill(Boolean(cli.values.global), Boolean(cli.values.force), Boolean(cli.values.yes));
|
|
2676
|
+
}
|
|
2677
|
+
catch (error) {
|
|
2678
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
2679
|
+
process.exit(1);
|
|
2680
|
+
}
|
|
2681
|
+
break;
|
|
2682
|
+
}
|
|
2683
|
+
case "help":
|
|
2684
|
+
case undefined: {
|
|
2685
|
+
console.log("Usage: qmd skill <show|install> [options]");
|
|
2686
|
+
console.log("");
|
|
2687
|
+
console.log("Commands:");
|
|
2688
|
+
console.log(" show Print the packaged QMD skill");
|
|
2689
|
+
console.log(" install Install into ./.agents/skills/qmd");
|
|
2690
|
+
console.log("");
|
|
2691
|
+
console.log("Options:");
|
|
2692
|
+
console.log(" --global Install into ~/.agents/skills/qmd");
|
|
2693
|
+
console.log(" --yes Also create the .claude/skills/qmd symlink");
|
|
2694
|
+
console.log(" -f, --force Replace existing install or symlink");
|
|
2695
|
+
process.exit(0);
|
|
2696
|
+
}
|
|
2697
|
+
default:
|
|
2698
|
+
console.error(`Unknown subcommand: ${subcommand}`);
|
|
2699
|
+
console.error("Run 'qmd skill help' for usage");
|
|
2700
|
+
process.exit(1);
|
|
2701
|
+
}
|
|
2702
|
+
break;
|
|
2703
|
+
}
|
|
2549
2704
|
case "cleanup": {
|
|
2550
2705
|
const db = getDb();
|
|
2551
2706
|
// 1. Clear llm_cache
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// Generated from skills/qmd source files. Keep this in sync when updating the packaged skill.
|
|
2
|
+
const EMBEDDED_QMD_SKILL_BASE64 = {
|
|
3
|
+
"SKILL.md": "LS0tCm5hbWU6IHFtZApkZXNjcmlwdGlvbjogU2VhcmNoIG1hcmtkb3duIGtub3dsZWRnZSBiYXNlcywgbm90ZXMsIGFuZCBkb2N1bWVudGF0aW9uIHVzaW5nIFFNRC4gVXNlIHdoZW4gdXNlcnMgYXNrIHRvIHNlYXJjaCBub3RlcywgZmluZCBkb2N1bWVudHMsIG9yIGxvb2sgdXAgaW5mb3JtYXRpb24uCmxpY2Vuc2U6IE1JVApjb21wYXRpYmlsaXR5OiBSZXF1aXJlcyBxbWQgQ0xJIG9yIE1DUCBzZXJ2ZXIuIEluc3RhbGwgdmlhIGBucG0gaW5zdGFsbCAtZyBAdG9iaWx1L3FtZGAuCm1ldGFkYXRhOgogIGF1dGhvcjogdG9iaQogIHZlcnNpb246ICIyLjAuMCIKYWxsb3dlZC10b29sczogQmFzaChxbWQ6KiksIG1jcF9fcW1kX18qCi0tLQoKIyBRTUQgLSBRdWljayBNYXJrZG93biBTZWFyY2gKCkxvY2FsIHNlYXJjaCBlbmdpbmUgZm9yIG1hcmtkb3duIGNvbnRlbnQuCgojIyBTdGF0dXMKCiFgcW1kIHN0YXR1cyAyPi9kZXYvbnVsbCB8fCBlY2hvICJOb3QgaW5zdGFsbGVkOiBucG0gaW5zdGFsbCAtZyBAdG9iaWx1L3FtZCJgCgojIyBNQ1A6IGBxdWVyeWAKCmBgYGpzb24KewogICJzZWFyY2hlcyI6IFsKICAgIHsgInR5cGUiOiAibGV4IiwgInF1ZXJ5IjogIkNBUCB0aGVvcmVtIGNvbnNpc3RlbmN5IiB9LAogICAgeyAidHlwZSI6ICJ2ZWMiLCAicXVlcnkiOiAidHJhZGVvZmYgYmV0d2VlbiBjb25zaXN0ZW5jeSBhbmQgYXZhaWxhYmlsaXR5IiB9CiAgXSwKICAiY29sbGVjdGlvbnMiOiBbImRvY3MiXSwKICAibGltaXQiOiAxMAp9CmBgYAoKIyMjIFF1ZXJ5IFR5cGVzCgp8IFR5cGUgfCBNZXRob2QgfCBJbnB1dCB8CnwtLS0tLS18LS0tLS0tLS18LS0tLS0tLXwKfCBgbGV4YCB8IEJNMjUgfCBLZXl3b3JkcyDigJQgZXhhY3QgdGVybXMsIG5hbWVzLCBjb2RlIHwKfCBgdmVjYCB8IFZlY3RvciB8IFF1ZXN0aW9uIOKAlCBuYXR1cmFsIGxhbmd1YWdlIHwKfCBgaHlkZWAgfCBWZWN0b3IgfCBBbnN3ZXIg4oCUIGh5cG90aGV0aWNhbCByZXN1bHQgKDUwLTEwMCB3b3JkcykgfAoKIyMjIFdyaXRpbmcgR29vZCBRdWVyaWVzCgoqKmxleCAoa2V5d29yZCkqKgotIDItNSB0ZXJtcywgbm8gZmlsbGVyIHdvcmRzCi0gRXhhY3QgcGhyYXNlOiBgImNvbm5lY3Rpb24gcG9vbCJgIChxdW90ZWQpCi0gRXhjbHVkZSB0ZXJtczogYHBlcmZvcm1hbmNlIC1zcG9ydHNgIChtaW51cyBwcmVmaXgpCi0gQ29kZSBpZGVudGlmaWVycyB3b3JrOiBgaGFuZGxlRXJyb3IgYXN5bmNgCgoqKnZlYyAoc2VtYW50aWMpKioKLSBGdWxsIG5hdHVyYWwgbGFuZ3VhZ2UgcXVlc3Rpb24KLSBCZSBzcGVjaWZpYzogYCJob3cgZG9lcyB0aGUgcmF0ZSBsaW1pdGVyIGhhbmRsZSBidXJzdCB0cmFmZmljImAKLSBJbmNsdWRlIGNvbnRleHQ6IGAiaW4gdGhlIHBheW1lbnQgc2VydmljZSwgaG93IGFyZSByZWZ1bmRzIHByb2Nlc3NlZCJgCgoqKmh5ZGUgKGh5cG90aGV0aWNhbCBkb2N1bWVudCkqKgotIFdyaXRlIDUwLTEwMCB3b3JkcyBvZiB3aGF0IHRoZSAqYW5zd2VyKiBsb29rcyBsaWtlCi0gVXNlIHRoZSB2b2NhYnVsYXJ5IHlvdSBleHBlY3QgaW4gdGhlIHJlc3VsdAoKKipleHBhbmQgKGF1dG8tZXhwYW5kKSoqCi0gVXNlIGEgc2luZ2xlLWxpbmUgcXVlcnkgKGltcGxpY2l0KSBvciBgZXhwYW5kOiBxdWVzdGlvbmAgb24gaXRzIG93biBsaW5lCi0gTGV0cyB0aGUgbG9jYWwgTExNIGdlbmVyYXRlIGxleC92ZWMvaHlkZSB2YXJpYXRpb25zCi0gRG8gbm90IG1peCBgZXhwYW5kOmAgd2l0aCBvdGhlciB0eXBlZCBsaW5lcyDigJQgaXQncyBlaXRoZXIgYSBzdGFuZGFsb25lIGV4cGFuZCBxdWVyeSBvciBhIGZ1bGwgcXVlcnkgZG9jdW1lbnQKCiMjIyBJbnRlbnQgKERpc2FtYmlndWF0aW9uKQoKV2hlbiBhIHF1ZXJ5IHRlcm0gaXMgYW1iaWd1b3VzLCBhZGQgYGludGVudGAgdG8gc3RlZXIgcmVzdWx0czoKCmBgYGpzb24KewogICJzZWFyY2hlcyI6IFsKICAgIHsgInR5cGUiOiAibGV4IiwgInF1ZXJ5IjogInBlcmZvcm1hbmNlIiB9CiAgXSwKICAiaW50ZW50IjogIndlYiBwYWdlIGxvYWQgdGltZXMgYW5kIENvcmUgV2ViIFZpdGFscyIKfQpgYGAKCkludGVudCBhZmZlY3RzIGV4cGFuc2lvbiwgcmVyYW5raW5nLCBjaHVuayBzZWxlY3Rpb24sIGFuZCBzbmlwcGV0IGV4dHJhY3Rpb24uIEl0IGRvZXMgbm90IHNlYXJjaCBvbiBpdHMgb3duIOKAlCBpdCdzIGEgc3RlZXJpbmcgc2lnbmFsIHRoYXQgZGlzYW1iaWd1YXRlcyBxdWVyaWVzIGxpa2UgInBlcmZvcm1hbmNlIiAod2ViLXBlcmYgdnMgdGVhbSBoZWFsdGggdnMgZml0bmVzcykuCgojIyMgQ29tYmluaW5nIFR5cGVzCgp8IEdvYWwgfCBBcHByb2FjaCB8CnwtLS0tLS18LS0tLS0tLS0tLXwKfCBLbm93IGV4YWN0IHRlcm1zIHwgYGxleGAgb25seSB8CnwgRG9uJ3Qga25vdyB2b2NhYnVsYXJ5IHwgVXNlIGEgc2luZ2xlLWxpbmUgcXVlcnkgKGltcGxpY2l0IGBleHBhbmQ6YCkgb3IgYHZlY2AgfAp8IEJlc3QgcmVjYWxsIHwgYGxleGAgKyBgdmVjYCB8CnwgQ29tcGxleCB0b3BpYyB8IGBsZXhgICsgYHZlY2AgKyBgaHlkZWAgfAp8IEFtYmlndW91cyBxdWVyeSB8IEFkZCBgaW50ZW50YCB0byBhbnkgY29tYmluYXRpb24gYWJvdmUgfAoKRmlyc3QgcXVlcnkgZ2V0cyAyeCB3ZWlnaHQgaW4gZnVzaW9uIOKAlCBwdXQgeW91ciBiZXN0IGd1ZXNzIGZpcnN0LgoKIyMjIExleCBRdWVyeSBTeW50YXgKCnwgU3ludGF4IHwgTWVhbmluZyB8IEV4YW1wbGUgfAp8LS0tLS0tLS18LS0tLS0tLS0tfC0tLS0tLS0tLXwKfCBgdGVybWAgfCBQcmVmaXggbWF0Y2ggfCBgcGVyZmAgbWF0Y2hlcyAicGVyZm9ybWFuY2UiIHwKfCBgInBocmFzZSJgIHwgRXhhY3QgcGhyYXNlIHwgYCJyYXRlIGxpbWl0ZXIiYCB8CnwgYC10ZXJtYCB8IEV4Y2x1ZGUgfCBgcGVyZm9ybWFuY2UgLXNwb3J0c2AgfAoKTm90ZTogYC10ZXJtYCBvbmx5IHdvcmtzIGluIGxleCBxdWVyaWVzLCBub3QgdmVjL2h5ZGUuCgojIyMgQ29sbGVjdGlvbiBGaWx0ZXJpbmcKCmBgYGpzb24KeyAiY29sbGVjdGlvbnMiOiBbImRvY3MiXSB9ICAgICAgICAgICAgICAvLyBTaW5nbGUKeyAiY29sbGVjdGlvbnMiOiBbImRvY3MiLCAibm90ZXMiXSB9ICAgICAvLyBNdWx0aXBsZSAoT1IpCmBgYAoKT21pdCB0byBzZWFyY2ggYWxsIGNvbGxlY3Rpb25zLgoKIyMgT3RoZXIgTUNQIFRvb2xzCgp8IFRvb2wgfCBVc2UgfAp8LS0tLS0tfC0tLS0tfAp8IGBnZXRgIHwgUmV0cmlldmUgZG9jIGJ5IHBhdGggb3IgYCNkb2NpZGAgfAp8IGBtdWx0aV9nZXRgIHwgUmV0cmlldmUgbXVsdGlwbGUgYnkgZ2xvYi9saXN0IHwKfCBgc3RhdHVzYCB8IENvbGxlY3Rpb25zIGFuZCBoZWFsdGggfAoKIyMgQ0xJCgpgYGBiYXNoCnFtZCBxdWVyeSAicXVlc3Rpb24iICAgICAgICAgICAgICAjIEF1dG8tZXhwYW5kICsgcmVyYW5rCnFtZCBxdWVyeSAkJ2xleDogWFxudmVjOiBZJyAgICAgICAjIFN0cnVjdHVyZWQKcW1kIHF1ZXJ5ICQnZXhwYW5kOiBxdWVzdGlvbicgICAgICMgRXhwbGljaXQgZXhwYW5kCnFtZCBxdWVyeSAtLWpzb24gLS1leHBsYWluICJxIiAgICAjIFNob3cgc2NvcmUgdHJhY2VzIChSUkYgKyByZXJhbmsgYmxlbmQpCnFtZCBzZWFyY2ggImtleXdvcmRzIiAgICAgICAgICAgICAjIEJNMjUgb25seSAobm8gTExNKQpxbWQgZ2V0ICIjYWJjMTIzIiAgICAgICAgICAgICAgICAgIyBCeSBkb2NpZApxbWQgbXVsdGktZ2V0ICJqb3VybmFscy8yMDI2LSoubWQiIC1sIDQwICAjIEJhdGNoIHB1bGwgc25pcHBldHMgYnkgZ2xvYgpxbWQgbXVsdGktZ2V0IG5vdGVzL2Zvby5tZCxub3Rlcy9iYXIubWQgICAjIENvbW1hLXNlcGFyYXRlZCBsaXN0LCBwcmVzZXJ2ZXMgb3JkZXIKYGBgCgojIyBIVFRQIEFQSQoKYGBgYmFzaApjdXJsIC1YIFBPU1QgaHR0cDovL2xvY2FsaG9zdDo4MTgxL3F1ZXJ5IFwKICAtSCAiQ29udGVudC1UeXBlOiBhcHBsaWNhdGlvbi9qc29uIiBcCiAgLWQgJ3sic2VhcmNoZXMiOiBbeyJ0eXBlIjogImxleCIsICJxdWVyeSI6ICJ0ZXN0In1dfScKYGBgCgojIyBTZXR1cAoKYGBgYmFzaApucG0gaW5zdGFsbCAtZyBAdG9iaWx1L3FtZApxbWQgY29sbGVjdGlvbiBhZGQgfi9ub3RlcyAtLW5hbWUgbm90ZXMKcW1kIGVtYmVkCmBgYAo=",
|
|
4
|
+
"references/mcp-setup.md": "IyBRTUQgTUNQIFNlcnZlciBTZXR1cAoKIyMgSW5zdGFsbAoKYGBgYmFzaApucG0gaW5zdGFsbCAtZyBAdG9iaWx1L3FtZApxbWQgY29sbGVjdGlvbiBhZGQgfi9wYXRoL3RvL21hcmtkb3duIC0tbmFtZSBteWtub3dsZWRnZQpxbWQgZW1iZWQKYGBgCgojIyBDb25maWd1cmUgTUNQIENsaWVudAoKKipDbGF1ZGUgQ29kZSoqIChgfi8uY2xhdWRlL3NldHRpbmdzLmpzb25gKToKYGBganNvbgp7CiAgIm1jcFNlcnZlcnMiOiB7CiAgICAicW1kIjogeyAiY29tbWFuZCI6ICJxbWQiLCAiYXJncyI6IFsibWNwIl0gfQogIH0KfQpgYGAKCioqQ2xhdWRlIERlc2t0b3AqKiAoYH4vTGlicmFyeS9BcHBsaWNhdGlvbiBTdXBwb3J0L0NsYXVkZS9jbGF1ZGVfZGVza3RvcF9jb25maWcuanNvbmApOgpgYGBqc29uCnsKICAibWNwU2VydmVycyI6IHsKICAgICJxbWQiOiB7ICJjb21tYW5kIjogInFtZCIsICJhcmdzIjogWyJtY3AiXSB9CiAgfQp9CmBgYAoKKipPcGVuQ2xhdyoqIChgfi8ub3BlbmNsYXcvb3BlbmNsYXcuanNvbmApOgpgYGBqc29uCnsKICAibWNwIjogewogICAgInNlcnZlcnMiOiB7CiAgICAgICJxbWQiOiB7ICJjb21tYW5kIjogInFtZCIsICJhcmdzIjogWyJtY3AiXSB9CiAgICB9CiAgfQp9CmBgYAoKIyMgSFRUUCBNb2RlCgpgYGBiYXNoCnFtZCBtY3AgLS1odHRwICAgICAgICAgICAgICAjIFBvcnQgODE4MQpxbWQgbWNwIC0taHR0cCAtLWRhZW1vbiAgICAgIyBCYWNrZ3JvdW5kCnFtZCBtY3Agc3RvcCAgICAgICAgICAgICAgICAjIFN0b3AgZGFlbW9uCmBgYAoKIyMgVG9vbHMKCiMjIyBzdHJ1Y3R1cmVkX3NlYXJjaAoKU2VhcmNoIHdpdGggcHJlLWV4cGFuZGVkIHF1ZXJpZXMuCgpgYGBqc29uCnsKICAic2VhcmNoZXMiOiBbCiAgICB7ICJ0eXBlIjogImxleCIsICJxdWVyeSI6ICJrZXl3b3JkIHBocmFzZXMiIH0sCiAgICB7ICJ0eXBlIjogInZlYyIsICJxdWVyeSI6ICJuYXR1cmFsIGxhbmd1YWdlIHF1ZXN0aW9uIiB9LAogICAgeyAidHlwZSI6ICJoeWRlIiwgInF1ZXJ5IjogImh5cG90aGV0aWNhbCBhbnN3ZXIgcGFzc2FnZS4uLiIgfQogIF0sCiAgImxpbWl0IjogMTAsCiAgImNvbGxlY3Rpb24iOiAib3B0aW9uYWwiLAogICJtaW5TY29yZSI6IDAuMAp9CmBgYAoKfCBUeXBlIHwgTWV0aG9kIHwgSW5wdXQgfAp8LS0tLS0tfC0tLS0tLS0tfC0tLS0tLS18CnwgYGxleGAgfCBCTTI1IHwgS2V5d29yZHMgKDItNSB0ZXJtcykgfAp8IGB2ZWNgIHwgVmVjdG9yIHwgUXVlc3Rpb24gfAp8IGBoeWRlYCB8IFZlY3RvciB8IEFuc3dlciBwYXNzYWdlICg1MC0xMDAgd29yZHMpIHwKCiMjIyBnZXQKClJldHJpZXZlIGRvY3VtZW50IGJ5IHBhdGggb3IgYCNkb2NpZGAuCgp8IFBhcmFtIHwgVHlwZSB8IERlc2NyaXB0aW9uIHwKfC0tLS0tLS18LS0tLS0tfC0tLS0tLS0tLS0tLS18CnwgYHBhdGhgIHwgc3RyaW5nIHwgRmlsZSBwYXRoIG9yIGAjZG9jaWRgIHwKfCBgZnVsbGAgfCBib29sPyB8IFJldHVybiBmdWxsIGNvbnRlbnQgfAp8IGBsaW5lTnVtYmVyc2AgfCBib29sPyB8IEFkZCBsaW5lIG51bWJlcnMgfAoKIyMjIG11bHRpX2dldAoKUmV0cmlldmUgbXVsdGlwbGUgZG9jdW1lbnRzLgoKfCBQYXJhbSB8IFR5cGUgfCBEZXNjcmlwdGlvbiB8CnwtLS0tLS0tfC0tLS0tLXwtLS0tLS0tLS0tLS0tfAp8IGBwYXR0ZXJuYCB8IHN0cmluZyB8IEdsb2Igb3IgY29tbWEtc2VwYXJhdGVkIGxpc3QgfAp8IGBtYXhCeXRlc2AgfCBudW1iZXI/IHwgU2tpcCBsYXJnZSBmaWxlcyAoZGVmYXVsdCAxMEtCKSB8CgojIyMgc3RhdHVzCgpJbmRleCBoZWFsdGggYW5kIGNvbGxlY3Rpb25zLiBObyBwYXJhbXMuCgojIyBUcm91Ymxlc2hvb3RpbmcKCi0gKipOb3Qgc3RhcnRpbmcqKjogYHdoaWNoIHFtZGAsIGBxbWQgbWNwYCBtYW51YWxseQotICoqTm8gcmVzdWx0cyoqOiBgcW1kIGNvbGxlY3Rpb24gbGlzdGAsIGBxbWQgZW1iZWRgCi0gKipTbG93IGZpcnN0IHNlYXJjaCoqOiBOb3JtYWwsIG1vZGVscyBsb2FkaW5nICh+M0dCKQo="
|
|
5
|
+
};
|
|
6
|
+
export function getEmbeddedQmdSkillFiles() {
|
|
7
|
+
return Object.entries(EMBEDDED_QMD_SKILL_BASE64).map(([relativePath, encoded]) => ({
|
|
8
|
+
relativePath,
|
|
9
|
+
content: Buffer.from(encoded, 'base64').toString('utf8'),
|
|
10
|
+
}));
|
|
11
|
+
}
|
|
12
|
+
export function getEmbeddedQmdSkillContent() {
|
|
13
|
+
return Buffer.from(EMBEDDED_QMD_SKILL_BASE64["SKILL.md"], "base64").toString("utf8");
|
|
14
|
+
}
|
package/dist/llm.js
CHANGED
|
@@ -47,7 +47,7 @@ export function formatDocForEmbedding(text, title, modelUri) {
|
|
|
47
47
|
// =============================================================================
|
|
48
48
|
// HuggingFace model URIs for node-llama-cpp
|
|
49
49
|
// Format: hf:<user>/<repo>/<file>
|
|
50
|
-
// Override via QMD_EMBED_MODEL env var (e.g. hf:Qwen/Qwen3-Embedding-0.6B-GGUF/
|
|
50
|
+
// Override via QMD_EMBED_MODEL env var (e.g. hf:Qwen/Qwen3-Embedding-0.6B-GGUF/Qwen3-Embedding-0.6B-Q8_0.gguf)
|
|
51
51
|
const DEFAULT_EMBED_MODEL = process.env.QMD_EMBED_MODEL ?? "hf:ggml-org/embeddinggemma-300M-GGUF/embeddinggemma-300M-Q8_0.gguf";
|
|
52
52
|
const DEFAULT_RERANK_MODEL = "hf:ggml-org/Qwen3-Reranker-0.6B-Q8_0-GGUF/qwen3-reranker-0.6b-q8_0.gguf";
|
|
53
53
|
// const DEFAULT_GENERATE_MODEL = "hf:ggml-org/Qwen3-0.6B-GGUF/Qwen3-0.6B-Q8_0.gguf";
|
package/package.json
CHANGED