@karmaniverous/jeeves-watcher 0.18.9 → 0.18.10

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/README.md CHANGED
@@ -29,7 +29,7 @@ Add a `vcs` block to your config:
29
29
  {
30
30
  "vcs": {
31
31
  "enabled": true,
32
- "commitDebounceMs": 30000,
32
+ "commitThrottleMs": 30000,
33
33
  "maxBatchSize": 1000,
34
34
  "commitMessage": {
35
35
  "enabled": true,
@@ -50,7 +50,7 @@ Add a `vcs` block to your config:
50
50
  | Property | Default | Description |
51
51
  |----------|---------|-------------|
52
52
  | `vcs.enabled` | `false` | Enable git-backed version control globally |
53
- | `vcs.commitDebounceMs` | `30000` | Debounce interval (ms) for batching file changes into commits. Min: 1000 |
53
+ | `vcs.commitThrottleMs` | `30000` | Throttle interval (ms) for batching file changes into commits. Min: 1000 |
54
54
  | `vcs.maxBatchSize` | `1000` | Maximum files per commit batch. Flushes immediately when exceeded. Min: 1 |
55
55
  | `vcs.commitMessage.enabled` | `true` | Enable AI-generated commit messages |
56
56
  | `vcs.commitMessage.provider` | `"anthropic"` | AI provider (currently only `"anthropic"` supported) |
@@ -338,7 +338,7 @@
338
338
  }
339
339
  ]
340
340
  },
