@karmaniverous/jeeves-watcher 0.17.9 → 0.17.11
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.
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createConfigQueryHandler as createConfigQueryHandler$1, createStatusHandler, createConfigApplyHandler, DEFAULT_PORTS, getBindAddress } from '@karmaniverous/jeeves';
|
|
3
|
-
import {
|
|
3
|
+
import { a as normalizeSlashes, n as normalizeError, G as GitignoreFilter, e as executeReindex, V as VALID_REINDEX_SCOPES, m as mergeInferenceRules, i as isPathWatched, g as getWatchRootBases, C as CONFIG_WATCH_VALID_SCOPES, r as retry, s as sleep, l as loadConfig } from './index.js';
|
|
4
4
|
export { b as startFromConfig } from './index.js';
|
|
5
5
|
import { mkdirSync, existsSync, readFileSync, writeFileSync, rmSync, renameSync, readdirSync, statSync } from 'node:fs';
|
|
6
6
|
import { join, dirname, resolve, extname, basename, isAbsolute } from 'node:path';
|
|
@@ -2562,10 +2562,15 @@ function createConfigReindexHandler(deps) {
|
|
|
2562
2562
|
plan: result.plan,
|
|
2563
2563
|
});
|
|
2564
2564
|
}
|
|
2565
|
-
//
|
|
2566
|
-
|
|
2565
|
+
// Live prune: fire and forget without pre-computing plan (avoids double-scrolling the collection).
|
|
2566
|
+
if (validScope === 'prune') {
|
|
2567
|
+
void executeReindex(reindexDeps, 'prune', pathParam, false);
|
|
2568
|
+
return await reply
|
|
2569
|
+
.status(200)
|
|
2570
|
+
.send({ status: 'started', scope: 'prune' });
|
|
2571
|
+
}
|
|
2572
|
+
// Non-prune scopes: compute plan first then execute async.
|
|
2567
2573
|
const planResult = await executeReindex(reindexDeps, validScope, pathParam, true);
|
|
2568
|
-
// Now fire actual reindex async
|
|
2569
2574
|
void executeReindex(reindexDeps, validScope, pathParam, false);
|
|
2570
2575
|
return await reply
|
|
2571
2576
|
.status(200)
|
|
@@ -3362,7 +3367,7 @@ function createSearchHandler(deps) {
|
|
|
3362
3367
|
const vectors = await deps.embeddingProvider.embed([query]);
|
|
3363
3368
|
const hybridConfig = deps.getHybridConfig?.();
|
|
3364
3369
|
if (hybridConfig?.enabled) {
|
|
3365
|
-
return deps.vectorStore.hybridSearch(vectors[0], query, limit, hybridConfig.textWeight, filter);
|
|
3370
|
+
return deps.vectorStore.hybridSearch(vectors[0], query, limit, hybridConfig.textWeight, filter, offset);
|
|
3366
3371
|
}
|
|
3367
3372
|
return deps.vectorStore.search(vectors[0], limit, filter, offset);
|
|
3368
3373
|
}, deps.logger, 'Search');
|
|
@@ -4332,6 +4337,8 @@ function computeLineOffsets(fullText, chunks) {
|
|
|
4332
4337
|
*/
|
|
4333
4338
|
/** Default number of points to upsert per batch (prevents OOM on large files). */
|
|
4334
4339
|
const DEFAULT_UPSERT_BATCH_SIZE = 50;
|
|
4340
|
+
/** Maximum chunks per Gemini batchEmbedContents request. */
|
|
4341
|
+
const EMBED_BATCH_SIZE = 100;
|
|
4335
4342
|
/**
|
|
4336
4343
|
* Embed text chunks, upsert to vector store, and clean up orphaned chunks.
|
|
4337
4344
|
*
|
|
@@ -4350,8 +4357,14 @@ async function embedAndUpsert(deps, text, filePath, metadata, existingPayload, f
|
|
|
4350
4357
|
const chunks = await splitter.splitText(text);
|
|
4351
4358
|
// Compute line offsets
|
|
4352
4359
|
const offsets = computeLineOffsets(text, chunks);
|
|
4353
|
-
// Embed
|
|
4354
|
-
const
|
|
4360
|
+
// Embed chunks in batches to respect Gemini's 100-doc limit
|
|
4361
|
+
const allVectors = [];
|
|
4362
|
+
for (let start = 0; start < chunks.length; start += EMBED_BATCH_SIZE) {
|
|
4363
|
+
const batch = chunks.slice(start, start + EMBED_BATCH_SIZE);
|
|
4364
|
+
const batchVectors = await embeddingProvider.embed(batch);
|
|
4365
|
+
allVectors.push(...batchVectors);
|
|
4366
|
+
}
|
|
4367
|
+
const vectors = allVectors;
|
|
4355
4368
|
// Build all points
|
|
4356
4369
|
const points = chunks.map((chunk, i) => ({
|
|
4357
4370
|
id: pointId(filePath, i),
|
|
@@ -5031,9 +5044,10 @@ async function ensureTextIndex(client, collectionName, fieldName, log) {
|
|
|
5031
5044
|
* @param limit - Maximum results to return.
|
|
5032
5045
|
* @param textWeight - Weight for text results in RRF (0–1).
|
|
5033
5046
|
* @param filter - Optional Qdrant filter.
|
|
5047
|
+
* @param offset - Optional result offset for pagination.
|
|
5034
5048
|
* @returns An array of search results.
|
|
5035
5049
|
*/
|
|
5036
|
-
async function hybridSearch(client, collectionName, vector, queryText, limit, textWeight, filter) {
|
|
5050
|
+
async function hybridSearch(client, collectionName, vector, queryText, limit, textWeight, filter, offset) {
|
|
5037
5051
|
const prefetchLimit = Math.max(limit * 3, 20);
|
|
5038
5052
|
const vectorWeight = 1 - textWeight;
|
|
5039
5053
|
const textFilter = {
|
|
@@ -5062,6 +5076,7 @@ async function hybridSearch(client, collectionName, vector, queryText, limit, te
|
|
|
5062
5076
|
},
|
|
5063
5077
|
limit,
|
|
5064
5078
|
with_payload: true,
|
|
5079
|
+
...(offset !== undefined ? { offset } : {}),
|
|
5065
5080
|
});
|
|
5066
5081
|
return result.points.map((p) => ({
|
|
5067
5082
|
id: String(p.id),
|
|
@@ -5359,10 +5374,11 @@ class VectorStoreClient {
|
|
|
5359
5374
|
* @param limit - Maximum results to return.
|
|
5360
5375
|
* @param textWeight - Weight for text results in RRF (0–1).
|
|
5361
5376
|
* @param filter - Optional Qdrant filter.
|
|
5377
|
+
* @param offset - Optional result offset for pagination.
|
|
5362
5378
|
* @returns An array of search results.
|
|
5363
5379
|
*/
|
|
5364
|
-
async hybridSearch(vector, queryText, limit, textWeight, filter) {
|
|
5365
|
-
return hybridSearch(this.client, this.collectionName, vector, queryText, limit, textWeight, filter);
|
|
5380
|
+
async hybridSearch(vector, queryText, limit, textWeight, filter, offset) {
|
|
5381
|
+
return hybridSearch(this.client, this.collectionName, vector, queryText, limit, textWeight, filter, offset);
|
|
5366
5382
|
}
|
|
5367
5383
|
/**
|
|
5368
5384
|
* Retrieve points with their vectors by ID.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { DEFAULT_PORTS, postJson, fetchJson, getPackageVersion, createServiceCli } from '@karmaniverous/jeeves';
|
|
2
|
+
import { substituteEnvVars, DEFAULT_PORTS, postJson, fetchJson, getPackageVersion, createServiceCli } from '@karmaniverous/jeeves';
|
|
3
3
|
import { dirname, resolve, join, relative } from 'node:path';
|
|
4
4
|
import { fileURLToPath } from 'node:url';
|
|
5
5
|
import { jeevesWatcherConfigSchema, LOGGING_DEFAULTS, API_DEFAULTS, EMBEDDING_DEFAULTS, CONFIG_WATCH_DEFAULTS, WATCH_DEFAULTS, ROOT_DEFAULTS, INIT_CONFIG_TEMPLATE, DEFAULT_PORT as DEFAULT_PORT$1, PLUGIN_PACKAGE, SERVICE_PACKAGE, COMPONENT_NAME } from '@karmaniverous/jeeves-watcher-core';
|
|
@@ -42,49 +42,6 @@ function mergeInferenceRules(existing, incoming) {
|
|
|
42
42
|
return merged;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
/**
|
|
46
|
-
* @module config/substituteEnvVars
|
|
47
|
-
*
|
|
48
|
-
* Deep-walks config objects and replaces `${VAR_NAME}` patterns with environment variable values.
|
|
49
|
-
*/
|
|
50
|
-
const ENV_PATTERN = /\$\{([^}]+)\}/g;
|
|
51
|
-
/**
|
|
52
|
-
* Replace `${VAR_NAME}` patterns in a string with `process.env.VAR_NAME`.
|
|
53
|
-
*
|
|
54
|
-
* @param value - The string to process.
|
|
55
|
-
* @returns The string with resolved env vars; unresolvable expressions left untouched.
|
|
56
|
-
*/
|
|
57
|
-
function substituteString(value) {
|
|
58
|
-
return value.replace(ENV_PATTERN, (match, varName) => {
|
|
59
|
-
const envValue = process.env[varName];
|
|
60
|
-
if (envValue === undefined)
|
|
61
|
-
return match;
|
|
62
|
-
return envValue;
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
/**
|
|
66
|
-
* Deep-walk a value and substitute `${VAR_NAME}` patterns in all string values.
|
|
67
|
-
*
|
|
68
|
-
* @param value - The value to walk (object, array, or primitive).
|
|
69
|
-
* @returns A new value with all env var references resolved.
|
|
70
|
-
*/
|
|
71
|
-
function substituteEnvVars(value) {
|
|
72
|
-
if (typeof value === 'string') {
|
|
73
|
-
return substituteString(value);
|
|
74
|
-
}
|
|
75
|
-
if (Array.isArray(value)) {
|
|
76
|
-
return value.map((item) => substituteEnvVars(item));
|
|
77
|
-
}
|
|
78
|
-
if (value !== null && typeof value === 'object') {
|
|
79
|
-
const result = {};
|
|
80
|
-
for (const [key, val] of Object.entries(value)) {
|
|
81
|
-
result[key] = substituteEnvVars(val);
|
|
82
|
-
}
|
|
83
|
-
return result;
|
|
84
|
-
}
|
|
85
|
-
return value;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
45
|
const MODULE_NAME = 'jeeves-watcher';
|
|
89
46
|
/**
|
|
90
47
|
* Merge sensible defaults into a loaded configuration.
|
|
@@ -267,7 +224,7 @@ async function startFromConfig(configPath, descriptor) {
|
|
|
267
224
|
const config = await loadConfig(resolvedPath);
|
|
268
225
|
// Dynamic import breaks the circular dependency between this module
|
|
269
226
|
// and app/index.ts (which defines JeevesWatcher and re-exports startFromConfig).
|
|
270
|
-
const { JeevesWatcher } = await import('./index-
|
|
227
|
+
const { JeevesWatcher } = await import('./index-DXiOIyDK.js');
|
|
271
228
|
const app = new JeevesWatcher(config, resolvedPath, descriptor);
|
|
272
229
|
installShutdownHandlers(() => app.stop());
|
|
273
230
|
await app.start();
|
|
@@ -545,11 +502,12 @@ function normalizeSlashes(path) {
|
|
|
545
502
|
*/
|
|
546
503
|
function isPathWatched(filePath, watchPaths, ignoredPaths) {
|
|
547
504
|
const normalised = normalizeSlashes(filePath);
|
|
548
|
-
const
|
|
505
|
+
const opts = { dot: true, nocase: process.platform === 'win32' };
|
|
506
|
+
const isIncluded = picomatch(watchPaths, opts);
|
|
549
507
|
if (!isIncluded(normalised))
|
|
550
508
|
return false;
|
|
551
509
|
if (ignoredPaths && ignoredPaths.length > 0) {
|
|
552
|
-
const isExcluded = picomatch(ignoredPaths,
|
|
510
|
+
const isExcluded = picomatch(ignoredPaths, opts);
|
|
553
511
|
if (isExcluded(normalised))
|
|
554
512
|
return false;
|
|
555
513
|
}
|
|
@@ -1498,4 +1456,4 @@ const watcherDescriptor = {
|
|
|
1498
1456
|
const program = createServiceCli(watcherDescriptor);
|
|
1499
1457
|
program.parse();
|
|
1500
1458
|
|
|
1501
|
-
export { CONFIG_WATCH_VALID_SCOPES as C, GitignoreFilter as G, VALID_REINDEX_SCOPES as V,
|
|
1459
|
+
export { CONFIG_WATCH_VALID_SCOPES as C, GitignoreFilter as G, VALID_REINDEX_SCOPES as V, normalizeSlashes as a, startFromConfig as b, executeReindex as e, getWatchRootBases as g, isPathWatched as i, loadConfig as l, mergeInferenceRules as m, normalizeError as n, retry as r, sleep as s };
|
package/dist/index.d.ts
CHANGED
|
@@ -783,9 +783,10 @@ interface VectorStore {
|
|
|
783
783
|
* @param limit - Maximum results to return.
|
|
784
784
|
* @param textWeight - Weight for text results in RRF (0–1).
|
|
785
785
|
* @param filter - Optional Qdrant filter.
|
|
786
|
+
* @param offset - Optional result offset for pagination.
|
|
786
787
|
* @returns An array of search results.
|
|
787
788
|
*/
|
|
788
|
-
hybridSearch(vector: number[], queryText: string, limit: number, textWeight: number, filter?: Record<string, unknown
|
|
789
|
+
hybridSearch(vector: number[], queryText: string, limit: number, textWeight: number, filter?: Record<string, unknown>, offset?: number): Promise<SearchResult[]>;
|
|
789
790
|
/**
|
|
790
791
|
* Retrieve points with their vectors by ID.
|
|
791
792
|
*
|
|
@@ -908,9 +909,10 @@ declare class VectorStoreClient implements VectorStore {
|
|
|
908
909
|
* @param limit - Maximum results to return.
|
|
909
910
|
* @param textWeight - Weight for text results in RRF (0–1).
|
|
910
911
|
* @param filter - Optional Qdrant filter.
|
|
912
|
+
* @param offset - Optional result offset for pagination.
|
|
911
913
|
* @returns An array of search results.
|
|
912
914
|
*/
|
|
913
|
-
hybridSearch(vector: number[], queryText: string, limit: number, textWeight: number, filter?: Record<string, unknown
|
|
915
|
+
hybridSearch(vector: number[], queryText: string, limit: number, textWeight: number, filter?: Record<string, unknown>, offset?: number): Promise<SearchResult[]>;
|
|
914
916
|
/**
|
|
915
917
|
* Retrieve points with their vectors by ID.
|
|
916
918
|
*
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { join, dirname, resolve, relative, extname, basename, isAbsolute } from 'node:path';
|
|
2
|
-
import { createConfigQueryHandler as createConfigQueryHandler$1, createStatusHandler, createConfigApplyHandler, DEFAULT_PORTS, getBindAddress, postJson, fetchJson, getPackageVersion } from '@karmaniverous/jeeves';
|
|
2
|
+
import { createConfigQueryHandler as createConfigQueryHandler$1, createStatusHandler, createConfigApplyHandler, substituteEnvVars, DEFAULT_PORTS, getBindAddress, postJson, fetchJson, getPackageVersion } from '@karmaniverous/jeeves';
|
|
3
3
|
import Fastify from 'fastify';
|
|
4
4
|
import { readdir, stat, readFile } from 'node:fs/promises';
|
|
5
5
|
import { parallel, capitalize, title, camel, snake, dash, isEqual, get, omit } from 'radash';
|
|
@@ -307,11 +307,12 @@ function normalizeSlashes(path) {
|
|
|
307
307
|
*/
|
|
308
308
|
function isPathWatched(filePath, watchPaths, ignoredPaths) {
|
|
309
309
|
const normalised = normalizeSlashes(filePath);
|
|
310
|
-
const
|
|
310
|
+
const opts = { dot: true, nocase: process.platform === 'win32' };
|
|
311
|
+
const isIncluded = picomatch(watchPaths, opts);
|
|
311
312
|
if (!isIncluded(normalised))
|
|
312
313
|
return false;
|
|
313
314
|
if (ignoredPaths && ignoredPaths.length > 0) {
|
|
314
|
-
const isExcluded = picomatch(ignoredPaths,
|
|
315
|
+
const isExcluded = picomatch(ignoredPaths, opts);
|
|
315
316
|
if (isExcluded(normalised))
|
|
316
317
|
return false;
|
|
317
318
|
}
|
|
@@ -1426,10 +1427,15 @@ function createConfigReindexHandler(deps) {
|
|
|
1426
1427
|
plan: result.plan,
|
|
1427
1428
|
});
|
|
1428
1429
|
}
|
|
1429
|
-
//
|
|
1430
|
-
|
|
1430
|
+
// Live prune: fire and forget without pre-computing plan (avoids double-scrolling the collection).
|
|
1431
|
+
if (validScope === 'prune') {
|
|
1432
|
+
void executeReindex(reindexDeps, 'prune', pathParam, false);
|
|
1433
|
+
return await reply
|
|
1434
|
+
.status(200)
|
|
1435
|
+
.send({ status: 'started', scope: 'prune' });
|
|
1436
|
+
}
|
|
1437
|
+
// Non-prune scopes: compute plan first then execute async.
|
|
1431
1438
|
const planResult = await executeReindex(reindexDeps, validScope, pathParam, true);
|
|
1432
|
-
// Now fire actual reindex async
|
|
1433
1439
|
void executeReindex(reindexDeps, validScope, pathParam, false);
|
|
1434
1440
|
return await reply
|
|
1435
1441
|
.status(200)
|
|
@@ -3352,7 +3358,7 @@ function createSearchHandler(deps) {
|
|
|
3352
3358
|
const vectors = await deps.embeddingProvider.embed([query]);
|
|
3353
3359
|
const hybridConfig = deps.getHybridConfig?.();
|
|
3354
3360
|
if (hybridConfig?.enabled) {
|
|
3355
|
-
return deps.vectorStore.hybridSearch(vectors[0], query, limit, hybridConfig.textWeight, filter);
|
|
3361
|
+
return deps.vectorStore.hybridSearch(vectors[0], query, limit, hybridConfig.textWeight, filter, offset);
|
|
3356
3362
|
}
|
|
3357
3363
|
return deps.vectorStore.search(vectors[0], limit, filter, offset);
|
|
3358
3364
|
}, deps.logger, 'Search');
|
|
@@ -4735,49 +4741,6 @@ class ConfigWatcher {
|
|
|
4735
4741
|
}
|
|
4736
4742
|
}
|
|
4737
4743
|
|
|
4738
|
-
/**
|
|
4739
|
-
* @module config/substituteEnvVars
|
|
4740
|
-
*
|
|
4741
|
-
* Deep-walks config objects and replaces `${VAR_NAME}` patterns with environment variable values.
|
|
4742
|
-
*/
|
|
4743
|
-
const ENV_PATTERN = /\$\{([^}]+)\}/g;
|
|
4744
|
-
/**
|
|
4745
|
-
* Replace `${VAR_NAME}` patterns in a string with `process.env.VAR_NAME`.
|
|
4746
|
-
*
|
|
4747
|
-
* @param value - The string to process.
|
|
4748
|
-
* @returns The string with resolved env vars; unresolvable expressions left untouched.
|
|
4749
|
-
*/
|
|
4750
|
-
function substituteString(value) {
|
|
4751
|
-
return value.replace(ENV_PATTERN, (match, varName) => {
|
|
4752
|
-
const envValue = process.env[varName];
|
|
4753
|
-
if (envValue === undefined)
|
|
4754
|
-
return match;
|
|
4755
|
-
return envValue;
|
|
4756
|
-
});
|
|
4757
|
-
}
|
|
4758
|
-
/**
|
|
4759
|
-
* Deep-walk a value and substitute `${VAR_NAME}` patterns in all string values.
|
|
4760
|
-
*
|
|
4761
|
-
* @param value - The value to walk (object, array, or primitive).
|
|
4762
|
-
* @returns A new value with all env var references resolved.
|
|
4763
|
-
*/
|
|
4764
|
-
function substituteEnvVars(value) {
|
|
4765
|
-
if (typeof value === 'string') {
|
|
4766
|
-
return substituteString(value);
|
|
4767
|
-
}
|
|
4768
|
-
if (Array.isArray(value)) {
|
|
4769
|
-
return value.map((item) => substituteEnvVars(item));
|
|
4770
|
-
}
|
|
4771
|
-
if (value !== null && typeof value === 'object') {
|
|
4772
|
-
const result = {};
|
|
4773
|
-
for (const [key, val] of Object.entries(value)) {
|
|
4774
|
-
result[key] = substituteEnvVars(val);
|
|
4775
|
-
}
|
|
4776
|
-
return result;
|
|
4777
|
-
}
|
|
4778
|
-
return value;
|
|
4779
|
-
}
|
|
4780
|
-
|
|
4781
4744
|
const MODULE_NAME = 'jeeves-watcher';
|
|
4782
4745
|
/**
|
|
4783
4746
|
* Merge sensible defaults into a loaded configuration.
|
|
@@ -5413,6 +5376,8 @@ function computeLineOffsets(fullText, chunks) {
|
|
|
5413
5376
|
*/
|
|
5414
5377
|
/** Default number of points to upsert per batch (prevents OOM on large files). */
|
|
5415
5378
|
const DEFAULT_UPSERT_BATCH_SIZE = 50;
|
|
5379
|
+
/** Maximum chunks per Gemini batchEmbedContents request. */
|
|
5380
|
+
const EMBED_BATCH_SIZE = 100;
|
|
5416
5381
|
/**
|
|
5417
5382
|
* Embed text chunks, upsert to vector store, and clean up orphaned chunks.
|
|
5418
5383
|
*
|
|
@@ -5431,8 +5396,14 @@ async function embedAndUpsert(deps, text, filePath, metadata, existingPayload, f
|
|
|
5431
5396
|
const chunks = await splitter.splitText(text);
|
|
5432
5397
|
// Compute line offsets
|
|
5433
5398
|
const offsets = computeLineOffsets(text, chunks);
|
|
5434
|
-
// Embed
|
|
5435
|
-
const
|
|
5399
|
+
// Embed chunks in batches to respect Gemini's 100-doc limit
|
|
5400
|
+
const allVectors = [];
|
|
5401
|
+
for (let start = 0; start < chunks.length; start += EMBED_BATCH_SIZE) {
|
|
5402
|
+
const batch = chunks.slice(start, start + EMBED_BATCH_SIZE);
|
|
5403
|
+
const batchVectors = await embeddingProvider.embed(batch);
|
|
5404
|
+
allVectors.push(...batchVectors);
|
|
5405
|
+
}
|
|
5406
|
+
const vectors = allVectors;
|
|
5436
5407
|
// Build all points
|
|
5437
5408
|
const points = chunks.map((chunk, i) => ({
|
|
5438
5409
|
id: pointId(filePath, i),
|
|
@@ -6112,9 +6083,10 @@ async function ensureTextIndex(client, collectionName, fieldName, log) {
|
|
|
6112
6083
|
* @param limit - Maximum results to return.
|
|
6113
6084
|
* @param textWeight - Weight for text results in RRF (0–1).
|
|
6114
6085
|
* @param filter - Optional Qdrant filter.
|
|
6086
|
+
* @param offset - Optional result offset for pagination.
|
|
6115
6087
|
* @returns An array of search results.
|
|
6116
6088
|
*/
|
|
6117
|
-
async function hybridSearch(client, collectionName, vector, queryText, limit, textWeight, filter) {
|
|
6089
|
+
async function hybridSearch(client, collectionName, vector, queryText, limit, textWeight, filter, offset) {
|
|
6118
6090
|
const prefetchLimit = Math.max(limit * 3, 20);
|
|
6119
6091
|
const vectorWeight = 1 - textWeight;
|
|
6120
6092
|
const textFilter = {
|
|
@@ -6143,6 +6115,7 @@ async function hybridSearch(client, collectionName, vector, queryText, limit, te
|
|
|
6143
6115
|
},
|
|
6144
6116
|
limit,
|
|
6145
6117
|
with_payload: true,
|
|
6118
|
+
...(offset !== undefined ? { offset } : {}),
|
|
6146
6119
|
});
|
|
6147
6120
|
return result.points.map((p) => ({
|
|
6148
6121
|
id: String(p.id),
|
|
@@ -6440,10 +6413,11 @@ class VectorStoreClient {
|
|
|
6440
6413
|
* @param limit - Maximum results to return.
|
|
6441
6414
|
* @param textWeight - Weight for text results in RRF (0–1).
|
|
6442
6415
|
* @param filter - Optional Qdrant filter.
|
|
6416
|
+
* @param offset - Optional result offset for pagination.
|
|
6443
6417
|
* @returns An array of search results.
|
|
6444
6418
|
*/
|
|
6445
|
-
async hybridSearch(vector, queryText, limit, textWeight, filter) {
|
|
6446
|
-
return hybridSearch(this.client, this.collectionName, vector, queryText, limit, textWeight, filter);
|
|
6419
|
+
async hybridSearch(vector, queryText, limit, textWeight, filter, offset) {
|
|
6420
|
+
return hybridSearch(this.client, this.collectionName, vector, queryText, limit, textWeight, filter, offset);
|
|
6447
6421
|
}
|
|
6448
6422
|
/**
|
|
6449
6423
|
* Retrieve points with their vectors by ID.
|
package/package.json
CHANGED
|
@@ -1,71 +1,27 @@
|
|
|
1
1
|
{
|
|
2
|
-
"name": "@karmaniverous/jeeves-watcher",
|
|
3
|
-
"version": "0.17.9",
|
|
4
2
|
"author": "Jason Williscroft",
|
|
5
|
-
"description": "Filesystem watcher that keeps a Qdrant vector store in sync with document changes",
|
|
6
|
-
"license": "BSD-3-Clause",
|
|
7
|
-
"type": "module",
|
|
8
|
-
"module": "dist/index.js",
|
|
9
|
-
"types": "dist/index.d.ts",
|
|
10
3
|
"bin": {
|
|
11
4
|
"jeeves-watcher": "./dist/cli/jeeves-watcher/index.js"
|
|
12
5
|
},
|
|
13
|
-
"exports": {
|
|
14
|
-
".": {
|
|
15
|
-
"types": "./dist/index.d.ts",
|
|
16
|
-
"default": "./dist/index.js"
|
|
17
|
-
}
|
|
18
|
-
},
|
|
19
|
-
"files": [
|
|
20
|
-
"dist",
|
|
21
|
-
"config.schema.json"
|
|
22
|
-
],
|
|
23
|
-
"publishConfig": {
|
|
24
|
-
"access": "public"
|
|
25
|
-
},
|
|
26
|
-
"repository": {
|
|
27
|
-
"type": "git",
|
|
28
|
-
"url": "git+https://github.com/karmaniverous/jeeves-watcher.git",
|
|
29
|
-
"directory": "packages/service"
|
|
30
|
-
},
|
|
31
6
|
"bugs": {
|
|
32
7
|
"url": "https://github.com/karmaniverous/jeeves-watcher/issues"
|
|
33
8
|
},
|
|
34
|
-
"homepage": "https://github.com/karmaniverous/jeeves-watcher#readme",
|
|
35
|
-
"keywords": [
|
|
36
|
-
"filesystem",
|
|
37
|
-
"watcher",
|
|
38
|
-
"qdrant",
|
|
39
|
-
"vector-store",
|
|
40
|
-
"embeddings",
|
|
41
|
-
"semantic-search",
|
|
42
|
-
"document-indexing",
|
|
43
|
-
"rag",
|
|
44
|
-
"langchain",
|
|
45
|
-
"gemini",
|
|
46
|
-
"typescript",
|
|
47
|
-
"cli"
|
|
48
|
-
],
|
|
49
|
-
"engines": {
|
|
50
|
-
"node": ">=22"
|
|
51
|
-
},
|
|
52
9
|
"dependencies": {
|
|
53
10
|
"@commander-js/extra-typings": "^14.0.0",
|
|
54
|
-
"@karmaniverous/jeeves": "^0.5.
|
|
55
|
-
"@karmaniverous/jeeves-watcher-core": "
|
|
11
|
+
"@karmaniverous/jeeves": "^0.5.11",
|
|
12
|
+
"@karmaniverous/jeeves-watcher-core": "^0.1.2",
|
|
56
13
|
"@karmaniverous/jsonmap": "^2.1.1",
|
|
57
14
|
"@langchain/textsplitters": "*",
|
|
58
15
|
"@qdrant/js-client-rest": "*",
|
|
59
|
-
"ajv": "
|
|
16
|
+
"ajv": "~8.18.0",
|
|
60
17
|
"ajv-formats": "*",
|
|
61
18
|
"better-sqlite3": "^12.10.0",
|
|
62
19
|
"cheerio": "^1.2.0",
|
|
63
20
|
"chokidar": "^5.0.0",
|
|
64
21
|
"cosmiconfig": "*",
|
|
65
|
-
"dayjs": "^1.11.
|
|
22
|
+
"dayjs": "^1.11.21",
|
|
66
23
|
"fastify": "*",
|
|
67
24
|
"handlebars": "^4.7.9",
|
|
68
|
-
"hast": "^1.0.0",
|
|
69
25
|
"hast-util-to-mdast": "^10.1.2",
|
|
70
26
|
"ignore": "^7.0.5",
|
|
71
27
|
"js-yaml": "*",
|
|
@@ -82,8 +38,9 @@
|
|
|
82
38
|
"uuid": "*",
|
|
83
39
|
"zod": "^4.4.3"
|
|
84
40
|
},
|
|
41
|
+
"description": "Filesystem watcher that keeps a Qdrant vector store in sync with document changes",
|
|
85
42
|
"devDependencies": {
|
|
86
|
-
"@dotenvx/dotenvx": "^1.
|
|
43
|
+
"@dotenvx/dotenvx": "^1.69.1",
|
|
87
44
|
"@rollup/plugin-alias": "^6.0.0",
|
|
88
45
|
"@rollup/plugin-commonjs": "^29.0.2",
|
|
89
46
|
"@rollup/plugin-json": "^6.1.0",
|
|
@@ -92,40 +49,62 @@
|
|
|
92
49
|
"@types/better-sqlite3": "^7.6.13",
|
|
93
50
|
"@types/fs-extra": "^11.0.4",
|
|
94
51
|
"@types/js-yaml": "*",
|
|
95
|
-
"@types/node": "^25.
|
|
52
|
+
"@types/node": "^25.9.1",
|
|
96
53
|
"@types/picomatch": "^4.0.3",
|
|
97
|
-
"@vitest/coverage-v8": "^4.1.
|
|
54
|
+
"@vitest/coverage-v8": "^4.1.7",
|
|
98
55
|
"cross-env": "^10.1.0",
|
|
99
56
|
"fs-extra": "^11.3.5",
|
|
100
57
|
"happy-dom": "^20.9.0",
|
|
101
|
-
"knip": "^6.
|
|
58
|
+
"knip": "^6.14.2",
|
|
102
59
|
"release-it": "^20.0.1",
|
|
103
|
-
"rollup": "^4.60.
|
|
60
|
+
"rollup": "^4.60.4",
|
|
104
61
|
"rollup-plugin-dts": "^6.4.1",
|
|
105
62
|
"tslib": "^2.8.1",
|
|
106
63
|
"typedoc": "^0.28.19",
|
|
107
64
|
"typedoc-plugin-mdn-links": "^5.1.1",
|
|
108
65
|
"typedoc-plugin-replace-text": "^4.2.0",
|
|
109
|
-
"vitest": "^4.1.
|
|
66
|
+
"vitest": "^4.1.7"
|
|
110
67
|
},
|
|
111
|
-
"
|
|
112
|
-
"
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
"
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
"
|
|
68
|
+
"engines": {
|
|
69
|
+
"node": ">=22"
|
|
70
|
+
},
|
|
71
|
+
"exports": {
|
|
72
|
+
".": {
|
|
73
|
+
"types": "./dist/index.d.ts",
|
|
74
|
+
"default": "./dist/index.js"
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
"files": [
|
|
78
|
+
"dist",
|
|
79
|
+
"config.schema.json"
|
|
80
|
+
],
|
|
81
|
+
"homepage": "https://github.com/karmaniverous/jeeves-watcher#readme",
|
|
82
|
+
"keywords": [
|
|
83
|
+
"filesystem",
|
|
84
|
+
"watcher",
|
|
85
|
+
"qdrant",
|
|
86
|
+
"vector-store",
|
|
87
|
+
"embeddings",
|
|
88
|
+
"semantic-search",
|
|
89
|
+
"document-indexing",
|
|
90
|
+
"rag",
|
|
91
|
+
"langchain",
|
|
92
|
+
"gemini",
|
|
93
|
+
"typescript",
|
|
94
|
+
"cli"
|
|
95
|
+
],
|
|
96
|
+
"license": "BSD-3-Clause",
|
|
97
|
+
"module": "dist/index.js",
|
|
98
|
+
"name": "@karmaniverous/jeeves-watcher",
|
|
99
|
+
"publishConfig": {
|
|
100
|
+
"access": "public"
|
|
122
101
|
},
|
|
123
102
|
"release-it": {
|
|
124
103
|
"git": {
|
|
125
104
|
"changelog": "npx git-cliff --unreleased --strip header",
|
|
126
105
|
"commitMessage": "chore: release @karmaniverous/jeeves-watcher v${version}",
|
|
127
|
-
"
|
|
128
|
-
"
|
|
106
|
+
"requireBranch": "main",
|
|
107
|
+
"tagName": "service/${version}"
|
|
129
108
|
},
|
|
130
109
|
"github": {
|
|
131
110
|
"release": true
|
|
@@ -137,18 +116,38 @@
|
|
|
137
116
|
"npm run test",
|
|
138
117
|
"npm run build"
|
|
139
118
|
],
|
|
140
|
-
"before:npm:release": [
|
|
141
|
-
"npx git-cliff -o CHANGELOG.md",
|
|
142
|
-
"git add -A"
|
|
143
|
-
],
|
|
144
119
|
"after:release": [
|
|
145
120
|
"git switch -c release/service/${version}",
|
|
146
121
|
"git push -u origin release/service/${version}",
|
|
147
122
|
"git switch ${branchName}"
|
|
123
|
+
],
|
|
124
|
+
"before:npm:release": [
|
|
125
|
+
"npx git-cliff -o CHANGELOG.md",
|
|
126
|
+
"git add -A"
|
|
148
127
|
]
|
|
149
128
|
},
|
|
150
129
|
"npm": {
|
|
151
130
|
"publish": true
|
|
152
131
|
}
|
|
153
|
-
}
|
|
132
|
+
},
|
|
133
|
+
"repository": {
|
|
134
|
+
"directory": "packages/service",
|
|
135
|
+
"type": "git",
|
|
136
|
+
"url": "git+https://github.com/karmaniverous/jeeves-watcher.git"
|
|
137
|
+
},
|
|
138
|
+
"scripts": {
|
|
139
|
+
"build": "npm run generate:schema && rimraf dist && cross-env NO_COLOR=1 rollup --config rollup.config.ts --configPlugin @rollup/plugin-typescript",
|
|
140
|
+
"changelog": "git-cliff -o CHANGELOG.md",
|
|
141
|
+
"diagrams": "cd diagrams && plantuml -tpng -o ../assets -r .",
|
|
142
|
+
"generate:schema": "tsx src/config/generate-schema.ts",
|
|
143
|
+
"lint": "eslint .",
|
|
144
|
+
"lint:fix": "eslint --fix .",
|
|
145
|
+
"release": "dotenvx run -f .env.local -- release-it",
|
|
146
|
+
"release:pre": "dotenvx run -f .env.local -- release-it --no-git.requireBranch --github.prerelease --preRelease",
|
|
147
|
+
"test": "vitest run",
|
|
148
|
+
"typecheck": "tsc"
|
|
149
|
+
},
|
|
150
|
+
"type": "module",
|
|
151
|
+
"types": "dist/index.d.ts",
|
|
152
|
+
"version": "0.17.11"
|
|
154
153
|
}
|