@wei840222/qmd 2026.9.6 → 2026.9.27
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 +32 -0
- package/README.md +84 -1
- package/dist/cli/build-info.json +2 -2
- package/dist/cli/qmd.js +141 -11
- package/dist/collections.d.ts +3 -0
- package/dist/collections.js +9 -4
- package/dist/{hybrid-llm.d.ts → hybrid.d.ts} +9 -3
- package/dist/hybrid.js +97 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +28 -4
- package/dist/llm.d.ts +19 -1
- package/dist/llm.js +28 -5
- package/dist/mcp/server.js +70 -6
- package/dist/metadata-filter.d.ts +74 -0
- package/dist/metadata-filter.js +279 -0
- package/dist/metadata-store.d.ts +54 -0
- package/dist/metadata-store.js +194 -0
- package/dist/metadata.d.ts +61 -0
- package/dist/metadata.js +221 -0
- package/dist/remote-jev.d.ts +38 -0
- package/dist/remote-jev.js +167 -0
- package/dist/remote-llm.d.ts +3 -1
- package/dist/remote-llm.js +21 -4
- package/dist/search/query-expansion.d.ts +1 -0
- package/dist/search/query-expansion.js +4 -1
- package/dist/search/zh-dict.txt +3 -0
- package/dist/store.d.ts +29 -16
- package/dist/store.js +349 -166
- package/package.json +3 -2
- package/scripts/sync-zh-dict.mjs +4 -1
- package/skills/qmd/SKILL.md +11 -0
- package/dist/hybrid-llm.js +0 -53
- package/skills/release/SKILL.md +0 -141
- package/skills/release/scripts/install-hooks.sh +0 -38
- package/skills/release/scripts/release-context.sh +0 -129
package/dist/store.d.ts
CHANGED
|
@@ -18,6 +18,8 @@ import type { LLM } from "./llm.js";
|
|
|
18
18
|
import { LlamaCpp, formatQueryForEmbedding, formatDocForEmbedding, type ILLMSession } from "./llm.js";
|
|
19
19
|
import type { NamedCollection, Collection, CollectionConfig } from "./collections.js";
|
|
20
20
|
import type { IndexDiagnostics } from "./diagnostics.js";
|
|
21
|
+
import { type DocumentMetadata } from "./metadata.js";
|
|
22
|
+
import { type MetadataFilter } from "./metadata-filter.js";
|
|
21
23
|
export declare const DEFAULT_EMBED_MODEL = "hf:ggml-org/embeddinggemma-300M-GGUF/embeddinggemma-300M-Q8_0.gguf";
|
|
22
24
|
export declare const DEFAULT_RERANK_MODEL = "hf:ggml-org/Qwen3-Reranker-0.6B-Q8_0-GGUF/qwen3-reranker-0.6b-q8_0.gguf";
|
|
23
25
|
export declare const DEFAULT_QUERY_MODEL = "hf:tobil/qmd-query-expansion-1.7B-gguf/qmd-query-expansion-1.7B-q4_k_m.gguf";
|
|
@@ -310,15 +312,16 @@ export type Store = {
|
|
|
310
312
|
isVirtualPath: typeof isVirtualPath;
|
|
311
313
|
resolveVirtualPath: (virtualPath: string) => string | null;
|
|
312
314
|
toVirtualPath: (absolutePath: string) => string | null;
|
|
313
|
-
searchCharFTS: (query: string, limit?: number, collectionFilter?: CollectionFilter) => SearchResult[];
|
|
314
|
-
searchFTS: (query: string, limit?: number, collectionFilter?: CollectionFilter) => SearchResult[];
|
|
315
|
-
searchVec: (query: string, model: string, limit?: number, collectionFilter?: CollectionFilter, session?: ILLMSession, precomputedEmbedding?: number[]) => Promise<SearchResult[]>;
|
|
315
|
+
searchCharFTS: (query: string, limit?: number, collectionFilter?: CollectionFilter, filter?: MetadataFilter) => SearchResult[];
|
|
316
|
+
searchFTS: (query: string, limit?: number, collectionFilter?: CollectionFilter, filter?: MetadataFilter) => SearchResult[];
|
|
317
|
+
searchVec: (query: string, model: string, limit?: number, collectionFilter?: CollectionFilter, session?: ILLMSession, precomputedEmbedding?: number[], filter?: MetadataFilter) => Promise<SearchResult[]>;
|
|
316
318
|
expandQuery: (query: string, model?: string, expansionContext?: string, options?: QueryExpansionOptions) => Promise<ExpandedQuery[]>;
|
|
317
319
|
/** Drop the cached expansion for a query so the next call regenerates. */
|
|
318
320
|
invalidateExpansionCache: (query: string, expansionContext?: string, options?: QueryExpansionOptions) => void;
|
|
319
321
|
rerank: (query: string, documents: {
|
|
320
322
|
file: string;
|
|
321
323
|
text: string;
|
|
324
|
+
title?: string;
|
|
322
325
|
}[], model?: string, rerankContext?: string) => Promise<{
|
|
323
326
|
file: string;
|
|
324
327
|
score: number;
|
|
@@ -347,7 +350,7 @@ export type Store = {
|
|
|
347
350
|
hash: string;
|
|
348
351
|
} | null;
|
|
349
352
|
insertContent: (hash: string, content: string, createdAt: string) => void;
|
|
350
|
-
insertDocument: (collectionName: string, path: string, title: string, hash: string, createdAt: string, modifiedAt: string) =>
|
|
353
|
+
insertDocument: (collectionName: string, path: string, title: string, hash: string, createdAt: string, modifiedAt: string) => number;
|
|
351
354
|
findActiveDocument: (collectionName: string, path: string) => {
|
|
352
355
|
id: number;
|
|
353
356
|
hash: string;
|
|
@@ -367,6 +370,7 @@ export type Store = {
|
|
|
367
370
|
body: string;
|
|
368
371
|
path: string;
|
|
369
372
|
}[];
|
|
373
|
+
insertEmbedding: (hash: string, seq: number, pos: number, embedding: Float32Array, model: string, embeddedAt: string, totalChunks?: number, fingerprint?: string, lease?: EmbeddingBuildLease) => void;
|
|
370
374
|
};
|
|
371
375
|
export type ReindexProgress = {
|
|
372
376
|
file: string;
|
|
@@ -385,6 +389,12 @@ export type ReindexResult = {
|
|
|
385
389
|
orphanedCleaned: number;
|
|
386
390
|
skipped: number;
|
|
387
391
|
skippedFiles: ReindexSkippedFile[];
|
|
392
|
+
/** Documents whose qmd.metadata frontmatter failed extraction this pass. */
|
|
393
|
+
metadataErrors: number;
|
|
394
|
+
metadataErrorFiles?: {
|
|
395
|
+
file: string;
|
|
396
|
+
error: string;
|
|
397
|
+
}[];
|
|
388
398
|
};
|
|
389
399
|
/**
|
|
390
400
|
* Re-index a single collection by scanning the filesystem and updating the database.
|
|
@@ -501,6 +511,7 @@ export declare function handelize(path: string): string;
|
|
|
501
511
|
* Search result extends DocumentResult with score and source info
|
|
502
512
|
*/
|
|
503
513
|
export type SearchResult = DocumentResult & {
|
|
514
|
+
metadata: DocumentMetadata;
|
|
504
515
|
score: number;
|
|
505
516
|
source: "fts" | "vec";
|
|
506
517
|
chunkPos?: number;
|
|
@@ -612,6 +623,8 @@ export type IndexStatus = {
|
|
|
612
623
|
totalDocuments: number;
|
|
613
624
|
needsEmbedding: number;
|
|
614
625
|
hasVectorIndex: boolean;
|
|
626
|
+
/** Active documents without current, error-free metadata extraction. */
|
|
627
|
+
pendingMetadata: number;
|
|
615
628
|
collections: CollectionInfo[];
|
|
616
629
|
/** Additive diagnostics populated by high-level composition roots. */
|
|
617
630
|
diagnostics?: IndexDiagnostics;
|
|
@@ -707,10 +720,11 @@ export declare function extractTitle(content: string, filename: string): string;
|
|
|
707
720
|
export declare function insertContent(db: Database, hash: string, content: string, createdAt: string): void;
|
|
708
721
|
/**
|
|
709
722
|
* Insert a new document into the documents table.
|
|
723
|
+
* Returns the document's id so callers can attach document-scoped state.
|
|
710
724
|
*/
|
|
711
|
-
export declare function insertDocument(db: Database, collectionName: string, path: string, title: string, hash: string, createdAt: string, modifiedAt: string):
|
|
725
|
+
export declare function insertDocument(db: Database, collectionName: string, path: string, title: string, hash: string, createdAt: string, modifiedAt: string): number;
|
|
712
726
|
/** Insert immutable content and its document row in the same lexical transaction. */
|
|
713
|
-
export declare function insertDocumentWithContent(db: Database, hash: string, content: string, contentCreatedAt: string, collectionName: string, path: string, title: string, documentCreatedAt: string, modifiedAt: string):
|
|
727
|
+
export declare function insertDocumentWithContent(db: Database, hash: string, content: string, contentCreatedAt: string, collectionName: string, path: string, title: string, documentCreatedAt: string, modifiedAt: string): number;
|
|
714
728
|
/**
|
|
715
729
|
* Find an active document by collection name and path.
|
|
716
730
|
*/
|
|
@@ -778,13 +792,6 @@ export declare function chunkDocumentAsync(content: string, maxChars?: number, o
|
|
|
778
792
|
text: string;
|
|
779
793
|
pos: number;
|
|
780
794
|
}[]>;
|
|
781
|
-
/**
|
|
782
|
-
* Chunk a document by actual token count using the LLM tokenizer.
|
|
783
|
-
* More accurate than character-based chunking but requires async.
|
|
784
|
-
*
|
|
785
|
-
* When filepath and chunkStrategy are provided, uses AST-aware break points
|
|
786
|
-
* for supported code files.
|
|
787
|
-
*/
|
|
788
795
|
export declare function chunkDocumentByTokens(content: string, maxTokens?: number, overlapTokens?: number, windowTokens?: number, filepath?: string, chunkStrategy?: ChunkStrategy, signal?: AbortSignal): Promise<{
|
|
789
796
|
text: string;
|
|
790
797
|
pos: number;
|
|
@@ -929,9 +936,9 @@ export declare const CJK_LEXICAL_CANDIDATE_DEPTH = 60;
|
|
|
929
936
|
export declare const CJK_LEXICAL_RRF_WEIGHTS: Readonly<Record<CjkLexicalChannel, number>>;
|
|
930
937
|
export type CollectionFilter = string | readonly string[];
|
|
931
938
|
export type CollectionScope = string | readonly string[] | undefined;
|
|
932
|
-
export declare function searchCharFTS(db: Database, query: string, limit?: number, collectionFilter?: CollectionFilter): SearchResult[];
|
|
933
|
-
export declare function searchFTS(db: Database, query: string, limit?: number, collectionFilter?:
|
|
934
|
-
export declare function searchVec(db: Database, query: string, model: string, limit?: number, collectionFilter?: CollectionFilter, session?: ILLMSession, precomputedEmbedding?: number[],
|
|
939
|
+
export declare function searchCharFTS(db: Database, query: string, limit?: number, collectionFilter?: CollectionFilter, filter?: MetadataFilter): SearchResult[];
|
|
940
|
+
export declare function searchFTS(db: Database, query: string, limit?: number, collectionFilter?: CollectionScope, filter?: MetadataFilter): SearchResult[];
|
|
941
|
+
export declare function searchVec(db: Database, query: string, model: string, limit?: number, collectionFilter?: CollectionFilter, session?: ILLMSession, precomputedEmbedding?: number[], providerOrLlm?: EmbeddingProvider | LLM, authorizeRemoteRequestOrFilter?: Store["authorizeRemoteRequest"] | MetadataFilter, llmOverride?: LLM, metadataFilter?: MetadataFilter): Promise<SearchResult[]>;
|
|
935
942
|
/**
|
|
936
943
|
* Get all unique content hashes that need embeddings (from active documents).
|
|
937
944
|
* Returns hash, document body, and a sample path for display purposes.
|
|
@@ -979,6 +986,7 @@ export declare function deleteExpansionCacheEntry(db: Database, query: string, m
|
|
|
979
986
|
export declare function rerank(query: string, documents: {
|
|
980
987
|
file: string;
|
|
981
988
|
text: string;
|
|
989
|
+
title?: string;
|
|
982
990
|
}[], model: string | undefined, db: Database, rerankContext?: string, llmOverride?: LLM): Promise<{
|
|
983
991
|
file: string;
|
|
984
992
|
score: number;
|
|
@@ -1104,6 +1112,7 @@ export type ExpansionErrorEvent = {
|
|
|
1104
1112
|
export interface HybridQueryOptions {
|
|
1105
1113
|
collection?: string | readonly string[];
|
|
1106
1114
|
collections?: readonly string[];
|
|
1115
|
+
filter?: MetadataFilter;
|
|
1107
1116
|
limit?: number;
|
|
1108
1117
|
minScore?: number;
|
|
1109
1118
|
candidateLimit?: number;
|
|
@@ -1128,6 +1137,7 @@ export interface HybridQueryResult {
|
|
|
1128
1137
|
score: number;
|
|
1129
1138
|
context: string | null;
|
|
1130
1139
|
docid: string;
|
|
1140
|
+
metadata: DocumentMetadata;
|
|
1131
1141
|
explain?: HybridQueryExplain;
|
|
1132
1142
|
}
|
|
1133
1143
|
export type RankedListMeta = {
|
|
@@ -1163,6 +1173,7 @@ export declare function getHybridRrfWeights(rankedListMeta: RankedListMeta[]): n
|
|
|
1163
1173
|
export declare function hybridQuery(store: Store, query: string, options?: HybridQueryOptions): Promise<HybridQueryResult[]>;
|
|
1164
1174
|
export interface VectorSearchOptions {
|
|
1165
1175
|
collection?: CollectionFilter;
|
|
1176
|
+
filter?: MetadataFilter;
|
|
1166
1177
|
limit?: number;
|
|
1167
1178
|
minScore?: number;
|
|
1168
1179
|
/** Additional context used only while generating query expansions. */
|
|
@@ -1179,6 +1190,7 @@ export interface VectorSearchResult {
|
|
|
1179
1190
|
score: number;
|
|
1180
1191
|
context: string | null;
|
|
1181
1192
|
docid: string;
|
|
1193
|
+
metadata: DocumentMetadata;
|
|
1182
1194
|
}
|
|
1183
1195
|
/**
|
|
1184
1196
|
* Vector-only semantic search with query expansion.
|
|
@@ -1196,6 +1208,7 @@ export declare function vectorSearchQuery(store: Store, query: string, options?:
|
|
|
1196
1208
|
*/
|
|
1197
1209
|
export interface StructuredSearchOptions {
|
|
1198
1210
|
collections?: string[];
|
|
1211
|
+
filter?: MetadataFilter;
|
|
1199
1212
|
limit?: number;
|
|
1200
1213
|
minScore?: number;
|
|
1201
1214
|
candidateLimit?: number;
|