341
- "commitDebounceMs": {
341
+ "commitThrottleMs": {
342
342
  "allOf": [
343
343
  {
344
344
  "$ref": "#/definitions/__schema14"
@@ -458,7 +458,7 @@
458
458
  },
459
459
  "__schema14": {
460
460
  "default": 30000,
461
- "description": "Debounce interval in milliseconds for batching commits. Default: 30000.",
461
+ "description": "Throttle interval in milliseconds for batching commits. Default: 30000.",
462
462
  "allOf": [
463
463
  {
464
464
  "$ref": "#/definitions/__schema15"
@@ -1487,7 +1487,7 @@
1487
1487
  "author": {
1488
1488
  "$ref": "#/definitions/__schema10"
1489
1489
  },
1490
- "commitDebounceMs": {
1490
+ "commitThrottleMs": {
1491
1491
  "$ref": "#/definitions/__schema14"
1492
1492
  },
1493
1493
  "maxBatchSize": {
@@ -10,7 +10,7 @@ import Ajv from 'ajv';
10
10
  import addFormats from 'ajv-formats';
11
11
  import picomatch from 'picomatch';
12
12
  import { deserialize, serialize } from 'node:v8';
13
- import { normalizeWatchPaths, vcsRetentionConfigSchema, extractWatchPathStrings, vcsAuthorConfigSchema, inferenceRuleSchema, jeevesWatcherConfigSchema } from '@karmaniverous/jeeves-watcher-core';
13
+ import { normalizeWatchPaths, vcsRetentionConfigSchema, extractWatchPathStrings, vcsAuthorConfigSchema, inferenceRuleSchema, jeevesWatcherConfigSchema, getEndpoint } from '@karmaniverous/jeeves-watcher-core';
14
14
  import { homedir } from 'node:os';
15
15
  import { access, rm, stat, readFile, writeFile, appendFile, mkdir } from 'node:fs/promises';
16
16
  import { pathToFileURL, fileURLToPath } from 'node:url';
@@ -1389,7 +1389,7 @@ async function pushToRemote(rootPath, remoteUrl, accessToken, pushErrors, logger
1389
1389
  * Per-root VCS manager for git-backed content versioning.
1390
1390
  *
1391
1391
  * Each VCS-enabled watch root gets its own VcsManager instance, which owns
1392
- * a debounced commit pipeline: file changes are batched, staged, committed
1392
+ * a throttled commit pipeline: file changes are batched, staged, committed
1393
1393
  * (with optional AI-generated messages), and optionally pushed to a remote.
1394
1394
  *
1395
1395
  * Concurrency: only one commit is in-flight at a time per root. Index.lock
@@ -1406,7 +1406,7 @@ class VcsManager {
1406
1406
  pendingReversions = [];
1407
1407
  _pushErrors = [];
1408
1408
  squashManager;
1409
- debounceTimer;
1409
+ throttleTimer;
1410
1410
  commitInFlight = Promise.resolve();
1411
1411
  consecutiveCommitFailures = 0;
1412
1412
  started = false;
@@ -1449,7 +1449,7 @@ class VcsManager {
1449
1449
  this.isBaseline = false;
1450
1450
  }
1451
1451
  /**
1452
- * Add a file to the pending set and reset the debounce timer.
1452
+ * Add a file to the pending set and start the throttle timer.
1453
1453
  * If the pending set exceeds maxBatchSize, flush immediately.
1454
1454
  *
1455
1455
  * @param filePath - Absolute path of the changed file.
@@ -1464,15 +1464,15 @@ class VcsManager {
1464
1464
  }
1465
1465
  this.pending.add(filePath);
1466
1466
  if (this.pending.size >= this.config.maxBatchSize) {
1467
- this.clearDebounce();
1467
+ this.clearThrottle();
1468
1468
  const batch = this.takeBatch(this.config.maxBatchSize);
1469
1469
  this.commitInFlight = this.commitInFlight.then(() => this.commitBatch(batch));
1470
1470
  if (this.pending.size > 0) {
1471
- this.resetDebounce();
1471
+ this.resetThrottle();
1472
1472
  }
1473
1473
  return;
1474
1474
  }
1475
- this.resetDebounce();
1475
+ this.resetThrottle();
1476
1476
  }
1477
1477
  /**
1478
1478
  * Record reversion metadata so the next commit uses a revert-prefixed message.
@@ -1497,7 +1497,7 @@ class VcsManager {
1497
1497
  * Flush all pending files immediately.
1498
1498
  */
1499
1499
  async flush() {
1500
- this.clearDebounce();
1500
+ this.clearThrottle();
1501
1501
  if (this.pending.size > 0) {
1502
1502
  const batch = [...this.pending];
1503
1503
  this.pending.clear();
@@ -1530,23 +1530,25 @@ class VcsManager {
1530
1530
  return batch;
1531
1531
  }
1532
1532
  /**
1533
- * Clear the debounce timer.
1533
+ * Clear the throttle timer.
1534
1534
  */
1535
- clearDebounce() {
1536
- if (this.debounceTimer !== undefined) {
1537
- clearTimeout(this.debounceTimer);
1538
- this.debounceTimer = undefined;
1535
+ clearThrottle() {
1536
+ if (this.throttleTimer !== undefined) {
1537
+ clearTimeout(this.throttleTimer);
1538
+ this.throttleTimer = undefined;
1539
1539
  }
1540
1540
  }
1541
1541
  /**
1542
- * Reset the debounce timer to fire flush() after commitDebounceMs.
1542
+ * Start the throttle timer to fire flush() after commitThrottleMs.
1543
+ * If a timer is already running, do not reset it — this is throttle, not debounce.
1543
1544
  */
1544
- resetDebounce() {
1545
- this.clearDebounce();
1546
- this.debounceTimer = setTimeout(() => {
1547
- this.debounceTimer = undefined;
1545
+ resetThrottle() {
1546
+ if (this.throttleTimer !== undefined)
1547
+ return;
1548
+ this.throttleTimer = setTimeout(() => {
1549
+ this.throttleTimer = undefined;
1548
1550
  void this.flush();
1549
- }, this.config.commitDebounceMs);
1551
+ }, this.config.commitThrottleMs);
1550
1552
  }
1551
1553
  /**
1552
1554
  * Check for and remove stale index.lock files before retrying.
@@ -1717,8 +1719,8 @@ class VcsCoordinator {
1717
1719
  /**
1718
1720
  * Signal that the initial filesystem scan is complete.
1719
1721
  *
1720
- * Flushes each manager's debounce buffer before ending baseline mode, ensuring
1721
- * any files still pending in the VCS debounce are committed with a
1722
+ * Flushes each manager's throttle buffer before ending baseline mode, ensuring
1723
+ * any files still pending in the VCS throttle are committed with a
1722
1724
  * `"baseline:"` prefix rather than `"watcher:"`. AI generation is not enabled
1723
1725
  * until all managers have completed their flush.
1724
1726
  */
@@ -5412,36 +5414,36 @@ function createApiServer(options) {
5412
5414
  };
5413
5415
  },
5414
5416
  });
5415
- app.get('/status', withCache(cacheTtlMs, async () => {
5417
+ app.get(getEndpoint('status').path, withCache(cacheTtlMs, async () => {
5416
5418
  const result = await coreStatusHandler();
5417
5419
  return result.body;
5418
5420
  }));
5419
- app.post('/metadata', createMetadataHandler({
5421
+ app.post(getEndpoint('metadata').path, createMetadataHandler({
5420
5422
  processor,
5421
5423
  getConfig,
5422
5424
  logger,
5423
5425
  configDir: dirname(configPath),
5424
5426
  }));
5425
- app.post('/render', withCache(cacheTtlMs, createRenderHandler({
5427
+ app.post(getEndpoint('render').path, withCache(cacheTtlMs, createRenderHandler({
5426
5428
  processor,
5427
5429
  getWatch: () => getConfig().watch,
5428
5430
  logger,
5429
5431
  })));
5430
- app.get('/search/facets', createFacetsHandler({
5432
+ app.get(getEndpoint('searchFacets').path, createFacetsHandler({
5431
5433
  getConfig,
5432
5434
  valuesManager,
5433
5435
  configDir: dirname(configPath),
5434
5436
  }));
5435
- app.post('/scan', createScanHandler({
5437
+ app.post(getEndpoint('scan').path, createScanHandler({
5436
5438
  vectorStore,
5437
5439
  logger,
5438
5440
  }));
5439
- app.post('/walk', createWalkHandler({
5441
+ app.post(getEndpoint('walk').path, createWalkHandler({
5440
5442
  getWatchPaths: () => extractWatchPathStrings(getConfig().watch.paths),
5441
5443
  getFileSystemWatcher,
5442
5444
  logger,
5443
5445
  }));
5444
- app.post('/search', createSearchHandler({
5446
+ app.post(getEndpoint('search').path, createSearchHandler({
5445
5447
  embeddingProvider,
5446
5448
  vectorStore,
5447
5449
  logger,
@@ -5452,12 +5454,12 @@ function createApiServer(options) {
5452
5454
  : undefined;
5453
5455
  },
5454
5456
  }));
5455
- app.post('/rebuild-metadata', createRebuildMetadataHandler({
5457
+ app.post(getEndpoint('rebuildMetadata').path, createRebuildMetadataHandler({
5456
5458
  enrichmentStore: options.enrichmentStore,
5457
5459
  vectorStore,
5458
5460
  logger,
5459
5461
  }));
5460
- app.post('/reindex', createConfigReindexHandler({
5462
+ app.post(getEndpoint('reindex').path, createConfigReindexHandler({
5461
5463
  getConfig,
5462
5464
  processor,
5463
5465
  logger,
@@ -5468,10 +5470,10 @@ function createApiServer(options) {
5468
5470
  vectorStore,
5469
5471
  queue,
5470
5472
  }));
5471
- app.get('/issues', withCache(cacheTtlMs, createIssuesHandler({ issuesManager })));
5472
- app.get('/config/schema', withCache(cacheTtlMs, createConfigSchemaHandler()));
5473
- app.post('/config/match', createConfigMatchHandler({ getConfig, logger }));
5474
- app.get('/config', withCache(cacheTtlMs, createConfigQueryHandler({
5473
+ app.get(getEndpoint('issues').path, withCache(cacheTtlMs, createIssuesHandler({ issuesManager })));
5474
+ app.get(getEndpoint('configSchema').path, withCache(cacheTtlMs, createConfigSchemaHandler()));
5475
+ app.post(getEndpoint('configMatch').path, createConfigMatchHandler({ getConfig, logger }));
5476
+ app.get(getEndpoint('config').path, withCache(cacheTtlMs, createConfigQueryHandler({
5475
5477
  getConfig,
5476
5478
  valuesManager,
5477
5479
  issuesManager,
@@ -5481,7 +5483,7 @@ function createApiServer(options) {
5481
5483
  ? () => virtualRuleStore.getAll()
5482
5484
  : undefined,
5483
5485
  })));
5484
- app.post('/config/validate', createConfigValidateHandler({
5486
+ app.post(getEndpoint('configValidate').path, createConfigValidateHandler({
5485
5487
  getConfig,
5486
5488
  logger,
5487
5489
  configDir: dirname(configPath),
@@ -5495,7 +5497,7 @@ function createApiServer(options) {
5495
5497
  return Promise.resolve();
5496
5498
  },
5497
5499
  });
5498
- app.post('/config/apply', async (request, reply) => {
5500
+ app.post(getEndpoint('configApply').path, async (request, reply) => {
5499
5501
  const { patch, replace } = request.body;
5500
5502
  const result = await coreConfigApplyHandler({ patch, replace });
5501
5503
  return reply.status(result.status).send(result.body);
@@ -5514,34 +5516,34 @@ function createApiServer(options) {
5514
5516
  gitignoreFilter,
5515
5517
  vectorStore,
5516
5518
  });
5517
- app.post('/rules/register', createRulesRegisterHandler({
5519
+ app.post(getEndpoint('rulesRegister').path, createRulesRegisterHandler({
5518
5520
  virtualRuleStore,
5519
5521
  logger,
5520
5522
  onRulesChanged,
5521
5523
  }));
5522
- app.delete('/rules/unregister', createRulesUnregisterHandler({
5524
+ app.delete(getEndpoint('rulesUnregister').path, createRulesUnregisterHandler({
5523
5525
  virtualRuleStore,
5524
5526
  logger,
5525
5527
  onRulesChanged,
5526
5528
  }));
5527
- app.delete('/rules/unregister/:source', createRulesUnregisterParamHandler({
5529
+ app.delete(getEndpoint('rulesUnregisterBySource').path, createRulesUnregisterParamHandler({
5528
5530
  virtualRuleStore,
5529
5531
  logger,
5530
5532
  onRulesChanged,
5531
5533
  }));
5532
- app.post('/points/delete', createPointsDeleteHandler({ vectorStore, logger }));
5533
- app.post('/rules/reapply', createRulesReapplyHandler({ processor, vectorStore, logger }));
5534
+ app.post(getEndpoint('pointsDelete').path, createPointsDeleteHandler({ vectorStore, logger }));
5535
+ app.post(getEndpoint('rulesReapply').path, createRulesReapplyHandler({ processor, vectorStore, logger }));
5534
5536
  }
5535
5537
  // VCS routes — only registered when a VcsCoordinator is provided
5536
5538
  if (options.vcsCoordinator) {
5537
5539
  const coordinator = options.vcsCoordinator;
5538
- app.get('/vcs/status', createVcsStatusHandler({ coordinator, logger }));
5539
- app.get('/vcs/history', createVcsHistoryHandler({ coordinator, logger }));
5540
- app.get('/vcs/show', createVcsShowHandler({ coordinator, logger }));
5541
- app.get('/vcs/diff', createVcsDiffHandler({ coordinator, logger }));
5542
- app.get('/vcs/check-exclusion', createVcsCheckExclusionHandler({ coordinator, logger }));
5543
- app.post('/vcs/revert', createVcsRevertHandler({ coordinator, logger }));
5544
- app.post('/vcs/exclude', createVcsExcludeHandler({ coordinator, logger }));
5540
+ app.get(getEndpoint('vcsStatus').path, createVcsStatusHandler({ coordinator, logger }));
5541
+ app.get(getEndpoint('vcsHistory').path, createVcsHistoryHandler({ coordinator, logger }));
5542
+ app.get(getEndpoint('vcsShow').path, createVcsShowHandler({ coordinator, logger }));
5543
+ app.get(getEndpoint('vcsDiff').path, createVcsDiffHandler({ coordinator, logger }));
5544
+ app.get(getEndpoint('vcsCheckExclusion').path, createVcsCheckExclusionHandler({ coordinator, logger }));
5545
+ app.post(getEndpoint('vcsRevert').path, createVcsRevertHandler({ coordinator, logger }));
5546
+ app.post(getEndpoint('vcsExclude').path, createVcsExcludeHandler({ coordinator, logger }));
5545
5547
  }
5546
5548
  return app;
5547
5549
  }
@@ -226,7 +226,7 @@ async function startFromConfig(configPath, descriptor) {
226
226
  const config = await loadConfig(resolvedPath);
227
227
  // Dynamic import breaks the circular dependency between this module
228
228
  // and app/index.ts (which defines JeevesWatcher and re-exports startFromConfig).
229
- const { JeevesWatcher } = await import('./index-xP2XrV4W.js');
229
+ const { JeevesWatcher } = await import('./index-B_g6RfR8.js');
230
230
  const app = new JeevesWatcher(config, resolvedPath, descriptor);
231
231
  installShutdownHandlers(() => app.stop());
232
232
  await app.start();
package/dist/index.d.ts CHANGED
@@ -1276,7 +1276,7 @@ interface PushError {
1276
1276
  * Per-root VCS manager for git-backed content versioning.
1277
1277
  *
1278
1278
  * Each VCS-enabled watch root gets its own VcsManager instance, which owns
1279
- * a debounced commit pipeline: file changes are batched, staged, committed
1279
+ * a throttled commit pipeline: file changes are batched, staged, committed
1280
1280
  * (with optional AI-generated messages), and optionally pushed to a remote.
1281
1281
  *
1282
1282
  * Concurrency: only one commit is in-flight at a time per root. Index.lock
@@ -1293,7 +1293,7 @@ declare class VcsManager {
1293
1293
  private readonly pendingReversions;
1294
1294
  private readonly _pushErrors;
1295
1295
  private readonly squashManager;
1296
- private debounceTimer;
1296
+ private throttleTimer;
1297
1297
  private commitInFlight;
1298
1298
  private consecutiveCommitFailures;
1299
1299
  private started;
@@ -1316,7 +1316,7 @@ declare class VcsManager {
1316
1316
  */
1317
1317
  endBaseline(): void;
1318
1318
  /**
1319
- * Add a file to the pending set and reset the debounce timer.
1319
+ * Add a file to the pending set and start the throttle timer.
1320
1320
  * If the pending set exceeds maxBatchSize, flush immediately.
1321
1321
  *
1322
1322
  * @param filePath - Absolute path of the changed file.
@@ -1348,13 +1348,14 @@ declare class VcsManager {
1348
1348
  */
1349
1349
  private takeBatch;
1350
1350
  /**
1351
- * Clear the debounce timer.
1351
+ * Clear the throttle timer.
1352
1352
  */
1353
- private clearDebounce;
1353
+ private clearThrottle;
1354
1354
  /**
1355
- * Reset the debounce timer to fire flush() after commitDebounceMs.
1355
+ * Start the throttle timer to fire flush() after commitThrottleMs.
1356
+ * If a timer is already running, do not reset it — this is throttle, not debounce.
1356
1357
  */
1357
- private resetDebounce;
1358
+ private resetThrottle;
1358
1359
  /**
1359
1360
  * Check for and remove stale index.lock files before retrying.
1360
1361
  */
@@ -1394,8 +1395,8 @@ declare class VcsCoordinator {
1394
1395
  /**
1395
1396
  * Signal that the initial filesystem scan is complete.
1396
1397
  *
1397
- * Flushes each manager's debounce buffer before ending baseline mode, ensuring
1398
- * any files still pending in the VCS debounce are committed with a
1398
+ * Flushes each manager's throttle buffer before ending baseline mode, ensuring
1399
+ * any files still pending in the VCS throttle are committed with a
1399
1400
  * `"baseline:"` prefix rather than `"watcher:"`. AI generation is not enabled
1400
1401
  * until all managers have completed their flush.
1401
1402
  */
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { join, dirname, resolve, relative, extname, basename, isAbsolute, sep } from 'node:path';
2
2
  import { createConfigQueryHandler as createConfigQueryHandler$1, createStatusHandler, createConfigApplyHandler, substituteEnvVars, DEFAULT_PORTS, getBindAddress, postJson, fetchJson, getPackageVersion } from '@karmaniverous/jeeves';
3
- import { extractWatchPathStrings, inferenceRuleSchema, jeevesWatcherConfigSchema, normalizeWatchPaths, vcsRetentionConfigSchema, vcsAuthorConfigSchema, 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';
3
+ import { extractWatchPathStrings, inferenceRuleSchema, jeevesWatcherConfigSchema, normalizeWatchPaths, vcsRetentionConfigSchema, vcsAuthorConfigSchema, getEndpoint, 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';
4
4
  export { apiConfigSchema, configWatchConfigSchema, embeddingConfigSchema, inferenceRuleSchema, jeevesWatcherConfigSchema, loggingConfigSchema, vectorStoreConfigSchema, watchConfigSchema } from '@karmaniverous/jeeves-watcher-core';
5
5
  import Fastify from 'fastify';
6
6
  import { readdir, stat, access, readFile, writeFile, mkdir, appendFile, rm } from 'node:fs/promises';
@@ -5008,7 +5008,7 @@ async function pushToRemote(rootPath, remoteUrl, accessToken, pushErrors, logger
5008
5008
  * Per-root VCS manager for git-backed content versioning.
5009
5009
  *
5010
5010
  * Each VCS-enabled watch root gets its own VcsManager instance, which owns
5011
- * a debounced commit pipeline: file changes are batched, staged, committed
5011
+ * a throttled commit pipeline: file changes are batched, staged, committed
5012
5012
  * (with optional AI-generated messages), and optionally pushed to a remote.
5013
5013
  *
5014
5014
  * Concurrency: only one commit is in-flight at a time per root. Index.lock
@@ -5025,7 +5025,7 @@ class VcsManager {
5025
5025
  pendingReversions = [];
5026
5026
  _pushErrors = [];
5027
5027
  squashManager;
5028
- debounceTimer;
5028
+ throttleTimer;
5029
5029
  commitInFlight = Promise.resolve();
5030
5030
  consecutiveCommitFailures = 0;
5031
5031
  started = false;
@@ -5068,7 +5068,7 @@ class VcsManager {
5068
5068
  this.isBaseline = false;
5069
5069
  }
5070
5070
  /**
5071
- * Add a file to the pending set and reset the debounce timer.
5071
+ * Add a file to the pending set and start the throttle timer.
5072
5072
  * If the pending set exceeds maxBatchSize, flush immediately.
5073
5073
  *
5074
5074
  * @param filePath - Absolute path of the changed file.
@@ -5083,15 +5083,15 @@ class VcsManager {
5083
5083
  }
5084
5084
  this.pending.add(filePath);
5085
5085
  if (this.pending.size >= this.config.maxBatchSize) {
5086
- this.clearDebounce();
5086
+ this.clearThrottle();
5087
5087
  const batch = this.takeBatch(this.config.maxBatchSize);
5088
5088
  this.commitInFlight = this.commitInFlight.then(() => this.commitBatch(batch));
5089
5089
  if (this.pending.size > 0) {
5090
- this.resetDebounce();
5090
+ this.resetThrottle();
5091
5091
  }
5092
5092
  return;
5093
5093
  }
5094
- this.resetDebounce();
5094
+ this.resetThrottle();
5095
5095
  }
5096
5096
  /**
5097
5097
  * Record reversion metadata so the next commit uses a revert-prefixed message.
@@ -5116,7 +5116,7 @@ class VcsManager {
5116
5116
  * Flush all pending files immediately.
5117
5117
  */
5118
5118
  async flush() {
5119
- this.clearDebounce();
5119
+ this.clearThrottle();
5120
5120
  if (this.pending.size > 0) {
5121
5121
  const batch = [...this.pending];
5122
5122
  this.pending.clear();
@@ -5149,23 +5149,25 @@ class VcsManager {
5149
5149
  return batch;
5150
5150
  }
5151
5151
  /**
5152
- * Clear the debounce timer.
5152
+ * Clear the throttle timer.
5153
5153
  */
5154
- clearDebounce() {
5155
- if (this.debounceTimer !== undefined) {
5156
- clearTimeout(this.debounceTimer);
5157
- this.debounceTimer = undefined;
5154
+ clearThrottle() {
5155
+ if (this.throttleTimer !== undefined) {
5156
+ clearTimeout(this.throttleTimer);
5157
+ this.throttleTimer = undefined;
5158
5158
  }
5159
5159
  }
5160
5160
  /**
5161
- * Reset the debounce timer to fire flush() after commitDebounceMs.
5161
+ * Start the throttle timer to fire flush() after commitThrottleMs.
5162
+ * If a timer is already running, do not reset it — this is throttle, not debounce.
5162
5163
  */
5163
- resetDebounce() {
5164
- this.clearDebounce();
5165
- this.debounceTimer = setTimeout(() => {
5166
- this.debounceTimer = undefined;
5164
+ resetThrottle() {
5165
+ if (this.throttleTimer !== undefined)
5166
+ return;
5167
+ this.throttleTimer = setTimeout(() => {
5168
+ this.throttleTimer = undefined;
5167
5169
  void this.flush();
5168
- }, this.config.commitDebounceMs);
5170
+ }, this.config.commitThrottleMs);
5169
5171
  }
5170
5172
  /**
5171
5173
  * Check for and remove stale index.lock files before retrying.
@@ -5336,8 +5338,8 @@ class VcsCoordinator {
5336
5338
  /**
5337
5339
  * Signal that the initial filesystem scan is complete.
5338
5340
  *
5339
- * Flushes each manager's debounce buffer before ending baseline mode, ensuring
5340
- * any files still pending in the VCS debounce are committed with a
5341
+ * Flushes each manager's throttle buffer before ending baseline mode, ensuring
5342
+ * any files still pending in the VCS throttle are committed with a
5341
5343
  * `"baseline:"` prefix rather than `"watcher:"`. AI generation is not enabled
5342
5344
  * until all managers have completed their flush.
5343
5345
  */
@@ -5901,36 +5903,36 @@ function createApiServer(options) {
5901
5903
  };
5902
5904
  },
5903
5905
  });
5904
- app.get('/status', withCache(cacheTtlMs, async () => {
5906
+ app.get(getEndpoint('status').path, withCache(cacheTtlMs, async () => {
5905
5907
  const result = await coreStatusHandler();
5906
5908
  return result.body;
5907
5909
  }));
5908
- app.post('/metadata', createMetadataHandler({
5910
+ app.post(getEndpoint('metadata').path, createMetadataHandler({
5909
5911
  processor,
5910
5912
  getConfig,
5911
5913
  logger,
5912
5914
  configDir: dirname(configPath),
5913
5915
  }));
5914
- app.post('/render', withCache(cacheTtlMs, createRenderHandler({
5916
+ app.post(getEndpoint('render').path, withCache(cacheTtlMs, createRenderHandler({
5915
5917
  processor,
5916
5918
  getWatch: () => getConfig().watch,
5917
5919
  logger,
5918
5920
  })));
5919
- app.get('/search/facets', createFacetsHandler({
5921
+ app.get(getEndpoint('searchFacets').path, createFacetsHandler({
5920
5922
  getConfig,
5921
5923
  valuesManager,
5922
5924
  configDir: dirname(configPath),
5923
5925
  }));
5924
- app.post('/scan', createScanHandler({
5926
+ app.post(getEndpoint('scan').path, createScanHandler({
5925
5927
  vectorStore,
5926
5928
  logger,
5927
5929
  }));
5928
- app.post('/walk', createWalkHandler({
5930
+ app.post(getEndpoint('walk').path, createWalkHandler({
5929
5931
  getWatchPaths: () => extractWatchPathStrings(getConfig().watch.paths),
5930
5932
  getFileSystemWatcher,
5931
5933
  logger,
5932
5934
  }));
5933
- app.post('/search', createSearchHandler({
5935
+ app.post(getEndpoint('search').path, createSearchHandler({
5934
5936
  embeddingProvider,
5935
5937
  vectorStore,
5936
5938
  logger,
@@ -5941,12 +5943,12 @@ function createApiServer(options) {
5941
5943
  : undefined;
5942
5944
  },
5943
5945
  }));
5944
- app.post('/rebuild-metadata', createRebuildMetadataHandler({
5946
+ app.post(getEndpoint('rebuildMetadata').path, createRebuildMetadataHandler({
5945
5947
  enrichmentStore: options.enrichmentStore,
5946
5948
  vectorStore,
5947
5949
  logger,
5948
5950
  }));
5949
- app.post('/reindex', createConfigReindexHandler({
5951
+ app.post(getEndpoint('reindex').path, createConfigReindexHandler({
5950
5952
  getConfig,
5951
5953
  processor,
5952
5954
  logger,
@@ -5957,10 +5959,10 @@ function createApiServer(options) {
5957
5959
  vectorStore,
5958
5960
  queue,
5959
5961
  }));
5960
- app.get('/issues', withCache(cacheTtlMs, createIssuesHandler({ issuesManager })));
5961
- app.get('/config/schema', withCache(cacheTtlMs, createConfigSchemaHandler()));
5962
- app.post('/config/match', createConfigMatchHandler({ getConfig, logger }));
5963
- app.get('/config', withCache(cacheTtlMs, createConfigQueryHandler({
5962
+ app.get(getEndpoint('issues').path, withCache(cacheTtlMs, createIssuesHandler({ issuesManager })));
5963
+ app.get(getEndpoint('configSchema').path, withCache(cacheTtlMs, createConfigSchemaHandler()));
5964
+ app.post(getEndpoint('configMatch').path, createConfigMatchHandler({ getConfig, logger }));
5965
+ app.get(getEndpoint('config').path, withCache(cacheTtlMs, createConfigQueryHandler({
5964
5966
  getConfig,
5965
5967
  valuesManager,
5966
5968
  issuesManager,
@@ -5970,7 +5972,7 @@ function createApiServer(options) {
5970
5972
  ? () => virtualRuleStore.getAll()
5971
5973
  : undefined,
5972
5974
  })));
5973
- app.post('/config/validate', createConfigValidateHandler({
5975
+ app.post(getEndpoint('configValidate').path, createConfigValidateHandler({
5974
5976
  getConfig,
5975
5977
  logger,
5976
5978
  configDir: dirname(configPath),
@@ -5984,7 +5986,7 @@ function createApiServer(options) {
5984
5986
  return Promise.resolve();
5985
5987
  },
5986
5988
  });
5987
- app.post('/config/apply', async (request, reply) => {
5989
+ app.post(getEndpoint('configApply').path, async (request, reply) => {
5988
5990
  const { patch, replace } = request.body;
5989
5991
  const result = await coreConfigApplyHandler({ patch, replace });
5990
5992
  return reply.status(result.status).send(result.body);
@@ -6003,34 +6005,34 @@ function createApiServer(options) {
6003
6005
  gitignoreFilter,
6004
6006
  vectorStore,
6005
6007
  });
6006
- app.post('/rules/register', createRulesRegisterHandler({
6008
+ app.post(getEndpoint('rulesRegister').path, createRulesRegisterHandler({
6007
6009
  virtualRuleStore,
6008
6010
  logger,
6009
6011
  onRulesChanged,
6010
6012
  }));
6011
- app.delete('/rules/unregister', createRulesUnregisterHandler({
6013
+ app.delete(getEndpoint('rulesUnregister').path, createRulesUnregisterHandler({
6012
6014
  virtualRuleStore,
6013
6015
  logger,
6014
6016
  onRulesChanged,
6015
6017
  }));
6016
- app.delete('/rules/unregister/:source', createRulesUnregisterParamHandler({
6018
+ app.delete(getEndpoint('rulesUnregisterBySource').path, createRulesUnregisterParamHandler({
6017
6019
  virtualRuleStore,
6018
6020
  logger,
6019
6021
  onRulesChanged,
6020
6022
  }));
6021
- app.post('/points/delete', createPointsDeleteHandler({ vectorStore, logger }));
6022
- app.post('/rules/reapply', createRulesReapplyHandler({ processor, vectorStore, logger }));
6023
+ app.post(getEndpoint('pointsDelete').path, createPointsDeleteHandler({ vectorStore, logger }));
6024
+ app.post(getEndpoint('rulesReapply').path, createRulesReapplyHandler({ processor, vectorStore, logger }));
6023
6025
  }
6024
6026
  // VCS routes — only registered when a VcsCoordinator is provided
6025
6027
  if (options.vcsCoordinator) {
6026
6028
  const coordinator = options.vcsCoordinator;
6027
- app.get('/vcs/status', createVcsStatusHandler({ coordinator, logger }));
6028
- app.get('/vcs/history', createVcsHistoryHandler({ coordinator, logger }));
6029
- app.get('/vcs/show', createVcsShowHandler({ coordinator, logger }));
6030
- app.get('/vcs/diff', createVcsDiffHandler({ coordinator, logger }));
6031
- app.get('/vcs/check-exclusion', createVcsCheckExclusionHandler({ coordinator, logger }));
6032
- app.post('/vcs/revert', createVcsRevertHandler({ coordinator, logger }));
6033
- app.post('/vcs/exclude', createVcsExcludeHandler({ coordinator, logger }));
6029
+ app.get(getEndpoint('vcsStatus').path, createVcsStatusHandler({ coordinator, logger }));
6030
+ app.get(getEndpoint('vcsHistory').path, createVcsHistoryHandler({ coordinator, logger }));
6031
+ app.get(getEndpoint('vcsShow').path, createVcsShowHandler({ coordinator, logger }));
6032
+ app.get(getEndpoint('vcsDiff').path, createVcsDiffHandler({ coordinator, logger }));
6033
+ app.get(getEndpoint('vcsCheckExclusion').path, createVcsCheckExclusionHandler({ coordinator, logger }));
6034
+ app.post(getEndpoint('vcsRevert').path, createVcsRevertHandler({ coordinator, logger }));
6035
+ app.post(getEndpoint('vcsExclude').path, createVcsExcludeHandler({ coordinator, logger }));
6034
6036
  }
6035
6037
  return app;
6036
6038
  }
package/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  "dependencies": {
10
10
  "@commander-js/extra-typings": "^14.0.0",
11
11
  "@karmaniverous/jeeves": "^0.5.12",
12
- "@karmaniverous/jeeves-watcher-core": "^0.2.3",
12
+ "@karmaniverous/jeeves-watcher-core": "^0.2.4",
13
13
  "@karmaniverous/jsonmap": "^2.1.1",
14
14
  "@langchain/textsplitters": "*",
15
15
  "@qdrant/js-client-rest": "*",
@@ -149,5 +149,5 @@
149
149
  },
150
150
  "type": "module",
151
151
  "types": "dist/index.d.ts",
152
- "version": "0.18.9"
152
+ "version": "0.18.10"
153
153
  }