@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 { n as normalizeSlashes, a 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';
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
- // Fire and forget plan is computed inside but we need it for the response.
2566
- // For non-prune scopes, compute plan first then execute async.
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 all chunks
4354
- const vectors = await embeddingProvider.embed(chunks);
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-07J6R3B8.js');
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 isIncluded = picomatch(watchPaths, { dot: true });
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, { dot: true });
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, normalizeError as a, startFromConfig as b, executeReindex as e, getWatchRootBases as g, isPathWatched as i, loadConfig as l, mergeInferenceRules as m, normalizeSlashes as n, retry as r, sleep as s };
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>): Promise<SearchResult[]>;
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>): Promise<SearchResult[]>;
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 isIncluded = picomatch(watchPaths, { dot: true });
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, { dot: true });
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
- // Fire and forget plan is computed inside but we need it for the response.
1430
- // For non-prune scopes, compute plan first then execute async.
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 all chunks
5435
- const vectors = await embeddingProvider.embed(chunks);
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.10",
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": "^8.18.0",
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.20",
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.65.0",
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.7.0",
52
+ "@types/node": "^25.9.1",
96
53
  "@types/picomatch": "^4.0.3",
97
- "@vitest/coverage-v8": "^4.1.6",
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.13.1",
58
+ "knip": "^6.14.2",
102
59
  "release-it": "^20.0.1",
103
- "rollup": "^4.60.3",
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.6"
66
+ "vitest": "^4.1.7"
110
67
  },
111
- "scripts": {
112
- "generate:schema": "tsx src/config/generate-schema.ts",
113
- "build": "npm run generate:schema && rimraf dist && cross-env NO_COLOR=1 rollup --config rollup.config.ts --configPlugin @rollup/plugin-typescript",
114
- "changelog": "git-cliff -o CHANGELOG.md",
115
- "diagrams": "cd diagrams && plantuml -tpng -o ../assets -r .",
116
- "lint": "eslint .",
117
- "lint:fix": "eslint --fix .",
118
- "release": "dotenvx run -f .env.local -- release-it",
119
- "release:pre": "dotenvx run -f .env.local -- release-it --no-git.requireBranch --github.prerelease --preRelease",
120
- "test": "vitest run",
121
- "typecheck": "tsc"
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
- "tagName": "service/${version}",
128
- "requireBranch": "main"
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
  }