@karmaniverous/jeeves-watcher 0.17.10 → 0.18.0
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 +128 -0
- package/config.schema.json +465 -176
- package/dist/cli/jeeves-watcher/{index-07J6R3B8.js → index-DtyqhT2s.js} +1590 -21
- package/dist/cli/jeeves-watcher/index.js +18 -60
- package/dist/index.d.ts +285 -5
- package/dist/index.js +1669 -142
- package/package.json +71 -72
|
@@ -1,8 +1,8 @@
|
|
|
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
|
-
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';
|
|
5
|
+
import { jeevesWatcherConfigSchema, LOGGING_DEFAULTS, API_DEFAULTS, EMBEDDING_DEFAULTS, CONFIG_WATCH_DEFAULTS, WATCH_DEFAULTS, ROOT_DEFAULTS, extractWatchPathStrings, INIT_CONFIG_TEMPLATE, DEFAULT_PORT as DEFAULT_PORT$1, PLUGIN_PACKAGE, SERVICE_PACKAGE, COMPONENT_NAME } from '@karmaniverous/jeeves-watcher-core';
|
|
6
6
|
import { packageDirectorySync } from 'package-directory';
|
|
7
7
|
import { readFileSync, existsSync, mkdirSync, renameSync, statSync, readdirSync } from 'node:fs';
|
|
8
8
|
import { cosmiconfig } from 'cosmiconfig';
|
|
@@ -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-DtyqhT2s.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
|
}
|
|
@@ -933,7 +891,7 @@ async function computePrunePlan(deps) {
|
|
|
933
891
|
continue;
|
|
934
892
|
}
|
|
935
893
|
seenFiles.add(filePath);
|
|
936
|
-
const watched = isPathWatched(filePath, config.watch.paths, config.watch.ignored);
|
|
894
|
+
const watched = isPathWatched(filePath, extractWatchPathStrings(config.watch.paths), config.watch.ignored);
|
|
937
895
|
const gitignored = gitignoreFilter
|
|
938
896
|
? gitignoreFilter.isIgnored(filePath)
|
|
939
897
|
: false;
|
|
@@ -953,7 +911,7 @@ async function computePrunePlan(deps) {
|
|
|
953
911
|
incomplete = true;
|
|
954
912
|
}
|
|
955
913
|
const orphanedFileList = [...orphanedFiles];
|
|
956
|
-
const byRoot = groupByRoot(orphanedFileList, config.watch.paths);
|
|
914
|
+
const byRoot = groupByRoot(orphanedFileList, extractWatchPathStrings(config.watch.paths));
|
|
957
915
|
return {
|
|
958
916
|
plan: {
|
|
959
917
|
total: totalPoints,
|
|
@@ -1069,18 +1027,18 @@ async function executeReindex(deps, scope, path, dryRun = false) {
|
|
|
1069
1027
|
}
|
|
1070
1028
|
else if (scope === 'rules' && pathArray && pathArray.length > 0) {
|
|
1071
1029
|
// Rules scope with path filter: list from watch roots intersected with caller globs
|
|
1072
|
-
fileList = await listFilesFromWatchRoots(config.watch.paths, config.watch.ignored, pathArray, isGitignored);
|
|
1030
|
+
fileList = await listFilesFromWatchRoots(extractWatchPathStrings(config.watch.paths), config.watch.ignored, pathArray, isGitignored);
|
|
1073
1031
|
}
|
|
1074
1032
|
else {
|
|
1075
1033
|
// rules or full: list files from globs
|
|
1076
|
-
fileList = await listFilesFromGlobs(config.watch.paths, config.watch.ignored, isGitignored);
|
|
1034
|
+
fileList = await listFilesFromGlobs(extractWatchPathStrings(config.watch.paths), config.watch.ignored, isGitignored);
|
|
1077
1035
|
}
|
|
1078
1036
|
if (fileList !== undefined) {
|
|
1079
1037
|
plan = {
|
|
1080
1038
|
total: fileList.length,
|
|
1081
1039
|
toProcess: fileList.length,
|
|
1082
1040
|
toDelete: 0,
|
|
1083
|
-
byRoot: groupByRoot(fileList, config.watch.paths),
|
|
1041
|
+
byRoot: groupByRoot(fileList, extractWatchPathStrings(config.watch.paths)),
|
|
1084
1042
|
};
|
|
1085
1043
|
}
|
|
1086
1044
|
if (dryRun) {
|
|
@@ -1091,7 +1049,7 @@ async function executeReindex(deps, scope, path, dryRun = false) {
|
|
|
1091
1049
|
total: pathFiles.length,
|
|
1092
1050
|
toProcess: pathFiles.length,
|
|
1093
1051
|
toDelete: 0,
|
|
1094
|
-
byRoot: groupByRoot(pathFiles, config.watch.paths),
|
|
1052
|
+
byRoot: groupByRoot(pathFiles, extractWatchPathStrings(config.watch.paths)),
|
|
1095
1053
|
};
|
|
1096
1054
|
}
|
|
1097
1055
|
return { filesProcessed: 0, durationMs: 0, errors: 0, plan };
|
|
@@ -1118,7 +1076,7 @@ async function executeReindex(deps, scope, path, dryRun = false) {
|
|
|
1118
1076
|
});
|
|
1119
1077
|
}
|
|
1120
1078
|
else if (scope === 'rules') {
|
|
1121
|
-
filesProcessed = await processAllFiles(config.watch.paths, config.watch.ignored, processor, 'processRulesUpdate', concurrency, {
|
|
1079
|
+
filesProcessed = await processAllFiles(extractWatchPathStrings(config.watch.paths), config.watch.ignored, processor, 'processRulesUpdate', concurrency, {
|
|
1122
1080
|
onTotal: (total) => reindexTracker?.setTotal(total),
|
|
1123
1081
|
onFileProcessed: () => reindexTracker?.incrementProcessed(),
|
|
1124
1082
|
}, isGitignored, fileList);
|
|
@@ -1129,7 +1087,7 @@ async function executeReindex(deps, scope, path, dryRun = false) {
|
|
|
1129
1087
|
total: uniqueFiles.length,
|
|
1130
1088
|
toProcess: uniqueFiles.length,
|
|
1131
1089
|
toDelete: 0,
|
|
1132
|
-
byRoot: groupByRoot(uniqueFiles, config.watch.paths),
|
|
1090
|
+
byRoot: groupByRoot(uniqueFiles, extractWatchPathStrings(config.watch.paths)),
|
|
1133
1091
|
};
|
|
1134
1092
|
reindexTracker?.setTotal(uniqueFiles.length);
|
|
1135
1093
|
await parallel(concurrency, uniqueFiles, async (filePath) => {
|
|
@@ -1140,7 +1098,7 @@ async function executeReindex(deps, scope, path, dryRun = false) {
|
|
|
1140
1098
|
}
|
|
1141
1099
|
else {
|
|
1142
1100
|
// Full reindex
|
|
1143
|
-
filesProcessed = await processAllFiles(config.watch.paths, config.watch.ignored, processor, 'processFile', concurrency, {
|
|
1101
|
+
filesProcessed = await processAllFiles(extractWatchPathStrings(config.watch.paths), config.watch.ignored, processor, 'processFile', concurrency, {
|
|
1144
1102
|
onTotal: (total) => reindexTracker?.setTotal(total),
|
|
1145
1103
|
onFileProcessed: () => reindexTracker?.incrementProcessed(),
|
|
1146
1104
|
}, isGitignored, fileList);
|
|
@@ -1188,7 +1146,7 @@ async function collectPathFiles(pathArray, config, gitignoreFilter) {
|
|
|
1188
1146
|
* Get the file list for a path-scoped reindex (for plan computation).
|
|
1189
1147
|
*/
|
|
1190
1148
|
async function getPathFileList(targetPath, config, gitignoreFilter) {
|
|
1191
|
-
const watched = isPathWatched(targetPath, config.watch.paths, config.watch.ignored);
|
|
1149
|
+
const watched = isPathWatched(targetPath, extractWatchPathStrings(config.watch.paths), config.watch.ignored);
|
|
1192
1150
|
if (!watched) {
|
|
1193
1151
|
throw new Error(`Path is outside watch scope: ${targetPath}`);
|
|
1194
1152
|
}
|
|
@@ -1200,7 +1158,7 @@ async function getPathFileList(targetPath, config, gitignoreFilter) {
|
|
|
1200
1158
|
return [targetPath];
|
|
1201
1159
|
if (stats.isDirectory()) {
|
|
1202
1160
|
const isGitignored = createIsGitignored(gitignoreFilter);
|
|
1203
|
-
const allWatchedFiles = await listFilesFromGlobs(config.watch.paths, config.watch.ignored, isGitignored);
|
|
1161
|
+
const allWatchedFiles = await listFilesFromGlobs(extractWatchPathStrings(config.watch.paths), config.watch.ignored, isGitignored);
|
|
1204
1162
|
const targetAbsPath = resolve(targetPath);
|
|
1205
1163
|
return allWatchedFiles.filter((f) => resolve(f).startsWith(targetAbsPath));
|
|
1206
1164
|
}
|
|
@@ -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
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { JeevesComponentDescriptor } from '@karmaniverous/jeeves';
|
|
2
2
|
import { FastifyInstance } from 'fastify';
|
|
3
3
|
import pino from 'pino';
|
|
4
|
-
import { EmbeddingConfig, InferenceRule, SchemaEntry, VectorStoreConfig,
|
|
4
|
+
import { EmbeddingConfig, InferenceRule, SchemaEntry, VectorStoreConfig, VcsConfig, JeevesWatcherConfig, WatchConfig, LoggingConfig, VcsRetentionConfig } from '@karmaniverous/jeeves-watcher-core';
|
|
5
5
|
export { ApiConfig, ConfigWatchConfig, EmbeddingConfig, InferenceRule, JeevesWatcherConfig, JeevesWatcherConfigInput, LoggingConfig, VectorStoreConfig, WatchConfig, apiConfigSchema, configWatchConfigSchema, embeddingConfigSchema, inferenceRuleSchema, jeevesWatcherConfigSchema, loggingConfigSchema, vectorStoreConfigSchema, watchConfigSchema } from '@karmaniverous/jeeves-watcher-core';
|
|
6
6
|
import { z } from 'zod';
|
|
7
7
|
import Handlebars from 'handlebars';
|
|
@@ -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
|
*
|
|
@@ -1225,6 +1227,192 @@ declare class EventQueue {
|
|
|
1225
1227
|
private maybeResolveIdleWorkers;
|
|
1226
1228
|
}
|
|
1227
1229
|
|
|
1230
|
+
/**
|
|
1231
|
+
* @module vcs/CommitMessageGenerator
|
|
1232
|
+
* Generates AI-powered commit messages via the Anthropic Messages API.
|
|
1233
|
+
*/
|
|
1234
|
+
|
|
1235
|
+
/**
|
|
1236
|
+
* Generates AI commit messages using the Anthropic Messages API.
|
|
1237
|
+
*/
|
|
1238
|
+
declare class CommitMessageGenerator {
|
|
1239
|
+
private readonly provider;
|
|
1240
|
+
private readonly model;
|
|
1241
|
+
private readonly apiKey;
|
|
1242
|
+
private readonly logger;
|
|
1243
|
+
constructor(provider: string, model: string, apiKey: string | undefined, logger: pino.Logger);
|
|
1244
|
+
/**
|
|
1245
|
+
* Generate a commit message from file changes.
|
|
1246
|
+
*
|
|
1247
|
+
* @param files - List of changed file paths.
|
|
1248
|
+
* @param diffSummary - Combined diff output (stat + patch).
|
|
1249
|
+
* @returns A one-line commit message, or null on failure.
|
|
1250
|
+
*/
|
|
1251
|
+
generate(files: string[], diffSummary: string): Promise<string | null>;
|
|
1252
|
+
}
|
|
1253
|
+
|
|
1254
|
+
/**
|
|
1255
|
+
* @module vcs/VcsManager
|
|
1256
|
+
* Per-root VCS manager for git-backed content versioning.
|
|
1257
|
+
*/
|
|
1258
|
+
|
|
1259
|
+
/** Metadata for a pending reversion to include in the commit message. */
|
|
1260
|
+
interface PendingReversion {
|
|
1261
|
+
glob: string;
|
|
1262
|
+
commit: string;
|
|
1263
|
+
paths: string[];
|
|
1264
|
+
}
|
|
1265
|
+
/** Push error record for status reporting. */
|
|
1266
|
+
interface PushError {
|
|
1267
|
+
timestamp: string;
|
|
1268
|
+
message: string;
|
|
1269
|
+
}
|
|
1270
|
+
/**
|
|
1271
|
+
* Per-root VCS manager for git-backed content versioning.
|
|
1272
|
+
*
|
|
1273
|
+
* Each VCS-enabled watch root gets its own VcsManager instance, which owns
|
|
1274
|
+
* a debounced commit pipeline: file changes are batched, staged, committed
|
|
1275
|
+
* (with optional AI-generated messages), and optionally pushed to a remote.
|
|
1276
|
+
*
|
|
1277
|
+
* Concurrency: only one commit is in-flight at a time per root. Index.lock
|
|
1278
|
+
* contention is handled with exponential backoff retries (D10).
|
|
1279
|
+
*/
|
|
1280
|
+
declare class VcsManager {
|
|
1281
|
+
readonly config: VcsConfig;
|
|
1282
|
+
readonly rootPath: string;
|
|
1283
|
+
readonly remoteUrl: string | undefined;
|
|
1284
|
+
private readonly accessToken;
|
|
1285
|
+
private readonly logger;
|
|
1286
|
+
private readonly commitMessageGenerator;
|
|
1287
|
+
private readonly pending;
|
|
1288
|
+
private readonly pendingReversions;
|
|
1289
|
+
private readonly _pushErrors;
|
|
1290
|
+
private readonly squashManager;
|
|
1291
|
+
private debounceTimer;
|
|
1292
|
+
private commitInFlight;
|
|
1293
|
+
private started;
|
|
1294
|
+
private _lastPushTime;
|
|
1295
|
+
constructor(rootPath: string, config: VcsConfig, logger: pino.Logger, commitMessageGenerator?: CommitMessageGenerator, remoteUrl?: string, accessToken?: string);
|
|
1296
|
+
get lastPushTime(): string | null;
|
|
1297
|
+
get pushErrors(): readonly PushError[];
|
|
1298
|
+
/**
|
|
1299
|
+
* Begin accepting file changes. Sets up the debounce mechanism.
|
|
1300
|
+
*/
|
|
1301
|
+
start(): void;
|
|
1302
|
+
/**
|
|
1303
|
+
* Add a file to the pending set and reset the debounce timer.
|
|
1304
|
+
* If the pending set exceeds maxBatchSize, flush immediately.
|
|
1305
|
+
*
|
|
1306
|
+
* @param filePath - Absolute path of the changed file.
|
|
1307
|
+
*/
|
|
1308
|
+
fileChanged(filePath: string): void;
|
|
1309
|
+
/**
|
|
1310
|
+
* Record reversion metadata so the next commit uses a revert-prefixed message.
|
|
1311
|
+
*
|
|
1312
|
+
* @param reversion - The reversion metadata to record.
|
|
1313
|
+
*/
|
|
1314
|
+
addPendingReversion(reversion: PendingReversion): void;
|
|
1315
|
+
/**
|
|
1316
|
+
* Stage a file deletion and add to pending set.
|
|
1317
|
+
* git add handles deleted files when the file is gone from disk.
|
|
1318
|
+
*
|
|
1319
|
+
* @param filePath - Absolute path of the deleted file.
|
|
1320
|
+
*/
|
|
1321
|
+
handleUnlink(filePath: string): void;
|
|
1322
|
+
/**
|
|
1323
|
+
* Flush all pending files immediately.
|
|
1324
|
+
*/
|
|
1325
|
+
flush(): Promise<void>;
|
|
1326
|
+
/**
|
|
1327
|
+
* Stop accepting file changes, flush pending, and clean up timers.
|
|
1328
|
+
*/
|
|
1329
|
+
stop(): Promise<void>;
|
|
1330
|
+
/**
|
|
1331
|
+
* Take up to N items from the pending set.
|
|
1332
|
+
*/
|
|
1333
|
+
private takeBatch;
|
|
1334
|
+
/**
|
|
1335
|
+
* Clear the debounce timer.
|
|
1336
|
+
*/
|
|
1337
|
+
private clearDebounce;
|
|
1338
|
+
/**
|
|
1339
|
+
* Reset the debounce timer to fire flush() after commitDebounceMs.
|
|
1340
|
+
*/
|
|
1341
|
+
private resetDebounce;
|
|
1342
|
+
/**
|
|
1343
|
+
* Get the cached diff for staged files, for AI context.
|
|
1344
|
+
*/
|
|
1345
|
+
private getStagedDiff;
|
|
1346
|
+
/**
|
|
1347
|
+
* Build the template commit message (no AI).
|
|
1348
|
+
*/
|
|
1349
|
+
private buildTemplateMessage;
|
|
1350
|
+
/**
|
|
1351
|
+
* Build the commit message, using AI when available with template fallback.
|
|
1352
|
+
*/
|
|
1353
|
+
private buildCommitMessage;
|
|
1354
|
+
/**
|
|
1355
|
+
* Commit a batch of files to the git repo with index.lock retry.
|
|
1356
|
+
*/
|
|
1357
|
+
private commitBatch;
|
|
1358
|
+
/**
|
|
1359
|
+
* Push to the configured remote if remoteUrl is set.
|
|
1360
|
+
* On failure: logs the error and records it in pushErrors; never throws.
|
|
1361
|
+
*/
|
|
1362
|
+
private pushIfConfigured;
|
|
1363
|
+
}
|
|
1364
|
+
|
|
1365
|
+
/**
|
|
1366
|
+
* @module vcs/VcsCoordinator
|
|
1367
|
+
* Orchestrates VCS across all watch roots. Routes file events to the correct
|
|
1368
|
+
* root's VcsManager instance.
|
|
1369
|
+
*/
|
|
1370
|
+
|
|
1371
|
+
/**
|
|
1372
|
+
* Orchestrates VCS across all VCS-enabled watch roots.
|
|
1373
|
+
*/
|
|
1374
|
+
declare class VcsCoordinator {
|
|
1375
|
+
private readonly managers;
|
|
1376
|
+
private readonly roots;
|
|
1377
|
+
private readonly logger;
|
|
1378
|
+
constructor(config: JeevesWatcherConfig, logger: pino.Logger);
|
|
1379
|
+
/**
|
|
1380
|
+
* Start all VcsManager instances.
|
|
1381
|
+
*/
|
|
1382
|
+
start(): void;
|
|
1383
|
+
/**
|
|
1384
|
+
* Route a file event to the correct root's VcsManager.
|
|
1385
|
+
*
|
|
1386
|
+
* @param filePath - Absolute path of the changed file.
|
|
1387
|
+
* @param event - The event type: add, change, or unlink.
|
|
1388
|
+
*/
|
|
1389
|
+
onFileChange(filePath: string, event: 'add' | 'change' | 'unlink'): void;
|
|
1390
|
+
/**
|
|
1391
|
+
* Flush all managers and clean up.
|
|
1392
|
+
*/
|
|
1393
|
+
stop(): Promise<void>;
|
|
1394
|
+
/**
|
|
1395
|
+
* Get the sorted root paths (longest-first).
|
|
1396
|
+
*/
|
|
1397
|
+
getRoots(): readonly string[];
|
|
1398
|
+
/**
|
|
1399
|
+
* Get the VcsManager for a specific root path.
|
|
1400
|
+
*/
|
|
1401
|
+
getManager(root: string): VcsManager | undefined;
|
|
1402
|
+
/**
|
|
1403
|
+
* Get all managers as [root, manager] pairs.
|
|
1404
|
+
*/
|
|
1405
|
+
getAllManagers(): ReadonlyMap<string, VcsManager>;
|
|
1406
|
+
/**
|
|
1407
|
+
* Find the VcsManager that owns the given normalized file path.
|
|
1408
|
+
* Uses longest-prefix-match against resolved watch roots.
|
|
1409
|
+
*
|
|
1410
|
+
* @param normalizedPath - Normalized absolute path (forward slashes).
|
|
1411
|
+
* @returns The matching VcsManager, or undefined.
|
|
1412
|
+
*/
|
|
1413
|
+
findManagerForPath(normalizedPath: string): VcsManager | undefined;
|
|
1414
|
+
}
|
|
1415
|
+
|
|
1228
1416
|
/**
|
|
1229
1417
|
* @module api/InitialScanTracker
|
|
1230
1418
|
* Tracks initial filesystem scan state for status reporting.
|
|
@@ -1342,6 +1530,8 @@ interface FileSystemWatcherOptions {
|
|
|
1342
1530
|
initialScanTracker?: InitialScanTracker;
|
|
1343
1531
|
/** Optional content hash cache for move detection. */
|
|
1344
1532
|
contentHashCache?: ContentHashCache;
|
|
1533
|
+
/** Optional callback for VCS file change notifications. */
|
|
1534
|
+
onVcsFileChange?: (filePath: string, event: 'add' | 'change' | 'unlink') => void;
|
|
1345
1535
|
}
|
|
1346
1536
|
/**
|
|
1347
1537
|
* Filesystem watcher that maps chokidar events to the processing queue.
|
|
@@ -1355,6 +1545,7 @@ declare class FileSystemWatcher {
|
|
|
1355
1545
|
private readonly gitignoreFilter?;
|
|
1356
1546
|
private readonly initialScanTracker?;
|
|
1357
1547
|
private readonly contentHashCache?;
|
|
1548
|
+
private readonly onVcsFileChange?;
|
|
1358
1549
|
private moveCorrelator?;
|
|
1359
1550
|
private globMatches;
|
|
1360
1551
|
private watcher;
|
|
@@ -1494,6 +1685,8 @@ interface ApiServerOptions {
|
|
|
1494
1685
|
getFileSystemWatcher?: () => FileSystemWatcher | undefined;
|
|
1495
1686
|
/** Optional enrichment store for persisted enrichment metadata. */
|
|
1496
1687
|
enrichmentStore?: EnrichmentStoreInterface;
|
|
1688
|
+
/** VCS coordinator for git-backed versioning API routes. */
|
|
1689
|
+
vcsCoordinator?: VcsCoordinator;
|
|
1497
1690
|
}
|
|
1498
1691
|
/**
|
|
1499
1692
|
* Create the Fastify API server with all routes registered.
|
|
@@ -1599,6 +1792,7 @@ declare class JeevesWatcher {
|
|
|
1599
1792
|
private gitignoreFilter;
|
|
1600
1793
|
private enrichmentStore;
|
|
1601
1794
|
private contentHashCache;
|
|
1795
|
+
private vcsCoordinator;
|
|
1602
1796
|
private readonly initialScanTracker;
|
|
1603
1797
|
private readonly version;
|
|
1604
1798
|
/** Create a new JeevesWatcher instance. */
|
|
@@ -1683,5 +1877,91 @@ declare function contentHash(text: string): string;
|
|
|
1683
1877
|
*/
|
|
1684
1878
|
declare function pointId(filePath: string, chunkIndex?: number): string;
|
|
1685
1879
|
|
|
1686
|
-
|
|
1687
|
-
|
|
1880
|
+
/**
|
|
1881
|
+
* @module vcs/resolveWatchRoot
|
|
1882
|
+
* Resolves which VCS-enabled watch root(s) own a given absolute path or glob.
|
|
1883
|
+
*/
|
|
1884
|
+
|
|
1885
|
+
/** Result of resolving a path to its watch root. */
|
|
1886
|
+
interface ResolvedWatchRoot {
|
|
1887
|
+
/** Absolute root path (normalized forward slashes). */
|
|
1888
|
+
root: string;
|
|
1889
|
+
/** Path relative to the root. */
|
|
1890
|
+
relativePath: string;
|
|
1891
|
+
}
|
|
1892
|
+
|
|
1893
|
+
/**
|
|
1894
|
+
* @module vcs/SquashManager
|
|
1895
|
+
* Handles scheduled squash retention for git-backed VCS roots.
|
|
1896
|
+
*/
|
|
1897
|
+
|
|
1898
|
+
/** Result of a squash operation. */
|
|
1899
|
+
interface SquashResult {
|
|
1900
|
+
squashed: boolean;
|
|
1901
|
+
commitsRemoved?: number;
|
|
1902
|
+
commitsRetained?: number;
|
|
1903
|
+
error?: string;
|
|
1904
|
+
}
|
|
1905
|
+
/** Commit metadata for retention calculation. */
|
|
1906
|
+
interface CommitInfo {
|
|
1907
|
+
hash: string;
|
|
1908
|
+
date: Date;
|
|
1909
|
+
}
|
|
1910
|
+
/**
|
|
1911
|
+
* Manages scheduled squash retention for a single VCS root.
|
|
1912
|
+
*
|
|
1913
|
+
* Runs on a cron schedule (checked every 60s). When triggered, squashes
|
|
1914
|
+
* commits older than the retention boundary (the tighter of maxAgeDays
|
|
1915
|
+
* and maxVersions) into a single "historical baseline" orphan commit,
|
|
1916
|
+
* then cherry-picks retained commits on top. Force-pushes to remote
|
|
1917
|
+
* if configured (D13).
|
|
1918
|
+
*/
|
|
1919
|
+
declare class SquashManager {
|
|
1920
|
+
private readonly rootPath;
|
|
1921
|
+
private readonly retention;
|
|
1922
|
+
private readonly remoteUrl;
|
|
1923
|
+
private readonly accessToken;
|
|
1924
|
+
private readonly logger;
|
|
1925
|
+
private intervalTimer;
|
|
1926
|
+
private running;
|
|
1927
|
+
constructor(rootPath: string, retention: VcsRetentionConfig, logger: pino.Logger, remoteUrl?: string, accessToken?: string);
|
|
1928
|
+
/**
|
|
1929
|
+
* Start the cron-based squash scheduler.
|
|
1930
|
+
* Checks every 60 seconds if the cron expression matches.
|
|
1931
|
+
*/
|
|
1932
|
+
start(): void;
|
|
1933
|
+
/**
|
|
1934
|
+
* Stop the cron scheduler.
|
|
1935
|
+
*/
|
|
1936
|
+
stop(): void;
|
|
1937
|
+
/**
|
|
1938
|
+
* Run the squash operation. Exposed publicly for testing.
|
|
1939
|
+
*/
|
|
1940
|
+
runSquash(): Promise<SquashResult>;
|
|
1941
|
+
/**
|
|
1942
|
+
* Get all commits in chronological order (oldest first).
|
|
1943
|
+
*/
|
|
1944
|
+
getCommitLog(): Promise<CommitInfo[]>;
|
|
1945
|
+
/**
|
|
1946
|
+
* Calculate the retention boundary index.
|
|
1947
|
+
* Returns the index of the oldest commit to KEEP.
|
|
1948
|
+
* All commits before this index will be squashed into a baseline.
|
|
1949
|
+
*
|
|
1950
|
+
* Strategy: find the tighter constraint between age and count.
|
|
1951
|
+
* - Age: keep commits newer than maxAgeDays
|
|
1952
|
+
* - Count: keep the last maxVersions commits
|
|
1953
|
+
* The boundary is the one that retains FEWER old commits (tighter).
|
|
1954
|
+
*/
|
|
1955
|
+
calculateRetentionBoundary(commits: CommitInfo[]): number;
|
|
1956
|
+
/**
|
|
1957
|
+
* Perform the squash: create orphan with baseline + cherry-pick retained commits.
|
|
1958
|
+
*/
|
|
1959
|
+
private performSquash;
|
|
1960
|
+
/**
|
|
1961
|
+
* Force push to remote after squash (history rewrite requires force).
|
|
1962
|
+
*/
|
|
1963
|
+
private forcePushIfConfigured;
|
|
1964
|
+
}
|
|
1965
|
+
|
|
1966
|
+
export { CommitMessageGenerator, ContentHashCache, DocumentProcessor, EnrichmentStore, EventQueue, FileSystemWatcher, GitignoreFilter, InitialScanTracker, IssuesManager, JeevesWatcher, ReindexTracker, SquashManager, SystemHealth, TemplateEngine, ValuesManager, VcsCoordinator, VcsManager, VectorStoreClient, VirtualRuleStore, applyRules, buildAttributes, buildTemplateEngine, compileRules, contentHash, createApiServer, createEmbeddingProvider, createHandlebarsInstance, createLogger, extractText, issueRecordSchema, loadConfig, loadCustomHelpers, mergeEnrichment, pointId, registerBuiltinHelpers, resolveTemplateSource, startFromConfig, watcherDescriptor };
|
|
1967
|
+
export type { AllHelpersIntrospection, ApiServerOptions, ApplyRulesOptions, ApplyRulesResult, CollectionInfo, CommitInfo, CompiledRule, CompiledTemplate, DocumentProcessorDeps, DocumentProcessorInterface, EmbeddingProvider, EnrichmentStoreInterface, EventQueueOptions, ExtractedText, Extractor, FileAttributes, FileSystemWatcherOptions, HelperModuleIntrospection, InitialScanStatus, IssueRecord, IssuesFile, JeevesWatcherFactories, JeevesWatcherRuntimeOptions, PayloadFieldSchema, PendingReversion, ProcessFn, ProcessorConfig, ProviderFactory, PushError, ReindexStatus, RenderResult, ResolvedWatchRoot, RuleLogger, ScrollPageResult, ScrolledPoint, SearchResult, SquashResult, SystemHealthOptions, ValuesIndex, VectorPoint, VectorStore, WatchEvent };
|