index.d.ts 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. /**
  2. * QMD SDK - Library mode for programmatic access to QMD search and indexing.
  3. *
  4. * Usage:
  5. * import { createStore } from '@tobilu/qmd'
  6. *
  7. * const store = await createStore({
  8. * dbPath: './my-index.sqlite',
  9. * config: {
  10. * collections: {
  11. * docs: { path: '/path/to/docs', pattern: '**\/*.md' }
  12. * }
  13. * }
  14. * })
  15. *
  16. * const results = await store.search({ query: "how does auth work?" })
  17. * await store.close()
  18. */
  19. import { extractSnippet, addLineNumbers, DEFAULT_MULTI_GET_MAX_BYTES, type Store as InternalStore, type DocumentResult, type DocumentNotFound, type SearchResult, type HybridQueryResult, type HybridQueryOptions, type HybridQueryExplain, type ExpandedQuery, type StructuredSearchOptions, type MultiGetResult, type IndexStatus, type IndexHealthInfo, type SearchHooks, type ReindexProgress, type ReindexResult, type EmbedProgress, type EmbedResult, type ChunkStrategy } from "./store.js";
  20. import { type Collection, type CollectionConfig, type NamedCollection, type ContextMap } from "./collections.js";
  21. export type { DocumentResult, DocumentNotFound, SearchResult, HybridQueryResult, HybridQueryOptions, HybridQueryExplain, ExpandedQuery, StructuredSearchOptions, MultiGetResult, IndexStatus, IndexHealthInfo, SearchHooks, ReindexProgress, ReindexResult, EmbedProgress, EmbedResult, Collection, CollectionConfig, NamedCollection, ContextMap, };
  22. export type { InternalStore };
  23. export { extractSnippet, addLineNumbers, DEFAULT_MULTI_GET_MAX_BYTES };
  24. export type { ChunkStrategy } from "./store.js";
  25. export { getDefaultDbPath } from "./store.js";
  26. export { Maintenance } from "./maintenance.js";
  27. import type { EmbeddingProvider } from "./embedding/index.js";
  28. export { createEmbeddingProvider, resolveProviderKind, assertCommercialEndpoint, OpenAIEmbeddingsProvider, CircuitBreaker, CircuitOpenError, HttpError, ModelMismatchError, assertModelCompatible, type EmbeddingProvider, type ProviderKind, type ProviderEmbedding, type ProviderEmbedOptions, type ProviderHealth, type CreateEmbeddingProviderOptions, type OpenAIProviderConfig, type EmbedProviderConfigFile, DEFAULT_BATCH_SIZE as DEFAULT_PROVIDER_BATCH_SIZE, DEFAULT_TIMEOUT_MS as DEFAULT_PROVIDER_TIMEOUT_MS, RETRY_BACKOFFS_MS as PROVIDER_RETRY_BACKOFFS_MS, } from "./embedding/index.js";
  29. export { CommercialApiHoldError, COMMERCIAL_API_HOLD_CODE, commercialApiHold, } from "./model-policy.js";
  30. export { getDistinctEmbeddingModels } from "./store.js";
  31. /**
  32. * Progress info emitted during update() for each file processed.
  33. */
  34. export type UpdateProgress = {
  35. collection: string;
  36. file: string;
  37. current: number;
  38. total: number;
  39. };
  40. /**
  41. * Aggregated result from update() across all collections.
  42. */
  43. export type UpdateResult = {
  44. collections: number;
  45. indexed: number;
  46. updated: number;
  47. unchanged: number;
  48. removed: number;
  49. needsEmbedding: number;
  50. };
  51. /**
  52. * Options for the unified search() method.
  53. */
  54. export interface SearchOptions {
  55. /** Simple query string — will be auto-expanded via LLM */
  56. query?: string;
  57. /** Pre-expanded queries (from expandQuery) — skips auto-expansion */
  58. queries?: ExpandedQuery[];
  59. /** Domain intent hint — steers expansion and reranking */
  60. intent?: string;
  61. /** Rerank results using LLM (default: true) */
  62. rerank?: boolean;
  63. /** Filter to a specific collection */
  64. collection?: string;
  65. /** Filter to specific collections */
  66. collections?: string[];
  67. /** Max results (default: 10) */
  68. limit?: number;
  69. /** Minimum score threshold */
  70. minScore?: number;
  71. /** Include explain traces */
  72. explain?: boolean;
  73. /** Chunk strategy: "auto" (default, uses AST for code files) or "regex" (legacy) */
  74. chunkStrategy?: ChunkStrategy;
  75. /**
  76. * Optional embedding provider for query-side encoding (i-loazq6ze).
  77. * When supplied, vec/hyde sub-queries are encoded through the provider
  78. * through the configured commercial API. Without one, learned work returns
  79. * typed HOLD.
  80. */
  81. embedProvider?: EmbeddingProvider;
  82. }
  83. /**
  84. * Options for searchLex() — BM25 keyword search.
  85. */
  86. export interface LexSearchOptions {
  87. limit?: number;
  88. collection?: string;
  89. }
  90. /**
  91. * Options for searchVector() — vector similarity search.
  92. */
  93. export interface VectorSearchOptions {
  94. limit?: number;
  95. collection?: string;
  96. /**
  97. * Optional embedding provider for query encoding (i-loazq6ze). Forwarded
  98. * through to `searchVec`. Without one, learned work returns typed HOLD.
  99. */
  100. embedProvider?: EmbeddingProvider;
  101. }
  102. /**
  103. * Options for expandQuery() — manual query expansion.
  104. */
  105. export interface ExpandQueryOptions {
  106. intent?: string;
  107. }
  108. /**
  109. * Options for creating a QMD store.
  110. *
  111. * Provide `dbPath` and optionally `configPath` (YAML file) or `config` (inline).
  112. * If neither configPath nor config is provided, the store reads from existing
  113. * DB state (useful for reopening a previously-configured store).
  114. */
  115. export interface StoreOptions {
  116. /** Path to the SQLite database file */
  117. dbPath: string;
  118. /** Path to a YAML config file (mutually exclusive with `config`) */
  119. configPath?: string;
  120. /** Inline collection config (mutually exclusive with `configPath`) */
  121. config?: CollectionConfig;
  122. /**
  123. * Optional default commercial embedding provider. When set, every learned
  124. * embedding operation uses this provider unless a search call supplies its
  125. * own `embedProvider`. MCP / HTTP constructs the provider once at startup
  126. * and injects it here so every query routes through the approved API.
  127. */
  128. embedProvider?: EmbeddingProvider;
  129. }
  130. /**
  131. * The QMD SDK store — provides search, retrieval, collection management,
  132. * context management, and indexing operations.
  133. *
  134. * All methods are async. Learned work uses an injected commercial provider or
  135. * the fail-closed compatibility adapter.
  136. */
  137. export interface QMDStore {
  138. /** The underlying internal store (for advanced use) */
  139. readonly internal: InternalStore;
  140. /** Path to the SQLite database */
  141. readonly dbPath: string;
  142. /** Full search: query expansion + multi-signal retrieval + LLM reranking */
  143. search(options: SearchOptions): Promise<HybridQueryResult[]>;
  144. /** BM25 keyword search (fast, no LLM) */
  145. searchLex(query: string, options?: LexSearchOptions): Promise<SearchResult[]>;
  146. /** Vector similarity search (embedding model, no reranking) */
  147. searchVector(query: string, options?: VectorSearchOptions): Promise<SearchResult[]>;
  148. /** Expand a query into typed sub-searches (lex/vec/hyde) for manual control */
  149. expandQuery(query: string, options?: ExpandQueryOptions): Promise<ExpandedQuery[]>;
  150. /** Get a single document by path or docid */
  151. get(pathOrDocid: string, options?: {
  152. includeBody?: boolean;
  153. }): Promise<DocumentResult | DocumentNotFound>;
  154. /** Get the body content of a document, optionally sliced by line range */
  155. getDocumentBody(pathOrDocid: string, opts?: {
  156. fromLine?: number;
  157. maxLines?: number;
  158. }): Promise<string | null>;
  159. /** Get multiple documents by glob pattern or comma-separated list */
  160. multiGet(pattern: string, options?: {
  161. includeBody?: boolean;
  162. maxBytes?: number;
  163. }): Promise<{
  164. docs: MultiGetResult[];
  165. errors: string[];
  166. }>;
  167. /** Add or update a collection */
  168. addCollection(name: string, opts: {
  169. path: string;
  170. pattern?: string;
  171. ignore?: string[];
  172. }): Promise<void>;
  173. /** Remove a collection */
  174. removeCollection(name: string): Promise<boolean>;
  175. /** Rename a collection */
  176. renameCollection(oldName: string, newName: string): Promise<boolean>;
  177. /** List all collections with document stats */
  178. listCollections(): Promise<{
  179. name: string;
  180. pwd: string;
  181. glob_pattern: string;
  182. doc_count: number;
  183. active_count: number;
  184. last_modified: string | null;
  185. includeByDefault: boolean;
  186. }[]>;
  187. /** Get names of collections included by default in queries */
  188. getDefaultCollectionNames(): Promise<string[]>;
  189. /** Add context for a path within a collection */
  190. addContext(collectionName: string, pathPrefix: string, contextText: string): Promise<boolean>;
  191. /** Remove context from a collection path */
  192. removeContext(collectionName: string, pathPrefix: string): Promise<boolean>;
  193. /** Set global context (applies to all collections) */
  194. setGlobalContext(context: string | undefined): Promise<void>;
  195. /** Get global context */
  196. getGlobalContext(): Promise<string | undefined>;
  197. /** List all contexts across all collections */
  198. listContexts(): Promise<Array<{
  199. collection: string;
  200. path: string;
  201. context: string;
  202. }>>;
  203. /** Re-index collections by scanning the filesystem */
  204. update(options?: {
  205. collections?: string[];
  206. onProgress?: (info: UpdateProgress) => void;
  207. }): Promise<UpdateResult>;
  208. /** Generate vector embeddings for documents that need them */
  209. embed(options?: {
  210. force?: boolean;
  211. model?: string;
  212. maxDocsPerBatch?: number;
  213. maxBatchBytes?: number;
  214. chunkStrategy?: ChunkStrategy;
  215. onProgress?: (info: EmbedProgress) => void;
  216. }): Promise<EmbedResult>;
  217. /** Get index status (document counts, collections, embedding state) */
  218. getStatus(): Promise<IndexStatus>;
  219. /** Get index health info (stale embeddings, etc.) */
  220. getIndexHealth(): Promise<IndexHealthInfo>;
  221. /** Close the store and release provider and database resources. */
  222. close(): Promise<void>;
  223. }
  224. /**
  225. * Create a QMD store for programmatic access to search and indexing.
  226. *
  227. * @example
  228. * ```typescript
  229. * // With a YAML config file
  230. * const store = await createStore({
  231. * dbPath: './index.sqlite',
  232. * configPath: './qmd.yml',
  233. * })
  234. *
  235. * // With inline config (no files needed besides the DB)
  236. * const store = await createStore({
  237. * dbPath: './index.sqlite',
  238. * config: {
  239. * collections: {
  240. * docs: { path: '/path/to/docs', pattern: '**\/*.md' }
  241. * }
  242. * }
  243. * })
  244. *
  245. * const results = await store.search({ query: "authentication flow" })
  246. * await store.close()
  247. * ```
  248. */
  249. export declare function createStore(options: StoreOptions): Promise<QMDStore>;