@karmaniverous/jeeves-watcher 0.19.1 → 0.21.0-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/LICENSE +28 -0
- package/README.md +37 -27
- package/config.schema.json +553 -199
- package/dist/cli/jeeves-watcher/index-CGVLEt3K.js +20913 -0
- package/dist/cli/jeeves-watcher/index.js +1193 -1169
- package/dist/index.d.ts +1624 -609
- package/dist/index.js +19662 -7549
- package/package.json +40 -28
- package/dist/cli/jeeves-watcher/index-C_bf9c9m.js +0 -8867
package/dist/index.d.ts
CHANGED
|
@@ -1,24 +1,59 @@
|
|
|
1
|
-
import { JeevesComponentDescriptor } from '@karmaniverous/jeeves';
|
|
2
1
|
import { FastifyInstance } from 'fastify';
|
|
2
|
+
import { JeevesComponentDescriptor } from '@karmaniverous/jeeves';
|
|
3
|
+
import { EmbeddingConfig, IssueRecord, InferenceRule, SchemaEntry, SourcesConfig, VectorStoreConfig, DocumentResult, DocumentRejectionError, DocumentFailure, VcsRetentionConfig, VcsConfig, JeevesWatcherConfig, VcsHealth, InitialScanStatus, RestartCause, ConfigWatchReindexScope, ChangeSourceHealth, WatchConfig, ReindexStatus, IndexCheckHealth, LoggingConfig } from '@karmaniverous/jeeves-watcher-core';
|
|
4
|
+
export { ApiConfig, ConfigWatchConfig, EmbeddingConfig, InferenceRule, InitialScanStatus, IssueRecord, JeevesWatcherConfig, JeevesWatcherConfigInput, LoggingConfig, ReindexStatus, VectorStoreConfig, WatchConfig, apiConfigSchema, configWatchConfigSchema, embeddingConfigSchema, inferenceRuleSchema, issueRecordSchema, jeevesWatcherConfigSchema, loggingConfigSchema, vectorStoreConfigSchema, watchConfigSchema } from '@karmaniverous/jeeves-watcher-core';
|
|
3
5
|
import pino from 'pino';
|
|
4
|
-
import {
|
|
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
|
-
import { z } from 'zod';
|
|
6
|
+
import { ErrorObject } from 'ajv';
|
|
7
7
|
import Handlebars from 'handlebars';
|
|
8
|
-
import {
|
|
8
|
+
import { z } from 'zod';
|
|
9
9
|
import { Stats } from 'node:fs';
|
|
10
|
+
import ParcelWatcher from '@parcel/watcher';
|
|
11
|
+
import { JsonMapMap } from '@karmaniverous/jsonmap';
|
|
10
12
|
|
|
11
13
|
/**
|
|
12
14
|
* @module embedding/types
|
|
13
15
|
* Embedding provider type definitions.
|
|
14
16
|
*/
|
|
15
17
|
|
|
18
|
+
/**
|
|
19
|
+
* Per-call budget for the shared rate limiter. Providers that do not
|
|
20
|
+
* rate-limit ignore the budget; providers that retry internally await
|
|
21
|
+
* `beforeRetry` before each retry.
|
|
22
|
+
*
|
|
23
|
+
* The budget bounds the limiter, not the provider's own network retries:
|
|
24
|
+
* each of the `attempts` provider calls may itself retry a transient
|
|
25
|
+
* (non-429) failure up to `NETWORK_RETRY_POLICY.attempts` times in all, with
|
|
26
|
+
* backoff sleeps, so one `embed()` can issue up to `attempts` x 5 HTTP
|
|
27
|
+
* requests.
|
|
28
|
+
*/
|
|
29
|
+
interface EmbedOptions {
|
|
30
|
+
/**
|
|
31
|
+
* Maximum provider calls for this call: a 429 ends a provider call and
|
|
32
|
+
* costs one attempt. Transient network retries inside a provider call do
|
|
33
|
+
* not count against it (see the interface note).
|
|
34
|
+
*/
|
|
35
|
+
attempts?: number;
|
|
36
|
+
/**
|
|
37
|
+
* Maximum total time to wait for the limiter (token or `Retry-After`
|
|
38
|
+
* pause), in ms. When a wait would exceed it, the call fails fast. The
|
|
39
|
+
* provider's own network-retry backoff sleeps are not counted.
|
|
40
|
+
*/
|
|
41
|
+
maxWaitMs?: number;
|
|
42
|
+
/**
|
|
43
|
+
* Awaited by a provider before each retry it makes internally (any HTTP
|
|
44
|
+
* request after the first of an `embed()` call), so every request draws
|
|
45
|
+
* from the shared limiter. Supplied by the rate-limited wrapper; it may
|
|
46
|
+
* reject (e.g. `EmbeddingUnavailableError`), which the provider must
|
|
47
|
+
* propagate without retrying.
|
|
48
|
+
*/
|
|
49
|
+
beforeRetry?: () => Promise<void>;
|
|
50
|
+
}
|
|
16
51
|
/**
|
|
17
52
|
* An embedding provider that converts text into vector representations.
|
|
18
53
|
*/
|
|
19
54
|
interface EmbeddingProvider {
|
|
20
|
-
/** Generate embedding vectors for the given texts. */
|
|
21
|
-
embed(texts: string[]): Promise<number[][]>;
|
|
55
|
+
/** Generate embedding vectors for the given texts (one provider request). */
|
|
56
|
+
embed(texts: string[], options?: EmbedOptions): Promise<number[][]>;
|
|
22
57
|
/** The dimensionality of the embedding vectors. */
|
|
23
58
|
dimensions: number;
|
|
24
59
|
}
|
|
@@ -46,9 +81,41 @@ type ProviderFactory = (config: EmbeddingConfig, logger?: pino.Logger) => Embedd
|
|
|
46
81
|
*/
|
|
47
82
|
declare function createEmbeddingProvider(config: EmbeddingConfig, logger?: pino.Logger, additionalProviders?: Map<string, ProviderFactory>): EmbeddingProvider;
|
|
48
83
|
|
|
84
|
+
/**
|
|
85
|
+
* @module embedding/EmbeddingHealth
|
|
86
|
+
* Embedding health (D86, D88, D89): wraps the shared rate-limited provider and tracks ok/failing (3+ failures since the last success and 60 s without one), with transition logs and alerts. Health shows codes, never provider text.
|
|
87
|
+
*
|
|
88
|
+
* A rate-limit wait that later succeeds is not a failure; any error a call
|
|
89
|
+
* throws (including a fail-fast `EmbeddingUnavailableError`) is. The first
|
|
90
|
+
* success returns the state to `ok`.
|
|
91
|
+
*/
|
|
92
|
+
|
|
93
|
+
/** Embedding health state. */
|
|
94
|
+
type EmbeddingHealthState = 'ok' | 'failing';
|
|
95
|
+
/** The most recent embedding error: when, and a machine-readable code. */
|
|
96
|
+
interface EmbeddingErrorSummary {
|
|
97
|
+
/** ISO timestamp. */
|
|
98
|
+
at: string;
|
|
99
|
+
/** `rate_limited`, `timeout`, `http_<status>`, `network` or `error`. */
|
|
100
|
+
code: string;
|
|
101
|
+
}
|
|
102
|
+
/** `GET /status` `health.embedding`. */
|
|
103
|
+
interface EmbeddingHealthSnapshot {
|
|
104
|
+
/** `ok` or `failing`. */
|
|
105
|
+
state: EmbeddingHealthState;
|
|
106
|
+
/** Last successful call (ISO), `null` before the first. */
|
|
107
|
+
lastSuccessAt: string | null;
|
|
108
|
+
/** Most recent error, `null` if none yet. */
|
|
109
|
+
lastError: EmbeddingErrorSummary | null;
|
|
110
|
+
/** When the state turned `failing` (ISO), `null` while `ok`. */
|
|
111
|
+
failingSince: string | null;
|
|
112
|
+
/** End of the stored provider back-off (ISO), `null` if none. */
|
|
113
|
+
backoffUntil: string | null;
|
|
114
|
+
}
|
|
115
|
+
|
|
49
116
|
/**
|
|
50
117
|
* @module enrichment/EnrichmentStore
|
|
51
|
-
* SQLite-backed enrichment metadata store. Persists path-keyed metadata at stateDir/enrichments.sqlite. Atomic writes, supports move.
|
|
118
|
+
* SQLite-backed enrichment metadata store. Persists path- or source-reference-keyed metadata (references verbatim) at stateDir/enrichments.sqlite. Atomic writes, supports move.
|
|
52
119
|
*/
|
|
53
120
|
|
|
54
121
|
/**
|
|
@@ -188,95 +255,44 @@ declare abstract class JsonFileStore<T> {
|
|
|
188
255
|
|
|
189
256
|
/**
|
|
190
257
|
* @module issues/types
|
|
191
|
-
*
|
|
258
|
+
* Issue record schema and types for the issues tracking system. IssueRecord is defined in core (GET /issues response); IssuesFile is the on-disk shape.
|
|
192
259
|
*/
|
|
193
260
|
|
|
194
|
-
/** Schema for a single issue record tracking a processing failure. */
|
|
195
|
-
declare const issueRecordSchema: z.ZodObject<{
|
|
196
|
-
type: z.ZodUnion<readonly [z.ZodLiteral<"type_collision">, z.ZodLiteral<"interpolation_error">]>;
|
|
197
|
-
property: z.ZodOptional<z.ZodString>;
|
|
198
|
-
rules: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
199
|
-
rule: z.ZodOptional<z.ZodString>;
|
|
200
|
-
types: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
201
|
-
message: z.ZodString;
|
|
202
|
-
timestamp: z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>;
|
|
203
|
-
}, z.core.$strip>;
|
|
204
|
-
/** A single issue record tracking a processing failure for a file. */
|
|
205
|
-
type IssueRecord = z.infer<typeof issueRecordSchema>;
|
|
206
261
|
/** Issues file: array of issue records per file path. */
|
|
207
262
|
type IssuesFile = Partial<Record<string, IssueRecord[]>>;
|
|
208
263
|
|
|
209
264
|
/**
|
|
210
265
|
* @module issues/IssuesManager
|
|
211
|
-
* Manages persistent issue tracking for file
|
|
266
|
+
* Manages persistent issue tracking for processing failures, keyed by document key (file path or source reference). Read-modify-write with in-memory cache.
|
|
212
267
|
*/
|
|
213
268
|
|
|
214
269
|
/**
|
|
215
|
-
* Manages a persistent issues.json file tracking processing failures per
|
|
270
|
+
* Manages a persistent issues.json file tracking processing failures per
|
|
271
|
+
* document key (file path or source reference).
|
|
216
272
|
*/
|
|
217
273
|
declare class IssuesManager extends JsonFileStore<IssuesFile> {
|
|
218
274
|
constructor(stateDir: string, logger: pino.Logger);
|
|
219
275
|
protected createEmpty(): IssuesFile;
|
|
220
|
-
/**
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
276
|
+
/**
|
|
277
|
+
* Record an issue for a document key (file path or source reference).
|
|
278
|
+
*
|
|
279
|
+
* @param key - Document key (file path or source reference).
|
|
280
|
+
* @param type - Canonical issue code.
|
|
281
|
+
* @param message - Error message.
|
|
282
|
+
* @param options - Optional operation, property, rule(s), types and
|
|
283
|
+
* structured `details` (stored as JSON, e.g. AJV errors).
|
|
284
|
+
*/
|
|
285
|
+
record(key: string, type: IssueRecord['type'], message: string, options?: Pick<IssueRecord, 'operation' | 'property' | 'rules' | 'rule' | 'types' | 'details'>): void;
|
|
286
|
+
/** Clear the issues of a document key (called on successful processing). */
|
|
287
|
+
clear(key: string): void;
|
|
228
288
|
/** Wipe all issues (called on full reindex start). */
|
|
229
289
|
clearAll(): void;
|
|
290
|
+
/** Get the current issues of one document key, if any. */
|
|
291
|
+
get(key: string): IssueRecord[] | undefined;
|
|
230
292
|
/** Get all current issues. */
|
|
231
293
|
getAll(): IssuesFile;
|
|
232
294
|
}
|
|
233
295
|
|
|
234
|
-
/**
|
|
235
|
-
* @module cache/ContentHashCache
|
|
236
|
-
* In-memory cache mapping normalized file paths to content hashes.
|
|
237
|
-
* Supports reverse lookup by hash for move correlation.
|
|
238
|
-
*/
|
|
239
|
-
/**
|
|
240
|
-
* In-memory content hash cache for move detection.
|
|
241
|
-
*
|
|
242
|
-
* Maps normalized file paths to SHA-256 content hashes.
|
|
243
|
-
* Supports reverse lookup (hash → paths) for correlating
|
|
244
|
-
* unlink+add events as file moves.
|
|
245
|
-
*/
|
|
246
|
-
declare class ContentHashCache {
|
|
247
|
-
private readonly pathToHash;
|
|
248
|
-
private readonly hashToPaths;
|
|
249
|
-
/**
|
|
250
|
-
* Store or update the content hash for a file path.
|
|
251
|
-
*
|
|
252
|
-
* @param filePath - The file path (will be normalized).
|
|
253
|
-
* @param hash - The SHA-256 content hash.
|
|
254
|
-
*/
|
|
255
|
-
set(filePath: string, hash: string): void;
|
|
256
|
-
/**
|
|
257
|
-
* Get the content hash for a file path.
|
|
258
|
-
*
|
|
259
|
-
* @param filePath - The file path (will be normalized).
|
|
260
|
-
* @returns The content hash, or undefined if not cached.
|
|
261
|
-
*/
|
|
262
|
-
get(filePath: string): string | undefined;
|
|
263
|
-
/**
|
|
264
|
-
* Remove a file path from the cache.
|
|
265
|
-
*
|
|
266
|
-
* @param filePath - The file path (will be normalized).
|
|
267
|
-
*/
|
|
268
|
-
delete(filePath: string): void;
|
|
269
|
-
/**
|
|
270
|
-
* Reverse lookup: get all file paths with a given content hash.
|
|
271
|
-
*
|
|
272
|
-
* @param hash - The content hash to look up.
|
|
273
|
-
* @returns Array of normalized file paths with that hash.
|
|
274
|
-
*/
|
|
275
|
-
getByHash(hash: string): string[];
|
|
276
|
-
/** Number of cached entries. */
|
|
277
|
-
get size(): number;
|
|
278
|
-
}
|
|
279
|
-
|
|
280
296
|
/**
|
|
281
297
|
* @module templates/engine
|
|
282
298
|
* Handlebars template compilation, caching, and resolution (file path vs named ref vs inline).
|
|
@@ -391,6 +407,29 @@ declare function buildTemplateEngine(rules: InferenceRule[], namedTemplates?: Re
|
|
|
391
407
|
*/
|
|
392
408
|
declare function registerBuiltinHelpers(hbs: typeof Handlebars): void;
|
|
393
409
|
|
|
410
|
+
/**
|
|
411
|
+
* @module rules/sourceAttributes
|
|
412
|
+
* Zod schema and builder for source-document rule attributes (`source` identity block + `json` record; no `file` key). Pure, no I/O.
|
|
413
|
+
*/
|
|
414
|
+
|
|
415
|
+
/**
|
|
416
|
+
* Attributes a source document is matched and resolved against. There is no
|
|
417
|
+
* `file` key, so file rules (`file.path` globs) never match a source
|
|
418
|
+
* document, and a source rule (`required: ["source"]`) never matches a file.
|
|
419
|
+
*/
|
|
420
|
+
declare const sourceAttributesSchema: z.ZodObject<{
|
|
421
|
+
source: z.ZodObject<{
|
|
422
|
+
ref: z.ZodString;
|
|
423
|
+
name: z.ZodString;
|
|
424
|
+
id: z.ZodString;
|
|
425
|
+
rule: z.ZodString;
|
|
426
|
+
retrievedAt: z.ZodString;
|
|
427
|
+
}, z.core.$strip>;
|
|
428
|
+
json: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
429
|
+
}, z.core.$strip>;
|
|
430
|
+
/** Attributes of a source document. */
|
|
431
|
+
type SourceAttributes = z.infer<typeof sourceAttributesSchema>;
|
|
432
|
+
|
|
394
433
|
/**
|
|
395
434
|
* @module rules/attributes
|
|
396
435
|
* Builds file attribute objects for rule matching. Pure function: derives attributes from path, stats, and extracted data.
|
|
@@ -420,6 +459,8 @@ interface FileAttributes {
|
|
|
420
459
|
/** Parsed JSON content, if any. */
|
|
421
460
|
json?: Record<string, unknown>;
|
|
422
461
|
}
|
|
462
|
+
/** Attributes rules are matched and resolved against: a file or a source document. */
|
|
463
|
+
type RuleAttributes = FileAttributes | SourceAttributes;
|
|
423
464
|
/**
|
|
424
465
|
* Build {@link FileAttributes} from a file path and stat info.
|
|
425
466
|
*
|
|
@@ -442,8 +483,13 @@ declare function buildAttributes(filePath: string, stats: Stats, extractedFrontm
|
|
|
442
483
|
interface CompiledRule {
|
|
443
484
|
/** The original rule definition. */
|
|
444
485
|
rule: InferenceRule;
|
|
445
|
-
/**
|
|
446
|
-
|
|
486
|
+
/**
|
|
487
|
+
* The compiled AJV validate function. After a failed call, `errors` holds
|
|
488
|
+
* the AJV errors (used for `match_failed` issues).
|
|
489
|
+
*/
|
|
490
|
+
validate: ((data: unknown) => boolean) & {
|
|
491
|
+
errors?: ErrorObject[] | null;
|
|
492
|
+
};
|
|
447
493
|
}
|
|
448
494
|
/**
|
|
449
495
|
* Compile an array of inference rules into executable validators.
|
|
@@ -454,9 +500,31 @@ interface CompiledRule {
|
|
|
454
500
|
*/
|
|
455
501
|
declare function compileRules(rules: InferenceRule[]): CompiledRule[];
|
|
456
502
|
|
|
503
|
+
/**
|
|
504
|
+
* @module rules/ruleErrors
|
|
505
|
+
* Interpolation errors collected while applying rules (schema `set` resolution, `render`, `template`): Zod schema, type and one-line formatting. Pure.
|
|
506
|
+
*/
|
|
507
|
+
|
|
508
|
+
/**
|
|
509
|
+
* One interpolation failure of a matched rule. The rule's output for that
|
|
510
|
+
* stage is missing (schema failure: the rule's metadata, map and render are
|
|
511
|
+
* skipped; render/template failure: the raw content is used instead).
|
|
512
|
+
*/
|
|
513
|
+
declare const ruleApplicationErrorSchema: z.ZodObject<{
|
|
514
|
+
rule: z.ZodString;
|
|
515
|
+
stage: z.ZodEnum<{
|
|
516
|
+
schema: "schema";
|
|
517
|
+
render: "render";
|
|
518
|
+
template: "template";
|
|
519
|
+
}>;
|
|
520
|
+
message: z.ZodString;
|
|
521
|
+
}, z.core.$strip>;
|
|
522
|
+
/** One interpolation failure of a matched rule. */
|
|
523
|
+
type RuleApplicationError = z.infer<typeof ruleApplicationErrorSchema>;
|
|
524
|
+
|
|
457
525
|
/**
|
|
458
526
|
* @module rules/apply
|
|
459
|
-
* Applies compiled inference rules to file attributes, producing merged metadata via
|
|
527
|
+
* Applies compiled inference rules to file or source attributes, producing merged metadata via schema resolution, JsonMap transforms and render/template output; collects interpolation errors.
|
|
460
528
|
*/
|
|
461
529
|
|
|
462
530
|
/**
|
|
@@ -478,6 +546,11 @@ interface ApplyRulesResult {
|
|
|
478
546
|
matchedRules: string[];
|
|
479
547
|
/** The renderAs value from the last matching rule that declares it, or null. */
|
|
480
548
|
renderAs: string | null;
|
|
549
|
+
/**
|
|
550
|
+
* Interpolation failures (schema `set` resolution, `render`, `template`)
|
|
551
|
+
* of matched rules, in order. Each was also logged as a warning.
|
|
552
|
+
*/
|
|
553
|
+
errors: RuleApplicationError[];
|
|
481
554
|
}
|
|
482
555
|
/**
|
|
483
556
|
* Optional parameters for applyRules beyond the required compiledRules and attributes.
|
|
@@ -503,14 +576,16 @@ interface ApplyRulesOptions {
|
|
|
503
576
|
*
|
|
504
577
|
* Rules are evaluated in order; later rules override earlier ones.
|
|
505
578
|
* If a rule has a `map`, the JsonMap transformation is applied after `set` resolution,
|
|
506
|
-
* and map output overrides set output on conflict.
|
|
579
|
+
* and map output overrides set output on conflict. A failing schema, render
|
|
580
|
+
* or template is logged and reported in `errors`; the rule's output for that
|
|
581
|
+
* stage is skipped (a schema failure skips the rest of the rule).
|
|
507
582
|
*
|
|
508
583
|
* @param compiledRules - The compiled rules to evaluate.
|
|
509
|
-
* @param attributes - The file attributes to match against.
|
|
584
|
+
* @param attributes - The file or source attributes to match against.
|
|
510
585
|
* @param options - Optional configuration for rule application.
|
|
511
|
-
* @returns The merged metadata
|
|
586
|
+
* @returns The merged metadata, optional rendered content and errors.
|
|
512
587
|
*/
|
|
513
|
-
declare function applyRules(compiledRules: CompiledRule[], attributes:
|
|
588
|
+
declare function applyRules(compiledRules: CompiledRule[], attributes: RuleAttributes, options?: ApplyRulesOptions): Promise<ApplyRulesResult>;
|
|
514
589
|
|
|
515
590
|
/**
|
|
516
591
|
* @module rules/virtualRules
|
|
@@ -560,6 +635,242 @@ declare class VirtualRuleStore {
|
|
|
560
635
|
get size(): number;
|
|
561
636
|
}
|
|
562
637
|
|
|
638
|
+
/**
|
|
639
|
+
* @module processor/DocumentLocks
|
|
640
|
+
* One in-process FIFO lock per document key (D98): every process, delete, move, too_large and metadata change of a document runs under it. API routes wait at most 10 s, then 503 (D118). Idle locks are dropped.
|
|
641
|
+
*
|
|
642
|
+
* Keys: the normalised file path (the same normalisation as point IDs) or
|
|
643
|
+
* the source reference. A move takes both keys in sorted order, so two moves
|
|
644
|
+
* cannot deadlock.
|
|
645
|
+
*/
|
|
646
|
+
|
|
647
|
+
/** Options of one locked operation. */
|
|
648
|
+
interface DocumentLockOptions {
|
|
649
|
+
/** Longest wait for the lock (omit: unbounded, as for background work). */
|
|
650
|
+
lockWaitMs?: number;
|
|
651
|
+
}
|
|
652
|
+
/**
|
|
653
|
+
* The lock key of a file.
|
|
654
|
+
*
|
|
655
|
+
* @param filePath - The file path, as given.
|
|
656
|
+
* @returns The normalised path (lower-case, forward slashes).
|
|
657
|
+
*/
|
|
658
|
+
declare function fileLockKey(filePath: string): string;
|
|
659
|
+
/** The per-document locks of one processor. */
|
|
660
|
+
declare class DocumentLocks {
|
|
661
|
+
private readonly logger;
|
|
662
|
+
private readonly locks;
|
|
663
|
+
/** @param logger - Logger for long-hold warnings. */
|
|
664
|
+
constructor(logger: pino.Logger);
|
|
665
|
+
/** Number of keys currently locked or waited for. */
|
|
666
|
+
get size(): number;
|
|
667
|
+
/**
|
|
668
|
+
* Run `work` under the lock of `key`.
|
|
669
|
+
*
|
|
670
|
+
* @param key - Document key ({@link fileLockKey} or a source reference).
|
|
671
|
+
* @param operation - Operation name (warnings, timeout error).
|
|
672
|
+
* @param work - The work (must not take the same key again).
|
|
673
|
+
* @param options - Bounded wait.
|
|
674
|
+
* @returns What `work` returns.
|
|
675
|
+
* @throws DocumentLockTimeoutError when a bounded wait runs out.
|
|
676
|
+
*/
|
|
677
|
+
run<T>(key: string, operation: string, work: () => Promise<T>, options?: DocumentLockOptions): Promise<T>;
|
|
678
|
+
/**
|
|
679
|
+
* Run `work` holding the locks of every key, taken one at a time in sorted
|
|
680
|
+
* order (duplicates once).
|
|
681
|
+
*
|
|
682
|
+
* @param keys - Document keys.
|
|
683
|
+
* @param operation - Operation name.
|
|
684
|
+
* @param work - The work.
|
|
685
|
+
* @param options - Bounded wait (per lock).
|
|
686
|
+
* @returns What `work` returns.
|
|
687
|
+
*/
|
|
688
|
+
runAll<T>(keys: string[], operation: string, work: () => Promise<T>, options?: DocumentLockOptions): Promise<T>;
|
|
689
|
+
private lockFor;
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
/**
|
|
693
|
+
* @module cache/ContentHashCache
|
|
694
|
+
* In-memory cache mapping normalized file paths to content hashes.
|
|
695
|
+
* Supports reverse lookup by hash for move correlation.
|
|
696
|
+
*/
|
|
697
|
+
/**
|
|
698
|
+
* In-memory content hash cache for move detection.
|
|
699
|
+
*
|
|
700
|
+
* Maps normalized file paths to SHA-256 content hashes.
|
|
701
|
+
* Supports reverse lookup (hash → paths) for correlating
|
|
702
|
+
* unlink+add events as file moves.
|
|
703
|
+
*/
|
|
704
|
+
declare class ContentHashCache {
|
|
705
|
+
private readonly pathToHash;
|
|
706
|
+
private readonly hashToPaths;
|
|
707
|
+
/**
|
|
708
|
+
* Store or update the content hash for a file path.
|
|
709
|
+
*
|
|
710
|
+
* @param filePath - The file path (will be normalized).
|
|
711
|
+
* @param hash - The SHA-256 content hash.
|
|
712
|
+
*/
|
|
713
|
+
set(filePath: string, hash: string): void;
|
|
714
|
+
/**
|
|
715
|
+
* Get the content hash for a file path.
|
|
716
|
+
*
|
|
717
|
+
* @param filePath - The file path (will be normalized).
|
|
718
|
+
* @returns The content hash, or undefined if not cached.
|
|
719
|
+
*/
|
|
720
|
+
get(filePath: string): string | undefined;
|
|
721
|
+
/**
|
|
722
|
+
* Remove a file path from the cache.
|
|
723
|
+
*
|
|
724
|
+
* @param filePath - The file path (will be normalized).
|
|
725
|
+
*/
|
|
726
|
+
delete(filePath: string): void;
|
|
727
|
+
/**
|
|
728
|
+
* Reverse lookup: get all file paths with a given content hash.
|
|
729
|
+
*
|
|
730
|
+
* @param hash - The content hash to look up.
|
|
731
|
+
* @returns Array of normalized file paths with that hash.
|
|
732
|
+
*/
|
|
733
|
+
getByHash(hash: string): string[];
|
|
734
|
+
/** Number of cached entries. */
|
|
735
|
+
get size(): number;
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
/**
|
|
739
|
+
* @module sources/types
|
|
740
|
+
* Zod schemas and derived types for source callback outcomes (document / gone / error) and reference rejections. Pure declarations; no I/O.
|
|
741
|
+
*/
|
|
742
|
+
|
|
743
|
+
/**
|
|
744
|
+
* Error codes a source callback can produce: the subset of the canonical
|
|
745
|
+
* issue codes that belong to retrieval.
|
|
746
|
+
*/
|
|
747
|
+
declare const sourceErrorCodeSchema: z.ZodEnum<{
|
|
748
|
+
source_unavailable: "source_unavailable";
|
|
749
|
+
unsupported_content_type: "unsupported_content_type";
|
|
750
|
+
}>;
|
|
751
|
+
/** A source callback error code. */
|
|
752
|
+
type SourceErrorCode = z.infer<typeof sourceErrorCodeSchema>;
|
|
753
|
+
/** Outcome of one source callback (discriminated on `kind`). */
|
|
754
|
+
declare const sourceRetrievalResultSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
755
|
+
kind: z.ZodLiteral<"document">;
|
|
756
|
+
body: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
757
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
758
|
+
kind: z.ZodLiteral<"gone">;
|
|
759
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
760
|
+
kind: z.ZodLiteral<"error">;
|
|
761
|
+
code: z.ZodEnum<{
|
|
762
|
+
source_unavailable: "source_unavailable";
|
|
763
|
+
unsupported_content_type: "unsupported_content_type";
|
|
764
|
+
}>;
|
|
765
|
+
message: z.ZodString;
|
|
766
|
+
}, z.core.$strip>], "kind">;
|
|
767
|
+
/** Outcome of one source callback. */
|
|
768
|
+
type SourceRetrievalResult = z.infer<typeof sourceRetrievalResultSchema>;
|
|
769
|
+
/**
|
|
770
|
+
* Why a reference was rejected before any request was made:
|
|
771
|
+
* `invalid_reference` (not `<name>://<id>`), `unknown_source` (name not in
|
|
772
|
+
* config `sources`), `invalid_id` (empty, `.` or `..` segment, or the built
|
|
773
|
+
* URL would leave the configured origin). The reference-level subset of
|
|
774
|
+
* core `documentRejectionCodeSchema`.
|
|
775
|
+
*/
|
|
776
|
+
declare const sourceRejectionCodeSchema: z.ZodEnum<{
|
|
777
|
+
invalid_reference: "invalid_reference";
|
|
778
|
+
unknown_source: "unknown_source";
|
|
779
|
+
invalid_id: "invalid_id";
|
|
780
|
+
}>;
|
|
781
|
+
/** A reference rejection code. */
|
|
782
|
+
type SourceRejectionCode = z.infer<typeof sourceRejectionCodeSchema>;
|
|
783
|
+
/** A parsed `<name>://<id>` reference. */
|
|
784
|
+
declare const parsedSourceReferenceSchema: z.ZodObject<{
|
|
785
|
+
ref: z.ZodString;
|
|
786
|
+
name: z.ZodString;
|
|
787
|
+
id: z.ZodString;
|
|
788
|
+
}, z.core.$strip>;
|
|
789
|
+
/** A parsed `<name>://<id>` reference. */
|
|
790
|
+
type ParsedSourceReference = z.infer<typeof parsedSourceReferenceSchema>;
|
|
791
|
+
/** A reference resolved against config: parsed parts plus the URL to request. */
|
|
792
|
+
declare const resolvedSourceReferenceSchema: z.ZodObject<{
|
|
793
|
+
ref: z.ZodString;
|
|
794
|
+
name: z.ZodString;
|
|
795
|
+
id: z.ZodString;
|
|
796
|
+
url: z.ZodString;
|
|
797
|
+
}, z.core.$strip>;
|
|
798
|
+
/** A reference resolved against config. */
|
|
799
|
+
type ResolvedSourceReference = z.infer<typeof resolvedSourceReferenceSchema>;
|
|
800
|
+
/**
|
|
801
|
+
* Thrown (or rejected) when a reference cannot be retrieved for a reason
|
|
802
|
+
* known before any request is made. No request is ever sent for a rejected
|
|
803
|
+
* reference.
|
|
804
|
+
*/
|
|
805
|
+
declare class SourceReferenceError extends Error {
|
|
806
|
+
/** Rejection code. */
|
|
807
|
+
readonly code: SourceRejectionCode;
|
|
808
|
+
/**
|
|
809
|
+
* @param code - Rejection code.
|
|
810
|
+
* @param message - Human-readable reason (never contains header values).
|
|
811
|
+
*/
|
|
812
|
+
constructor(code: SourceRejectionCode, message: string);
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
/**
|
|
816
|
+
* @module sources/SourceClient
|
|
817
|
+
* Registry of configured sources: resolves `<name>://<id>` to a config-built URL and retrieves it with per-source concurrency caps. Network I/O via requestSource.
|
|
818
|
+
*/
|
|
819
|
+
|
|
820
|
+
/**
|
|
821
|
+
* Retrieves source documents by callback. Injected into later pipeline
|
|
822
|
+
* stages (resolver, notify queue, reindex) so tests can substitute it.
|
|
823
|
+
*/
|
|
824
|
+
interface SourceRetriever {
|
|
825
|
+
/**
|
|
826
|
+
* Validate a reference and build its URL without making a request.
|
|
827
|
+
*
|
|
828
|
+
* @throws {@link SourceReferenceError}
|
|
829
|
+
*/
|
|
830
|
+
resolve(reference: string): ResolvedSourceReference;
|
|
831
|
+
/**
|
|
832
|
+
* Retrieve a document. Rejects with {@link SourceReferenceError} (and
|
|
833
|
+
* sends nothing) for an invalid reference; otherwise never rejects.
|
|
834
|
+
*/
|
|
835
|
+
retrieve(reference: string): Promise<SourceRetrievalResult>;
|
|
836
|
+
}
|
|
837
|
+
/**
|
|
838
|
+
* The source callback client. Constructed once from the parsed `sources`
|
|
839
|
+
* config (defaults applied, `${ENV}` already substituted at load). Each
|
|
840
|
+
* source gets its own concurrency semaphore; the `timeoutMs` clock starts
|
|
841
|
+
* when a request leaves the queue, not while it waits for a slot. Callbacks
|
|
842
|
+
* do not draw from the embedding rate limiter.
|
|
843
|
+
*/
|
|
844
|
+
declare class SourceClient implements SourceRetriever {
|
|
845
|
+
private readonly entries;
|
|
846
|
+
/**
|
|
847
|
+
* @param sources - The parsed `sources` config section.
|
|
848
|
+
* @throws Error when a `url` template is not an absolute http(s) URL or
|
|
849
|
+
* places `{id}` in its origin (scheme, host or port).
|
|
850
|
+
*/
|
|
851
|
+
constructor(sources?: SourcesConfig);
|
|
852
|
+
/** {@inheritDoc SourceRetriever.resolve} */
|
|
853
|
+
resolve(reference: string): ResolvedSourceReference;
|
|
854
|
+
/** {@inheritDoc SourceRetriever.retrieve} */
|
|
855
|
+
retrieve(reference: string): Promise<SourceRetrievalResult>;
|
|
856
|
+
private resolveEntry;
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
/**
|
|
860
|
+
* @module sources/sourceUrl
|
|
861
|
+
* Pure helpers: parse `<name>://<id>` references, encode ids segment-by-segment, and build callback URLs from a configured template. No I/O.
|
|
862
|
+
*/
|
|
863
|
+
|
|
864
|
+
/**
|
|
865
|
+
* Parse a source reference.
|
|
866
|
+
*
|
|
867
|
+
* @param reference - A `<name>://<id>` string.
|
|
868
|
+
* @returns The parsed reference.
|
|
869
|
+
* @throws {@link SourceReferenceError} `invalid_reference` when the string
|
|
870
|
+
* does not match the core reference schema.
|
|
871
|
+
*/
|
|
872
|
+
declare function parseSourceReference(reference: string): ParsedSourceReference;
|
|
873
|
+
|
|
563
874
|
/**
|
|
564
875
|
* @module util/BinaryFileStore
|
|
565
876
|
* Binary-backed read/modify/write store with in-memory caching and debounced flush.
|
|
@@ -619,7 +930,7 @@ declare abstract class BinaryFileStore<T> {
|
|
|
619
930
|
/** Per-rule distinct values: rule name → field name → sorted unique values. */
|
|
620
931
|
type ValuesIndex = Record<string, Record<string, unknown[]>>;
|
|
621
932
|
/**
|
|
622
|
-
* Manages a persistent values.
|
|
933
|
+
* Manages a persistent values.v8 file tracking distinct metadata values per rule.
|
|
623
934
|
*/
|
|
624
935
|
declare class ValuesManager extends BinaryFileStore<ValuesIndex> {
|
|
625
936
|
constructor(stateDir: string, logger: pino.Logger);
|
|
@@ -636,6 +947,74 @@ declare class ValuesManager extends BinaryFileStore<ValuesIndex> {
|
|
|
636
947
|
getForRule(ruleName: string): Record<string, unknown[]>;
|
|
637
948
|
}
|
|
638
949
|
|
|
950
|
+
/**
|
|
951
|
+
* @module vectorStore/systemIndexes
|
|
952
|
+
* System payload indexes (D74, D154, D155): created at startup by background wait=true calls (startup never waits), reported as building, ready, conflict or failed; plus keyword-index readiness for by-filter writes. Qdrant I/O.
|
|
953
|
+
*
|
|
954
|
+
* `chunk_index` (integer) lets `countFacets` count documents, not chunks;
|
|
955
|
+
* `file_path` (keyword) serves metadata writes by filter (D139);
|
|
956
|
+
* `matched_rules` (keyword) serves rule-scoped counts (D155). A field
|
|
957
|
+
* already indexed with another type is left alone (`conflict`): writes keep
|
|
958
|
+
* using ID addressing, and `countFacets` answers 503 naming the index.
|
|
959
|
+
*/
|
|
960
|
+
|
|
961
|
+
/** State of one system index (`GET /status` `health.collection.systemIndexes`). */
|
|
962
|
+
type SystemIndexState = 'building' | 'ready' | 'conflict' | 'failed';
|
|
963
|
+
|
|
964
|
+
/**
|
|
965
|
+
* @module vectorStore/facets
|
|
966
|
+
* Qdrant reads behind `countFacets` (spec Design 12): approximate facet counts (D194), one-point ordered scrolls for a field's range, and the collection's payload index types. Every count and scroll passes Qdrant's `timeout` (whole seconds) so an abandoned call also stops in Qdrant. Qdrant I/O.
|
|
967
|
+
*/
|
|
968
|
+
|
|
969
|
+
/** A facet value as Qdrant reports it. */
|
|
970
|
+
type FacetValue = string | number | boolean;
|
|
971
|
+
/** One counted value. */
|
|
972
|
+
interface FacetHit {
|
|
973
|
+
/** The payload value. */
|
|
974
|
+
value: FacetValue;
|
|
975
|
+
/** Points holding it. */
|
|
976
|
+
count: number;
|
|
977
|
+
}
|
|
978
|
+
/** Which end of a range an ordered scroll reads. */
|
|
979
|
+
type RangeEnd = 'min' | 'max';
|
|
980
|
+
/** A range bound: a number, a stored date string, or null when nothing matched. */
|
|
981
|
+
type RangeBound = number | string | null;
|
|
982
|
+
/** One facet count or range read: field, filter and Qdrant timeout. */
|
|
983
|
+
interface FacetRead {
|
|
984
|
+
/** Payload field. */
|
|
985
|
+
field: string;
|
|
986
|
+
/** Qdrant filter (already scoped by the caller). */
|
|
987
|
+
filter: Record<string, unknown>;
|
|
988
|
+
/** Qdrant `timeout` query parameter, whole seconds. */
|
|
989
|
+
timeoutS: number;
|
|
990
|
+
}
|
|
991
|
+
/** Facet reads used by `countFacets` (`VectorStoreClient.facets`). */
|
|
992
|
+
interface FacetStore {
|
|
993
|
+
/**
|
|
994
|
+
* Approximate value counts of a field, highest first (D194).
|
|
995
|
+
*
|
|
996
|
+
* @param read - Field, filter and timeout.
|
|
997
|
+
* @param limit - Most values returned.
|
|
998
|
+
* @returns The counted values.
|
|
999
|
+
*/
|
|
1000
|
+
facetCounts(read: FacetRead, limit: number): Promise<FacetHit[]>;
|
|
1001
|
+
/**
|
|
1002
|
+
* One end of a field's range over the filter.
|
|
1003
|
+
*
|
|
1004
|
+
* @param read - Field, filter and timeout.
|
|
1005
|
+
* @param end - `min` or `max`.
|
|
1006
|
+
* @returns The bound, or null when no point holds the field.
|
|
1007
|
+
*/
|
|
1008
|
+
rangeBound(read: FacetRead, end: RangeEnd): Promise<RangeBound>;
|
|
1009
|
+
/** @returns Payload index type by field (`keyword`, `integer`, ...). */
|
|
1010
|
+
payloadIndexTypes(): Promise<Record<string, string>>;
|
|
1011
|
+
/**
|
|
1012
|
+
* @param field - A system index field (`chunk_index`, `matched_rules`).
|
|
1013
|
+
* @returns Its state, or undefined before startup.
|
|
1014
|
+
*/
|
|
1015
|
+
systemIndexState(field: string): SystemIndexState | undefined;
|
|
1016
|
+
}
|
|
1017
|
+
|
|
639
1018
|
/**
|
|
640
1019
|
* @module vectorStore/types
|
|
641
1020
|
* Vector store interface and type definitions.
|
|
@@ -730,11 +1109,50 @@ interface VectorStore {
|
|
|
730
1109
|
* @param payload - Payload fields to set.
|
|
731
1110
|
*/
|
|
732
1111
|
setPayload(ids: string[], payload: Record<string, unknown>): Promise<void>;
|
|
1112
|
+
/**
|
|
1113
|
+
* Remove payload keys from the specified point IDs (other keys kept).
|
|
1114
|
+
*
|
|
1115
|
+
* @param ids - Point IDs to update.
|
|
1116
|
+
* @param keys - Payload keys to remove.
|
|
1117
|
+
*/
|
|
1118
|
+
deletePayload(ids: string[], keys: string[]): Promise<void>;
|
|
1119
|
+
/**
|
|
1120
|
+
* Whether `field` has a ready `keyword` payload index, so a by-filter
|
|
1121
|
+
* write on it is cheap (D154). A system index counts once its background
|
|
1122
|
+
* build returned; any other field when it was keyword-indexed at startup.
|
|
1123
|
+
*
|
|
1124
|
+
* @param field - Payload field.
|
|
1125
|
+
* @returns True when by-filter writes on `field` may be used.
|
|
1126
|
+
*/
|
|
1127
|
+
keywordIndexReady(field: string): boolean;
|
|
1128
|
+
/**
|
|
1129
|
+
* Set payload fields on every point matching a filter (D139).
|
|
1130
|
+
*
|
|
1131
|
+
* @param filter - Qdrant filter selecting one document's points.
|
|
1132
|
+
* @param payload - Payload fields to set.
|
|
1133
|
+
*/
|
|
1134
|
+
setPayloadWhere(filter: Record<string, unknown>, payload: Record<string, unknown>): Promise<void>;
|
|
1135
|
+
/**
|
|
1136
|
+
* Remove payload keys from every point matching a filter (D139).
|
|
1137
|
+
*
|
|
1138
|
+
* @param filter - Qdrant filter selecting one document's points.
|
|
1139
|
+
* @param keys - Payload keys to remove.
|
|
1140
|
+
*/
|
|
1141
|
+
deletePayloadWhere(filter: Record<string, unknown>, keys: string[]): Promise<void>;
|
|
1142
|
+
/**
|
|
1143
|
+
* The IDs among `ids` that exist, in the given order (no payload, no
|
|
1144
|
+
* vectors; needs no index, D154).
|
|
1145
|
+
*
|
|
1146
|
+
* @param ids - Candidate point IDs.
|
|
1147
|
+
* @returns The existing IDs.
|
|
1148
|
+
*/
|
|
1149
|
+
existingIds(ids: string[]): Promise<string[]>;
|
|
733
1150
|
/**
|
|
734
1151
|
* Get the payload of a point by ID.
|
|
735
1152
|
*
|
|
736
1153
|
* @param id - The point ID.
|
|
737
1154
|
* @returns The payload, or `null` if the point doesn't exist.
|
|
1155
|
+
* @throws When the read fails (never reported as a missing point).
|
|
738
1156
|
*/
|
|
739
1157
|
getPayload(id: string): Promise<Record<string, unknown> | null>;
|
|
740
1158
|
/**
|
|
@@ -796,19 +1214,29 @@ interface VectorStore {
|
|
|
796
1214
|
getPointsWithVectors(ids: string[]): Promise<VectorPoint[]>;
|
|
797
1215
|
}
|
|
798
1216
|
|
|
1217
|
+
/**
|
|
1218
|
+
* @module vectorStore
|
|
1219
|
+
* Qdrant-backed {@link VectorStore}: collection setup, retried writes (see `writes`), payload reads, search, hybrid search and scrolling. Qdrant I/O.
|
|
1220
|
+
*/
|
|
1221
|
+
|
|
799
1222
|
/**
|
|
800
1223
|
* Client wrapper for Qdrant vector store operations.
|
|
801
1224
|
*
|
|
802
1225
|
* Implements the {@link VectorStore} interface for dependency inversion.
|
|
1226
|
+
* Writes (upsert, delete, set/delete payload) are retried, each retry on a
|
|
1227
|
+
* fresh client (see QdrantWriter).
|
|
803
1228
|
*/
|
|
804
1229
|
declare class VectorStoreClient implements VectorStore {
|
|
1230
|
+
/** Facet reads behind `countFacets` (spec Design 12). */
|
|
1231
|
+
readonly facets: FacetStore;
|
|
805
1232
|
private readonly client;
|
|
806
|
-
private
|
|
1233
|
+
private readonly writer;
|
|
807
1234
|
private readonly clientConfig;
|
|
808
1235
|
private readonly collectionName;
|
|
809
1236
|
private readonly dims;
|
|
810
|
-
private readonly log;
|
|
811
1237
|
private readonly pinoLogger?;
|
|
1238
|
+
private readonly payloadIndexes;
|
|
1239
|
+
private readonly systemIndexes;
|
|
812
1240
|
/**
|
|
813
1241
|
* Create a new VectorStoreClient.
|
|
814
1242
|
*
|
|
@@ -823,123 +1251,71 @@ declare class VectorStoreClient implements VectorStore {
|
|
|
823
1251
|
* Used to avoid stale HTTP keep-alive connections. The Qdrant JS client's
|
|
824
1252
|
* internal undici Agent uses keepAliveTimeout: 10s, which causes ECONNRESET
|
|
825
1253
|
* when connections sit idle during slow embedding calls (Gemini p99 ~8s).
|
|
826
|
-
*
|
|
1254
|
+
* Writes therefore run on their own client, replaced on every retry
|
|
1255
|
+
* (see QdrantWriter).
|
|
827
1256
|
*/
|
|
828
1257
|
private createClient;
|
|
829
|
-
/**
|
|
830
|
-
* Count points matching a filter.
|
|
831
|
-
*
|
|
832
|
-
* @param filter - Optional Qdrant filter.
|
|
833
|
-
* @returns The number of matching points.
|
|
834
|
-
*/
|
|
1258
|
+
/** {@inheritDoc VectorStore.count} */
|
|
835
1259
|
count(filter?: Record<string, unknown>): Promise<number>;
|
|
836
1260
|
/**
|
|
837
|
-
* Ensure the collection exists
|
|
1261
|
+
* Ensure the collection exists (Cosine, configured dimensions) and create
|
|
1262
|
+
* any missing payload indexes (configured plus `source`/`source_rule`),
|
|
1263
|
+
* then start the background system-index builds (D74, D154; not awaited).
|
|
838
1264
|
*/
|
|
839
1265
|
ensureCollection(): Promise<void>;
|
|
840
|
-
/**
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
/**
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
*
|
|
854
|
-
* @param points - The points to upsert.
|
|
855
|
-
*/
|
|
1266
|
+
/** @returns Each system index's state (`health.collection.systemIndexes`). */
|
|
1267
|
+
systemIndexStates(): Record<string, SystemIndexState>;
|
|
1268
|
+
/** @returns A promise settling once the background index builds end. */
|
|
1269
|
+
whenSystemIndexesSettled(): Promise<void>;
|
|
1270
|
+
/** {@inheritDoc VectorStore.keywordIndexReady} */
|
|
1271
|
+
keywordIndexReady(field: string): boolean;
|
|
1272
|
+
/** {@inheritDoc VectorStore.setPayloadWhere} */
|
|
1273
|
+
setPayloadWhere(filter: Record<string, unknown>, payload: Record<string, unknown>): Promise<void>;
|
|
1274
|
+
/** {@inheritDoc VectorStore.deletePayloadWhere} */
|
|
1275
|
+
deletePayloadWhere(filter: Record<string, unknown>, keys: string[]): Promise<void>;
|
|
1276
|
+
/** {@inheritDoc VectorStore.existingIds} */
|
|
1277
|
+
existingIds(ids: string[]): Promise<string[]>;
|
|
1278
|
+
/** {@inheritDoc VectorStore.upsert} */
|
|
856
1279
|
upsert(points: VectorPoint[]): Promise<void>;
|
|
857
|
-
/**
|
|
858
|
-
* Delete points by their IDs.
|
|
859
|
-
*
|
|
860
|
-
* Uses the shared client. On retry, creates a fresh client to recover.
|
|
861
|
-
*
|
|
862
|
-
* @param ids - The point IDs to delete.
|
|
863
|
-
*/
|
|
1280
|
+
/** {@inheritDoc VectorStore.delete} */
|
|
864
1281
|
delete(ids: string[]): Promise<void>;
|
|
865
|
-
/**
|
|
866
|
-
* Set payload fields for the specified point IDs.
|
|
867
|
-
*
|
|
868
|
-
* This merges the given payload object into each point's existing payload.
|
|
869
|
-
*
|
|
870
|
-
* @param ids - Point IDs to update.
|
|
871
|
-
* @param payload - Payload fields to set.
|
|
872
|
-
*/
|
|
1282
|
+
/** {@inheritDoc VectorStore.setPayload} */
|
|
873
1283
|
setPayload(ids: string[], payload: Record<string, unknown>): Promise<void>;
|
|
874
|
-
/**
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
* @param id - The point ID.
|
|
878
|
-
* @returns The payload, or `null` if the point doesn't exist.
|
|
879
|
-
*/
|
|
1284
|
+
/** {@inheritDoc VectorStore.deletePayload} */
|
|
1285
|
+
deletePayload(ids: string[], keys: string[]): Promise<void>;
|
|
1286
|
+
/** {@inheritDoc VectorStore.getPayload} */
|
|
880
1287
|
getPayload(id: string): Promise<Record<string, unknown> | null>;
|
|
881
|
-
/**
|
|
882
|
-
* Get collection info including point count, dimensions, and payload field schema.
|
|
883
|
-
*
|
|
884
|
-
* When Qdrant has payload indexes, uses `payload_schema` directly. Otherwise
|
|
885
|
-
* samples points to discover fields and infer types.
|
|
886
|
-
*/
|
|
1288
|
+
/** {@inheritDoc VectorStore.getCollectionInfo} */
|
|
887
1289
|
getCollectionInfo(): Promise<CollectionInfo>;
|
|
888
|
-
/**
|
|
889
|
-
* Search for similar vectors.
|
|
890
|
-
*
|
|
891
|
-
* @param vector - The query vector.
|
|
892
|
-
* @param limit - Maximum results to return.
|
|
893
|
-
* @param filter - Optional Qdrant filter.
|
|
894
|
-
* @returns An array of search results.
|
|
895
|
-
*/
|
|
1290
|
+
/** {@inheritDoc VectorStore.search} */
|
|
896
1291
|
search(vector: number[], limit: number, filter?: Record<string, unknown>, offset?: number): Promise<SearchResult[]>;
|
|
897
|
-
/**
|
|
898
|
-
* Create a full-text payload index on the specified field.
|
|
899
|
-
* Idempotent — skips if the field already has a text index.
|
|
900
|
-
*
|
|
901
|
-
* @param fieldName - The payload field to index.
|
|
902
|
-
*/
|
|
1292
|
+
/** {@inheritDoc VectorStore.ensureTextIndex} */
|
|
903
1293
|
ensureTextIndex(fieldName: string): Promise<void>;
|
|
904
|
-
/**
|
|
905
|
-
* Hybrid search combining dense vector and full-text match with RRF fusion.
|
|
906
|
-
*
|
|
907
|
-
* @param vector - The query vector.
|
|
908
|
-
* @param queryText - The raw query text for full-text matching.
|
|
909
|
-
* @param limit - Maximum results to return.
|
|
910
|
-
* @param textWeight - Weight for text results in RRF (0–1).
|
|
911
|
-
* @param filter - Optional Qdrant filter.
|
|
912
|
-
* @param offset - Optional result offset for pagination.
|
|
913
|
-
* @returns An array of search results.
|
|
914
|
-
*/
|
|
1294
|
+
/** {@inheritDoc VectorStore.hybridSearch} */
|
|
915
1295
|
hybridSearch(vector: number[], queryText: string, limit: number, textWeight: number, filter?: Record<string, unknown>, offset?: number): Promise<SearchResult[]>;
|
|
916
|
-
/**
|
|
917
|
-
* Retrieve points with their vectors by ID.
|
|
918
|
-
*
|
|
919
|
-
* @param ids - The point IDs to retrieve.
|
|
920
|
-
* @returns Points with vectors and payloads; missing IDs are omitted.
|
|
921
|
-
*/
|
|
1296
|
+
/** {@inheritDoc VectorStore.getPointsWithVectors} */
|
|
922
1297
|
getPointsWithVectors(ids: string[]): Promise<VectorPoint[]>;
|
|
923
|
-
/**
|
|
924
|
-
* Scroll one page of points matching a filter.
|
|
925
|
-
*
|
|
926
|
-
* @param filter - Optional Qdrant filter.
|
|
927
|
-
* @param limit - Page size.
|
|
928
|
-
* @param offset - Cursor offset from previous page.
|
|
929
|
-
* @param fields - Optional field projection.
|
|
930
|
-
* @returns Page of points and next cursor.
|
|
931
|
-
*/
|
|
1298
|
+
/** {@inheritDoc VectorStore.scrollPage} */
|
|
932
1299
|
scrollPage(filter?: Record<string, unknown>, limit?: number, offset?: string | number, fields?: string[]): Promise<ScrollPageResult>;
|
|
933
|
-
/**
|
|
934
|
-
* Scroll through all points matching a filter.
|
|
935
|
-
*
|
|
936
|
-
* @param filter - Optional Qdrant filter.
|
|
937
|
-
* @param limit - Page size for scrolling.
|
|
938
|
-
* @yields Scrolled points.
|
|
939
|
-
*/
|
|
1300
|
+
/** {@inheritDoc VectorStore.scroll} */
|
|
940
1301
|
scroll(filter?: Record<string, unknown>, limit?: number): AsyncGenerator<ScrolledPoint>;
|
|
941
1302
|
}
|
|
942
1303
|
|
|
1304
|
+
/**
|
|
1305
|
+
* @module processor/processingLimits
|
|
1306
|
+
* Resolve the `processing` ceilings (D44, D64) from the live config to bytes and a chunk count; read per document, so a reload applies to the next one. Pure.
|
|
1307
|
+
*/
|
|
1308
|
+
|
|
1309
|
+
/** The resolved ceilings. */
|
|
1310
|
+
interface ProcessingLimits {
|
|
1311
|
+
/** Largest file processed (bytes, checked with `stat` before extraction). */
|
|
1312
|
+
maxFileBytes: number;
|
|
1313
|
+
/** Most chunks one document may split into. */
|
|
1314
|
+
maxChunksPerFile: number;
|
|
1315
|
+
/** Largest extracted text (UTF-8 bytes). */
|
|
1316
|
+
maxTextBytes: number;
|
|
1317
|
+
}
|
|
1318
|
+
|
|
943
1319
|
/**
|
|
944
1320
|
* @module processor/ProcessorConfig
|
|
945
1321
|
* Configuration interface for DocumentProcessor, extracted for single-responsibility.
|
|
@@ -963,10 +1339,48 @@ interface ProcessorConfig {
|
|
|
963
1339
|
globalSchemas?: Record<string, SchemaEntry>;
|
|
964
1340
|
}
|
|
965
1341
|
|
|
1342
|
+
/**
|
|
1343
|
+
* @module processor/DocumentProcessorDeps
|
|
1344
|
+
* Constructor dependencies for DocumentProcessor (config, embedding provider, vector store, rules, optional stores), extracted for single-responsibility.
|
|
1345
|
+
*/
|
|
1346
|
+
|
|
1347
|
+
/**
|
|
1348
|
+
* Dependencies injected into DocumentProcessor.
|
|
1349
|
+
*/
|
|
1350
|
+
interface DocumentProcessorDeps {
|
|
1351
|
+
/** Processor configuration (chunk sizes, directories, maps). */
|
|
1352
|
+
config: ProcessorConfig;
|
|
1353
|
+
/** Provider for generating text embeddings. */
|
|
1354
|
+
embeddingProvider: EmbeddingProvider;
|
|
1355
|
+
/** Vector store for persistence. */
|
|
1356
|
+
vectorStore: VectorStore;
|
|
1357
|
+
/** Pre-compiled inference rules for metadata extraction. */
|
|
1358
|
+
compiledRules: CompiledRule[];
|
|
1359
|
+
/** Pino logger instance. */
|
|
1360
|
+
logger: pino.Logger;
|
|
1361
|
+
/** Optional Handlebars template engine for content templates. */
|
|
1362
|
+
templateEngine?: TemplateEngine;
|
|
1363
|
+
/** Optional enrichment store for persisted enrichment metadata. */
|
|
1364
|
+
enrichmentStore?: EnrichmentStoreInterface;
|
|
1365
|
+
/** Optional issues manager; processing failures are recorded as typed issues (#255). */
|
|
1366
|
+
issuesManager?: IssuesManager;
|
|
1367
|
+
/** Optional values manager for tracking rule-extracted values. */
|
|
1368
|
+
valuesManager?: ValuesManager;
|
|
1369
|
+
/** Optional content hash cache for move detection. */
|
|
1370
|
+
contentHashCache?: ContentHashCache;
|
|
1371
|
+
/** Optional source callback client; without it, source documents fail `source_unavailable`. */
|
|
1372
|
+
sourceRetriever?: SourceRetriever;
|
|
1373
|
+
/** Per-document locks (D98); default: the processor's own. */
|
|
1374
|
+
documentLocks?: DocumentLocks;
|
|
1375
|
+
/** The processing ceilings, read per document (D44); default: every default. */
|
|
1376
|
+
getProcessingLimits?: () => ProcessingLimits;
|
|
1377
|
+
}
|
|
1378
|
+
|
|
966
1379
|
/**
|
|
967
1380
|
* @module processor/renderResult
|
|
968
|
-
*
|
|
1381
|
+
* The render endpoint result and its one constructor from a resolved document (file or source). Pure, no I/O.
|
|
969
1382
|
*/
|
|
1383
|
+
|
|
970
1384
|
/**
|
|
971
1385
|
* Result returned by {@link DocumentProcessorInterface.renderFile}.
|
|
972
1386
|
*/
|
|
@@ -983,6 +1397,73 @@ interface RenderResult {
|
|
|
983
1397
|
transformed: boolean;
|
|
984
1398
|
}
|
|
985
1399
|
|
|
1400
|
+
/**
|
|
1401
|
+
* @module processor/documentPipeline
|
|
1402
|
+
* The shared indexing pipeline for resolved documents (file or source): onResolved hook, empty check, text and chunk ceilings (too_large), hash compare, streamed embed and upsert; plus point deletion.
|
|
1403
|
+
*/
|
|
1404
|
+
|
|
1405
|
+
/**
|
|
1406
|
+
* Options for indexing one document (see
|
|
1407
|
+
* {@link SourceOperationsInterface.process}).
|
|
1408
|
+
*/
|
|
1409
|
+
interface IndexOptions {
|
|
1410
|
+
/**
|
|
1411
|
+
* Re-embed and rewrite even when the content hash is unchanged (source
|
|
1412
|
+
* documents on a `full` reindex).
|
|
1413
|
+
*/
|
|
1414
|
+
force?: boolean;
|
|
1415
|
+
}
|
|
1416
|
+
|
|
1417
|
+
/**
|
|
1418
|
+
* @module processor/SourceOperations
|
|
1419
|
+
* Source-document operations for the API: notify validation (reference, configured source, rule), stored designated rule lookup, uncached render, metadata enrichment and processing. Qdrant and callback I/O.
|
|
1420
|
+
*/
|
|
1421
|
+
|
|
1422
|
+
/** Outcome of rendering a source document (`POST /render { source }`). */
|
|
1423
|
+
type SourceRenderOutcome = {
|
|
1424
|
+
kind: 'rendered';
|
|
1425
|
+
result: RenderResult;
|
|
1426
|
+
} | {
|
|
1427
|
+
kind: 'gone';
|
|
1428
|
+
} | {
|
|
1429
|
+
kind: 'failed';
|
|
1430
|
+
error: DocumentFailure;
|
|
1431
|
+
};
|
|
1432
|
+
/** Source-document operations used by the API. */
|
|
1433
|
+
interface SourceOperationsInterface {
|
|
1434
|
+
/** Process a reference with its designated rule (see `processSourceDocument`); `force` re-embeds unchanged content. */
|
|
1435
|
+
process(ref: string, rule: string, options?: IndexOptions): Promise<DocumentResult>;
|
|
1436
|
+
/** Synchronously validate a notification; `undefined` when acceptable. */
|
|
1437
|
+
validate(ref: string, rule: string): DocumentRejectionError | undefined;
|
|
1438
|
+
/** Designated rule stored on the document's chunk-0 point, or `null` if not indexed. */
|
|
1439
|
+
storedRule(ref: string): Promise<string | null>;
|
|
1440
|
+
/**
|
|
1441
|
+
* The compiled rule a designated rule name resolves to in the merged rule
|
|
1442
|
+
* set (config rules, then virtual rules: first of that name), or
|
|
1443
|
+
* `undefined` when no such rule exists.
|
|
1444
|
+
*/
|
|
1445
|
+
compiledRule(name: string): CompiledRule | undefined;
|
|
1446
|
+
/** Retrieve and render a document without embedding or writing anything. */
|
|
1447
|
+
render(ref: string, rule: string): Promise<SourceRenderOutcome>;
|
|
1448
|
+
/**
|
|
1449
|
+
* Merge enrichment metadata into an indexed document's points; `null` if
|
|
1450
|
+
* not indexed. `options.lockWaitMs` bounds the document-lock wait (D118).
|
|
1451
|
+
*/
|
|
1452
|
+
updateMetadata(ref: string, metadata: Record<string, unknown>, options?: DocumentLockOptions): Promise<Record<string, unknown> | null>;
|
|
1453
|
+
/**
|
|
1454
|
+
* Run `work` under the processor's document lock of `ref` (D98), e.g. a
|
|
1455
|
+
* whole-document delete. `ref` is any document key: a source reference,
|
|
1456
|
+
* or `fileLockKey(path)` for a file (`POST /rebuild-metadata`).
|
|
1457
|
+
* `options.lockWaitMs` bounds the wait (D118).
|
|
1458
|
+
*/
|
|
1459
|
+
withLock<T>(ref: string, operation: string, work: () => Promise<T>, options?: DocumentLockOptions): Promise<T>;
|
|
1460
|
+
}
|
|
1461
|
+
/** A processor exposing source operations (`DocumentProcessor` implements it). */
|
|
1462
|
+
interface SourceOperationsProvider {
|
|
1463
|
+
/** Source operations bound to the processor's current rules and stores. */
|
|
1464
|
+
sourceOperations(): SourceOperationsInterface;
|
|
1465
|
+
}
|
|
1466
|
+
|
|
986
1467
|
/**
|
|
987
1468
|
* @module processor/types
|
|
988
1469
|
* Document processor interface definitions.
|
|
@@ -998,10 +1479,16 @@ interface DocumentProcessorInterface {
|
|
|
998
1479
|
processFile(filePath: string): Promise<void>;
|
|
999
1480
|
/** Delete a file's points/metadata from the system. */
|
|
1000
1481
|
deleteFile(filePath: string): Promise<void>;
|
|
1001
|
-
/**
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1482
|
+
/**
|
|
1483
|
+
* Process a metadata sidecar update for a file (payload update only).
|
|
1484
|
+
* `options.lockWaitMs` bounds the document-lock wait (API routes, D118).
|
|
1485
|
+
*/
|
|
1486
|
+
processMetadataUpdate(filePath: string, metadata: Record<string, unknown>, options?: DocumentLockOptions): Promise<Record<string, unknown> | null>;
|
|
1487
|
+
/**
|
|
1488
|
+
* Process a rules update for a file (rebuild merged metadata, payload
|
|
1489
|
+
* update only). `options.lockWaitMs` bounds the document-lock wait.
|
|
1490
|
+
*/
|
|
1491
|
+
processRulesUpdate(filePath: string, options?: DocumentLockOptions): Promise<Record<string, unknown> | null>;
|
|
1005
1492
|
/** Render a file through the rule engine without embedding. */
|
|
1006
1493
|
renderFile(filePath: string): Promise<RenderResult>;
|
|
1007
1494
|
/** Move a file's vector points and metadata from old path to new path (no re-embed). */
|
|
@@ -1009,76 +1496,61 @@ interface DocumentProcessorInterface {
|
|
|
1009
1496
|
/** Update compiled inference rules and associated engines. */
|
|
1010
1497
|
updateRules(compiledRules: CompiledRule[], templateEngine?: TemplateEngine, customMapLib?: Record<string, (...args: unknown[]) => unknown>): void;
|
|
1011
1498
|
}
|
|
1012
|
-
|
|
1013
1499
|
/**
|
|
1014
|
-
*
|
|
1015
|
-
*
|
|
1016
|
-
*
|
|
1500
|
+
* The processor the service runs on: file operations plus source operations.
|
|
1501
|
+
* `createDocumentProcessor` returns it; the API server and the notify queue
|
|
1502
|
+
* depend on it (`DocumentProcessor` implements it). Adapt a custom file-only
|
|
1503
|
+
* processor with `withoutSourceSupport`, whose source operations fail.
|
|
1017
1504
|
*/
|
|
1505
|
+
type WatcherProcessor = DocumentProcessorInterface & SourceOperationsProvider;
|
|
1018
1506
|
|
|
1019
1507
|
/**
|
|
1020
|
-
*
|
|
1508
|
+
* @module processor
|
|
1021
1509
|
*
|
|
1022
|
-
*
|
|
1510
|
+
* Core document processing pipeline. Resolves files and source documents, computes embeddings, syncs with vector store.
|
|
1023
1511
|
*/
|
|
1024
|
-
|
|
1025
|
-
/** Processor configuration (chunk sizes, directories, maps). */
|
|
1026
|
-
config: ProcessorConfig;
|
|
1027
|
-
/** Provider for generating text embeddings. */
|
|
1028
|
-
embeddingProvider: EmbeddingProvider;
|
|
1029
|
-
/** Vector store for persistence. */
|
|
1030
|
-
vectorStore: VectorStore;
|
|
1031
|
-
/** Pre-compiled inference rules for metadata extraction. */
|
|
1032
|
-
compiledRules: CompiledRule[];
|
|
1033
|
-
/** Pino logger instance. */
|
|
1034
|
-
logger: pino.Logger;
|
|
1035
|
-
/** Optional Handlebars template engine for content templates. */
|
|
1036
|
-
templateEngine?: TemplateEngine;
|
|
1037
|
-
/** Optional enrichment store for persisted enrichment metadata. */
|
|
1038
|
-
enrichmentStore?: EnrichmentStoreInterface;
|
|
1039
|
-
/** Optional issues manager for tracking processing errors. */
|
|
1040
|
-
issuesManager?: IssuesManager;
|
|
1041
|
-
/** Optional values manager for tracking rule-extracted values. */
|
|
1042
|
-
valuesManager?: ValuesManager;
|
|
1043
|
-
/** Optional content hash cache for move detection. */
|
|
1044
|
-
contentHashCache?: ContentHashCache;
|
|
1045
|
-
}
|
|
1512
|
+
|
|
1046
1513
|
/**
|
|
1047
1514
|
* Core document processing pipeline.
|
|
1048
1515
|
*
|
|
1049
1516
|
* Handles extracting text, computing embeddings, and syncing with the vector store.
|
|
1050
1517
|
*/
|
|
1051
|
-
declare class DocumentProcessor implements
|
|
1518
|
+
declare class DocumentProcessor implements WatcherProcessor {
|
|
1519
|
+
private readonly deps;
|
|
1052
1520
|
private config;
|
|
1053
|
-
private readonly embeddingProvider;
|
|
1054
|
-
private readonly vectorStore;
|
|
1055
1521
|
private compiledRules;
|
|
1056
|
-
private readonly logger;
|
|
1057
1522
|
private templateEngine?;
|
|
1058
|
-
private readonly
|
|
1059
|
-
private readonly issuesManager?;
|
|
1060
|
-
private readonly valuesManager?;
|
|
1061
|
-
private readonly contentHashCache?;
|
|
1523
|
+
private readonly locks;
|
|
1062
1524
|
/**
|
|
1063
1525
|
* Create a new DocumentProcessor.
|
|
1064
1526
|
*
|
|
1065
1527
|
* @param deps - The processor dependencies.
|
|
1066
1528
|
*/
|
|
1067
|
-
constructor(
|
|
1068
|
-
/**
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
private
|
|
1529
|
+
constructor(deps: DocumentProcessorDeps);
|
|
1530
|
+
/** The processing ceilings now (read per document, D44). */
|
|
1531
|
+
private limits;
|
|
1532
|
+
/** Rule context reflecting the current rules, templates and config. */
|
|
1533
|
+
private ruleContext;
|
|
1534
|
+
/** Shared pipeline dependencies. */
|
|
1535
|
+
private pipelineContext;
|
|
1536
|
+
/** File resolver bound to the current rule context. */
|
|
1537
|
+
private fileResolver;
|
|
1538
|
+
/** Dependencies of the payload-only file operations. */
|
|
1539
|
+
private fileOperations;
|
|
1072
1540
|
/**
|
|
1073
|
-
*
|
|
1541
|
+
* Run a file operation with standard failure handling: log, and record a
|
|
1542
|
+
* typed issue when `context.issueType` (the code for untagged failures)
|
|
1543
|
+
* is given; return `fallback` on failure.
|
|
1074
1544
|
*/
|
|
1075
|
-
private
|
|
1545
|
+
private withFailureHandling;
|
|
1076
1546
|
/**
|
|
1077
1547
|
* Process a file through the full pipeline: extract, hash, chunk, embed, upsert.
|
|
1078
1548
|
*
|
|
1079
1549
|
* @param filePath - The file to process.
|
|
1080
1550
|
*/
|
|
1081
1551
|
processFile(filePath: string): Promise<void>;
|
|
1552
|
+
/** {@inheritDoc SourceOperationsProvider.sourceOperations} */
|
|
1553
|
+
sourceOperations(): SourceOperationsInterface;
|
|
1082
1554
|
/**
|
|
1083
1555
|
* Delete all chunks for a file from the vector store and remove metadata.
|
|
1084
1556
|
*
|
|
@@ -1086,22 +1558,28 @@ declare class DocumentProcessor implements DocumentProcessorInterface {
|
|
|
1086
1558
|
*/
|
|
1087
1559
|
deleteFile(filePath: string): Promise<void>;
|
|
1088
1560
|
/**
|
|
1089
|
-
* Process a metadata update: merge into enrichment store, update Qdrant
|
|
1561
|
+
* Process a metadata update: merge into enrichment store, update Qdrant
|
|
1562
|
+
* payloads (no re-embed). The stored `file_path` (casing included) and
|
|
1563
|
+
* `matched_rules` are kept.
|
|
1090
1564
|
*
|
|
1091
1565
|
* @param filePath - The file whose metadata to update.
|
|
1092
1566
|
* @param metadata - The new metadata to merge.
|
|
1567
|
+
* @param options - Bounded lock wait (API routes, D118).
|
|
1093
1568
|
* @returns The merged payload, or `null` if the file is not indexed.
|
|
1569
|
+
* @throws DocumentLockTimeoutError when a bounded lock wait runs out.
|
|
1094
1570
|
*/
|
|
1095
|
-
processMetadataUpdate(filePath: string, metadata: Record<string, unknown
|
|
1571
|
+
processMetadataUpdate(filePath: string, metadata: Record<string, unknown>, options?: DocumentLockOptions): Promise<Record<string, unknown> | null>;
|
|
1096
1572
|
/**
|
|
1097
|
-
* Re-apply inference rules to a file without re-embedding
|
|
1098
|
-
*
|
|
1099
|
-
*
|
|
1573
|
+
* Re-apply inference rules to a file without re-embedding (see
|
|
1574
|
+
* `reapplyFileRules`: system fields and the stored `file_path` are
|
|
1575
|
+
* re-asserted; interpolation failures are recorded as an issue).
|
|
1100
1576
|
*
|
|
1101
1577
|
* @param filePath - The file to update.
|
|
1578
|
+
* @param options - Bounded lock wait (API routes, D118).
|
|
1102
1579
|
* @returns The merged metadata, or `null` if the file is not indexed.
|
|
1580
|
+
* @throws DocumentLockTimeoutError when a bounded lock wait runs out.
|
|
1103
1581
|
*/
|
|
1104
|
-
processRulesUpdate(filePath: string): Promise<Record<string, unknown> | null>;
|
|
1582
|
+
processRulesUpdate(filePath: string, options?: DocumentLockOptions): Promise<Record<string, unknown> | null>;
|
|
1105
1583
|
/**
|
|
1106
1584
|
* Render a file through the rule engine without embedding.
|
|
1107
1585
|
* Returns rendered content, renderAs, matched rules, and metadata.
|
|
@@ -1128,10 +1606,29 @@ declare class DocumentProcessor implements DocumentProcessorInterface {
|
|
|
1128
1606
|
updateRules(compiledRules: CompiledRule[], templateEngine?: TemplateEngine, customMapLib?: Record<string, (...args: unknown[]) => unknown>): void;
|
|
1129
1607
|
}
|
|
1130
1608
|
|
|
1609
|
+
/**
|
|
1610
|
+
* @module queue/pausable
|
|
1611
|
+
* The pause/resume/quiesce surface shared by the file event queue and the source notify queue, and a combinator that drives several queues as one (used by prune). No I/O.
|
|
1612
|
+
*/
|
|
1613
|
+
/**
|
|
1614
|
+
* A queue that can stop starting new work, resume, and report when its
|
|
1615
|
+
* in-flight work has finished. Prune uses this to quiesce every writer
|
|
1616
|
+
* before it computes and executes its plan.
|
|
1617
|
+
*/
|
|
1618
|
+
interface PausableQueue {
|
|
1619
|
+
/** Stop starting new work; enqueues are still accepted. */
|
|
1620
|
+
pause(): void;
|
|
1621
|
+
/** Resume starting work. */
|
|
1622
|
+
resume(): void;
|
|
1623
|
+
/** Resolve once no work is in flight (queued work may remain). */
|
|
1624
|
+
waitForIdleWorkers(): Promise<void>;
|
|
1625
|
+
}
|
|
1626
|
+
|
|
1131
1627
|
/**
|
|
1132
1628
|
* @module queue
|
|
1133
|
-
* Debounced,
|
|
1629
|
+
* Debounced, concurrent event queue for file watchers. Manages priority queuing and async callbacks. Embedding request rate is limited by the shared embedding provider wrapper, not here. No direct I/O.
|
|
1134
1630
|
*/
|
|
1631
|
+
|
|
1135
1632
|
/**
|
|
1136
1633
|
* A watch event.
|
|
1137
1634
|
*/
|
|
@@ -1157,27 +1654,22 @@ interface EventQueueOptions {
|
|
|
1157
1654
|
debounceMs: number;
|
|
1158
1655
|
/** Maximum number of concurrent processors. */
|
|
1159
1656
|
concurrency: number;
|
|
1160
|
-
/** Optional max processed events per minute (token bucket). */
|
|
1161
|
-
rateLimitPerMinute?: number;
|
|
1162
1657
|
}
|
|
1163
1658
|
/**
|
|
1164
|
-
* A debounced,
|
|
1659
|
+
* A debounced, concurrent event queue.
|
|
1165
1660
|
*/
|
|
1166
1661
|
declare class EventQueue {
|
|
1167
1662
|
private readonly debounceMs;
|
|
1168
1663
|
private readonly concurrency;
|
|
1169
|
-
private readonly rateLimitPerMinute?;
|
|
1170
1664
|
private started;
|
|
1171
1665
|
private paused;
|
|
1666
|
+
private stopped;
|
|
1172
1667
|
private active;
|
|
1173
1668
|
private readonly debounceTimers;
|
|
1174
1669
|
private readonly latestByKey;
|
|
1175
1670
|
private readonly normalQueue;
|
|
1176
1671
|
private readonly lowQueue;
|
|
1177
|
-
private
|
|
1178
|
-
private lastRefillMs;
|
|
1179
|
-
private drainWaiters;
|
|
1180
|
-
private idleWorkerWaiters;
|
|
1672
|
+
private readonly signals;
|
|
1181
1673
|
/**
|
|
1182
1674
|
* Create an event queue.
|
|
1183
1675
|
*
|
|
@@ -1185,16 +1677,25 @@ declare class EventQueue {
|
|
|
1185
1677
|
*/
|
|
1186
1678
|
constructor(options: EventQueueOptions);
|
|
1187
1679
|
/**
|
|
1188
|
-
* Enqueue an event, debounced per path+priority.
|
|
1680
|
+
* Enqueue an event, debounced per path+priority. Ignored once stopped.
|
|
1189
1681
|
*
|
|
1190
1682
|
* @param event - The watch event.
|
|
1191
1683
|
* @param fn - The processing function to invoke when dequeued.
|
|
1192
1684
|
*/
|
|
1193
1685
|
enqueue(event: WatchEvent, fn: ProcessFn): void;
|
|
1194
1686
|
/**
|
|
1195
|
-
* Start processing events.
|
|
1687
|
+
* Start processing events (events enqueued earlier are held until now).
|
|
1688
|
+
*/
|
|
1689
|
+
start(): void;
|
|
1690
|
+
/**
|
|
1691
|
+
* Alias of {@link EventQueue.start}, kept for existing callers.
|
|
1196
1692
|
*/
|
|
1197
1693
|
process(): void;
|
|
1694
|
+
/**
|
|
1695
|
+
* Stop: cancel pending debounces, drop queued events, ignore new ones, and
|
|
1696
|
+
* resolve once in-flight work finishes. Drain waiters resolve then too.
|
|
1697
|
+
*/
|
|
1698
|
+
stop(): Promise<void>;
|
|
1198
1699
|
/**
|
|
1199
1700
|
* Pause processing events. Events can still be enqueued but will not be processed.
|
|
1200
1701
|
*/
|
|
@@ -1218,13 +1719,136 @@ declare class EventQueue {
|
|
|
1218
1719
|
*/
|
|
1219
1720
|
waitForIdleWorkers(): Promise<void>;
|
|
1220
1721
|
private push;
|
|
1221
|
-
private refillTokens;
|
|
1222
|
-
private takeToken;
|
|
1223
1722
|
private nextItem;
|
|
1224
1723
|
private pump;
|
|
1225
1724
|
private isIdle;
|
|
1226
|
-
private
|
|
1227
|
-
|
|
1725
|
+
private settle;
|
|
1726
|
+
}
|
|
1727
|
+
|
|
1728
|
+
/**
|
|
1729
|
+
* @module queue/sourceNotifyTypes
|
|
1730
|
+
* Options, errors and job bookkeeping types of the source notify queue (validated options schema, stopped error, coalesced jobs and their waiters). No I/O.
|
|
1731
|
+
*/
|
|
1732
|
+
|
|
1733
|
+
/**
|
|
1734
|
+
* Default number of references processed at once: the core
|
|
1735
|
+
* `embedding.concurrency` default, which the service passes in.
|
|
1736
|
+
*/
|
|
1737
|
+
declare const DEFAULT_SOURCE_NOTIFY_CONCURRENCY: number;
|
|
1738
|
+
/** Options for the source notify queue. */
|
|
1739
|
+
declare const sourceNotifyQueueOptionsSchema: z.ZodObject<{
|
|
1740
|
+
concurrency: z.ZodDefault<z.ZodNumber>;
|
|
1741
|
+
}, z.core.$strip>;
|
|
1742
|
+
/** Options for the source notify queue (input form; defaults applied). */
|
|
1743
|
+
type SourceNotifyQueueOptions = z.input<typeof sourceNotifyQueueOptionsSchema>;
|
|
1744
|
+
/** Issues-store operations the queue needs. */
|
|
1745
|
+
type SourceQueueIssues = Pick<IssuesManager, 'record' | 'clear'>;
|
|
1746
|
+
/** Per-run options of `SourceNotifyQueue.processNow`. */
|
|
1747
|
+
interface ProcessNowOptions {
|
|
1748
|
+
/**
|
|
1749
|
+
* Re-embed even when content is unchanged (reindex scope `full`). Merged
|
|
1750
|
+
* as OR into a run it joins.
|
|
1751
|
+
*/
|
|
1752
|
+
force?: boolean;
|
|
1753
|
+
}
|
|
1754
|
+
/** Rejection for `SourceNotifyQueue.processNow` after `stop()`. */
|
|
1755
|
+
declare class SourceNotifyQueueStoppedError extends Error {
|
|
1756
|
+
/** Create the error. */
|
|
1757
|
+
constructor();
|
|
1758
|
+
}
|
|
1759
|
+
|
|
1760
|
+
/**
|
|
1761
|
+
* @module queue/SourceNotifyQueue
|
|
1762
|
+
* In-memory notify queue for source documents, keyed by reference: pending notifications merge, in-flight ones mark the reference dirty for exactly one re-run. Runs each reference through the source operations; records an issue when a run rejects unexpectedly.
|
|
1763
|
+
*/
|
|
1764
|
+
|
|
1765
|
+
/** What the queue runs: one reference with its designated rule. */
|
|
1766
|
+
type SourceProcess = Pick<SourceOperationsInterface, 'process'>;
|
|
1767
|
+
/**
|
|
1768
|
+
* Coalescing queue for source-document notifications (Decision 12).
|
|
1769
|
+
*
|
|
1770
|
+
* - A notification for a **pending** reference is merged into it (the latest
|
|
1771
|
+
* rule wins; the reference keeps its place in line).
|
|
1772
|
+
* - One for an **in-flight** reference marks it dirty: when the current run
|
|
1773
|
+
* ends the reference is queued once more (at the back), however many
|
|
1774
|
+
* notifications arrived meanwhile.
|
|
1775
|
+
* - Every run calls `process`, which retrieves current state, so a
|
|
1776
|
+
* burst on one reference costs at most two retrievals and the final state
|
|
1777
|
+
* wins. Runs never overlap for the same reference.
|
|
1778
|
+
*
|
|
1779
|
+
* References are compared exactly (case-sensitive), like source point IDs.
|
|
1780
|
+
* The queue holds work until {@link start}; {@link pause} (prune) stops new
|
|
1781
|
+
* runs without rejecting enqueues. Failures never escape: `process`
|
|
1782
|
+
* records issues itself, and an unexpected rejection becomes a `failed`
|
|
1783
|
+
* result and an `extraction_error` issue (with the designated rule).
|
|
1784
|
+
*
|
|
1785
|
+
* Reindex runs go through {@link processNow} as well, so a notification and
|
|
1786
|
+
* a reindex of one reference never run in parallel and the latest state wins.
|
|
1787
|
+
*/
|
|
1788
|
+
declare class SourceNotifyQueue implements PausableQueue {
|
|
1789
|
+
private readonly processor;
|
|
1790
|
+
private readonly logger?;
|
|
1791
|
+
private readonly issues?;
|
|
1792
|
+
private readonly concurrency;
|
|
1793
|
+
private started;
|
|
1794
|
+
private paused;
|
|
1795
|
+
private stopped;
|
|
1796
|
+
private readonly pending;
|
|
1797
|
+
private readonly inFlight;
|
|
1798
|
+
private readonly signals;
|
|
1799
|
+
/**
|
|
1800
|
+
* @param processor - Processes one reference with its designated rule
|
|
1801
|
+
* (source operations).
|
|
1802
|
+
* @param options - Queue options (validated).
|
|
1803
|
+
* @param logger - Logger for unexpected processing rejections.
|
|
1804
|
+
* @param issues - Issues store for unexpected processing rejections.
|
|
1805
|
+
*/
|
|
1806
|
+
constructor(processor: SourceProcess, options?: SourceNotifyQueueOptions, logger?: pino.Logger | undefined, issues?: SourceQueueIssues | undefined);
|
|
1807
|
+
/**
|
|
1808
|
+
* Notify that a source document changed (fire and forget).
|
|
1809
|
+
*
|
|
1810
|
+
* @param ref - The exact `<name>://<id>` reference.
|
|
1811
|
+
* @param rule - The designated rule name.
|
|
1812
|
+
* @returns `false` when the queue is stopped and the notification was dropped.
|
|
1813
|
+
*/
|
|
1814
|
+
enqueue(ref: string, rule: string): boolean;
|
|
1815
|
+
/**
|
|
1816
|
+
* Process a reference and resolve with the result of a run that started
|
|
1817
|
+
* after this call, so the result reflects the source's state at or after
|
|
1818
|
+
* the call (the `?wait=true` path). Coalesces with other notifications:
|
|
1819
|
+
* if the reference is pending, this joins that run; if it is in flight,
|
|
1820
|
+
* this waits for the current run and then the one dirty re-run.
|
|
1821
|
+
*
|
|
1822
|
+
* @param ref - The exact `<name>://<id>` reference.
|
|
1823
|
+
* @param rule - The designated rule name.
|
|
1824
|
+
* @param options - `force` re-embeds unchanged content.
|
|
1825
|
+
* @returns The per-document result.
|
|
1826
|
+
* @throws {@link SourceNotifyQueueStoppedError} (as a rejection) when the
|
|
1827
|
+
* queue is stopped before the run starts.
|
|
1828
|
+
*/
|
|
1829
|
+
processNow(ref: string, rule: string, options?: ProcessNowOptions): Promise<DocumentResult>;
|
|
1830
|
+
/** Start processing (work enqueued earlier is held until now). */
|
|
1831
|
+
start(): void;
|
|
1832
|
+
/** {@inheritDoc PausableQueue.pause} */
|
|
1833
|
+
pause(): void;
|
|
1834
|
+
/** {@inheritDoc PausableQueue.resume} */
|
|
1835
|
+
resume(): void;
|
|
1836
|
+
/** {@inheritDoc PausableQueue.waitForIdleWorkers} */
|
|
1837
|
+
waitForIdleWorkers(): Promise<void>;
|
|
1838
|
+
/** Resolve once nothing is pending, owed (dirty) or in flight. */
|
|
1839
|
+
drain(): Promise<void>;
|
|
1840
|
+
/**
|
|
1841
|
+
* Stop: drop pending and owed runs (their `processNow` callers reject with
|
|
1842
|
+
* {@link SourceNotifyQueueStoppedError}), refuse new work, and resolve once
|
|
1843
|
+
* in-flight runs finish.
|
|
1844
|
+
*/
|
|
1845
|
+
stop(): Promise<void>;
|
|
1846
|
+
private schedule;
|
|
1847
|
+
private pump;
|
|
1848
|
+
private run;
|
|
1849
|
+
private execute;
|
|
1850
|
+
private isIdle;
|
|
1851
|
+
private settle;
|
|
1228
1852
|
}
|
|
1229
1853
|
|
|
1230
1854
|
/**
|
|
@@ -1270,6 +1894,166 @@ declare class CommitMessageGenerator {
|
|
|
1270
1894
|
generate(files: string[], diffSummary: string): Promise<string | null>;
|
|
1271
1895
|
}
|
|
1272
1896
|
|
|
1897
|
+
/**
|
|
1898
|
+
* @module vcs/RootGitLock
|
|
1899
|
+
* Per-root, in-process FIFO async mutex serialising the watcher's own git work on a root: batch commits (with push), squash, untracking and temp-file sweeps (D66, D81). Never re-entered. Logs long waits and holds; an API route's wait is bounded (D102).
|
|
1900
|
+
*
|
|
1901
|
+
* It cannot exclude other processes (people and agents run git in the same
|
|
1902
|
+
* repositories), so everything done under it must also be safe without it.
|
|
1903
|
+
*/
|
|
1904
|
+
|
|
1905
|
+
/** FIFO mutex for one VCS root. */
|
|
1906
|
+
declare class RootGitLock {
|
|
1907
|
+
private readonly lock;
|
|
1908
|
+
/**
|
|
1909
|
+
* @param root - Repository root (named in warnings).
|
|
1910
|
+
* @param logger - Logger for long-wait and long-hold warnings.
|
|
1911
|
+
*/
|
|
1912
|
+
constructor(root: string, logger: pino.Logger);
|
|
1913
|
+
/** The operation holding the lock, if any. */
|
|
1914
|
+
get heldBy(): string | undefined;
|
|
1915
|
+
/**
|
|
1916
|
+
* Run `work` while holding the lock. Callers queue in arrival order; the
|
|
1917
|
+
* lock is released when `work` settles, whatever its outcome.
|
|
1918
|
+
*
|
|
1919
|
+
* @param operation - Operation name, for warnings and {@link heldBy}.
|
|
1920
|
+
* @param work - The work to run under the lock (must not take it again).
|
|
1921
|
+
* @returns What `work` returns.
|
|
1922
|
+
*/
|
|
1923
|
+
run<T>(operation: string, work: () => Promise<T>): Promise<T>;
|
|
1924
|
+
/**
|
|
1925
|
+
* {@link run}, giving up when the lock is not acquired within `waitMs`
|
|
1926
|
+
* (D102). A caller that gives up never runs `work`; its place in the
|
|
1927
|
+
* queue passes straight on, so later callers keep their order.
|
|
1928
|
+
*
|
|
1929
|
+
* @param operation - Operation name, for warnings and {@link heldBy}.
|
|
1930
|
+
* @param waitMs - Longest wait for the lock.
|
|
1931
|
+
* @param work - The work to run under the lock (must not take it again).
|
|
1932
|
+
* @returns What `work` returns.
|
|
1933
|
+
* @throws LockWaitTimeoutError when the wait runs out.
|
|
1934
|
+
*/
|
|
1935
|
+
runWithin<T>(operation: string, waitMs: number, work: () => Promise<T>): Promise<T>;
|
|
1936
|
+
}
|
|
1937
|
+
|
|
1938
|
+
/**
|
|
1939
|
+
* @module vcs/squashPlumbing
|
|
1940
|
+
* Plumbing-only history rewrite for squash retention (D148, D166): list the first-parent history, rebuild it with `commit-tree` from a parentless baseline, keeping each retained commit's tree, raw message, identities and raw dates. Never touches the working tree or the index.
|
|
1941
|
+
*/
|
|
1942
|
+
/** Commit metadata for retention calculation. */
|
|
1943
|
+
interface CommitInfo {
|
|
1944
|
+
/** Full hash. */
|
|
1945
|
+
hash: string;
|
|
1946
|
+
/** Author date. */
|
|
1947
|
+
date: Date;
|
|
1948
|
+
}
|
|
1949
|
+
|
|
1950
|
+
/**
|
|
1951
|
+
* @module vcs/SquashManager
|
|
1952
|
+
* Scheduled squash retention for one VCS root: under RootGitLock, flush the pending batch, then rewrite the branch in plumbing and move it with a compare-and-swap `update-ref` (D101, D148, D166). Force-pushes when a remote is set.
|
|
1953
|
+
*
|
|
1954
|
+
* No checkout, reset or cherry-pick runs, so the working tree and the index
|
|
1955
|
+
* are never touched: a file untracked by `/vcs/exclude` or the size cap
|
|
1956
|
+
* keeps its newest content on disk, and no clean tree is needed. Squash
|
|
1957
|
+
* still refuses while a merge, rebase, cherry-pick or revert is in
|
|
1958
|
+
* progress, or when HEAD is not on the configured branch (D20).
|
|
1959
|
+
*/
|
|
1960
|
+
|
|
1961
|
+
/** Result of a squash operation. */
|
|
1962
|
+
interface SquashResult {
|
|
1963
|
+
squashed: boolean;
|
|
1964
|
+
commitsRemoved?: number;
|
|
1965
|
+
commitsRetained?: number;
|
|
1966
|
+
error?: string;
|
|
1967
|
+
}
|
|
1968
|
+
/** Test hooks around the reference update (not public API). @internal */
|
|
1969
|
+
interface SquashHooks {
|
|
1970
|
+
/** Receives the rebuilt tip; returns the tip to check and publish. */
|
|
1971
|
+
rebuiltTip?: (tip: string) => Promise<string>;
|
|
1972
|
+
/** Runs after the tree check, just before `update-ref`. */
|
|
1973
|
+
beforeUpdateRef?: () => Promise<void>;
|
|
1974
|
+
}
|
|
1975
|
+
/** Options for SquashManager construction beyond the required params. */
|
|
1976
|
+
interface SquashManagerOptions {
|
|
1977
|
+
/** Git branch name for squash operations. Default: "master". */
|
|
1978
|
+
branch?: string;
|
|
1979
|
+
/** The root's lock; squash holds it for its whole run (D81). */
|
|
1980
|
+
lock: RootGitLock;
|
|
1981
|
+
/**
|
|
1982
|
+
* Commit pending changes inside the hold through the non-locking commit
|
|
1983
|
+
* path (D101). Resolves false when that commit failed (squash refuses).
|
|
1984
|
+
*/
|
|
1985
|
+
flushInHold?: () => Promise<boolean>;
|
|
1986
|
+
/** Remote URL for force-push after squash. */
|
|
1987
|
+
remoteUrl?: string;
|
|
1988
|
+
/** Access token for HTTPS push authentication. */
|
|
1989
|
+
accessToken?: string;
|
|
1990
|
+
/** Test hooks (not public API). @internal */
|
|
1991
|
+
hooks?: SquashHooks;
|
|
1992
|
+
}
|
|
1993
|
+
/**
|
|
1994
|
+
* Manages scheduled squash retention for a single VCS root.
|
|
1995
|
+
*
|
|
1996
|
+
* Runs on a cron schedule (checked every 60s). When triggered, squashes
|
|
1997
|
+
* commits older than the retention boundary (the tighter of maxAgeDays
|
|
1998
|
+
* and maxVersions) into a single "historical baseline" commit and
|
|
1999
|
+
* recreates the retained commits on top of it.
|
|
2000
|
+
*/
|
|
2001
|
+
declare class SquashManager {
|
|
2002
|
+
private readonly rootPath;
|
|
2003
|
+
private readonly retention;
|
|
2004
|
+
private readonly logger;
|
|
2005
|
+
private readonly options;
|
|
2006
|
+
private readonly branch;
|
|
2007
|
+
private intervalTimer;
|
|
2008
|
+
private running;
|
|
2009
|
+
constructor(rootPath: string, retention: VcsRetentionConfig, logger: pino.Logger, options: SquashManagerOptions);
|
|
2010
|
+
/**
|
|
2011
|
+
* Start the cron-based squash scheduler.
|
|
2012
|
+
* Checks every 60 seconds if the cron expression matches.
|
|
2013
|
+
*/
|
|
2014
|
+
start(): void;
|
|
2015
|
+
/**
|
|
2016
|
+
* Stop the cron scheduler.
|
|
2017
|
+
*/
|
|
2018
|
+
stop(): void;
|
|
2019
|
+
/**
|
|
2020
|
+
* Run the squash under the root's lock: flush, guard, rewrite, publish,
|
|
2021
|
+
* force-push. Exposed publicly for testing.
|
|
2022
|
+
*/
|
|
2023
|
+
runSquash(): Promise<SquashResult>;
|
|
2024
|
+
/**
|
|
2025
|
+
* Refuse while an abandoned cherry-pick, rebase or merge is present, or
|
|
2026
|
+
* when HEAD is not on the configured branch (#249, D20: report only).
|
|
2027
|
+
*
|
|
2028
|
+
* @returns The refusal reason, or undefined if the squash may proceed.
|
|
2029
|
+
*/
|
|
2030
|
+
private checkRepoPreconditions;
|
|
2031
|
+
/** Rewrite and publish the branch (inside the hold). */
|
|
2032
|
+
private squashBranch;
|
|
2033
|
+
/** Log a finished squash, force push if configured, and report it. */
|
|
2034
|
+
private completed;
|
|
2035
|
+
/**
|
|
2036
|
+
* Get all first-parent commits of HEAD in chronological order (oldest
|
|
2037
|
+
* first), or none when HEAD is unborn.
|
|
2038
|
+
*/
|
|
2039
|
+
getCommitLog(): Promise<CommitInfo[]>;
|
|
2040
|
+
/**
|
|
2041
|
+
* Calculate the retention boundary index.
|
|
2042
|
+
* Returns the index of the oldest commit to KEEP.
|
|
2043
|
+
* All commits before this index will be squashed into a baseline.
|
|
2044
|
+
*
|
|
2045
|
+
* Strategy: find the tighter constraint between age and count.
|
|
2046
|
+
* - Age: keep commits newer than maxAgeDays
|
|
2047
|
+
* - Count: keep the last maxVersions commits
|
|
2048
|
+
* The boundary is the one that retains FEWER old commits (tighter).
|
|
2049
|
+
*/
|
|
2050
|
+
calculateRetentionBoundary(commits: CommitInfo[]): number;
|
|
2051
|
+
/**
|
|
2052
|
+
* Force push to remote after squash (history rewrite requires force).
|
|
2053
|
+
*/
|
|
2054
|
+
private forcePushIfConfigured;
|
|
2055
|
+
}
|
|
2056
|
+
|
|
1273
2057
|
/**
|
|
1274
2058
|
* @module vcs/types
|
|
1275
2059
|
* Shared types for the VCS subsystem.
|
|
@@ -1288,7 +2072,7 @@ interface PushError {
|
|
|
1288
2072
|
|
|
1289
2073
|
/**
|
|
1290
2074
|
* @module vcs/VcsManager
|
|
1291
|
-
* Per-root VCS manager for git-backed content versioning.
|
|
2075
|
+
* Per-root VCS manager for git-backed content versioning: a throttled batch queue, a circuit breaker, the root's RootGitLock, squash scheduling and startup maintenance. Commits run through {@link BatchCommitter} under the lock.
|
|
1292
2076
|
*/
|
|
1293
2077
|
|
|
1294
2078
|
/** Per-root circuit breaker state, exposed via /vcs/status. */
|
|
@@ -1296,75 +2080,56 @@ interface VcsBreakerState extends CircuitBreakerSnapshot {
|
|
|
1296
2080
|
/** Files queued or in flight, not yet committed. */
|
|
1297
2081
|
pendingCount: number;
|
|
1298
2082
|
}
|
|
2083
|
+
/** Optional VcsManager collaborators. */
|
|
2084
|
+
interface VcsManagerOptions {
|
|
2085
|
+
/** `vcs.maxFileBytes` in bytes, read at each staging (D67). */
|
|
2086
|
+
getMaxFileBytes?: () => number;
|
|
2087
|
+
/** Path-list timeout override (tests only). */
|
|
2088
|
+
timeoutFor?: (paths: number) => number;
|
|
2089
|
+
}
|
|
1299
2090
|
/**
|
|
1300
|
-
* Per-root VCS manager
|
|
1301
|
-
*
|
|
1302
|
-
* Each VCS-enabled watch root gets its own VcsManager instance, which owns
|
|
1303
|
-
* a throttled commit pipeline: file changes are batched, staged, committed
|
|
1304
|
-
* (with optional AI-generated messages), and optionally pushed to a remote.
|
|
1305
|
-
*
|
|
1306
|
-
* Concurrency: only one commit is in-flight at a time per root. Index.lock
|
|
1307
|
-
* contention is handled with exponential backoff retries (D10). Failed
|
|
1308
|
-
* batches are always retained; a circuit breaker spaces out retries of a
|
|
1309
|
-
* persistently failing root (#249).
|
|
2091
|
+
* Per-root VCS manager: batches file changes and commits them under the
|
|
2092
|
+
* root's {@link RootGitLock}; failed batches are always retained (#249).
|
|
1310
2093
|
*/
|
|
1311
2094
|
declare class VcsManager {
|
|
1312
2095
|
readonly config: VcsConfig;
|
|
1313
2096
|
readonly rootPath: string;
|
|
1314
2097
|
readonly remoteUrl: string | undefined;
|
|
1315
|
-
|
|
2098
|
+
/** Serialises this root's git work (D66, D81). */
|
|
2099
|
+
readonly lock: RootGitLock;
|
|
1316
2100
|
private readonly logger;
|
|
1317
|
-
private readonly
|
|
2101
|
+
private readonly committer;
|
|
1318
2102
|
private readonly breaker;
|
|
1319
|
-
private readonly
|
|
2103
|
+
private readonly queue;
|
|
1320
2104
|
private readonly pendingReversions;
|
|
1321
|
-
private readonly _pushErrors;
|
|
1322
2105
|
private readonly squashManager;
|
|
1323
|
-
private
|
|
1324
|
-
private breakerRetryTimer;
|
|
1325
|
-
private commitInFlight;
|
|
1326
|
-
private inFlightFileCount;
|
|
2106
|
+
private sweepTimer;
|
|
1327
2107
|
private started;
|
|
1328
|
-
private paused;
|
|
1329
2108
|
private isBaseline;
|
|
1330
|
-
|
|
1331
|
-
constructor(rootPath: string, config: VcsConfig, logger: pino.Logger, commitMessageGenerator?: CommitMessageGenerator, remoteUrl?: string, accessToken?: string);
|
|
2109
|
+
constructor(rootPath: string, config: VcsConfig, logger: pino.Logger, commitMessageGenerator?: CommitMessageGenerator, remoteUrl?: string, accessToken?: string, options?: VcsManagerOptions);
|
|
1332
2110
|
get lastPushTime(): string | null;
|
|
1333
2111
|
get pushErrors(): readonly PushError[];
|
|
1334
2112
|
/** Current circuit breaker state and backlog, for /vcs/status. */
|
|
1335
2113
|
get breakerState(): VcsBreakerState;
|
|
2114
|
+
/** First breaker trip since the last success, for `health.vcs`. */
|
|
2115
|
+
get trippedSince(): string | null;
|
|
1336
2116
|
/**
|
|
1337
|
-
* Begin accepting file changes
|
|
1338
|
-
*
|
|
1339
|
-
*
|
|
1340
|
-
* Performs startup orphan detection/recovery before starting the squash
|
|
1341
|
-
* manager, ensuring the repo is on the configured branch, and reports
|
|
1342
|
-
* (never clears) an abandoned cherry-pick, rebase, or merge.
|
|
1343
|
-
*
|
|
1344
|
-
* Baseline mode (commit prefix `"baseline:"`) remains active until
|
|
1345
|
-
* {@link endBaseline} is called by the coordinator after the initial scan.
|
|
2117
|
+
* Begin accepting file changes after startup maintenance under the lock
|
|
2118
|
+
* (never a checkout, D167); start the hourly sweep and squash. Baseline
|
|
2119
|
+
* mode lasts until {@link endBaseline}.
|
|
1346
2120
|
*/
|
|
1347
2121
|
start(): Promise<void>;
|
|
1348
|
-
/**
|
|
1349
|
-
* Signal that the initial filesystem scan is complete.
|
|
1350
|
-
* Clears the baseline flag so subsequent commits use normal "watcher: batch" messages.
|
|
1351
|
-
*/
|
|
2122
|
+
/** Initial scan done: later commits use `watcher: batch` messages. */
|
|
1352
2123
|
endBaseline(): void;
|
|
1353
2124
|
/**
|
|
1354
|
-
* Add a file to the pending set and start the throttle timer
|
|
1355
|
-
*
|
|
1356
|
-
*
|
|
1357
|
-
* The circuit breaker is intentionally not reset here: recovery is
|
|
2125
|
+
* Add a file to the pending set and start the throttle timer; a full set
|
|
2126
|
+
* commits at once. The breaker is intentionally not reset here: recovery is
|
|
1358
2127
|
* time-based, so a busy root cannot hammer a deterministic failure.
|
|
1359
2128
|
*
|
|
1360
2129
|
* @param filePath - Absolute path of the changed file.
|
|
1361
2130
|
*/
|
|
1362
2131
|
fileChanged(filePath: string): void;
|
|
1363
|
-
/**
|
|
1364
|
-
* Record reversion metadata so the next commit uses a revert-prefixed message.
|
|
1365
|
-
*
|
|
1366
|
-
* @param reversion - The reversion metadata to record.
|
|
1367
|
-
*/
|
|
2132
|
+
/** Record a reversion so the next commit uses a revert-prefixed message. */
|
|
1368
2133
|
addPendingReversion(reversion: PendingReversion): void;
|
|
1369
2134
|
/**
|
|
1370
2135
|
* Queue a deleted file. Staging records the deletion if git tracks it.
|
|
@@ -1372,66 +2137,31 @@ declare class VcsManager {
|
|
|
1372
2137
|
* @param filePath - Absolute path of the deleted file.
|
|
1373
2138
|
*/
|
|
1374
2139
|
handleUnlink(filePath: string): void;
|
|
1375
|
-
/**
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
* Used by SquashManager to coordinate squash operations.
|
|
1379
|
-
*/
|
|
1380
|
-
pause(): Promise<void>;
|
|
1381
|
-
/**
|
|
1382
|
-
* Resume the commit pipeline after a pause.
|
|
1383
|
-
* Re-enables normal commit operations and starts a throttle timer
|
|
1384
|
-
* if there are pending files that accumulated during the pause.
|
|
1385
|
-
*/
|
|
1386
|
-
resume(): void;
|
|
1387
|
-
/**
|
|
1388
|
-
* Commit all pending files now, in batches of at most maxBatchSize.
|
|
1389
|
-
*/
|
|
2140
|
+
/** Push now; the caller holds {@link lock} (`/vcs/exclude`, D71). */
|
|
2141
|
+
pushInHold(): Promise<void>;
|
|
2142
|
+
/** Commit all pending files now, in batches of at most maxBatchSize. */
|
|
1390
2143
|
flush(): Promise<void>;
|
|
1391
|
-
/**
|
|
1392
|
-
* Stop accepting file changes, flush pending, and clean up timers.
|
|
1393
|
-
*/
|
|
2144
|
+
/** Stop accepting file changes, flush pending, and clean up timers. */
|
|
1394
2145
|
stop(): Promise<void>;
|
|
2146
|
+
/** Run a squash now (as the cron does); undefined when retention is off. */
|
|
2147
|
+
runSquash(): ReturnType<SquashManager['runSquash']> | undefined;
|
|
1395
2148
|
/**
|
|
1396
2149
|
* Add tracked-but-deleted paths (`git ls-files --deleted`) in this
|
|
1397
2150
|
* manager's watch scope to pending, so the next commit (typically the
|
|
1398
|
-
* baseline) records deletions
|
|
1399
|
-
* Called by the coordinator before flush/endBaseline on startup. See #249.
|
|
2151
|
+
* baseline) records deletions made while nothing was watching (#249).
|
|
1400
2152
|
*
|
|
1401
2153
|
* @param isInScope - Returns true if the absolute path routes to this
|
|
1402
2154
|
* manager (the coordinator's routing and watch-scope logic).
|
|
1403
2155
|
*/
|
|
1404
2156
|
reconcileDeletions(isInScope: (absolutePath: string) => boolean): Promise<void>;
|
|
1405
|
-
/** Take up to maxBatchSize files from the pending set. */
|
|
1406
|
-
private takeBatch;
|
|
1407
|
-
/** Chain a batch behind the in-flight commit, tracking it as backlog. */
|
|
1408
|
-
private enqueueBatch;
|
|
1409
|
-
/** Put files back in the pending set. Pending is a set, so this cannot grow it past the distinct paths seen. */
|
|
1410
|
-
private retain;
|
|
1411
|
-
private clearThrottle;
|
|
1412
2157
|
/**
|
|
1413
|
-
*
|
|
1414
|
-
*
|
|
1415
|
-
|
|
1416
|
-
private resetThrottle;
|
|
1417
|
-
private clearBreakerRetry;
|
|
1418
|
-
/**
|
|
1419
|
-
* Ensure a timer will flush pending files when the breaker's cooldown
|
|
1420
|
-
* elapses, without needing a new file-change event.
|
|
1421
|
-
*/
|
|
1422
|
-
private scheduleBreakerRetry;
|
|
1423
|
-
/**
|
|
1424
|
-
* Commit a batch with index.lock retry, stale lock detection, pause
|
|
1425
|
-
* support, and the circuit breaker. A failed batch is always retained.
|
|
1426
|
-
*/
|
|
1427
|
-
private commitBatch;
|
|
1428
|
-
/**
|
|
1429
|
-
* One commit attempt: stage, skip if nothing is staged, commit, push.
|
|
2158
|
+
* Commit a batch (the caller holds the lock) with index.lock retry,
|
|
2159
|
+
* stale lock removal and the circuit breaker. A failed batch is always
|
|
2160
|
+
* retained.
|
|
1430
2161
|
*
|
|
1431
|
-
* @returns true
|
|
2162
|
+
* @returns true on success (including "nothing staged").
|
|
1432
2163
|
*/
|
|
1433
|
-
private
|
|
1434
|
-
private onCommitSuccess;
|
|
2164
|
+
private commitBatch;
|
|
1435
2165
|
private onCommitFailure;
|
|
1436
2166
|
}
|
|
1437
2167
|
|
|
@@ -1449,10 +2179,15 @@ declare class VcsCoordinator {
|
|
|
1449
2179
|
private readonly roots;
|
|
1450
2180
|
private readonly logger;
|
|
1451
2181
|
private readonly isInWatchScope;
|
|
1452
|
-
constructor(config: JeevesWatcherConfig, logger: pino.Logger);
|
|
1453
2182
|
/**
|
|
1454
|
-
*
|
|
1455
|
-
*
|
|
2183
|
+
* @param config - Config at construction (roots, remotes, retention).
|
|
2184
|
+
* @param logger - Logger.
|
|
2185
|
+
* @param getConfig - Live config, for settings read at each staging
|
|
2186
|
+
* (`vcs.maxFileBytes`, D67). Default: the construction config.
|
|
2187
|
+
*/
|
|
2188
|
+
constructor(config: JeevesWatcherConfig, logger: pino.Logger, getConfig?: () => JeevesWatcherConfig);
|
|
2189
|
+
/**
|
|
2190
|
+
* Start all VcsManager instances (each runs its startup maintenance).
|
|
1456
2191
|
*/
|
|
1457
2192
|
start(): Promise<void>;
|
|
1458
2193
|
/**
|
|
@@ -1475,6 +2210,12 @@ declare class VcsCoordinator {
|
|
|
1475
2210
|
* Flush all managers and clean up.
|
|
1476
2211
|
*/
|
|
1477
2212
|
stop(): Promise<void>;
|
|
2213
|
+
/**
|
|
2214
|
+
* VCS state for `GET /status` `health.vcs` (D86).
|
|
2215
|
+
*
|
|
2216
|
+
* @returns Root count, total backlog, tripped roots and the oldest trip.
|
|
2217
|
+
*/
|
|
2218
|
+
getHealth(): VcsHealth;
|
|
1478
2219
|
/**
|
|
1479
2220
|
* Get the sorted root paths (longest-first).
|
|
1480
2221
|
*/
|
|
@@ -1497,25 +2238,129 @@ declare class VcsCoordinator {
|
|
|
1497
2238
|
findManagerForPath(normalizedPath: string): VcsManager | undefined;
|
|
1498
2239
|
}
|
|
1499
2240
|
|
|
2241
|
+
/**
|
|
2242
|
+
* @module health
|
|
2243
|
+
* Tracks consecutive system-level failures and applies exponential backoff.
|
|
2244
|
+
* Triggers fatal error callback when maxRetries is exceeded.
|
|
2245
|
+
*/
|
|
2246
|
+
|
|
2247
|
+
/**
|
|
2248
|
+
* Options for {@link SystemHealth}.
|
|
2249
|
+
*/
|
|
2250
|
+
interface SystemHealthOptions {
|
|
2251
|
+
/** Maximum consecutive failures before fatal. Default: Infinity. */
|
|
2252
|
+
maxRetries?: number;
|
|
2253
|
+
/** Maximum backoff delay in milliseconds. Default: 60000. */
|
|
2254
|
+
maxBackoffMs?: number;
|
|
2255
|
+
/** Base delay in milliseconds for exponential backoff. Default: 1000. */
|
|
2256
|
+
baseDelayMs?: number;
|
|
2257
|
+
/** Called when maxRetries is exceeded. If not set, throws. */
|
|
2258
|
+
onFatalError?: (error: unknown) => void;
|
|
2259
|
+
/** Logger instance. */
|
|
2260
|
+
logger: pino.Logger;
|
|
2261
|
+
}
|
|
2262
|
+
/**
|
|
2263
|
+
* Tracks system health via consecutive failure count and exponential backoff.
|
|
2264
|
+
*/
|
|
2265
|
+
declare class SystemHealth {
|
|
2266
|
+
private consecutiveFailures;
|
|
2267
|
+
private readonly maxRetries;
|
|
2268
|
+
private readonly maxBackoffMs;
|
|
2269
|
+
private readonly baseDelayMs;
|
|
2270
|
+
private readonly onFatalError?;
|
|
2271
|
+
private readonly logger;
|
|
2272
|
+
constructor(options: SystemHealthOptions);
|
|
2273
|
+
/**
|
|
2274
|
+
* Record a successful system operation. Resets the failure counter.
|
|
2275
|
+
*/
|
|
2276
|
+
recordSuccess(): void;
|
|
2277
|
+
/**
|
|
2278
|
+
* Record a system-level failure. If maxRetries is exceeded, triggers fatal error.
|
|
2279
|
+
*
|
|
2280
|
+
* @param error - The error that occurred.
|
|
2281
|
+
* @returns Whether the watcher should continue (false = fatal).
|
|
2282
|
+
*/
|
|
2283
|
+
recordFailure(error: unknown): boolean;
|
|
2284
|
+
/**
|
|
2285
|
+
* Compute the current backoff delay based on consecutive failures.
|
|
2286
|
+
*
|
|
2287
|
+
* @returns Delay in milliseconds.
|
|
2288
|
+
*/
|
|
2289
|
+
get currentBackoffMs(): number;
|
|
2290
|
+
/**
|
|
2291
|
+
* Sleep for the current backoff duration.
|
|
2292
|
+
*
|
|
2293
|
+
* @param signal - Optional abort signal.
|
|
2294
|
+
*/
|
|
2295
|
+
backoff(signal?: AbortSignal): Promise<void>;
|
|
2296
|
+
/**
|
|
2297
|
+
* Run one operation with health tracking: back off, run it and record
|
|
2298
|
+
* the success, or record its failure.
|
|
2299
|
+
*
|
|
2300
|
+
* @param fn - The operation.
|
|
2301
|
+
* @returns False when the failure was fatal (the caller stops).
|
|
2302
|
+
* @throws When retries are exhausted and no fatal-error callback is set.
|
|
2303
|
+
*/
|
|
2304
|
+
run(fn: () => Promise<void>): Promise<boolean>;
|
|
2305
|
+
/** Current consecutive failure count. */
|
|
2306
|
+
get failures(): number;
|
|
2307
|
+
}
|
|
2308
|
+
|
|
2309
|
+
/**
|
|
2310
|
+
* @module watcher/changeSource/types
|
|
2311
|
+
* The change-source seam (spec Design 9, D120, D149): a `ChangeSource` supplies raw events and root signals to a `ChangeSink`; `FileSystemWatcher` implements the sink and owns every decision. Types only.
|
|
2312
|
+
*/
|
|
2313
|
+
|
|
2314
|
+
/** A classified event, as chokidar reports it. */
|
|
2315
|
+
type ClassifiedEventType = 'add' | 'change' | 'unlink' | 'addDir' | 'unlinkDir';
|
|
2316
|
+
/**
|
|
2317
|
+
* One unclassified event of a parcel batch (D149): an absolute path and a
|
|
2318
|
+
* type that is a hint only (`lstat` decides).
|
|
2319
|
+
*/
|
|
2320
|
+
interface RawChangeEvent {
|
|
2321
|
+
/** Absolute path. */
|
|
2322
|
+
path: string;
|
|
2323
|
+
/** Parcel's event type. */
|
|
2324
|
+
type: 'create' | 'update' | 'delete';
|
|
2325
|
+
}
|
|
2326
|
+
/**
|
|
2327
|
+
* Where a change source delivers events and signals. Implemented by
|
|
2328
|
+
* `FileSystemWatcher`, which owns classification, stability waits, pairing,
|
|
2329
|
+
* renewals and every reconcile trigger (D120).
|
|
2330
|
+
*/
|
|
2331
|
+
interface ChangeSink {
|
|
2332
|
+
/** A classified event (chokidar). */
|
|
2333
|
+
event: (type: ClassifiedEventType, path: string, stats?: Stats) => void;
|
|
2334
|
+
/** One whole parcel batch for a root, sorted by path (D149). */
|
|
2335
|
+
rawEvents: (root: string, events: RawChangeEvent[]) => void;
|
|
2336
|
+
/** The source finished its initial set for `root`. */
|
|
2337
|
+
initialScanDone: (root: string) => void;
|
|
2338
|
+
/** The source re-created `root`'s subscription after an error (D131). */
|
|
2339
|
+
resubscribed: (root: string) => void;
|
|
2340
|
+
/**
|
|
2341
|
+
* `root` became unreachable (D109), or is reachable but cannot be
|
|
2342
|
+
* watched (`reachable`, D156: it is still reconciled); `code` is the
|
|
2343
|
+
* error code.
|
|
2344
|
+
*/
|
|
2345
|
+
rootUnavailable: (root: string, code: string, options?: RootUnavailableOptions) => void;
|
|
2346
|
+
/** `root` is reachable again (D109). */
|
|
2347
|
+
rootAvailable: (root: string) => void;
|
|
2348
|
+
}
|
|
2349
|
+
/** Details of {@link ChangeSink.rootUnavailable}. */
|
|
2350
|
+
interface RootUnavailableOptions {
|
|
2351
|
+
/**
|
|
2352
|
+
* The root is still on disk but unwatched (a non-transient subscribe
|
|
2353
|
+
* failure, D156): it counts in `unavailableRoots` and is still
|
|
2354
|
+
* reconciled.
|
|
2355
|
+
*/
|
|
2356
|
+
reachable?: boolean;
|
|
2357
|
+
}
|
|
2358
|
+
|
|
1500
2359
|
/**
|
|
1501
2360
|
* @module api/InitialScanTracker
|
|
1502
2361
|
* Tracks initial filesystem scan state for status reporting.
|
|
1503
2362
|
*/
|
|
1504
|
-
|
|
1505
|
-
interface InitialScanStatus {
|
|
1506
|
-
/** Whether the initial scan is currently in progress. */
|
|
1507
|
-
active: boolean;
|
|
1508
|
-
/** Number of files matched by watch globs. */
|
|
1509
|
-
filesMatched?: number;
|
|
1510
|
-
/** Number of files enqueued for processing so far. */
|
|
1511
|
-
filesEnqueued?: number;
|
|
1512
|
-
/** ISO 8601 timestamp when the scan started. */
|
|
1513
|
-
startedAt?: string;
|
|
1514
|
-
/** ISO 8601 timestamp when the scan completed. */
|
|
1515
|
-
completedAt?: string;
|
|
1516
|
-
/** Total scan duration in milliseconds. */
|
|
1517
|
-
durationMs?: number;
|
|
1518
|
-
}
|
|
2363
|
+
|
|
1519
2364
|
/**
|
|
1520
2365
|
* Tracks the state of the initial filesystem scan after service start.
|
|
1521
2366
|
*/
|
|
@@ -1540,66 +2385,173 @@ declare class InitialScanTracker {
|
|
|
1540
2385
|
}
|
|
1541
2386
|
|
|
1542
2387
|
/**
|
|
1543
|
-
* @module
|
|
1544
|
-
*
|
|
1545
|
-
* Triggers fatal error callback when maxRetries is exceeded.
|
|
2388
|
+
* @module watcher/fileEvents
|
|
2389
|
+
* What a filtered file event does: the VCS hook, move correlation and the processing queue. I/O: enqueues processor work.
|
|
1546
2390
|
*/
|
|
1547
2391
|
|
|
2392
|
+
/** VCS change callback. */
|
|
2393
|
+
type VcsFileChange = (filePath: string, event: 'add' | 'change' | 'unlink') => void;
|
|
2394
|
+
|
|
1548
2395
|
/**
|
|
1549
|
-
*
|
|
2396
|
+
* @module watcher/inventory/Inventory
|
|
2397
|
+
* `FileSystemWatcher`'s inventory (D99): the files that passed its filters, keyed by `normalizeDocumentKey`, with the child-set directory index (D127, D150). Pure.
|
|
1550
2398
|
*/
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
/**
|
|
1561
|
-
|
|
2399
|
+
/** File size and modification time, as a walk or `stat` reports them. */
|
|
2400
|
+
interface FileStats {
|
|
2401
|
+
/** Size in bytes. */
|
|
2402
|
+
size: number;
|
|
2403
|
+
/** Modification time (ms since epoch). */
|
|
2404
|
+
mtimeMs: number;
|
|
2405
|
+
}
|
|
2406
|
+
/** One inventory entry. */
|
|
2407
|
+
interface InventoryEntry {
|
|
2408
|
+
/** The path as the source reported it. */
|
|
2409
|
+
path: string;
|
|
2410
|
+
/** Size, when the inventory tracks stats (parcel source). */
|
|
2411
|
+
size?: number;
|
|
2412
|
+
/** Modification time, when the inventory tracks stats. */
|
|
2413
|
+
mtimeMs?: number;
|
|
1562
2414
|
}
|
|
1563
2415
|
/**
|
|
1564
|
-
*
|
|
2416
|
+
* The files the change source last saw that pass `FileSystemWatcher`'s
|
|
2417
|
+
* filters. Stats are stored only when `trackStats` is set (the parcel
|
|
2418
|
+
* source, whose initial set is the walk); under chokidar entries hold paths
|
|
2419
|
+
* only (spec Design 9).
|
|
1565
2420
|
*/
|
|
1566
|
-
declare class
|
|
1567
|
-
private
|
|
1568
|
-
private readonly
|
|
1569
|
-
private readonly
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
2421
|
+
declare class Inventory {
|
|
2422
|
+
private readonly trackStats;
|
|
2423
|
+
private readonly entries;
|
|
2424
|
+
private readonly index;
|
|
2425
|
+
/** @param trackStats - Store size and mtime with each entry. */
|
|
2426
|
+
constructor(trackStats: boolean);
|
|
2427
|
+
/** Number of files. */
|
|
2428
|
+
get size(): number;
|
|
2429
|
+
/** Add or update a file. */
|
|
2430
|
+
set(path: string, stats?: FileStats): void;
|
|
1574
2431
|
/**
|
|
1575
|
-
*
|
|
2432
|
+
* Remove a file.
|
|
2433
|
+
*
|
|
2434
|
+
* @returns True when it was present.
|
|
1576
2435
|
*/
|
|
1577
|
-
|
|
2436
|
+
delete(path: string): boolean;
|
|
2437
|
+
/** The entry for a path, if present. */
|
|
2438
|
+
get(path: string): InventoryEntry | undefined;
|
|
1578
2439
|
/**
|
|
1579
|
-
*
|
|
1580
|
-
*
|
|
1581
|
-
* @param error - The error that occurred.
|
|
1582
|
-
* @returns Whether the watcher should continue (false = fatal).
|
|
2440
|
+
* Whether a path is a directory the inventory holds files under (D127:
|
|
2441
|
+
* an absent path is classified as a directory delete by this).
|
|
1583
2442
|
*/
|
|
1584
|
-
|
|
2443
|
+
isDirectory(path: string): boolean;
|
|
2444
|
+
/** Every file path, as the source reported it (`/walk`, D83). */
|
|
2445
|
+
paths(): string[];
|
|
1585
2446
|
/**
|
|
1586
|
-
*
|
|
2447
|
+
* The entries beneath a directory, at any depth, keyed by document key;
|
|
2448
|
+
* O(subtree size), never a scan of the inventory.
|
|
2449
|
+
*/
|
|
2450
|
+
entriesUnder(dir: string): Map<string, InventoryEntry>;
|
|
2451
|
+
}
|
|
2452
|
+
|
|
2453
|
+
/**
|
|
2454
|
+
* @module watcher/changeSource/parcelModule
|
|
2455
|
+
* Loading `@parcel/watcher` only when it is selected (D125): a cached dynamic import whose failure becomes a refusal naming the chokidar switch, the native-load error test, and the explicit backend per platform (D124). I/O: the import.
|
|
2456
|
+
*/
|
|
2457
|
+
|
|
2458
|
+
/** The parts of `@parcel/watcher` the parcel source uses. */
|
|
2459
|
+
type ParcelWatcherModule = Pick<typeof ParcelWatcher, 'subscribe'>;
|
|
2460
|
+
/** Imports the module (injectable for tests). */
|
|
2461
|
+
type ParcelImporter = () => Promise<ParcelWatcherModule>;
|
|
2462
|
+
|
|
2463
|
+
/**
|
|
2464
|
+
* @module watcher/changeSource/restart
|
|
2465
|
+
* The process-restart seam of D196: on Windows the parcel source never unsubscribes (`@parcel/watcher` 2.6.0 crashes the process natively there), so a watcher rebuild or a subscription recovery exits the process for the service manager to restart it. The app implements the graceful restarter; `exitingRestarter` is the fallback for a watcher built without the app. I/O: `process.exit` in that fallback only.
|
|
2466
|
+
*/
|
|
2467
|
+
|
|
2468
|
+
/** One request to exit for a restart. */
|
|
2469
|
+
interface RestartRequest {
|
|
2470
|
+
/** The cause (a code, no path: it reaches health, D89). */
|
|
2471
|
+
cause: RestartCause;
|
|
2472
|
+
/** The root concerned, for the log line only. */
|
|
2473
|
+
root?: string;
|
|
2474
|
+
/** The error behind it, for the log line only. */
|
|
2475
|
+
err?: unknown;
|
|
2476
|
+
/**
|
|
2477
|
+
* A config reload's reindex scope (`configWatch.reindex`), run by the
|
|
2478
|
+
* restarted process instead of this one.
|
|
2479
|
+
*/
|
|
2480
|
+
reindex?: ConfigWatchReindexScope;
|
|
2481
|
+
}
|
|
2482
|
+
/**
|
|
2483
|
+
* Exits the process for a service-manager restart (D196). `restart`
|
|
2484
|
+
* returns at once: the exit follows a graceful stop, so callers inside the
|
|
2485
|
+
* change source's queue never wait on themselves. Only the first request
|
|
2486
|
+
* of a process counts. Injected, so tests never call `process.exit`.
|
|
2487
|
+
*/
|
|
2488
|
+
interface ProcessRestarter {
|
|
2489
|
+
/** Log the cause, stop gracefully, then exit with code 75 (`EX_TEMPFAIL`). */
|
|
2490
|
+
restart: (request: RestartRequest) => void;
|
|
2491
|
+
}
|
|
2492
|
+
|
|
2493
|
+
/**
|
|
2494
|
+
* @module watcher/ChangeSourceHealthTracker
|
|
2495
|
+
* `health.changeSource` (D133, D157): counters since start, owned by the app so they survive watcher rebuilds, plus the cause of the exit for a restart this process started after (D196). Pure.
|
|
2496
|
+
*/
|
|
2497
|
+
|
|
2498
|
+
/**
|
|
2499
|
+
* Counts and timestamps behind `health.changeSource`. Never holds a path in
|
|
2500
|
+
* its snapshot (D89).
|
|
2501
|
+
*/
|
|
2502
|
+
declare class ChangeSourceHealthTracker {
|
|
2503
|
+
private source;
|
|
2504
|
+
private resubscribes;
|
|
2505
|
+
private renewFailures;
|
|
2506
|
+
private reconcileEvents;
|
|
2507
|
+
private reconcileErrors;
|
|
2508
|
+
private lastReconcileAt;
|
|
2509
|
+
private lastReconcileDurationMs;
|
|
2510
|
+
private lastRenewDurationMs;
|
|
2511
|
+
private lastRestart;
|
|
2512
|
+
private readonly unavailable;
|
|
2513
|
+
private pendingStability;
|
|
2514
|
+
/** Record the running source and its pending-stability reader. */
|
|
2515
|
+
attach(source: ChangeSourceHealth['source'], pending: () => number): void;
|
|
2516
|
+
/** A subscription was re-created after an error (D131). */
|
|
2517
|
+
recordResubscribe(): void;
|
|
2518
|
+
/**
|
|
2519
|
+
* A renewal forced a source rebuild (D165), or rejected inside one
|
|
2520
|
+
* (D176).
|
|
1587
2521
|
*
|
|
1588
|
-
* @
|
|
2522
|
+
* @param count - Failures to add (default 1).
|
|
1589
2523
|
*/
|
|
1590
|
-
|
|
2524
|
+
recordRenewFailure(count?: number): void;
|
|
2525
|
+
/** A subscription renewal finished (Linux parcel, D129, D157). */
|
|
2526
|
+
recordRenew(durationMs: number): void;
|
|
1591
2527
|
/**
|
|
1592
|
-
*
|
|
2528
|
+
* The previous process exited for a restart (D196): its cause and when.
|
|
1593
2529
|
*
|
|
1594
|
-
* @param
|
|
2530
|
+
* @param restart - The record it left.
|
|
1595
2531
|
*/
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
2532
|
+
recordRestart(restart: {
|
|
2533
|
+
cause: RestartCause;
|
|
2534
|
+
at: string;
|
|
2535
|
+
}): void;
|
|
2536
|
+
/** Mark a root unavailable (D109) or available again. */
|
|
2537
|
+
setUnavailable(root: string, unavailable: boolean): void;
|
|
2538
|
+
/** Synthetic events a reconcile emitted (D90). */
|
|
2539
|
+
recordReconcileEvents(count: number): void;
|
|
2540
|
+
/** A reconcile finished (walk and compare). */
|
|
2541
|
+
recordReconcile(durationMs: number, at: Date): void;
|
|
2542
|
+
/** A reconcile errored and emitted nothing (D90). */
|
|
2543
|
+
recordReconcileError(): void;
|
|
2544
|
+
/** The `health.changeSource` body. */
|
|
2545
|
+
snapshot(): ChangeSourceHealth;
|
|
1599
2546
|
}
|
|
1600
2547
|
|
|
1601
2548
|
/**
|
|
1602
|
-
*
|
|
2549
|
+
* @module watcher/running
|
|
2550
|
+
* What one `FileSystemWatcher.start` builds: the change source (parcel or chokidar, D125), filters, inventory, filtered handlers, queue actions and, for parcel, the batch pipeline, wired together. Pure apart from constructing the source (not started here).
|
|
2551
|
+
*/
|
|
2552
|
+
|
|
2553
|
+
/**
|
|
2554
|
+
* Options for `FileSystemWatcher` beyond basic config.
|
|
1603
2555
|
*/
|
|
1604
2556
|
interface FileSystemWatcherOptions {
|
|
1605
2557
|
/** Maximum consecutive system-level failures before fatal error. */
|
|
@@ -1615,27 +2567,75 @@ interface FileSystemWatcherOptions {
|
|
|
1615
2567
|
/** Optional content hash cache for move detection. */
|
|
1616
2568
|
contentHashCache?: ContentHashCache;
|
|
1617
2569
|
/** Optional callback for VCS file change notifications. */
|
|
1618
|
-
onVcsFileChange?:
|
|
1619
|
-
/**
|
|
1620
|
-
|
|
2570
|
+
onVcsFileChange?: VcsFileChange;
|
|
2571
|
+
/**
|
|
2572
|
+
* Optional callback invoked when the initial filesystem scan completes,
|
|
2573
|
+
* with the index check's view of the watcher that completed it (D197).
|
|
2574
|
+
*/
|
|
2575
|
+
onInitialScanComplete?: (view: IndexCheckView) => void | Promise<void>;
|
|
2576
|
+
/** `health.changeSource` counters (D133), owned by the app across rebuilds. */
|
|
2577
|
+
changeSourceHealth?: ChangeSourceHealthTracker;
|
|
2578
|
+
/** Live `watch.reconcileIntervalMs` (D111), read at each scheduling. */
|
|
2579
|
+
getReconcileIntervalMs?: () => number | undefined;
|
|
2580
|
+
/** Imports `@parcel/watcher` (tests; default the real module, D125). */
|
|
2581
|
+
importParcel?: ParcelImporter;
|
|
2582
|
+
/** The service state directory (the parcel rebuild sentinel, D165). */
|
|
2583
|
+
stateDir?: string;
|
|
2584
|
+
/**
|
|
2585
|
+
* Exits for a service-manager restart where parcel never unsubscribes
|
|
2586
|
+
* (Windows, D196); default an immediate exit.
|
|
2587
|
+
*/
|
|
2588
|
+
restarter?: ProcessRestarter;
|
|
2589
|
+
}
|
|
2590
|
+
|
|
2591
|
+
/**
|
|
2592
|
+
* @module watcher/indexCheck/view
|
|
2593
|
+
* What the index check at start (D197) reads from a running `FileSystemWatcher`: its roots, why a root must be skipped (unavailable D109, unwatched D156, start walk failed) and whether the inventory holds a path. Pure.
|
|
2594
|
+
*/
|
|
2595
|
+
|
|
2596
|
+
/** Why a root is not checked (besides being gone at check time). */
|
|
2597
|
+
type IndexCheckSkipReason = 'unavailable' | 'unwatched' | 'walkFailed';
|
|
2598
|
+
/** The running watcher as the index check sees it. */
|
|
2599
|
+
interface IndexCheckView {
|
|
2600
|
+
/** The resolved watch roots, nested ones collapsed (D195 case). */
|
|
2601
|
+
roots: readonly string[];
|
|
2602
|
+
/**
|
|
2603
|
+
* Why the root must be skipped, or undefined when it can be checked.
|
|
2604
|
+
*
|
|
2605
|
+
* @param root - One of {@link IndexCheckView.roots}.
|
|
2606
|
+
*/
|
|
2607
|
+
skipReason: (root: string) => IndexCheckSkipReason | undefined;
|
|
2608
|
+
/**
|
|
2609
|
+
* Whether the inventory holds the file (its point-ID key form).
|
|
2610
|
+
*
|
|
2611
|
+
* @param path - A file path.
|
|
2612
|
+
*/
|
|
2613
|
+
has: (path: string) => boolean;
|
|
2614
|
+
/** Whether this running state is still the watcher's (no stop or rebuild). */
|
|
2615
|
+
live: () => boolean;
|
|
1621
2616
|
}
|
|
2617
|
+
|
|
1622
2618
|
/**
|
|
1623
|
-
*
|
|
2619
|
+
* @module watcher
|
|
2620
|
+
* Filesystem watcher: drives a change source (parcel or chokidar, D125) through the `ChangeSink` seam, filters its events, keeps the inventory and enqueues processing. I/O: watches files, enqueues processor work.
|
|
1624
2621
|
*/
|
|
1625
|
-
|
|
2622
|
+
|
|
2623
|
+
/**
|
|
2624
|
+
* Filesystem watcher. A change source only reports events (D120); this
|
|
2625
|
+
* class filters them, keeps the inventory (D99) and maps them to the
|
|
2626
|
+
* processing queue.
|
|
2627
|
+
*/
|
|
2628
|
+
declare class FileSystemWatcher implements ChangeSink {
|
|
1626
2629
|
private readonly config;
|
|
1627
2630
|
private readonly queue;
|
|
1628
2631
|
private readonly processor;
|
|
1629
2632
|
private readonly logger;
|
|
2633
|
+
private readonly options;
|
|
1630
2634
|
private readonly health;
|
|
1631
|
-
private
|
|
1632
|
-
|
|
1633
|
-
private
|
|
1634
|
-
private
|
|
1635
|
-
private readonly onInitialScanComplete?;
|
|
1636
|
-
private moveCorrelator?;
|
|
1637
|
-
private globMatches;
|
|
1638
|
-
private watcher;
|
|
2635
|
+
private running;
|
|
2636
|
+
/** A stopped source left its watches live (D196). */
|
|
2637
|
+
private leftWatches;
|
|
2638
|
+
private initialScanComplete;
|
|
1639
2639
|
/**
|
|
1640
2640
|
* Create a new FileSystemWatcher.
|
|
1641
2641
|
*
|
|
@@ -1647,36 +2647,64 @@ declare class FileSystemWatcher {
|
|
|
1647
2647
|
*/
|
|
1648
2648
|
constructor(config: WatchConfig, queue: EventQueue, processor: DocumentProcessorInterface, logger: pino.Logger, options?: FileSystemWatcherOptions);
|
|
1649
2649
|
/**
|
|
1650
|
-
* Start watching the filesystem and processing events.
|
|
1651
|
-
|
|
1652
|
-
start(): void;
|
|
1653
|
-
/**
|
|
1654
|
-
* Get the list of all currently watched file paths (absolute).
|
|
2650
|
+
* Start watching the filesystem and processing events. With parcel the
|
|
2651
|
+
* roots are subscribed first, then walked in the background (D58).
|
|
1655
2652
|
*
|
|
1656
|
-
*
|
|
1657
|
-
* Returns an empty array if the watcher hasn't been started.
|
|
2653
|
+
* @throws ChangeSourceLoadError when parcel is selected and cannot load.
|
|
1658
2654
|
*/
|
|
1659
|
-
|
|
1660
|
-
/**
|
|
1661
|
-
|
|
2655
|
+
start(): Promise<void>;
|
|
2656
|
+
/** A classified event from the change source (chokidar), with the stats it read, if any. */
|
|
2657
|
+
event(type: ClassifiedEventType, path: string, stats?: Stats): void;
|
|
2658
|
+
/**
|
|
2659
|
+
* The directory-create handler (D91, D120): reconcile a directory created
|
|
2660
|
+
* after the initial scan, so files written into it before its watch was
|
|
2661
|
+
* set up are not missed. The reconciler drops it before the scan ends.
|
|
2662
|
+
*/
|
|
2663
|
+
private directoryCreated;
|
|
2664
|
+
/** Start a reconcile of `dir` (every trigger is owned here, D120). */
|
|
2665
|
+
private reconcile;
|
|
2666
|
+
/**
|
|
2667
|
+
* A raw parcel batch (D149): into the FIFO, classified from the disk and
|
|
2668
|
+
* applied in order.
|
|
2669
|
+
*/
|
|
2670
|
+
rawEvents(root: string, events: RawChangeEvent[]): void;
|
|
2671
|
+
/** The source finished its initial set for a root; the scan completes when every root has. */
|
|
2672
|
+
initialScanDone(sourceRoot: string): void;
|
|
2673
|
+
/** The source re-created a root's subscription after an error (D131). */
|
|
2674
|
+
resubscribed(sourceRoot: string): void;
|
|
2675
|
+
/** A root is unreachable (D109), or reachable but unwatched (D156). */
|
|
2676
|
+
rootUnavailable(sourceRoot: string, code: string, options?: RootUnavailableOptions): void;
|
|
2677
|
+
/** A root is reachable again (D109). */
|
|
2678
|
+
rootAvailable(sourceRoot: string): void;
|
|
2679
|
+
/** A root signal's context (the canonical root), or undefined when not running. */
|
|
2680
|
+
private signal;
|
|
2681
|
+
/**
|
|
2682
|
+
* The inventory's file paths (absolute, as the source reported them):
|
|
2683
|
+
* matched files only, never directories or filtered files (D83). No
|
|
2684
|
+
* filesystem I/O; empty before start.
|
|
1662
2685
|
*/
|
|
2686
|
+
getWatchedFiles(): string[];
|
|
2687
|
+
/** Whether the initial filesystem scan is complete. */
|
|
1663
2688
|
get isReady(): boolean;
|
|
1664
2689
|
/**
|
|
1665
|
-
*
|
|
2690
|
+
* Whether a rebuild must exit for a restart (D196): the running source,
|
|
2691
|
+
* or one this watcher stopped (its watches stay live), cannot release
|
|
2692
|
+
* its watches in-process (parcel on Windows).
|
|
1666
2693
|
*/
|
|
2694
|
+
get restartsToRebuild(): boolean;
|
|
2695
|
+
/** The running watcher's inventory (D99), undefined before start. */
|
|
2696
|
+
get inventory(): Inventory | undefined;
|
|
2697
|
+
/** What the index check at start reads (D197); undefined before start. */
|
|
2698
|
+
get indexCheckView(): IndexCheckView | undefined;
|
|
2699
|
+
/** Stop the filesystem watcher. */
|
|
1667
2700
|
stop(): Promise<void>;
|
|
1668
|
-
/**
|
|
1669
|
-
* Get the system health tracker.
|
|
1670
|
-
*/
|
|
2701
|
+
/** Get the system health tracker. */
|
|
1671
2702
|
get systemHealth(): SystemHealth;
|
|
1672
2703
|
/**
|
|
1673
|
-
*
|
|
1674
|
-
|
|
1675
|
-
private isGitignored;
|
|
1676
|
-
/**
|
|
1677
|
-
* If the changed file is a `.gitignore`, invalidate the filter cache.
|
|
2704
|
+
* Re-arm the periodic reconcile timers with the live interval: a reload
|
|
2705
|
+
* that changed only `watch.reconcileIntervalMs` needs no rebuild (D111).
|
|
1678
2706
|
*/
|
|
1679
|
-
|
|
2707
|
+
refreshReconcileSchedule(): void;
|
|
1680
2708
|
/**
|
|
1681
2709
|
* Wrap a processing operation with health tracking.
|
|
1682
2710
|
* On success, resets the failure counter.
|
|
@@ -1689,19 +2717,7 @@ declare class FileSystemWatcher {
|
|
|
1689
2717
|
* @module api/ReindexTracker
|
|
1690
2718
|
* Tracks reindex operation state for status reporting. Single instance shared across handlers.
|
|
1691
2719
|
*/
|
|
1692
|
-
|
|
1693
|
-
interface ReindexStatus {
|
|
1694
|
-
/** Whether a reindex operation is currently in progress. */
|
|
1695
|
-
active: boolean;
|
|
1696
|
-
/** The active reindex scope (when {@link active} is true). */
|
|
1697
|
-
scope?: string;
|
|
1698
|
-
/** ISO 8601 timestamp when the current reindex started (when {@link active} is true). */
|
|
1699
|
-
startedAt?: string;
|
|
1700
|
-
/** Number of files processed so far (when {@link active} is true). */
|
|
1701
|
-
filesProcessed?: number;
|
|
1702
|
-
/** Total number of files to process (when {@link active} is true). */
|
|
1703
|
-
totalFiles?: number;
|
|
1704
|
-
}
|
|
2720
|
+
|
|
1705
2721
|
/**
|
|
1706
2722
|
* Tracks the state of reindex operations.
|
|
1707
2723
|
*/
|
|
@@ -1724,24 +2740,30 @@ declare class ReindexTracker {
|
|
|
1724
2740
|
}
|
|
1725
2741
|
|
|
1726
2742
|
/**
|
|
1727
|
-
* @module api
|
|
1728
|
-
*
|
|
2743
|
+
* @module api/apiServerOptions
|
|
2744
|
+
* Options accepted by createApiServer: processor, stores, queues, config access, trackers and optional collaborators (virtual rules, VCS, source queue). Types only.
|
|
1729
2745
|
*/
|
|
1730
2746
|
|
|
1731
2747
|
/**
|
|
1732
|
-
* Options for
|
|
2748
|
+
* Options for `createApiServer`.
|
|
1733
2749
|
*/
|
|
1734
2750
|
interface ApiServerOptions {
|
|
2751
|
+
/**
|
|
2752
|
+
* Queues paused while a prune deletes points. The service passes
|
|
2753
|
+
* `combinePausableQueues(fileQueue, sourceQueue)` (`app/index.ts`), so a
|
|
2754
|
+
* prune quiesces both the file event queue and the source notify queue.
|
|
2755
|
+
*/
|
|
2756
|
+
queue: PausableQueue;
|
|
2757
|
+
/** Source notify queue (`POST /documents`); absent in file-only setups. */
|
|
2758
|
+
sourceQueue?: SourceNotifyQueue;
|
|
1735
2759
|
/** The component descriptor (used for config-apply handler). */
|
|
1736
2760
|
descriptor: JeevesComponentDescriptor;
|
|
1737
|
-
/** The document processor. */
|
|
1738
|
-
processor:
|
|
2761
|
+
/** The document processor: file and source operations. */
|
|
2762
|
+
processor: WatcherProcessor;
|
|
1739
2763
|
/** The vector store client. */
|
|
1740
2764
|
vectorStore: VectorStoreClient;
|
|
1741
2765
|
/** The embedding provider. */
|
|
1742
2766
|
embeddingProvider: EmbeddingProvider;
|
|
1743
|
-
/** The event queue. */
|
|
1744
|
-
queue: EventQueue;
|
|
1745
2767
|
/** The application configuration (used as initial/fallback value). */
|
|
1746
2768
|
config: JeevesWatcherConfig;
|
|
1747
2769
|
/** Config getter for live config access after hot-reload. */
|
|
@@ -1758,27 +2780,56 @@ interface ApiServerOptions {
|
|
|
1758
2780
|
configPath: string;
|
|
1759
2781
|
/** Helper introspection for merged document. */
|
|
1760
2782
|
helperIntrospection?: AllHelpersIntrospection;
|
|
1761
|
-
/** Virtual rule store for externally registered inference rules
|
|
1762
|
-
|
|
2783
|
+
/** Virtual rule store for externally registered inference rules (the
|
|
2784
|
+
* `/rules/*` routes). */
|
|
2785
|
+
virtualRuleStore: VirtualRuleStore;
|
|
1763
2786
|
/** Gitignore filter for reindex path validation. */
|
|
1764
2787
|
gitignoreFilter?: GitignoreFilter;
|
|
1765
2788
|
/** Service version string for /status endpoint. */
|
|
1766
2789
|
version?: string;
|
|
1767
2790
|
/** Initial scan tracker for /status visibility. */
|
|
1768
2791
|
initialScanTracker?: InitialScanTracker;
|
|
1769
|
-
/** Filesystem watcher instance for /walk endpoint (
|
|
2792
|
+
/** Filesystem watcher instance for /walk endpoint (its inventory, D83). */
|
|
1770
2793
|
fileSystemWatcher?: FileSystemWatcher;
|
|
1771
2794
|
/** Getter for live filesystem watcher access after hot-reload rebuilds. */
|
|
1772
2795
|
getFileSystemWatcher?: () => FileSystemWatcher | undefined;
|
|
1773
2796
|
/** Optional enrichment store for persisted enrichment metadata. */
|
|
1774
2797
|
enrichmentStore?: EnrichmentStoreInterface;
|
|
1775
|
-
/** VCS coordinator for git-backed versioning
|
|
2798
|
+
/** VCS coordinator for the git-backed versioning (`/vcs/*`) routes; without
|
|
2799
|
+
* it they answer as unregistered (`api/featureGates`). */
|
|
1776
2800
|
vcsCoordinator?: VcsCoordinator;
|
|
2801
|
+
/**
|
|
2802
|
+
* Longest document-lock wait of `POST /metadata`, `POST /rules/reapply`
|
|
2803
|
+
* and `POST /documents/delete` (default 10 s, D118; tests only).
|
|
2804
|
+
*/
|
|
2805
|
+
documentLockWaitMs?: number;
|
|
2806
|
+
/** Embedding health (`GET /status` `health.embedding`, D88). */
|
|
2807
|
+
embeddingHealth?: {
|
|
2808
|
+
snapshot: () => EmbeddingHealthSnapshot;
|
|
2809
|
+
};
|
|
2810
|
+
/** Change-source health (`GET /status` `health.changeSource`, D133). */
|
|
2811
|
+
changeSourceHealth?: {
|
|
2812
|
+
snapshot: () => ChangeSourceHealth;
|
|
2813
|
+
};
|
|
2814
|
+
/** Index check at start (`health.indexCheck`, D197). */
|
|
2815
|
+
indexCheckHealth?: {
|
|
2816
|
+
snapshot: () => IndexCheckHealth;
|
|
2817
|
+
};
|
|
1777
2818
|
}
|
|
2819
|
+
|
|
2820
|
+
/**
|
|
2821
|
+
* @module api
|
|
2822
|
+
* Fastify API server factory. Registers every `WATCHER_CATALOG` route (plus `GET /openapi.json`) from the catalog, and returns an unstarted server instance.
|
|
2823
|
+
*/
|
|
2824
|
+
|
|
1778
2825
|
/**
|
|
1779
2826
|
* Create the Fastify API server with all routes registered.
|
|
1780
2827
|
*
|
|
1781
|
-
* The returned instance is not yet listening
|
|
2828
|
+
* The returned instance is not yet listening; call `server.listen()` to
|
|
2829
|
+
* start. The catalog routes are registered in a child plugin, so a
|
|
2830
|
+
* registration error surfaces from `ready()` or `listen()` (spec #281 D29).
|
|
2831
|
+
* The `/vcs/*` routes answer as unregistered unless a `vcsCoordinator` is
|
|
2832
|
+
* given (`api/featureGates`).
|
|
1782
2833
|
*
|
|
1783
2834
|
* @param options - The server options.
|
|
1784
2835
|
* @returns A configured Fastify instance.
|
|
@@ -1786,29 +2837,90 @@ interface ApiServerOptions {
|
|
|
1786
2837
|
declare function createApiServer(options: ApiServerOptions): FastifyInstance;
|
|
1787
2838
|
|
|
1788
2839
|
/**
|
|
1789
|
-
* @module
|
|
1790
|
-
*
|
|
2840
|
+
* @module config/warnings
|
|
2841
|
+
* The non-fatal config warning shape shared by config loading (unknown source keys, reserved rule field names) and `POST /config/validate`. Types only.
|
|
2842
|
+
*/
|
|
2843
|
+
/** A non-fatal config validation warning. */
|
|
2844
|
+
interface ConfigWarning {
|
|
2845
|
+
/** Config location the warning refers to. */
|
|
2846
|
+
path: string;
|
|
2847
|
+
/** Human-readable warning message. */
|
|
2848
|
+
message: string;
|
|
2849
|
+
}
|
|
2850
|
+
|
|
2851
|
+
/**
|
|
2852
|
+
* @module config/loadConfig
|
|
2853
|
+
* Loads the watcher config via cosmiconfig: schema validation, rule/map file resolution, defaults, env substitution and secret checks; reports non-fatal warnings (unknown source keys, reserved rule field names) through onWarning. Reads files.
|
|
2854
|
+
*/
|
|
2855
|
+
|
|
2856
|
+
/** Options of {@link loadConfig}. */
|
|
2857
|
+
interface LoadConfigOptions {
|
|
2858
|
+
/**
|
|
2859
|
+
* Receives non-fatal warnings once the config has loaded successfully:
|
|
2860
|
+
* unknown keys under `sources.<name>` (which validation drops), then rule
|
|
2861
|
+
* schema properties named like reserved system fields.
|
|
2862
|
+
*/
|
|
2863
|
+
onWarning?: (warning: ConfigWarning) => void;
|
|
2864
|
+
}
|
|
2865
|
+
/**
|
|
2866
|
+
* Load the jeeves-watcher configuration.
|
|
2867
|
+
*
|
|
2868
|
+
* @param configPath - Optional explicit path to a config file.
|
|
2869
|
+
* @param options - Optional warning sink.
|
|
2870
|
+
* @returns The loaded configuration.
|
|
2871
|
+
* @throws If no configuration is found or validation fails.
|
|
1791
2872
|
*/
|
|
2873
|
+
declare function loadConfig(configPath?: string, options?: LoadConfigOptions): Promise<JeevesWatcherConfig>;
|
|
1792
2874
|
|
|
1793
2875
|
/**
|
|
1794
|
-
* Create a pino logger
|
|
2876
|
+
* Create a pino logger. With `logging.file`, the file is open (or the
|
|
2877
|
+
* call rejects) before the logger is returned, so no early line is lost.
|
|
1795
2878
|
*
|
|
1796
2879
|
* @param config - Optional logging configuration.
|
|
1797
2880
|
* @returns A configured pino logger.
|
|
1798
2881
|
*/
|
|
1799
|
-
declare function createLogger(config?: LoggingConfig): pino.Logger
|
|
2882
|
+
declare function createLogger(config?: LoggingConfig): Promise<pino.Logger>;
|
|
2883
|
+
|
|
2884
|
+
/**
|
|
2885
|
+
* @module app/processRestarter
|
|
2886
|
+
* The app's exit for a service-manager restart (D196): log the cause, leave a restart record in the state directory, stop gracefully (with a hard deadline), then exit with `RESTART_EXIT_CODE`; at the next start, read the record, report it in `health.changeSource` (the app runs any deferred config reindex) and clear it once the start succeeded. I/O: the record file, a timer, `process.exit`.
|
|
2887
|
+
*/
|
|
2888
|
+
|
|
2889
|
+
/** What `createProcessRestarter` needs from the app. */
|
|
2890
|
+
interface ProcessRestarterDeps {
|
|
2891
|
+
/** The state directory (the record goes there). */
|
|
2892
|
+
stateDir: string;
|
|
2893
|
+
/** The app's logger, once it exists. */
|
|
2894
|
+
logger: () => pino.Logger | undefined;
|
|
2895
|
+
/** The app's graceful stop. */
|
|
2896
|
+
stop: () => Promise<void>;
|
|
2897
|
+
/**
|
|
2898
|
+
* The longest the graceful stop may take before the process exits
|
|
2899
|
+
* anyway: some stop steps (a hung `lstat` or git call) have no timeout.
|
|
2900
|
+
*/
|
|
2901
|
+
deadlineMs: number;
|
|
2902
|
+
/** `process.exit` (tests). */
|
|
2903
|
+
exit?: (code: number) => void;
|
|
2904
|
+
/** The clock (tests). */
|
|
2905
|
+
now?: () => Date;
|
|
2906
|
+
}
|
|
1800
2907
|
|
|
1801
2908
|
/**
|
|
1802
2909
|
* @module app/factories
|
|
1803
2910
|
* Component factory interfaces and defaults for {@link JeevesWatcher}. Override in tests to inject mocks.
|
|
1804
2911
|
*/
|
|
1805
2912
|
|
|
2913
|
+
/** Runtime options for {@link JeevesWatcher} that aren't serializable in config. */
|
|
2914
|
+
interface JeevesWatcherRuntimeOptions {
|
|
2915
|
+
/** Callback invoked on unrecoverable system error. If not set, throws. */
|
|
2916
|
+
onFatalError?: (error: unknown) => void;
|
|
2917
|
+
}
|
|
1806
2918
|
/**
|
|
1807
2919
|
* Component factories for {@link JeevesWatcher}. Override in tests to inject mocks.
|
|
1808
2920
|
*/
|
|
1809
2921
|
interface JeevesWatcherFactories {
|
|
1810
2922
|
/** Load and validate a {@link JeevesWatcherConfig} from disk. */
|
|
1811
|
-
loadConfig: (configPath?: string) => Promise<JeevesWatcherConfig>;
|
|
2923
|
+
loadConfig: (configPath?: string, options?: LoadConfigOptions) => Promise<JeevesWatcherConfig>;
|
|
1812
2924
|
/** Create a pino logger instance. */
|
|
1813
2925
|
createLogger: typeof createLogger;
|
|
1814
2926
|
/** Create an embedding provider from config. */
|
|
@@ -1818,15 +2930,43 @@ interface JeevesWatcherFactories {
|
|
|
1818
2930
|
/** Compile inference rules from config. */
|
|
1819
2931
|
compileRules: typeof compileRules;
|
|
1820
2932
|
/** Create a document processor for file ingestion. */
|
|
1821
|
-
createDocumentProcessor: (deps: ConstructorParameters<typeof DocumentProcessor>[0]) =>
|
|
2933
|
+
createDocumentProcessor: (deps: ConstructorParameters<typeof DocumentProcessor>[0]) => WatcherProcessor;
|
|
1822
2934
|
/** Create an event queue for batching file-system events. */
|
|
1823
2935
|
createEventQueue: (options: ConstructorParameters<typeof EventQueue>[0]) => EventQueue;
|
|
1824
2936
|
/** Create a file-system watcher for the configured watch paths. */
|
|
1825
2937
|
createFileSystemWatcher: (config: JeevesWatcherConfig['watch'], queue: EventQueue, processor: DocumentProcessorInterface, logger: pino.Logger, options?: FileSystemWatcherOptions) => FileSystemWatcher;
|
|
1826
2938
|
/** Create the HTTP API server. */
|
|
1827
2939
|
createApiServer: typeof createApiServer;
|
|
2940
|
+
/** Import `@parcel/watcher` when it is the selected source (D125). */
|
|
2941
|
+
importParcel: ParcelImporter;
|
|
2942
|
+
/**
|
|
2943
|
+
* The exit for a service-manager restart (D196). Tests replace it, so
|
|
2944
|
+
* they never call `process.exit`.
|
|
2945
|
+
*/
|
|
2946
|
+
createProcessRestarter: (deps: ProcessRestarterDeps) => ProcessRestarter;
|
|
1828
2947
|
}
|
|
1829
2948
|
|
|
2949
|
+
/**
|
|
2950
|
+
* @module app/sources
|
|
2951
|
+
* Startup wiring for source documents: builds the source callback client from `sources` config (read at startup only), the notify queue over the processor's source operations, and the adapter giving a file-only processor failing source operations. No I/O.
|
|
2952
|
+
*/
|
|
2953
|
+
|
|
2954
|
+
/**
|
|
2955
|
+
* Adapt a custom file-only processor to the {@link WatcherProcessor} the
|
|
2956
|
+
* service runs on. File operations are forwarded unchanged. Its source
|
|
2957
|
+
* operations fail: every notify-queue run returns a `failed` result with
|
|
2958
|
+
* `source_unavailable` (the run's issue, as for a failing callback), and
|
|
2959
|
+
* every other source operation throws the API's `503 not_available`, so
|
|
2960
|
+
* `POST /documents`, `POST /metadata { source }`, `POST /render { source }`
|
|
2961
|
+
* and `POST /reindex { source }` answer as before source support existed.
|
|
2962
|
+
* Use it in a custom `createDocumentProcessor` factory; never wrap a
|
|
2963
|
+
* processor that has source operations of its own (they would be hidden).
|
|
2964
|
+
*
|
|
2965
|
+
* @param processor - The file-only processor.
|
|
2966
|
+
* @returns The processor with failing source operations.
|
|
2967
|
+
*/
|
|
2968
|
+
declare function withoutSourceSupport(processor: DocumentProcessorInterface): WatcherProcessor;
|
|
2969
|
+
|
|
1830
2970
|
/**
|
|
1831
2971
|
* @module app/startFromConfig
|
|
1832
2972
|
* Convenience entry point: loads config from disk and starts a {@link JeevesWatcher}.
|
|
@@ -1850,14 +2990,7 @@ declare function startFromConfig(configPath?: string, descriptor?: JeevesCompone
|
|
|
1850
2990
|
* Main application orchestrator. Wires components, manages lifecycle (start/stop/reload).
|
|
1851
2991
|
*/
|
|
1852
2992
|
|
|
1853
|
-
/**
|
|
1854
|
-
interface JeevesWatcherRuntimeOptions {
|
|
1855
|
-
/** Callback invoked on unrecoverable system error. If not set, throws. */
|
|
1856
|
-
onFatalError?: (error: unknown) => void;
|
|
1857
|
-
}
|
|
1858
|
-
/**
|
|
1859
|
-
* Main application class that wires together all components.
|
|
1860
|
-
*/
|
|
2993
|
+
/** Main application class that wires together all components. */
|
|
1861
2994
|
declare class JeevesWatcher {
|
|
1862
2995
|
private config;
|
|
1863
2996
|
private readonly configPath?;
|
|
@@ -1867,52 +3000,41 @@ declare class JeevesWatcher {
|
|
|
1867
3000
|
private logger;
|
|
1868
3001
|
private watcher;
|
|
1869
3002
|
private queue;
|
|
3003
|
+
private sourceQueue;
|
|
1870
3004
|
private server;
|
|
1871
3005
|
private processor;
|
|
1872
3006
|
private configWatcher;
|
|
1873
|
-
private
|
|
1874
|
-
private valuesManager;
|
|
3007
|
+
private stores;
|
|
1875
3008
|
private helperIntrospection;
|
|
1876
|
-
private virtualRuleStore;
|
|
3009
|
+
private readonly virtualRuleStore;
|
|
1877
3010
|
private vectorStore;
|
|
1878
3011
|
private embeddingProvider;
|
|
3012
|
+
private embeddingHealth;
|
|
1879
3013
|
private gitignoreFilter;
|
|
1880
|
-
private enrichmentStore;
|
|
1881
|
-
private contentHashCache;
|
|
1882
3014
|
private vcsCoordinator;
|
|
1883
3015
|
private readonly initialScanTracker;
|
|
3016
|
+
private readonly changeSourceHealth;
|
|
3017
|
+
private readonly indexCheck;
|
|
3018
|
+
private readonly restarter;
|
|
3019
|
+
/** The state directory (default `ROOT_DEFAULTS.stateDir`). */
|
|
3020
|
+
private readonly stateDir;
|
|
1884
3021
|
private readonly version;
|
|
1885
3022
|
/** Create a new JeevesWatcher instance. */
|
|
1886
3023
|
constructor(config: JeevesWatcherConfig, configPath?: string, descriptor?: JeevesComponentDescriptor, factories?: Partial<JeevesWatcherFactories>, runtimeOptions?: JeevesWatcherRuntimeOptions);
|
|
1887
|
-
/**
|
|
1888
|
-
* Start the watcher, API server, and all components.
|
|
1889
|
-
*/
|
|
3024
|
+
/** Start the watcher, API server, and all components. */
|
|
1890
3025
|
start(): Promise<void>;
|
|
1891
|
-
/** Set up logger, VCS, embedding provider, and vector store. */
|
|
1892
|
-
private initInfrastructure;
|
|
1893
3026
|
/** Build the processing pipeline: rules, templates, processor, queue, VCS. */
|
|
1894
3027
|
private initPipeline;
|
|
1895
3028
|
/** Wire up watcher and VCS coordinator, then start all services. */
|
|
1896
3029
|
private startServicesAndWatcher;
|
|
1897
|
-
/**
|
|
1898
|
-
* Gracefully stop all components.
|
|
1899
|
-
*/
|
|
3030
|
+
/** Gracefully stop: API server first (no new notifications), then producers, then queues drain (shutdownComponents). */
|
|
1900
3031
|
stop(): Promise<void>;
|
|
1901
|
-
|
|
1902
|
-
private
|
|
1903
|
-
private
|
|
3032
|
+
/** Wiring every watcher the app builds shares, across rebuilds. */
|
|
3033
|
+
private watcherWiring;
|
|
3034
|
+
private apiServerOptions;
|
|
1904
3035
|
private reloadConfig;
|
|
1905
3036
|
}
|
|
1906
3037
|
|
|
1907
|
-
/**
|
|
1908
|
-
* Load the jeeves-watcher configuration.
|
|
1909
|
-
*
|
|
1910
|
-
* @param configPath - Optional explicit path to a config file.
|
|
1911
|
-
* @returns The loaded configuration.
|
|
1912
|
-
* @throws If no configuration is found or validation fails.
|
|
1913
|
-
*/
|
|
1914
|
-
declare function loadConfig(configPath?: string): Promise<JeevesWatcherConfig>;
|
|
1915
|
-
|
|
1916
3038
|
/**
|
|
1917
3039
|
* @module descriptor
|
|
1918
3040
|
* Jeeves Component Descriptor for the watcher service. Single source of truth
|
|
@@ -1983,112 +3105,5 @@ interface ResolvedWatchRoot {
|
|
|
1983
3105
|
relativePath: string;
|
|
1984
3106
|
}
|
|
1985
3107
|
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
* Handles scheduled squash retention for git-backed VCS roots.
|
|
1989
|
-
*/
|
|
1990
|
-
|
|
1991
|
-
/** Result of a squash operation. */
|
|
1992
|
-
interface SquashResult {
|
|
1993
|
-
squashed: boolean;
|
|
1994
|
-
commitsRemoved?: number;
|
|
1995
|
-
commitsRetained?: number;
|
|
1996
|
-
error?: string;
|
|
1997
|
-
}
|
|
1998
|
-
/** Commit metadata for retention calculation. */
|
|
1999
|
-
interface CommitInfo {
|
|
2000
|
-
hash: string;
|
|
2001
|
-
date: Date;
|
|
2002
|
-
}
|
|
2003
|
-
/** Options for SquashManager construction beyond the required params. */
|
|
2004
|
-
interface SquashManagerOptions {
|
|
2005
|
-
/** Git branch name for squash operations. Default: "master". */
|
|
2006
|
-
branch?: string;
|
|
2007
|
-
/** Called before squash to drain and pause the commit pipeline. */
|
|
2008
|
-
pauseCommits?: () => Promise<void>;
|
|
2009
|
-
/** Called after squash to resume the commit pipeline. */
|
|
2010
|
-
resumeCommits?: () => void;
|
|
2011
|
-
/** Remote URL for force-push after squash. */
|
|
2012
|
-
remoteUrl?: string;
|
|
2013
|
-
/** Access token for HTTPS push authentication. */
|
|
2014
|
-
accessToken?: string;
|
|
2015
|
-
}
|
|
2016
|
-
/**
|
|
2017
|
-
* Manages scheduled squash retention for a single VCS root.
|
|
2018
|
-
*
|
|
2019
|
-
* Runs on a cron schedule (checked every 60s). When triggered, squashes
|
|
2020
|
-
* commits older than the retention boundary (the tighter of maxAgeDays
|
|
2021
|
-
* and maxVersions) into a single "historical baseline" orphan commit,
|
|
2022
|
-
* then cherry-picks retained commits on top. Force-pushes to remote
|
|
2023
|
-
* if configured (D13).
|
|
2024
|
-
*/
|
|
2025
|
-
declare class SquashManager {
|
|
2026
|
-
private readonly rootPath;
|
|
2027
|
-
private readonly retention;
|
|
2028
|
-
private readonly branch;
|
|
2029
|
-
private readonly pauseCommits;
|
|
2030
|
-
private readonly resumeCommits;
|
|
2031
|
-
private readonly remoteUrl;
|
|
2032
|
-
private readonly accessToken;
|
|
2033
|
-
private readonly logger;
|
|
2034
|
-
private intervalTimer;
|
|
2035
|
-
private running;
|
|
2036
|
-
constructor(rootPath: string, retention: VcsRetentionConfig, logger: pino.Logger, options?: SquashManagerOptions);
|
|
2037
|
-
/**
|
|
2038
|
-
* Start the cron-based squash scheduler.
|
|
2039
|
-
* Checks every 60 seconds if the cron expression matches.
|
|
2040
|
-
*/
|
|
2041
|
-
start(): void;
|
|
2042
|
-
/**
|
|
2043
|
-
* Stop the cron scheduler.
|
|
2044
|
-
*/
|
|
2045
|
-
stop(): void;
|
|
2046
|
-
/**
|
|
2047
|
-
* Run the squash operation. Exposed publicly for testing.
|
|
2048
|
-
*
|
|
2049
|
-
* Coordinates with VcsManager by calling pause/resume callbacks
|
|
2050
|
-
* to drain and suspend the commit pipeline during the squash.
|
|
2051
|
-
*/
|
|
2052
|
-
runSquash(): Promise<SquashResult>;
|
|
2053
|
-
/**
|
|
2054
|
-
* Refuse to start a multi-step history rewrite while another git
|
|
2055
|
-
* operation holds the index or an abandoned cherry-pick, rebase, or merge
|
|
2056
|
-
* is present (#249: report only, never auto-clear).
|
|
2057
|
-
*
|
|
2058
|
-
* @returns The refusal reason, or undefined if the squash may proceed.
|
|
2059
|
-
*/
|
|
2060
|
-
private checkRepoPreconditions;
|
|
2061
|
-
/**
|
|
2062
|
-
* Get all commits in chronological order (oldest first).
|
|
2063
|
-
*/
|
|
2064
|
-
getCommitLog(): Promise<CommitInfo[]>;
|
|
2065
|
-
/**
|
|
2066
|
-
* Calculate the retention boundary index.
|
|
2067
|
-
* Returns the index of the oldest commit to KEEP.
|
|
2068
|
-
* All commits before this index will be squashed into a baseline.
|
|
2069
|
-
*
|
|
2070
|
-
* Strategy: find the tighter constraint between age and count.
|
|
2071
|
-
* - Age: keep commits newer than maxAgeDays
|
|
2072
|
-
* - Count: keep the last maxVersions commits
|
|
2073
|
-
* The boundary is the one that retains FEWER old commits (tighter).
|
|
2074
|
-
*/
|
|
2075
|
-
calculateRetentionBoundary(commits: CommitInfo[]): number;
|
|
2076
|
-
/**
|
|
2077
|
-
* Perform the squash: create orphan with baseline + cherry-pick retained commits.
|
|
2078
|
-
* Uses the configured branch name instead of dynamic detection (Bug 1).
|
|
2079
|
-
*/
|
|
2080
|
-
private performSquash;
|
|
2081
|
-
/**
|
|
2082
|
-
* Best-effort cleanup after a failed squash. Aborts any half-finished
|
|
2083
|
-
* cherry-pick first, so a failure never leaves a sequencer behind (#249),
|
|
2084
|
-
* then returns to the configured branch and removes a leftover lock.
|
|
2085
|
-
*/
|
|
2086
|
-
private cleanupFailedSquash;
|
|
2087
|
-
/**
|
|
2088
|
-
* Force push to remote after squash (history rewrite requires force).
|
|
2089
|
-
*/
|
|
2090
|
-
private forcePushIfConfigured;
|
|
2091
|
-
}
|
|
2092
|
-
|
|
2093
|
-
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 };
|
|
2094
|
-
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, SquashManagerOptions, SquashResult, SystemHealthOptions, ValuesIndex, VectorPoint, VectorStore, WatchEvent };
|
|
3108
|
+
export { ChangeSourceHealthTracker, CommitMessageGenerator, ContentHashCache, DEFAULT_SOURCE_NOTIFY_CONCURRENCY, DocumentLocks, DocumentProcessor, EnrichmentStore, EventQueue, FileSystemWatcher, GitignoreFilter, InitialScanTracker, Inventory, IssuesManager, JeevesWatcher, ReindexTracker, RootGitLock, SourceClient, SourceNotifyQueue, SourceNotifyQueueStoppedError, SourceReferenceError, SquashManager, SystemHealth, TemplateEngine, ValuesManager, VcsCoordinator, VcsManager, VectorStoreClient, VirtualRuleStore, applyRules, buildAttributes, buildTemplateEngine, compileRules, contentHash, createApiServer, createEmbeddingProvider, createHandlebarsInstance, createLogger, extractText, fileLockKey, loadConfig, loadCustomHelpers, mergeEnrichment, parseSourceReference, parsedSourceReferenceSchema, pointId, registerBuiltinHelpers, resolveTemplateSource, resolvedSourceReferenceSchema, sourceAttributesSchema, sourceErrorCodeSchema, sourceNotifyQueueOptionsSchema, sourceRejectionCodeSchema, sourceRetrievalResultSchema, startFromConfig, watcherDescriptor, withoutSourceSupport };
|
|
3109
|
+
export type { AllHelpersIntrospection, ApiServerOptions, ApplyRulesOptions, ApplyRulesResult, ChangeSink, CircuitBreakerSnapshot, ClassifiedEventType, CollectionInfo, CommitInfo, CompiledRule, CompiledTemplate, ConfigWarning, DocumentLockOptions, DocumentProcessorDeps, DocumentProcessorInterface, EmbedOptions, EmbeddingErrorSummary, EmbeddingHealthSnapshot, EmbeddingHealthState, EmbeddingProvider, EnrichmentStoreInterface, EventQueueOptions, ExtractedText, Extractor, FacetHit, FacetRead, FacetStore, FacetValue, FileAttributes, FileStats, FileSystemWatcherOptions, HelperModuleIntrospection, IndexCheckSkipReason, IndexCheckView, IndexOptions, InventoryEntry, IssuesFile, JeevesWatcherFactories, JeevesWatcherRuntimeOptions, LoadConfigOptions, ParcelImporter, ParcelWatcherModule, ParsedSourceReference, PausableQueue, PayloadFieldSchema, PendingReversion, ProcessFn, ProcessNowOptions, ProcessRestarter, ProcessRestarterDeps, ProcessingLimits, ProcessorConfig, ProviderFactory, PushError, RangeBound, RangeEnd, RawChangeEvent, RenderResult, ResolvedSourceReference, ResolvedWatchRoot, RestartRequest, RootUnavailableOptions, RuleAttributes, RuleLogger, ScrollPageResult, ScrolledPoint, SearchResult, SourceAttributes, SourceErrorCode, SourceNotifyQueueOptions, SourceOperationsInterface, SourceOperationsProvider, SourceProcess, SourceQueueIssues, SourceRejectionCode, SourceRenderOutcome, SourceRetrievalResult, SourceRetriever, SquashManagerOptions, SquashResult, SystemHealthOptions, SystemIndexState, ValuesIndex, VcsBreakerState, VcsFileChange, VcsManagerOptions, VectorPoint, VectorStore, WatchEvent, WatcherProcessor };
|