@karmaniverous/jeeves-watcher 0.18.9 → 0.18.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.
- package/README.md +4 -2
- package/config.schema.json +203 -180
- package/dist/cli/jeeves-watcher/{index-xP2XrV4W.js → index-ZbXuE9a7.js} +335 -182
- package/dist/cli/jeeves-watcher/index.js +48 -3
- package/dist/index.d.ts +56 -13
- package/dist/index.js +291 -93
- package/package.json +2 -2
|
@@ -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-
|
|
229
|
+
const { JeevesWatcher } = await import('./index-ZbXuE9a7.js');
|
|
230
230
|
const app = new JeevesWatcher(config, resolvedPath, descriptor);
|
|
231
231
|
installShutdownHandlers(() => app.stop());
|
|
232
232
|
await app.start();
|
|
@@ -621,6 +621,39 @@ async function retry(fn, options) {
|
|
|
621
621
|
*/
|
|
622
622
|
/** Promisified execFile for git commands. */
|
|
623
623
|
const execFileAsync = promisify(execFile);
|
|
624
|
+
/** Standard timeout (ms) for most git operations. */
|
|
625
|
+
const GIT_TIMEOUT_STANDARD = 30_000;
|
|
626
|
+
/** Extended timeout (ms) for cherry-pick operations. */
|
|
627
|
+
const GIT_TIMEOUT_CHERRY_PICK = 120_000;
|
|
628
|
+
/** Timeout (ms) for push operations. */
|
|
629
|
+
const GIT_TIMEOUT_PUSH = 60_000;
|
|
630
|
+
/**
|
|
631
|
+
* Extract string fields from a child-process error.
|
|
632
|
+
* Node's execFile wraps failures in an Error with `stderr`, `stdout`, and
|
|
633
|
+
* `code` properties that aren't part of the Error type.
|
|
634
|
+
*/
|
|
635
|
+
function getExecErrorFields(error) {
|
|
636
|
+
if (!(error instanceof Error)) {
|
|
637
|
+
return { message: String(error), stderr: '', stdout: '' };
|
|
638
|
+
}
|
|
639
|
+
const rec = error;
|
|
640
|
+
const stderr = typeof rec['stderr'] === 'string' ? rec['stderr'] : '';
|
|
641
|
+
const stdout = typeof rec['stdout'] === 'string' ? rec['stdout'] : '';
|
|
642
|
+
return { message: error.message || '', stderr, stdout };
|
|
643
|
+
}
|
|
644
|
+
/**
|
|
645
|
+
* Build an authenticated push URL by injecting a token into an HTTPS remote.
|
|
646
|
+
* Non-HTTPS URLs are returned as-is.
|
|
647
|
+
*
|
|
648
|
+
* @param remoteUrl - The remote repository URL.
|
|
649
|
+
* @param accessToken - Optional access token to inject.
|
|
650
|
+
* @returns The URL with the token injected if applicable.
|
|
651
|
+
*/
|
|
652
|
+
function buildAuthenticatedPushUrl(remoteUrl, accessToken) {
|
|
653
|
+
if (!accessToken)
|
|
654
|
+
return remoteUrl;
|
|
655
|
+
return remoteUrl.replace(/^https:\/\//, `https://${encodeURIComponent(accessToken)}@`);
|
|
656
|
+
}
|
|
624
657
|
/**
|
|
625
658
|
* Stage files via stdin to avoid ENAMETOOLONG on Windows.
|
|
626
659
|
*
|
|
@@ -632,22 +665,34 @@ const execFileAsync = promisify(execFile);
|
|
|
632
665
|
*
|
|
633
666
|
* @param files - Absolute paths of files to stage.
|
|
634
667
|
* @param cwd - Repository root (working directory for git).
|
|
668
|
+
* @param timeoutMs - Kill the child process after this many milliseconds. Default: 30000.
|
|
635
669
|
*/
|
|
636
|
-
function gitAddViaStdin(files, cwd) {
|
|
670
|
+
function gitAddViaStdin(files, cwd, timeoutMs = 30_000) {
|
|
637
671
|
return new Promise((resolve, reject) => {
|
|
672
|
+
let timedOut = false;
|
|
638
673
|
const child = execFile('git', ['add', '--pathspec-from-file=-', '--pathspec-file-nul'], { cwd }, (error) => {
|
|
674
|
+
clearTimeout(timer);
|
|
675
|
+
if (timedOut)
|
|
676
|
+
return;
|
|
639
677
|
if (error)
|
|
640
678
|
reject(error);
|
|
641
679
|
else
|
|
642
680
|
resolve();
|
|
643
681
|
});
|
|
682
|
+
const timer = setTimeout(() => {
|
|
683
|
+
timedOut = true;
|
|
684
|
+
child.kill();
|
|
685
|
+
reject(new Error(`git add timed out after ${String(timeoutMs)}ms`));
|
|
686
|
+
}, timeoutMs);
|
|
644
687
|
if (!child.stdin) {
|
|
688
|
+
clearTimeout(timer);
|
|
645
689
|
reject(new Error('Failed to open stdin for git add'));
|
|
646
690
|
return;
|
|
647
691
|
}
|
|
648
692
|
// Suppress EPIPE — expected if git exits before we finish writing
|
|
649
693
|
child.stdin.on('error', (err) => {
|
|
650
694
|
if (err.code !== 'EPIPE') {
|
|
695
|
+
clearTimeout(timer);
|
|
651
696
|
reject(err);
|
|
652
697
|
}
|
|
653
698
|
});
|
|
@@ -1581,4 +1626,4 @@ const watcherDescriptor = {
|
|
|
1581
1626
|
const program = createServiceCli(watcherDescriptor);
|
|
1582
1627
|
program.parse();
|
|
1583
1628
|
|
|
1584
|
-
export { CONFIG_WATCH_VALID_SCOPES as C,
|
|
1629
|
+
export { CONFIG_WATCH_VALID_SCOPES as C, GIT_TIMEOUT_CHERRY_PICK as G, VALID_REINDEX_SCOPES as V, GIT_TIMEOUT_PUSH as a, GIT_TIMEOUT_STANDARD as b, GitignoreFilter as c, buildAuthenticatedPushUrl as d, execFileAsync as e, executeReindex as f, findRootForPath as g, getExecErrorFields as h, getWatchRootBases as i, gitAddViaStdin as j, isPathWatched as k, loadConfig as l, mergeInferenceRules as m, normalizeError as n, normalizePathCase as o, normalizeSlashes as p, startFromConfig as q, retry as r, sleep as s };
|
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
|
|
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,10 +1293,11 @@ declare class VcsManager {
|
|
|
1293
1293
|
private readonly pendingReversions;
|
|
1294
1294
|
private readonly _pushErrors;
|
|
1295
1295
|
private readonly squashManager;
|
|
1296
|
-
private
|
|
1296
|
+
private throttleTimer;
|
|
1297
1297
|
private commitInFlight;
|
|
1298
1298
|
private consecutiveCommitFailures;
|
|
1299
1299
|
private started;
|
|
1300
|
+
private paused;
|
|
1300
1301
|
private isBaseline;
|
|
1301
1302
|
private _lastPushTime;
|
|
1302
1303
|
constructor(rootPath: string, config: VcsConfig, logger: pino.Logger, commitMessageGenerator?: CommitMessageGenerator, remoteUrl?: string, accessToken?: string);
|
|
@@ -1306,17 +1307,20 @@ declare class VcsManager {
|
|
|
1306
1307
|
* Begin accepting file changes. Sets the manager to started state and
|
|
1307
1308
|
* starts the squash manager if configured.
|
|
1308
1309
|
*
|
|
1310
|
+
* Performs startup orphan detection/recovery before starting the squash
|
|
1311
|
+
* manager, ensuring the repo is on the configured branch.
|
|
1312
|
+
*
|
|
1309
1313
|
* Baseline mode (commit prefix `"baseline:"`) remains active until
|
|
1310
1314
|
* {@link endBaseline} is called by the coordinator after the initial scan.
|
|
1311
1315
|
*/
|
|
1312
|
-
start(): void
|
|
1316
|
+
start(): Promise<void>;
|
|
1313
1317
|
/**
|
|
1314
1318
|
* Signal that the initial filesystem scan is complete.
|
|
1315
1319
|
* Clears the baseline flag so subsequent commits use normal "watcher: batch" messages.
|
|
1316
1320
|
*/
|
|
1317
1321
|
endBaseline(): void;
|
|
1318
1322
|
/**
|
|
1319
|
-
* Add a file to the pending set and
|
|
1323
|
+
* Add a file to the pending set and start the throttle timer.
|
|
1320
1324
|
* If the pending set exceeds maxBatchSize, flush immediately.
|
|
1321
1325
|
*
|
|
1322
1326
|
* @param filePath - Absolute path of the changed file.
|
|
@@ -1335,6 +1339,18 @@ declare class VcsManager {
|
|
|
1335
1339
|
* @param filePath - Absolute path of the deleted file.
|
|
1336
1340
|
*/
|
|
1337
1341
|
handleUnlink(filePath: string): void;
|
|
1342
|
+
/**
|
|
1343
|
+
* Pause the commit pipeline. Drains pending commits via flush(), then
|
|
1344
|
+
* sets a flag that makes commitBatch queue instead of execute.
|
|
1345
|
+
* Used by SquashManager to coordinate squash operations.
|
|
1346
|
+
*/
|
|
1347
|
+
pause(): Promise<void>;
|
|
1348
|
+
/**
|
|
1349
|
+
* Resume the commit pipeline after a pause.
|
|
1350
|
+
* Re-enables normal commit operations and starts a throttle timer
|
|
1351
|
+
* if there are pending files that accumulated during the pause.
|
|
1352
|
+
*/
|
|
1353
|
+
resume(): void;
|
|
1338
1354
|
/**
|
|
1339
1355
|
* Flush all pending files immediately.
|
|
1340
1356
|
*/
|
|
@@ -1348,20 +1364,26 @@ declare class VcsManager {
|
|
|
1348
1364
|
*/
|
|
1349
1365
|
private takeBatch;
|
|
1350
1366
|
/**
|
|
1351
|
-
* Clear the
|
|
1367
|
+
* Clear the throttle timer.
|
|
1352
1368
|
*/
|
|
1353
|
-
private
|
|
1369
|
+
private clearThrottle;
|
|
1354
1370
|
/**
|
|
1355
|
-
*
|
|
1371
|
+
* Start the throttle timer to fire flush() after commitThrottleMs.
|
|
1372
|
+
* If a timer is already running, do not reset it — this is throttle, not debounce.
|
|
1356
1373
|
*/
|
|
1357
|
-
private
|
|
1374
|
+
private resetThrottle;
|
|
1358
1375
|
/**
|
|
1359
1376
|
* Check for and remove stale index.lock files before retrying.
|
|
1360
1377
|
*/
|
|
1361
1378
|
private removeStaleLock;
|
|
1379
|
+
/**
|
|
1380
|
+
* Check whether a git error represents a "nothing to commit" state.
|
|
1381
|
+
* Git outputs this message to stdout (not stderr) on exit code 1.
|
|
1382
|
+
*/
|
|
1383
|
+
private isNothingToCommitError;
|
|
1362
1384
|
/**
|
|
1363
1385
|
* Commit a batch of files to the git repo with index.lock retry,
|
|
1364
|
-
* stale lock detection, circuit breaker, and re-queue cap.
|
|
1386
|
+
* stale lock detection, circuit breaker, pause support, and re-queue cap.
|
|
1365
1387
|
*/
|
|
1366
1388
|
private commitBatch;
|
|
1367
1389
|
}
|
|
@@ -1382,8 +1404,9 @@ declare class VcsCoordinator {
|
|
|
1382
1404
|
constructor(config: JeevesWatcherConfig, logger: pino.Logger);
|
|
1383
1405
|
/**
|
|
1384
1406
|
* Start all VcsManager instances.
|
|
1407
|
+
* Runs startup orphan detection/recovery for each root.
|
|
1385
1408
|
*/
|
|
1386
|
-
start(): void
|
|
1409
|
+
start(): Promise<void>;
|
|
1387
1410
|
/**
|
|
1388
1411
|
* Route a file event to the correct root's VcsManager.
|
|
1389
1412
|
*
|
|
@@ -1394,8 +1417,8 @@ declare class VcsCoordinator {
|
|
|
1394
1417
|
/**
|
|
1395
1418
|
* Signal that the initial filesystem scan is complete.
|
|
1396
1419
|
*
|
|
1397
|
-
* Flushes each manager's
|
|
1398
|
-
* any files still pending in the VCS
|
|
1420
|
+
* Flushes each manager's throttle buffer before ending baseline mode, ensuring
|
|
1421
|
+
* any files still pending in the VCS throttle are committed with a
|
|
1399
1422
|
* `"baseline:"` prefix rather than `"watcher:"`. AI generation is not enabled
|
|
1400
1423
|
* until all managers have completed their flush.
|
|
1401
1424
|
*/
|
|
@@ -1938,15 +1961,31 @@ interface CommitInfo {
|
|
|
1938
1961
|
* then cherry-picks retained commits on top. Force-pushes to remote
|
|
1939
1962
|
* if configured (D13).
|
|
1940
1963
|
*/
|
|
1964
|
+
/** Options for SquashManager construction beyond the required params. */
|
|
1965
|
+
interface SquashManagerOptions {
|
|
1966
|
+
/** Git branch name for squash operations. Default: "master". */
|
|
1967
|
+
branch?: string;
|
|
1968
|
+
/** Called before squash to drain and pause the commit pipeline. */
|
|
1969
|
+
pauseCommits?: () => Promise<void>;
|
|
1970
|
+
/** Called after squash to resume the commit pipeline. */
|
|
1971
|
+
resumeCommits?: () => void;
|
|
1972
|
+
/** Remote URL for force-push after squash. */
|
|
1973
|
+
remoteUrl?: string;
|
|
1974
|
+
/** Access token for HTTPS push authentication. */
|
|
1975
|
+
accessToken?: string;
|
|
1976
|
+
}
|
|
1941
1977
|
declare class SquashManager {
|
|
1942
1978
|
private readonly rootPath;
|
|
1943
1979
|
private readonly retention;
|
|
1980
|
+
private readonly branch;
|
|
1981
|
+
private readonly pauseCommits;
|
|
1982
|
+
private readonly resumeCommits;
|
|
1944
1983
|
private readonly remoteUrl;
|
|
1945
1984
|
private readonly accessToken;
|
|
1946
1985
|
private readonly logger;
|
|
1947
1986
|
private intervalTimer;
|
|
1948
1987
|
private running;
|
|
1949
|
-
constructor(rootPath: string, retention: VcsRetentionConfig, logger: pino.Logger,
|
|
1988
|
+
constructor(rootPath: string, retention: VcsRetentionConfig, logger: pino.Logger, options?: SquashManagerOptions);
|
|
1950
1989
|
/**
|
|
1951
1990
|
* Start the cron-based squash scheduler.
|
|
1952
1991
|
* Checks every 60 seconds if the cron expression matches.
|
|
@@ -1958,6 +1997,9 @@ declare class SquashManager {
|
|
|
1958
1997
|
stop(): void;
|
|
1959
1998
|
/**
|
|
1960
1999
|
* Run the squash operation. Exposed publicly for testing.
|
|
2000
|
+
*
|
|
2001
|
+
* Coordinates with VcsManager by calling pause/resume callbacks
|
|
2002
|
+
* to drain and suspend the commit pipeline during the squash.
|
|
1961
2003
|
*/
|
|
1962
2004
|
runSquash(): Promise<SquashResult>;
|
|
1963
2005
|
/**
|
|
@@ -1977,6 +2019,7 @@ declare class SquashManager {
|
|
|
1977
2019
|
calculateRetentionBoundary(commits: CommitInfo[]): number;
|
|
1978
2020
|
/**
|
|
1979
2021
|
* Perform the squash: create orphan with baseline + cherry-pick retained commits.
|
|
2022
|
+
* Uses the configured branch name instead of dynamic detection (Bug 1).
|
|
1980
2023
|
*/
|
|
1981
2024
|
private performSquash;
|
|
1982
2025
|
/**
|