@karmaniverous/jeeves-watcher 0.18.8 → 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 +2 -2
- package/config.schema.json +231 -183
- package/dist/cli/jeeves-watcher/{index-BjghvUnc.js → index-B_g6RfR8.js} +115 -130
- package/dist/cli/jeeves-watcher/index.js +148 -23
- package/dist/index.d.ts +17 -10
- package/dist/index.js +256 -148
- package/package.json +2 -2
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createConfigQueryHandler as createConfigQueryHandler$1, createStatusHandler, createConfigApplyHandler, DEFAULT_PORTS, getBindAddress } from '@karmaniverous/jeeves';
|
|
3
|
-
import {
|
|
4
|
-
export {
|
|
3
|
+
import { d as normalizeSlashes, n as normalizeError, e as execFileAsync, r as retry, b as gitAddViaStdin, c as normalizePathCase, f as findRootForPath, G as GitignoreFilter, a as executeReindex, V as VALID_REINDEX_SCOPES, m as mergeInferenceRules, i as isPathWatched, g as getWatchRootBases, C as CONFIG_WATCH_VALID_SCOPES, s as sleep, l as loadConfig } from './index.js';
|
|
4
|
+
export { h 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, relative, sep, isAbsolute } from 'node:path';
|
|
7
7
|
import Database from 'better-sqlite3';
|
|
@@ -10,11 +10,9 @@ 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, extractWatchPathStrings, vcsAuthorConfigSchema, inferenceRuleSchema, jeevesWatcherConfigSchema } from '@karmaniverous/jeeves-watcher-core';
|
|
14
|
-
import { execFile } from 'node:child_process';
|
|
15
|
-
import { promisify } from 'node:util';
|
|
13
|
+
import { normalizeWatchPaths, vcsRetentionConfigSchema, extractWatchPathStrings, vcsAuthorConfigSchema, inferenceRuleSchema, jeevesWatcherConfigSchema, getEndpoint } from '@karmaniverous/jeeves-watcher-core';
|
|
16
14
|
import { homedir } from 'node:os';
|
|
17
|
-
import { access, rm, readFile, writeFile, appendFile, mkdir
|
|
15
|
+
import { access, rm, stat, readFile, writeFile, appendFile, mkdir } from 'node:fs/promises';
|
|
18
16
|
import { pathToFileURL, fileURLToPath } from 'node:url';
|
|
19
17
|
import { packageDirectorySync } from 'package-directory';
|
|
20
18
|
import { JsonMap } from '@karmaniverous/jsonmap';
|
|
@@ -40,6 +38,8 @@ import mammoth from 'mammoth';
|
|
|
40
38
|
import { MarkdownTextSplitter, RecursiveCharacterTextSplitter } from '@langchain/textsplitters';
|
|
41
39
|
import { QdrantClient } from '@qdrant/js-client-rest';
|
|
42
40
|
import 'cosmiconfig';
|
|
41
|
+
import 'node:child_process';
|
|
42
|
+
import 'node:util';
|
|
43
43
|
|
|
44
44
|
/**
|
|
45
45
|
* @module api/InitialScanTracker
|
|
@@ -928,77 +928,6 @@ class CommitMessageGenerator {
|
|
|
928
928
|
}
|
|
929
929
|
}
|
|
930
930
|
|
|
931
|
-
/**
|
|
932
|
-
* @module vcs/gitExec
|
|
933
|
-
* Shared git execution utilities.
|
|
934
|
-
*/
|
|
935
|
-
/** Promisified execFile for git commands. */
|
|
936
|
-
const execFileAsync = promisify(execFile);
|
|
937
|
-
/**
|
|
938
|
-
* Stage files via stdin to avoid ENAMETOOLONG on Windows.
|
|
939
|
-
*
|
|
940
|
-
* Uses `git add --pathspec-from-file=- --pathspec-file-nul` so the file list is piped
|
|
941
|
-
* through stdin (NUL-delimited) instead of passed as command-line
|
|
942
|
-
* arguments. This sidesteps the Windows CreateProcessW 32 767-char
|
|
943
|
-
* limit that triggers ENAMETOOLONG when batches contain many files
|
|
944
|
-
* with long absolute paths.
|
|
945
|
-
*
|
|
946
|
-
* @param files - Absolute paths of files to stage.
|
|
947
|
-
* @param cwd - Repository root (working directory for git).
|
|
948
|
-
*/
|
|
949
|
-
function gitAddViaStdin(files, cwd) {
|
|
950
|
-
return new Promise((resolve, reject) => {
|
|
951
|
-
const child = execFile('git', ['add', '--pathspec-from-file=-', '--pathspec-file-nul'], { cwd }, (error) => {
|
|
952
|
-
if (error)
|
|
953
|
-
reject(error);
|
|
954
|
-
else
|
|
955
|
-
resolve();
|
|
956
|
-
});
|
|
957
|
-
if (!child.stdin) {
|
|
958
|
-
reject(new Error('Failed to open stdin for git add'));
|
|
959
|
-
return;
|
|
960
|
-
}
|
|
961
|
-
// Suppress EPIPE — expected if git exits before we finish writing
|
|
962
|
-
child.stdin.on('error', (err) => {
|
|
963
|
-
if (err.code !== 'EPIPE') {
|
|
964
|
-
reject(err);
|
|
965
|
-
}
|
|
966
|
-
});
|
|
967
|
-
child.stdin.end(files.join('\0'));
|
|
968
|
-
});
|
|
969
|
-
}
|
|
970
|
-
/**
|
|
971
|
-
* Normalize a path for case-insensitive comparison on Windows.
|
|
972
|
-
* On Windows, lowercases the entire path; on other platforms, returns as-is.
|
|
973
|
-
*
|
|
974
|
-
* @param p - The path string to normalize.
|
|
975
|
-
* @param platform - The platform to check against (default: `process.platform`).
|
|
976
|
-
* @returns The normalized path.
|
|
977
|
-
*/
|
|
978
|
-
function normalizePathCase(p, platform = process.platform) {
|
|
979
|
-
return platform === 'win32' ? p.toLowerCase() : p;
|
|
980
|
-
}
|
|
981
|
-
/**
|
|
982
|
-
* Find the longest-prefix-match root for a normalized path.
|
|
983
|
-
* Roots must be sorted longest-first for correct nested matching.
|
|
984
|
-
*
|
|
985
|
-
* @param roots - Root paths sorted longest-first.
|
|
986
|
-
* @param normalizedPath - Normalized absolute path (forward slashes).
|
|
987
|
-
* @param platform - The platform to check against (default: `process.platform`).
|
|
988
|
-
* @returns The matching root, or undefined.
|
|
989
|
-
*/
|
|
990
|
-
function findRootForPath(roots, normalizedPath, platform = process.platform) {
|
|
991
|
-
const comparePath = normalizePathCase(normalizedPath, platform);
|
|
992
|
-
for (const root of roots) {
|
|
993
|
-
const compareRoot = normalizePathCase(root, platform);
|
|
994
|
-
if (comparePath === compareRoot ||
|
|
995
|
-
comparePath.startsWith(compareRoot + '/')) {
|
|
996
|
-
return root;
|
|
997
|
-
}
|
|
998
|
-
}
|
|
999
|
-
return undefined;
|
|
1000
|
-
}
|
|
1001
|
-
|
|
1002
931
|
/**
|
|
1003
932
|
* @module vcs/resolveCommitMessageApiKey
|
|
1004
933
|
* Resolves the API key for AI commit message generation.
|
|
@@ -1460,7 +1389,7 @@ async function pushToRemote(rootPath, remoteUrl, accessToken, pushErrors, logger
|
|
|
1460
1389
|
* Per-root VCS manager for git-backed content versioning.
|
|
1461
1390
|
*
|
|
1462
1391
|
* Each VCS-enabled watch root gets its own VcsManager instance, which owns
|
|
1463
|
-
* a
|
|
1392
|
+
* a throttled commit pipeline: file changes are batched, staged, committed
|
|
1464
1393
|
* (with optional AI-generated messages), and optionally pushed to a remote.
|
|
1465
1394
|
*
|
|
1466
1395
|
* Concurrency: only one commit is in-flight at a time per root. Index.lock
|
|
@@ -1477,8 +1406,9 @@ class VcsManager {
|
|
|
1477
1406
|
pendingReversions = [];
|
|
1478
1407
|
_pushErrors = [];
|
|
1479
1408
|
squashManager;
|
|
1480
|
-
|
|
1409
|
+
throttleTimer;
|
|
1481
1410
|
commitInFlight = Promise.resolve();
|
|
1411
|
+
consecutiveCommitFailures = 0;
|
|
1482
1412
|
started = false;
|
|
1483
1413
|
isBaseline = true;
|
|
1484
1414
|
_lastPushTime = null;
|
|
@@ -1519,7 +1449,7 @@ class VcsManager {
|
|
|
1519
1449
|
this.isBaseline = false;
|
|
1520
1450
|
}
|
|
1521
1451
|
/**
|
|
1522
|
-
* Add a file to the pending set and
|
|
1452
|
+
* Add a file to the pending set and start the throttle timer.
|
|
1523
1453
|
* If the pending set exceeds maxBatchSize, flush immediately.
|
|
1524
1454
|
*
|
|
1525
1455
|
* @param filePath - Absolute path of the changed file.
|
|
@@ -1527,17 +1457,22 @@ class VcsManager {
|
|
|
1527
1457
|
fileChanged(filePath) {
|
|
1528
1458
|
if (!this.started)
|
|
1529
1459
|
return;
|
|
1460
|
+
// Reset circuit breaker on new file change so the system can recover
|
|
1461
|
+
if (this.consecutiveCommitFailures >= this.config.maxConsecutiveFailures) {
|
|
1462
|
+
this.logger.info({ root: this.rootPath }, 'VCS circuit breaker reset — new file change received, retrying commits');
|
|
1463
|
+
this.consecutiveCommitFailures = 0;
|
|
1464
|
+
}
|
|
1530
1465
|
this.pending.add(filePath);
|
|
1531
1466
|
if (this.pending.size >= this.config.maxBatchSize) {
|
|
1532
|
-
this.
|
|
1467
|
+
this.clearThrottle();
|
|
1533
1468
|
const batch = this.takeBatch(this.config.maxBatchSize);
|
|
1534
1469
|
this.commitInFlight = this.commitInFlight.then(() => this.commitBatch(batch));
|
|
1535
1470
|
if (this.pending.size > 0) {
|
|
1536
|
-
this.
|
|
1471
|
+
this.resetThrottle();
|
|
1537
1472
|
}
|
|
1538
1473
|
return;
|
|
1539
1474
|
}
|
|
1540
|
-
this.
|
|
1475
|
+
this.resetThrottle();
|
|
1541
1476
|
}
|
|
1542
1477
|
/**
|
|
1543
1478
|
* Record reversion metadata so the next commit uses a revert-prefixed message.
|
|
@@ -1562,7 +1497,7 @@ class VcsManager {
|
|
|
1562
1497
|
* Flush all pending files immediately.
|
|
1563
1498
|
*/
|
|
1564
1499
|
async flush() {
|
|
1565
|
-
this.
|
|
1500
|
+
this.clearThrottle();
|
|
1566
1501
|
if (this.pending.size > 0) {
|
|
1567
1502
|
const batch = [...this.pending];
|
|
1568
1503
|
this.pending.clear();
|
|
@@ -1595,31 +1530,65 @@ class VcsManager {
|
|
|
1595
1530
|
return batch;
|
|
1596
1531
|
}
|
|
1597
1532
|
/**
|
|
1598
|
-
* Clear the
|
|
1533
|
+
* Clear the throttle timer.
|
|
1599
1534
|
*/
|
|
1600
|
-
|
|
1601
|
-
if (this.
|
|
1602
|
-
clearTimeout(this.
|
|
1603
|
-
this.
|
|
1535
|
+
clearThrottle() {
|
|
1536
|
+
if (this.throttleTimer !== undefined) {
|
|
1537
|
+
clearTimeout(this.throttleTimer);
|
|
1538
|
+
this.throttleTimer = undefined;
|
|
1604
1539
|
}
|
|
1605
1540
|
}
|
|
1606
1541
|
/**
|
|
1607
|
-
*
|
|
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.
|
|
1608
1544
|
*/
|
|
1609
|
-
|
|
1610
|
-
this.
|
|
1611
|
-
|
|
1612
|
-
|
|
1545
|
+
resetThrottle() {
|
|
1546
|
+
if (this.throttleTimer !== undefined)
|
|
1547
|
+
return;
|
|
1548
|
+
this.throttleTimer = setTimeout(() => {
|
|
1549
|
+
this.throttleTimer = undefined;
|
|
1613
1550
|
void this.flush();
|
|
1614
|
-
}, this.config.
|
|
1551
|
+
}, this.config.commitThrottleMs);
|
|
1615
1552
|
}
|
|
1616
1553
|
/**
|
|
1617
|
-
*
|
|
1554
|
+
* Check for and remove stale index.lock files before retrying.
|
|
1555
|
+
*/
|
|
1556
|
+
async removeStaleLock() {
|
|
1557
|
+
const lockPath = join(this.rootPath, '.git', 'index.lock');
|
|
1558
|
+
try {
|
|
1559
|
+
const lockStat = await stat(lockPath);
|
|
1560
|
+
const ageMs = Date.now() - lockStat.mtimeMs;
|
|
1561
|
+
if (ageMs > this.config.staleLockThresholdMs) {
|
|
1562
|
+
await rm(lockPath, { force: true });
|
|
1563
|
+
this.logger.warn({ root: this.rootPath, ageMs }, 'Removed stale index.lock');
|
|
1564
|
+
}
|
|
1565
|
+
}
|
|
1566
|
+
catch (error) {
|
|
1567
|
+
const code = error.code;
|
|
1568
|
+
if (code !== 'ENOENT') {
|
|
1569
|
+
this.logger.warn({ root: this.rootPath, err: normalizeError(error) }, 'Unable to remove stale index.lock');
|
|
1570
|
+
}
|
|
1571
|
+
}
|
|
1572
|
+
}
|
|
1573
|
+
/**
|
|
1574
|
+
* Commit a batch of files to the git repo with index.lock retry,
|
|
1575
|
+
* stale lock detection, circuit breaker, and re-queue cap.
|
|
1618
1576
|
*/
|
|
1619
1577
|
async commitBatch(files) {
|
|
1620
1578
|
if (files.length === 0)
|
|
1621
1579
|
return;
|
|
1580
|
+
// Circuit breaker: skip if too many consecutive failures
|
|
1581
|
+
if (this.consecutiveCommitFailures >= this.config.maxConsecutiveFailures) {
|
|
1582
|
+
this.logger.error({
|
|
1583
|
+
root: this.rootPath,
|
|
1584
|
+
consecutiveFailures: this.consecutiveCommitFailures,
|
|
1585
|
+
discardedFiles: files.length,
|
|
1586
|
+
}, 'VCS circuit breaker tripped — pending files discarded until next successful commit');
|
|
1587
|
+
return;
|
|
1588
|
+
}
|
|
1622
1589
|
try {
|
|
1590
|
+
// Check for stale lock before first attempt
|
|
1591
|
+
await this.removeStaleLock();
|
|
1623
1592
|
await retry(async (attempt) => {
|
|
1624
1593
|
await gitAddViaStdin(files, this.rootPath);
|
|
1625
1594
|
// Build message after staging so getStagedDiff can see the changes.
|
|
@@ -1645,12 +1614,22 @@ class VcsManager {
|
|
|
1645
1614
|
this.logger.warn({ root: this.rootPath, attempt, delay: delayMs }, 'index.lock contention, retrying');
|
|
1646
1615
|
},
|
|
1647
1616
|
});
|
|
1617
|
+
// Success — reset circuit breaker
|
|
1618
|
+
this.consecutiveCommitFailures = 0;
|
|
1648
1619
|
}
|
|
1649
1620
|
catch (error) {
|
|
1650
|
-
|
|
1621
|
+
this.consecutiveCommitFailures++;
|
|
1622
|
+
// Re-queue cap: only re-queue up to maxBatchSize files
|
|
1623
|
+
const cap = this.config.maxBatchSize;
|
|
1624
|
+
const toRequeue = files.slice(0, cap);
|
|
1625
|
+
const overflow = files.length - toRequeue.length;
|
|
1626
|
+
for (const f of toRequeue) {
|
|
1651
1627
|
this.pending.add(f);
|
|
1652
1628
|
}
|
|
1653
|
-
|
|
1629
|
+
if (overflow > 0) {
|
|
1630
|
+
this.logger.warn({ root: this.rootPath, overflow, cap }, 'Re-queue cap exceeded — discarded overflow files');
|
|
1631
|
+
}
|
|
1632
|
+
this.logger.warn({ root: this.rootPath, fileCount: toRequeue.length }, 'Re-queued files after commit failure');
|
|
1654
1633
|
this.logger.error({ root: this.rootPath, err: normalizeError(error) }, 'VCS commit failed');
|
|
1655
1634
|
}
|
|
1656
1635
|
}
|
|
@@ -1682,10 +1661,14 @@ class VcsCoordinator {
|
|
|
1682
1661
|
// Deduplicate: skip if another glob already resolved to this root.
|
|
1683
1662
|
if (this.managers.has(rootKey))
|
|
1684
1663
|
continue;
|
|
1664
|
+
const mergedRetention = entry.vcs?.retention ??
|
|
1665
|
+
config.vcs.retention ??
|
|
1666
|
+
vcsRetentionConfigSchema.parse({});
|
|
1685
1667
|
const mergedConfig = {
|
|
1686
1668
|
...config.vcs,
|
|
1687
1669
|
...entry.vcs,
|
|
1688
1670
|
enabled: true,
|
|
1671
|
+
retention: mergedRetention,
|
|
1689
1672
|
};
|
|
1690
1673
|
// Create CommitMessageGenerator if AI commit messages are configured
|
|
1691
1674
|
const cmConfig = mergedConfig.commitMessage;
|
|
@@ -1736,8 +1719,8 @@ class VcsCoordinator {
|
|
|
1736
1719
|
/**
|
|
1737
1720
|
* Signal that the initial filesystem scan is complete.
|
|
1738
1721
|
*
|
|
1739
|
-
* Flushes each manager's
|
|
1740
|
-
* any files still pending in the VCS
|
|
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
|
|
1741
1724
|
* `"baseline:"` prefix rather than `"watcher:"`. AI generation is not enabled
|
|
1742
1725
|
* until all managers have completed their flush.
|
|
1743
1726
|
*/
|
|
@@ -3179,10 +3162,10 @@ function createWatcher(config, factories, queue, processor, logger, runtimeOptio
|
|
|
3179
3162
|
* Tear down and rebuild the filesystem watcher with new config.
|
|
3180
3163
|
* Falls back to the old watcher if the new one fails to start.
|
|
3181
3164
|
*/
|
|
3182
|
-
async function rebuildWatcher(newConfig, factories, queue, processor, logger, runtimeOptions, oldState, initialScanTracker, contentHashCache) {
|
|
3165
|
+
async function rebuildWatcher(newConfig, factories, queue, processor, logger, runtimeOptions, oldState, initialScanTracker, contentHashCache, onVcsFileChange, onInitialScanComplete) {
|
|
3183
3166
|
try {
|
|
3184
3167
|
await oldState.watcher.stop();
|
|
3185
|
-
const { watcher: newWatcher, gitignoreFilter: newGitignoreFilter } = createWatcher(newConfig, factories, queue, processor, logger, runtimeOptions, initialScanTracker, contentHashCache);
|
|
3168
|
+
const { watcher: newWatcher, gitignoreFilter: newGitignoreFilter } = createWatcher(newConfig, factories, queue, processor, logger, runtimeOptions, initialScanTracker, contentHashCache, onVcsFileChange, onInitialScanComplete);
|
|
3186
3169
|
newWatcher.start();
|
|
3187
3170
|
logger.info('Filesystem watcher rebuilt successfully');
|
|
3188
3171
|
return { watcher: newWatcher, gitignoreFilter: newGitignoreFilter };
|
|
@@ -3377,7 +3360,7 @@ async function reloadConfig(state, deps) {
|
|
|
3377
3360
|
// Rebuild filesystem watcher if watch config changed
|
|
3378
3361
|
if (watchConfigChanged(oldConfig, newConfig)) {
|
|
3379
3362
|
logger.info('Watch config changed, rebuilding filesystem watcher...');
|
|
3380
|
-
const newState = await rebuildWatcher(newConfig, deps.factories, deps.queue, processor, logger, deps.runtimeOptions, { watcher: state.watcher, gitignoreFilter: state.gitignoreFilter }, deps.initialScanTracker, deps.contentHashCache);
|
|
3363
|
+
const newState = await rebuildWatcher(newConfig, deps.factories, deps.queue, processor, logger, deps.runtimeOptions, { watcher: state.watcher, gitignoreFilter: state.gitignoreFilter }, deps.initialScanTracker, deps.contentHashCache, deps.onVcsFileChange, deps.onInitialScanComplete);
|
|
3381
3364
|
state.watcher = newState.watcher;
|
|
3382
3365
|
state.gitignoreFilter = newState.gitignoreFilter;
|
|
3383
3366
|
}
|
|
@@ -5431,36 +5414,36 @@ function createApiServer(options) {
|
|
|
5431
5414
|
};
|
|
5432
5415
|
},
|
|
5433
5416
|
});
|
|
5434
|
-
app.get('
|
|
5417
|
+
app.get(getEndpoint('status').path, withCache(cacheTtlMs, async () => {
|
|
5435
5418
|
const result = await coreStatusHandler();
|
|
5436
5419
|
return result.body;
|
|
5437
5420
|
}));
|
|
5438
|
-
app.post('
|
|
5421
|
+
app.post(getEndpoint('metadata').path, createMetadataHandler({
|
|
5439
5422
|
processor,
|
|
5440
5423
|
getConfig,
|
|
5441
5424
|
logger,
|
|
5442
5425
|
configDir: dirname(configPath),
|
|
5443
5426
|
}));
|
|
5444
|
-
app.post('
|
|
5427
|
+
app.post(getEndpoint('render').path, withCache(cacheTtlMs, createRenderHandler({
|
|
5445
5428
|
processor,
|
|
5446
5429
|
getWatch: () => getConfig().watch,
|
|
5447
5430
|
logger,
|
|
5448
5431
|
})));
|
|
5449
|
-
app.get('
|
|
5432
|
+
app.get(getEndpoint('searchFacets').path, createFacetsHandler({
|
|
5450
5433
|
getConfig,
|
|
5451
5434
|
valuesManager,
|
|
5452
5435
|
configDir: dirname(configPath),
|
|
5453
5436
|
}));
|
|
5454
|
-
app.post('
|
|
5437
|
+
app.post(getEndpoint('scan').path, createScanHandler({
|
|
5455
5438
|
vectorStore,
|
|
5456
5439
|
logger,
|
|
5457
5440
|
}));
|
|
5458
|
-
app.post('
|
|
5441
|
+
app.post(getEndpoint('walk').path, createWalkHandler({
|
|
5459
5442
|
getWatchPaths: () => extractWatchPathStrings(getConfig().watch.paths),
|
|
5460
5443
|
getFileSystemWatcher,
|
|
5461
5444
|
logger,
|
|
5462
5445
|
}));
|
|
5463
|
-
app.post('
|
|
5446
|
+
app.post(getEndpoint('search').path, createSearchHandler({
|
|
5464
5447
|
embeddingProvider,
|
|
5465
5448
|
vectorStore,
|
|
5466
5449
|
logger,
|
|
@@ -5471,12 +5454,12 @@ function createApiServer(options) {
|
|
|
5471
5454
|
: undefined;
|
|
5472
5455
|
},
|
|
5473
5456
|
}));
|
|
5474
|
-
app.post('
|
|
5457
|
+
app.post(getEndpoint('rebuildMetadata').path, createRebuildMetadataHandler({
|
|
5475
5458
|
enrichmentStore: options.enrichmentStore,
|
|
5476
5459
|
vectorStore,
|
|
5477
5460
|
logger,
|
|
5478
5461
|
}));
|
|
5479
|
-
app.post('
|
|
5462
|
+
app.post(getEndpoint('reindex').path, createConfigReindexHandler({
|
|
5480
5463
|
getConfig,
|
|
5481
5464
|
processor,
|
|
5482
5465
|
logger,
|
|
@@ -5487,10 +5470,10 @@ function createApiServer(options) {
|
|
|
5487
5470
|
vectorStore,
|
|
5488
5471
|
queue,
|
|
5489
5472
|
}));
|
|
5490
|
-
app.get('
|
|
5491
|
-
app.get('
|
|
5492
|
-
app.post('
|
|
5493
|
-
app.get('
|
|
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({
|
|
5494
5477
|
getConfig,
|
|
5495
5478
|
valuesManager,
|
|
5496
5479
|
issuesManager,
|
|
@@ -5500,7 +5483,7 @@ function createApiServer(options) {
|
|
|
5500
5483
|
? () => virtualRuleStore.getAll()
|
|
5501
5484
|
: undefined,
|
|
5502
5485
|
})));
|
|
5503
|
-
app.post('
|
|
5486
|
+
app.post(getEndpoint('configValidate').path, createConfigValidateHandler({
|
|
5504
5487
|
getConfig,
|
|
5505
5488
|
logger,
|
|
5506
5489
|
configDir: dirname(configPath),
|
|
@@ -5514,7 +5497,7 @@ function createApiServer(options) {
|
|
|
5514
5497
|
return Promise.resolve();
|
|
5515
5498
|
},
|
|
5516
5499
|
});
|
|
5517
|
-
app.post('
|
|
5500
|
+
app.post(getEndpoint('configApply').path, async (request, reply) => {
|
|
5518
5501
|
const { patch, replace } = request.body;
|
|
5519
5502
|
const result = await coreConfigApplyHandler({ patch, replace });
|
|
5520
5503
|
return reply.status(result.status).send(result.body);
|
|
@@ -5533,34 +5516,34 @@ function createApiServer(options) {
|
|
|
5533
5516
|
gitignoreFilter,
|
|
5534
5517
|
vectorStore,
|
|
5535
5518
|
});
|
|
5536
|
-
app.post('
|
|
5519
|
+
app.post(getEndpoint('rulesRegister').path, createRulesRegisterHandler({
|
|
5537
5520
|
virtualRuleStore,
|
|
5538
5521
|
logger,
|
|
5539
5522
|
onRulesChanged,
|
|
5540
5523
|
}));
|
|
5541
|
-
app.delete('
|
|
5524
|
+
app.delete(getEndpoint('rulesUnregister').path, createRulesUnregisterHandler({
|
|
5542
5525
|
virtualRuleStore,
|
|
5543
5526
|
logger,
|
|
5544
5527
|
onRulesChanged,
|
|
5545
5528
|
}));
|
|
5546
|
-
app.delete('
|
|
5529
|
+
app.delete(getEndpoint('rulesUnregisterBySource').path, createRulesUnregisterParamHandler({
|
|
5547
5530
|
virtualRuleStore,
|
|
5548
5531
|
logger,
|
|
5549
5532
|
onRulesChanged,
|
|
5550
5533
|
}));
|
|
5551
|
-
app.post('
|
|
5552
|
-
app.post('
|
|
5534
|
+
app.post(getEndpoint('pointsDelete').path, createPointsDeleteHandler({ vectorStore, logger }));
|
|
5535
|
+
app.post(getEndpoint('rulesReapply').path, createRulesReapplyHandler({ processor, vectorStore, logger }));
|
|
5553
5536
|
}
|
|
5554
5537
|
// VCS routes — only registered when a VcsCoordinator is provided
|
|
5555
5538
|
if (options.vcsCoordinator) {
|
|
5556
5539
|
const coordinator = options.vcsCoordinator;
|
|
5557
|
-
app.get('
|
|
5558
|
-
app.get('
|
|
5559
|
-
app.get('
|
|
5560
|
-
app.get('
|
|
5561
|
-
app.get('
|
|
5562
|
-
app.post('
|
|
5563
|
-
app.post('
|
|
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 }));
|
|
5564
5547
|
}
|
|
5565
5548
|
return app;
|
|
5566
5549
|
}
|
|
@@ -7989,6 +7972,8 @@ class JeevesWatcher {
|
|
|
7989
7972
|
contentHashCache: this.contentHashCache,
|
|
7990
7973
|
valuesManager: this.valuesManager,
|
|
7991
7974
|
issuesManager: this.issuesManager,
|
|
7975
|
+
onVcsFileChange: (filePath, event) => this.vcsCoordinator?.onFileChange(filePath, event),
|
|
7976
|
+
onInitialScanComplete: () => this.vcsCoordinator?.onInitialScanComplete(),
|
|
7992
7977
|
});
|
|
7993
7978
|
this.config = state.config;
|
|
7994
7979
|
this.watcher = state.watcher;
|