Skip to content

Commit 1d81bac

Browse files
committed
Merge remote-tracking branch 'upstream/main'
2 parents 0682dcc + cfd640e commit 1d81bac

14 files changed

Lines changed: 2759 additions & 2496 deletions

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55
### Fixes
66

77
- GPU: respect explicit `QMD_LLAMA_GPU=metal|vulkan|cuda` backend overrides instead of always using auto GPU selection. #529
8+
- Fix: preserve original filename case in `handelize()`. The previous
9+
`.toLowerCase()` call made indexed paths unreachable on case-sensitive
10+
filesystems (Linux). `qmd update` automatically migrates legacy
11+
lowercase paths without re-embedding.
812

913
## [2.1.0] - 2026-04-05
1014

finetune/pyproject.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,10 @@ dependencies = [
2121

2222
[dependency-groups]
2323
dev = []
24+
25+
[tool.uv]
26+
constraint-dependencies = [
27+
"authlib>=1.6.9",
28+
"aiohttp>=3.13.4",
29+
"cryptography>=46.0.7",
30+
]

finetune/uv.lock

Lines changed: 2292 additions & 2383 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pnpm-lock.yaml

Lines changed: 17 additions & 40 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/cli/qmd.ts

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ import {
4545
insertContent,
4646
insertDocument,
4747
findActiveDocument,
48+
findOrMigrateLegacyDocument,
4849
updateDocumentTitle,
4950
updateDocument,
5051
deactivateDocument,
@@ -110,6 +111,7 @@ enableProductionMode();
110111

111112
let store: ReturnType<typeof createStore> | null = null;
112113
let storeDbPathOverride: string | undefined;
114+
let currentIndexName = "index";
113115

114116
function getStore(): ReturnType<typeof createStore> {
115117
if (!store) {
@@ -160,6 +162,10 @@ function getDbPath(): string {
160162
return store?.dbPath ?? storeDbPathOverride ?? getDefaultDbPath();
161163
}
162164

165+
function getActiveIndexName(): string {
166+
return currentIndexName;
167+
}
168+
163169
function setIndexName(name: string | null): void {
164170
let normalizedName = name;
165171
// Normalize relative paths to prevent malformed database paths
@@ -170,6 +176,7 @@ function setIndexName(name: string | null): void {
170176
// Replace path separators with underscores to create a valid filename
171177
normalizedName = absolutePath.replace(/\//g, '_').replace(/^_/, '');
172178
}
179+
currentIndexName = normalizedName || "index";
173180
storeDbPathOverride = normalizedName ? getDefaultDbPath(normalizedName) : undefined;
174181
// Reset open handle so next use opens the new index
175182
closeDb();
@@ -821,8 +828,6 @@ function contextRemove(pathArg: string): void {
821828
}
822829

823830
function getDocument(filename: string, fromLine?: number, maxLines?: number, lineNumbers?: boolean): void {
824-
const db = getDb();
825-
826831
// Parse :linenum suffix from filename (e.g., "file.md:100")
827832
let inputPath = filename;
828833
const colonMatch = inputPath.match(/:(\d+)$/);
@@ -834,6 +839,14 @@ function getDocument(filename: string, fromLine?: number, maxLines?: number, lin
834839
}
835840
}
836841

842+
const parsedIndexPath = isVirtualPath(inputPath) ? parseVirtualPath(inputPath) : null;
843+
if (parsedIndexPath?.indexName) {
844+
setIndexName(parsedIndexPath.indexName);
845+
setConfigIndexName(parsedIndexPath.indexName);
846+
}
847+
848+
const db = getDb();
849+
837850
// Handle docid lookup (#abc123, abc123, "#abc123", "abc123", etc.)
838851
if (isDocid(inputPath)) {
839852
const docidMatch = findDocumentByDocid(db, inputPath);
@@ -845,7 +858,6 @@ function getDocument(filename: string, fromLine?: number, maxLines?: number, lin
845858
process.exit(1);
846859
}
847860
}
848-
849861
let doc: { collectionName: string; path: string; body: string } | null = null;
850862
let virtualPath: string;
851863

@@ -1570,8 +1582,8 @@ async function indexFiles(pwd?: string, globPattern: string = DEFAULT_GLOB, coll
15701582
const hash = await hashContent(content);
15711583
const title = extractTitle(content, relativeFile);
15721584

1573-
// Check if document exists in this collection with this path
1574-
const existing = findActiveDocument(db, collectionName, path);
1585+
// Check if document exists (also migrates legacy lowercase paths)
1586+
const existing = findOrMigrateLegacyDocument(db, collectionName, path);
15751587

15761588
if (existing) {
15771589
if (existing.hash === hash) {
@@ -1928,7 +1940,18 @@ function outputResults(results: OutputRow[], query: string, opts: OutputOptions)
19281940
}
19291941

19301942
// Helper to create qmd:// URI from displayPath
1931-
const toQmdPath = (displayPath: string) => `qmd://${displayPath}`;
1943+
const toQmdPath = (displayPath: string) => {
1944+
const [collectionName, ...segments] = displayPath.split("/");
1945+
if (!collectionName || segments.length === 0) {
1946+
return `qmd://${displayPath}`;
1947+
}
1948+
const indexName = getActiveIndexName();
1949+
return buildVirtualPath(
1950+
collectionName,
1951+
segments.join("/"),
1952+
indexName === "index" ? undefined : indexName,
1953+
);
1954+
};
19321955

19331956
if (opts.format === "json") {
19341957
// JSON output for LLM consumption

0 commit comments

Comments
 (0)