@karmaniverous/jeeves-watcher 0.19.1 → 0.20.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/dist/index.d.ts CHANGED
@@ -1,10 +1,11 @@
1
- import { JeevesComponentDescriptor } from '@karmaniverous/jeeves';
2
1
  import { FastifyInstance } from 'fastify';
2
+ import { JeevesComponentDescriptor } from '@karmaniverous/jeeves';
3
3
  import pino from 'pino';
4
- import { EmbeddingConfig, InferenceRule, SchemaEntry, VectorStoreConfig, VcsConfig, JeevesWatcherConfig, WatchConfig, LoggingConfig, VcsRetentionConfig } from '@karmaniverous/jeeves-watcher-core';
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';
4
+ import { EmbeddingConfig, IssueRecord, InferenceRule, SchemaEntry, SourcesConfig, VectorStoreConfig, DocumentResult, DocumentRejectionError, DocumentFailure, VcsConfig, JeevesWatcherConfig, WatchConfig, LoggingConfig, VcsRetentionConfig } from '@karmaniverous/jeeves-watcher-core';
5
+ export { ApiConfig, ConfigWatchConfig, EmbeddingConfig, InferenceRule, IssueRecord, JeevesWatcherConfig, JeevesWatcherConfigInput, LoggingConfig, VectorStoreConfig, WatchConfig, apiConfigSchema, configWatchConfigSchema, embeddingConfigSchema, inferenceRuleSchema, issueRecordSchema, jeevesWatcherConfigSchema, loggingConfigSchema, vectorStoreConfigSchema, watchConfigSchema } from '@karmaniverous/jeeves-watcher-core';
6
+ import { ErrorObject } from 'ajv';
7
7
  import Handlebars from 'handlebars';
8
+ import { z } from 'zod';
8
9
  import { JsonMapMap } from '@karmaniverous/jsonmap';
9
10
  import { Stats } from 'node:fs';
10
11
 
@@ -13,12 +14,45 @@ import { Stats } from 'node:fs';
13
14
  * Embedding provider type definitions.
14
15
  */
15
16
 
17
+ /**
18
+ * Per-call budget for the shared rate limiter. Providers that do not
19
+ * rate-limit ignore the budget; providers that retry internally await
20
+ * `beforeRetry` before each retry.
21
+ *
22
+ * The budget bounds the limiter, not the provider's own network retries:
23
+ * each of the `attempts` provider calls may itself retry a transient
24
+ * (non-429) failure up to `NETWORK_RETRY_POLICY.attempts` times in all, with
25
+ * backoff sleeps, so one `embed()` can issue up to `attempts` x 5 HTTP
26
+ * requests.
27
+ */
28
+ interface EmbedOptions {
29
+ /**
30
+ * Maximum provider calls for this call: a 429 ends a provider call and
31
+ * costs one attempt. Transient network retries inside a provider call do
32
+ * not count against it (see the interface note).
33
+ */
34
+ attempts?: number;
35
+ /**
36
+ * Maximum total time to wait for the limiter (token or `Retry-After`
37
+ * pause), in ms. When a wait would exceed it, the call fails fast. The
38
+ * provider's own network-retry backoff sleeps are not counted.
39
+ */
40
+ maxWaitMs?: number;
41
+ /**
42
+ * Awaited by a provider before each retry it makes internally (any HTTP
43
+ * request after the first of an `embed()` call), so every request draws
44
+ * from the shared limiter. Supplied by the rate-limited wrapper; it may
45
+ * reject (e.g. `EmbeddingUnavailableError`), which the provider must
46
+ * propagate without retrying.
47
+ */
48
+ beforeRetry?: () => Promise<void>;
49
+ }
16
50
  /**
17
51
  * An embedding provider that converts text into vector representations.
18
52
  */
19
53
  interface EmbeddingProvider {
20
- /** Generate embedding vectors for the given texts. */
21
- embed(texts: string[]): Promise<number[][]>;
54
+ /** Generate embedding vectors for the given texts (one provider request). */
55
+ embed(texts: string[], options?: EmbedOptions): Promise<number[][]>;
22
56
  /** The dimensionality of the embedding vectors. */
23
57
  dimensions: number;
24
58
  }
@@ -48,7 +82,7 @@ declare function createEmbeddingProvider(config: EmbeddingConfig, logger?: pino.
48
82
 
49
83
  /**
50
84
  * @module enrichment/EnrichmentStore
51
- * SQLite-backed enrichment metadata store. Persists path-keyed metadata at stateDir/enrichments.sqlite. Atomic writes, supports move.
85
+ * SQLite-backed enrichment metadata store. Persists path- or source-reference-keyed metadata (references verbatim) at stateDir/enrichments.sqlite. Atomic writes, supports move.
52
86
  */
53
87
 
54
88
  /**
@@ -188,95 +222,44 @@ declare abstract class JsonFileStore<T> {
188
222
 
189
223
  /**
190
224
  * @module issues/types
191
- * Zod schemas and TypeScript types for the issues tracking system. Defines IssueRecord and IssuesFile structures.
225
+ * 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
226
  */
193
227
 
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
228
  /** Issues file: array of issue records per file path. */
207
229
  type IssuesFile = Partial<Record<string, IssueRecord[]>>;
208
230
 
209
231
  /**
210
232
  * @module issues/IssuesManager
211
- * Manages persistent issue tracking for file processing failures. Read-modify-write with in-memory cache.
233
+ * Manages persistent issue tracking for processing failures, keyed by document key (file path or source reference). Read-modify-write with in-memory cache.
212
234
  */
213
235
 
214
236
  /**
215
- * Manages a persistent issues.json file tracking processing failures per file.
237
+ * Manages a persistent issues.json file tracking processing failures per
238
+ * document key (file path or source reference).
216
239
  */
217
240
  declare class IssuesManager extends JsonFileStore<IssuesFile> {
218
241
  constructor(stateDir: string, logger: pino.Logger);
219
242
  protected createEmpty(): IssuesFile;
220
- /** Record or update an issue for a file path. */
221
- record(filePath: string, type: IssueRecord['type'], message: string, options?: {
222
- property?: string;
223
- rules?: string[];
224
- types?: string[];
225
- }): void;
226
- /** Clear an issue for a file path (called on successful processing). */
227
- clear(filePath: string): void;
243
+ /**
244
+ * Record an issue for a document key (file path or source reference).
245
+ *
246
+ * @param key - Document key (file path or source reference).
247
+ * @param type - Canonical issue code.
248
+ * @param message - Error message.
249
+ * @param options - Optional operation, property, rule(s), types and
250
+ * structured `details` (stored as JSON, e.g. AJV errors).
251
+ */
252
+ record(key: string, type: IssueRecord['type'], message: string, options?: Pick<IssueRecord, 'operation' | 'property' | 'rules' | 'rule' | 'types' | 'details'>): void;
253
+ /** Clear the issues of a document key (called on successful processing). */
254
+ clear(key: string): void;
228
255
  /** Wipe all issues (called on full reindex start). */
229
256
  clearAll(): void;
257
+ /** Get the current issues of one document key, if any. */
258
+ get(key: string): IssueRecord[] | undefined;
230
259
  /** Get all current issues. */
231
260
  getAll(): IssuesFile;
232
261
  }
233
262
 
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
263
  /**
281
264
  * @module templates/engine
282
265
  * Handlebars template compilation, caching, and resolution (file path vs named ref vs inline).
@@ -391,6 +374,29 @@ declare function buildTemplateEngine(rules: InferenceRule[], namedTemplates?: Re
391
374
  */
392
375
  declare function registerBuiltinHelpers(hbs: typeof Handlebars): void;
393
376
 
377
+ /**
378
+ * @module rules/sourceAttributes
379
+ * Zod schema and builder for source-document rule attributes (`source` identity block + `json` record; no `file` key). Pure, no I/O.
380
+ */
381
+
382
+ /**
383
+ * Attributes a source document is matched and resolved against. There is no
384
+ * `file` key, so file rules (`file.path` globs) never match a source
385
+ * document, and a source rule (`required: ["source"]`) never matches a file.
386
+ */
387
+ declare const sourceAttributesSchema: z.ZodObject<{
388
+ source: z.ZodObject<{
389
+ ref: z.ZodString;
390
+ name: z.ZodString;
391
+ id: z.ZodString;
392
+ rule: z.ZodString;
393
+ retrievedAt: z.ZodString;
394
+ }, z.core.$strip>;
395
+ json: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
396
+ }, z.core.$strip>;
397
+ /** Attributes of a source document. */
398
+ type SourceAttributes = z.infer<typeof sourceAttributesSchema>;
399
+
394
400
  /**
395
401
  * @module rules/attributes
396
402
  * Builds file attribute objects for rule matching. Pure function: derives attributes from path, stats, and extracted data.
@@ -420,6 +426,8 @@ interface FileAttributes {
420
426
  /** Parsed JSON content, if any. */
421
427
  json?: Record<string, unknown>;
422
428
  }
429
+ /** Attributes rules are matched and resolved against: a file or a source document. */
430
+ type RuleAttributes = FileAttributes | SourceAttributes;
423
431
  /**
424
432
  * Build {@link FileAttributes} from a file path and stat info.
425
433
  *
@@ -442,8 +450,13 @@ declare function buildAttributes(filePath: string, stats: Stats, extractedFrontm
442
450
  interface CompiledRule {
443
451
  /** The original rule definition. */
444
452
  rule: InferenceRule;
445
- /** The compiled AJV validate function. */
446
- validate: (data: unknown) => boolean;
453
+ /**
454
+ * The compiled AJV validate function. After a failed call, `errors` holds
455
+ * the AJV errors (used for `match_failed` issues).
456
+ */
457
+ validate: ((data: unknown) => boolean) & {
458
+ errors?: ErrorObject[] | null;
459
+ };
447
460
  }
448
461
  /**
449
462
  * Compile an array of inference rules into executable validators.
@@ -454,9 +467,31 @@ interface CompiledRule {
454
467
  */
455
468
  declare function compileRules(rules: InferenceRule[]): CompiledRule[];
456
469
 
470
+ /**
471
+ * @module rules/ruleErrors
472
+ * Interpolation errors collected while applying rules (schema `set` resolution, `render`, `template`): Zod schema, type and one-line formatting. Pure.
473
+ */
474
+
475
+ /**
476
+ * One interpolation failure of a matched rule. The rule's output for that
477
+ * stage is missing (schema failure: the rule's metadata, map and render are
478
+ * skipped; render/template failure: the raw content is used instead).
479
+ */
480
+ declare const ruleApplicationErrorSchema: z.ZodObject<{
481
+ rule: z.ZodString;
482
+ stage: z.ZodEnum<{
483
+ schema: "schema";
484
+ render: "render";
485
+ template: "template";
486
+ }>;
487
+ message: z.ZodString;
488
+ }, z.core.$strip>;
489
+ /** One interpolation failure of a matched rule. */
490
+ type RuleApplicationError = z.infer<typeof ruleApplicationErrorSchema>;
491
+
457
492
  /**
458
493
  * @module rules/apply
459
- * Applies compiled inference rules to file attributes, producing merged metadata via template resolution and JsonMap transforms.
494
+ * 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
495
  */
461
496
 
462
497
  /**
@@ -478,6 +513,11 @@ interface ApplyRulesResult {
478
513
  matchedRules: string[];
479
514
  /** The renderAs value from the last matching rule that declares it, or null. */
480
515
  renderAs: string | null;
516
+ /**
517
+ * Interpolation failures (schema `set` resolution, `render`, `template`)
518
+ * of matched rules, in order. Each was also logged as a warning.
519
+ */
520
+ errors: RuleApplicationError[];
481
521
  }
482
522
  /**
483
523
  * Optional parameters for applyRules beyond the required compiledRules and attributes.
@@ -503,14 +543,16 @@ interface ApplyRulesOptions {
503
543
  *
504
544
  * Rules are evaluated in order; later rules override earlier ones.
505
545
  * If a rule has a `map`, the JsonMap transformation is applied after `set` resolution,
506
- * and map output overrides set output on conflict.
546
+ * and map output overrides set output on conflict. A failing schema, render
547
+ * or template is logged and reported in `errors`; the rule's output for that
548
+ * stage is skipped (a schema failure skips the rest of the rule).
507
549
  *
508
550
  * @param compiledRules - The compiled rules to evaluate.
509
- * @param attributes - The file attributes to match against.
551
+ * @param attributes - The file or source attributes to match against.
510
552
  * @param options - Optional configuration for rule application.
511
- * @returns The merged metadata and optional rendered content.
553
+ * @returns The merged metadata, optional rendered content and errors.
512
554
  */
513
- declare function applyRules(compiledRules: CompiledRule[], attributes: FileAttributes, options?: ApplyRulesOptions): Promise<ApplyRulesResult>;
555
+ declare function applyRules(compiledRules: CompiledRule[], attributes: RuleAttributes, options?: ApplyRulesOptions): Promise<ApplyRulesResult>;
514
556
 
515
557
  /**
516
558
  * @module rules/virtualRules
@@ -560,6 +602,188 @@ declare class VirtualRuleStore {
560
602
  get size(): number;
561
603
  }
562
604
 
605
+ /**
606
+ * @module cache/ContentHashCache
607
+ * In-memory cache mapping normalized file paths to content hashes.
608
+ * Supports reverse lookup by hash for move correlation.
609
+ */
610
+ /**
611
+ * In-memory content hash cache for move detection.
612
+ *
613
+ * Maps normalized file paths to SHA-256 content hashes.
614
+ * Supports reverse lookup (hash → paths) for correlating
615
+ * unlink+add events as file moves.
616
+ */
617
+ declare class ContentHashCache {
618
+ private readonly pathToHash;
619
+ private readonly hashToPaths;
620
+ /**
621
+ * Store or update the content hash for a file path.
622
+ *
623
+ * @param filePath - The file path (will be normalized).
624
+ * @param hash - The SHA-256 content hash.
625
+ */
626
+ set(filePath: string, hash: string): void;
627
+ /**
628
+ * Get the content hash for a file path.
629
+ *
630
+ * @param filePath - The file path (will be normalized).
631
+ * @returns The content hash, or undefined if not cached.
632
+ */
633
+ get(filePath: string): string | undefined;
634
+ /**
635
+ * Remove a file path from the cache.
636
+ *
637
+ * @param filePath - The file path (will be normalized).
638
+ */
639
+ delete(filePath: string): void;
640
+ /**
641
+ * Reverse lookup: get all file paths with a given content hash.
642
+ *
643
+ * @param hash - The content hash to look up.
644
+ * @returns Array of normalized file paths with that hash.
645
+ */
646
+ getByHash(hash: string): string[];
647
+ /** Number of cached entries. */
648
+ get size(): number;
649
+ }
650
+
651
+ /**
652
+ * @module sources/types
653
+ * Zod schemas and derived types for source callback outcomes (document / gone / error) and reference rejections. Pure declarations; no I/O.
654
+ */
655
+
656
+ /**
657
+ * Error codes a source callback can produce: the subset of the canonical
658
+ * issue codes that belong to retrieval.
659
+ */
660
+ declare const sourceErrorCodeSchema: z.ZodEnum<{
661
+ source_unavailable: "source_unavailable";
662
+ unsupported_content_type: "unsupported_content_type";
663
+ }>;
664
+ /** A source callback error code. */
665
+ type SourceErrorCode = z.infer<typeof sourceErrorCodeSchema>;
666
+ /** Outcome of one source callback (discriminated on `kind`). */
667
+ declare const sourceRetrievalResultSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
668
+ kind: z.ZodLiteral<"document">;
669
+ body: z.ZodRecord<z.ZodString, z.ZodUnknown>;
670
+ }, z.core.$strip>, z.ZodObject<{
671
+ kind: z.ZodLiteral<"gone">;
672
+ }, z.core.$strip>, z.ZodObject<{
673
+ kind: z.ZodLiteral<"error">;
674
+ code: z.ZodEnum<{
675
+ source_unavailable: "source_unavailable";
676
+ unsupported_content_type: "unsupported_content_type";
677
+ }>;
678
+ message: z.ZodString;
679
+ }, z.core.$strip>], "kind">;
680
+ /** Outcome of one source callback. */
681
+ type SourceRetrievalResult = z.infer<typeof sourceRetrievalResultSchema>;
682
+ /**
683
+ * Why a reference was rejected before any request was made:
684
+ * `invalid_reference` (not `<name>://<id>`), `unknown_source` (name not in
685
+ * config `sources`), `invalid_id` (empty, `.` or `..` segment, or the built
686
+ * URL would leave the configured origin). The reference-level subset of
687
+ * core `documentRejectionCodeSchema`.
688
+ */
689
+ declare const sourceRejectionCodeSchema: z.ZodEnum<{
690
+ invalid_reference: "invalid_reference";
691
+ unknown_source: "unknown_source";
692
+ invalid_id: "invalid_id";
693
+ }>;
694
+ /** A reference rejection code. */
695
+ type SourceRejectionCode = z.infer<typeof sourceRejectionCodeSchema>;
696
+ /** A parsed `<name>://<id>` reference. */
697
+ declare const parsedSourceReferenceSchema: z.ZodObject<{
698
+ ref: z.ZodString;
699
+ name: z.ZodString;
700
+ id: z.ZodString;
701
+ }, z.core.$strip>;
702
+ /** A parsed `<name>://<id>` reference. */
703
+ type ParsedSourceReference = z.infer<typeof parsedSourceReferenceSchema>;
704
+ /** A reference resolved against config: parsed parts plus the URL to request. */
705
+ declare const resolvedSourceReferenceSchema: z.ZodObject<{
706
+ ref: z.ZodString;
707
+ name: z.ZodString;
708
+ id: z.ZodString;
709
+ url: z.ZodString;
710
+ }, z.core.$strip>;
711
+ /** A reference resolved against config. */
712
+ type ResolvedSourceReference = z.infer<typeof resolvedSourceReferenceSchema>;
713
+ /**
714
+ * Thrown (or rejected) when a reference cannot be retrieved for a reason
715
+ * known before any request is made. No request is ever sent for a rejected
716
+ * reference.
717
+ */
718
+ declare class SourceReferenceError extends Error {
719
+ /** Rejection code. */
720
+ readonly code: SourceRejectionCode;
721
+ /**
722
+ * @param code - Rejection code.
723
+ * @param message - Human-readable reason (never contains header values).
724
+ */
725
+ constructor(code: SourceRejectionCode, message: string);
726
+ }
727
+
728
+ /**
729
+ * @module sources/SourceClient
730
+ * 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.
731
+ */
732
+
733
+ /**
734
+ * Retrieves source documents by callback. Injected into later pipeline
735
+ * stages (resolver, notify queue, reindex) so tests can substitute it.
736
+ */
737
+ interface SourceRetriever {
738
+ /**
739
+ * Validate a reference and build its URL without making a request.
740
+ *
741
+ * @throws {@link SourceReferenceError}
742
+ */
743
+ resolve(reference: string): ResolvedSourceReference;
744
+ /**
745
+ * Retrieve a document. Rejects with {@link SourceReferenceError} (and
746
+ * sends nothing) for an invalid reference; otherwise never rejects.
747
+ */
748
+ retrieve(reference: string): Promise<SourceRetrievalResult>;
749
+ }
750
+ /**
751
+ * The source callback client. Constructed once from the parsed `sources`
752
+ * config (defaults applied, `${ENV}` already substituted at load). Each
753
+ * source gets its own concurrency semaphore; the `timeoutMs` clock starts
754
+ * when a request leaves the queue, not while it waits for a slot. Callbacks
755
+ * do not draw from the embedding rate limiter.
756
+ */
757
+ declare class SourceClient implements SourceRetriever {
758
+ private readonly entries;
759
+ /**
760
+ * @param sources - The parsed `sources` config section.
761
+ * @throws Error when a `url` template is not an absolute http(s) URL or
762
+ * places `{id}` in its origin (scheme, host or port).
763
+ */
764
+ constructor(sources?: SourcesConfig);
765
+ /** {@inheritDoc SourceRetriever.resolve} */
766
+ resolve(reference: string): ResolvedSourceReference;
767
+ /** {@inheritDoc SourceRetriever.retrieve} */
768
+ retrieve(reference: string): Promise<SourceRetrievalResult>;
769
+ private resolveEntry;
770
+ }
771
+
772
+ /**
773
+ * @module sources/sourceUrl
774
+ * Pure helpers: parse `<name>://<id>` references, encode ids segment-by-segment, and build callback URLs from a configured template. No I/O.
775
+ */
776
+
777
+ /**
778
+ * Parse a source reference.
779
+ *
780
+ * @param reference - A `<name>://<id>` string.
781
+ * @returns The parsed reference.
782
+ * @throws {@link SourceReferenceError} `invalid_reference` when the string
783
+ * does not match the core reference schema.
784
+ */
785
+ declare function parseSourceReference(reference: string): ParsedSourceReference;
786
+
563
787
  /**
564
788
  * @module util/BinaryFileStore
565
789
  * Binary-backed read/modify/write store with in-memory caching and debounced flush.
@@ -619,7 +843,7 @@ declare abstract class BinaryFileStore<T> {
619
843
  /** Per-rule distinct values: rule name → field name → sorted unique values. */
620
844
  type ValuesIndex = Record<string, Record<string, unknown[]>>;
621
845
  /**
622
- * Manages a persistent values.json file tracking distinct metadata values per rule.
846
+ * Manages a persistent values.v8 file tracking distinct metadata values per rule.
623
847
  */
624
848
  declare class ValuesManager extends BinaryFileStore<ValuesIndex> {
625
849
  constructor(stateDir: string, logger: pino.Logger);
@@ -730,11 +954,19 @@ interface VectorStore {
730
954
  * @param payload - Payload fields to set.
731
955
  */
732
956
  setPayload(ids: string[], payload: Record<string, unknown>): Promise<void>;
957
+ /**
958
+ * Remove payload keys from the specified point IDs (other keys kept).
959
+ *
960
+ * @param ids - Point IDs to update.
961
+ * @param keys - Payload keys to remove.
962
+ */
963
+ deletePayload(ids: string[], keys: string[]): Promise<void>;
733
964
  /**
734
965
  * Get the payload of a point by ID.
735
966
  *
736
967
  * @param id - The point ID.
737
968
  * @returns The payload, or `null` if the point doesn't exist.
969
+ * @throws When the read fails (never reported as a missing point).
738
970
  */
739
971
  getPayload(id: string): Promise<Record<string, unknown> | null>;
740
972
  /**
@@ -796,19 +1028,26 @@ interface VectorStore {
796
1028
  getPointsWithVectors(ids: string[]): Promise<VectorPoint[]>;
797
1029
  }
798
1030
 
1031
+ /**
1032
+ * @module vectorStore
1033
+ * Qdrant-backed {@link VectorStore}: collection setup, retried writes (see `writes`), payload reads, search, hybrid search and scrolling. Qdrant I/O.
1034
+ */
1035
+
799
1036
  /**
800
1037
  * Client wrapper for Qdrant vector store operations.
801
1038
  *
802
1039
  * Implements the {@link VectorStore} interface for dependency inversion.
1040
+ * Writes (upsert, delete, set/delete payload) are retried, each retry on a
1041
+ * fresh client (see QdrantWriter).
803
1042
  */
804
1043
  declare class VectorStoreClient implements VectorStore {
805
1044
  private readonly client;
806
- private writeClient;
1045
+ private readonly writer;
807
1046
  private readonly clientConfig;
808
1047
  private readonly collectionName;
809
1048
  private readonly dims;
810
- private readonly log;
811
1049
  private readonly pinoLogger?;
1050
+ private readonly payloadIndexes;
812
1051
  /**
813
1052
  * Create a new VectorStoreClient.
814
1053
  *
@@ -823,7 +1062,8 @@ declare class VectorStoreClient implements VectorStore {
823
1062
  * Used to avoid stale HTTP keep-alive connections. The Qdrant JS client's
824
1063
  * internal undici Agent uses keepAliveTimeout: 10s, which causes ECONNRESET
825
1064
  * when connections sit idle during slow embedding calls (Gemini p99 ~8s).
826
- * Creating a fresh client for write operations ensures clean TCP connections.
1065
+ * Writes therefore run on their own client, replaced on every retry
1066
+ * (see QdrantWriter).
827
1067
  */
828
1068
  private createClient;
829
1069
  /**
@@ -834,48 +1074,24 @@ declare class VectorStoreClient implements VectorStore {
834
1074
  */
835
1075
  count(filter?: Record<string, unknown>): Promise<number>;
836
1076
  /**
837
- * Ensure the collection exists with correct dimensions and Cosine distance.
1077
+ * Ensure the collection exists (Cosine, configured dimensions) and create
1078
+ * any missing payload indexes (configured plus `source`/`source_rule`).
838
1079
  */
839
1080
  ensureCollection(): Promise<void>;
840
- /**
841
- * Retry a Qdrant operation with standardized config and logging.
842
- *
843
- * @param operation - Operation name for logging (e.g., 'upsert', 'delete').
844
- * @param fn - Async function to retry.
845
- */
846
- private retryOperation;
847
- private getWriteClient;
848
- /**
849
- * Upsert points into the collection.
850
- *
851
- * Uses the shared client. On retry (after ECONNRESET from stale connections),
852
- * creates a fresh client to recover.
853
- *
854
- * @param points - The points to upsert.
855
- */
1081
+ /** {@inheritDoc VectorStore.upsert} */
856
1082
  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
- */
1083
+ /** {@inheritDoc VectorStore.delete} */
864
1084
  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
- */
1085
+ /** {@inheritDoc VectorStore.setPayload} */
873
1086
  setPayload(ids: string[], payload: Record<string, unknown>): Promise<void>;
1087
+ /** {@inheritDoc VectorStore.deletePayload} */
1088
+ deletePayload(ids: string[], keys: string[]): Promise<void>;
874
1089
  /**
875
1090
  * Get the payload of a point by ID.
876
1091
  *
877
1092
  * @param id - The point ID.
878
1093
  * @returns The payload, or `null` if the point doesn't exist.
1094
+ * @throws When the read fails (never reported as a missing point).
879
1095
  */
880
1096
  getPayload(id: string): Promise<Record<string, unknown> | null>;
881
1097
  /**
@@ -918,6 +1134,7 @@ declare class VectorStoreClient implements VectorStore {
918
1134
  *
919
1135
  * @param ids - The point IDs to retrieve.
920
1136
  * @returns Points with vectors and payloads; missing IDs are omitted.
1137
+ * @throws When the read fails (never reported as missing points).
921
1138
  */
922
1139
  getPointsWithVectors(ids: string[]): Promise<VectorPoint[]>;
923
1140
  /**
@@ -963,10 +1180,44 @@ interface ProcessorConfig {
963
1180
  globalSchemas?: Record<string, SchemaEntry>;
964
1181
  }
965
1182
 
1183
+ /**
1184
+ * @module processor/DocumentProcessorDeps
1185
+ * Constructor dependencies for DocumentProcessor (config, embedding provider, vector store, rules, optional stores), extracted for single-responsibility.
1186
+ */
1187
+
1188
+ /**
1189
+ * Dependencies injected into DocumentProcessor.
1190
+ */
1191
+ interface DocumentProcessorDeps {
1192
+ /** Processor configuration (chunk sizes, directories, maps). */
1193
+ config: ProcessorConfig;
1194
+ /** Provider for generating text embeddings. */
1195
+ embeddingProvider: EmbeddingProvider;
1196
+ /** Vector store for persistence. */
1197
+ vectorStore: VectorStore;
1198
+ /** Pre-compiled inference rules for metadata extraction. */
1199
+ compiledRules: CompiledRule[];
1200
+ /** Pino logger instance. */
1201
+ logger: pino.Logger;
1202
+ /** Optional Handlebars template engine for content templates. */
1203
+ templateEngine?: TemplateEngine;
1204
+ /** Optional enrichment store for persisted enrichment metadata. */
1205
+ enrichmentStore?: EnrichmentStoreInterface;
1206
+ /** Optional issues manager; processing failures are recorded as typed issues (#255). */
1207
+ issuesManager?: IssuesManager;
1208
+ /** Optional values manager for tracking rule-extracted values. */
1209
+ valuesManager?: ValuesManager;
1210
+ /** Optional content hash cache for move detection. */
1211
+ contentHashCache?: ContentHashCache;
1212
+ /** Optional source callback client; without it, source documents fail `source_unavailable`. */
1213
+ sourceRetriever?: SourceRetriever;
1214
+ }
1215
+
966
1216
  /**
967
1217
  * @module processor/renderResult
968
- * Type definition for the render endpoint result.
1218
+ * The render endpoint result and its one constructor from a resolved document (file or source). Pure, no I/O.
969
1219
  */
1220
+
970
1221
  /**
971
1222
  * Result returned by {@link DocumentProcessorInterface.renderFile}.
972
1223
  */
@@ -983,6 +1234,63 @@ interface RenderResult {
983
1234
  transformed: boolean;
984
1235
  }
985
1236
 
1237
+ /**
1238
+ * @module processor/documentPipeline
1239
+ * The shared indexing pipeline for resolved documents (file or source): onResolved hook, empty check, hash compare, chunk, embed, upsert, orphan cleanup; plus point deletion.
1240
+ */
1241
+
1242
+ /**
1243
+ * Options for indexing one document (see
1244
+ * {@link SourceOperationsInterface.process}).
1245
+ */
1246
+ interface IndexOptions {
1247
+ /**
1248
+ * Re-embed and rewrite even when the content hash is unchanged (source
1249
+ * documents on a `full` reindex).
1250
+ */
1251
+ force?: boolean;
1252
+ }
1253
+
1254
+ /**
1255
+ * @module processor/SourceOperations
1256
+ * 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.
1257
+ */
1258
+
1259
+ /** Outcome of rendering a source document (`POST /render { source }`). */
1260
+ type SourceRenderOutcome = {
1261
+ kind: 'rendered';
1262
+ result: RenderResult;
1263
+ } | {
1264
+ kind: 'gone';
1265
+ } | {
1266
+ kind: 'failed';
1267
+ error: DocumentFailure;
1268
+ };
1269
+ /** Source-document operations used by the API. */
1270
+ interface SourceOperationsInterface {
1271
+ /** Process a reference with its designated rule (see `processSourceDocument`); `force` re-embeds unchanged content. */
1272
+ process(ref: string, rule: string, options?: IndexOptions): Promise<DocumentResult>;
1273
+ /** Synchronously validate a notification; `undefined` when acceptable. */
1274
+ validate(ref: string, rule: string): DocumentRejectionError | undefined;
1275
+ /** Designated rule stored on the document's chunk-0 point, or `null` if not indexed. */
1276
+ storedRule(ref: string): Promise<string | null>;
1277
+ /**
1278
+ * The compiled rule a designated rule name resolves to in the merged rule
1279
+ * set (config rules, then virtual rules: first of that name), or
1280
+ * `undefined` when no such rule exists.
1281
+ */
1282
+ compiledRule(name: string): CompiledRule | undefined;
1283
+ /** Retrieve and render a document without embedding or writing anything. */
1284
+ render(ref: string, rule: string): Promise<SourceRenderOutcome>;
1285
+ /** Merge enrichment metadata into an indexed document's points; `null` if not indexed. */
1286
+ updateMetadata(ref: string, metadata: Record<string, unknown>): Promise<Record<string, unknown> | null>;
1287
+ }
1288
+ /** A processor exposing source operations (`DocumentProcessor` implements it). */
1289
+ interface SourceOperationsProvider {
1290
+ /** Source operations bound to the processor's current rules and stores. */
1291
+ sourceOperations(): SourceOperationsInterface;
1292
+ }
1293
+
986
1294
  /**
987
1295
  * @module processor/types
988
1296
  * Document processor interface definitions.
@@ -1009,46 +1317,26 @@ interface DocumentProcessorInterface {
1009
1317
  /** Update compiled inference rules and associated engines. */
1010
1318
  updateRules(compiledRules: CompiledRule[], templateEngine?: TemplateEngine, customMapLib?: Record<string, (...args: unknown[]) => unknown>): void;
1011
1319
  }
1012
-
1013
1320
  /**
1014
- * @module processor
1015
- *
1016
- * Core document processing pipeline. Handles extracting text, computing embeddings, syncing with vector store.
1321
+ * The processor the service runs on: file operations plus source operations.
1322
+ * `createDocumentProcessor` returns it; the API server and the notify queue
1323
+ * depend on it (`DocumentProcessor` implements it). Adapt a custom file-only
1324
+ * processor with `withoutSourceSupport`, whose source operations fail.
1017
1325
  */
1326
+ type WatcherProcessor = DocumentProcessorInterface & SourceOperationsProvider;
1018
1327
 
1019
1328
  /**
1020
- * Core document processing pipeline.
1329
+ * @module processor
1021
1330
  *
1022
- * Handles extracting text, computing embeddings, and syncing with the vector store.
1331
+ * Core document processing pipeline. Resolves files and source documents, computes embeddings, syncs with vector store.
1023
1332
  */
1024
- interface DocumentProcessorDeps {
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
- }
1333
+
1046
1334
  /**
1047
1335
  * Core document processing pipeline.
1048
1336
  *
1049
1337
  * Handles extracting text, computing embeddings, and syncing with the vector store.
1050
1338
  */
1051
- declare class DocumentProcessor implements DocumentProcessorInterface {
1339
+ declare class DocumentProcessor implements WatcherProcessor {
1052
1340
  private config;
1053
1341
  private readonly embeddingProvider;
1054
1342
  private readonly vectorStore;
@@ -1059,26 +1347,35 @@ declare class DocumentProcessor implements DocumentProcessorInterface {
1059
1347
  private readonly issuesManager?;
1060
1348
  private readonly valuesManager?;
1061
1349
  private readonly contentHashCache?;
1350
+ private readonly sourceRetriever?;
1062
1351
  /**
1063
1352
  * Create a new DocumentProcessor.
1064
1353
  *
1065
1354
  * @param deps - The processor dependencies.
1066
1355
  */
1067
- constructor({ config, embeddingProvider, vectorStore, compiledRules, logger, templateEngine, enrichmentStore, issuesManager, valuesManager, contentHashCache, }: DocumentProcessorDeps);
1068
- /**
1069
- * Build merged metadata for a file and add matched_rules.
1070
- */
1071
- private buildMetadataWithRules;
1356
+ constructor(deps: DocumentProcessorDeps);
1357
+ /** Rule context reflecting the current rules, templates and config. */
1358
+ private ruleContext;
1359
+ /** Shared pipeline dependencies. */
1360
+ private pipelineContext;
1361
+ /** File resolver bound to the current rule context. */
1362
+ private fileResolver;
1363
+ /** Dependencies of the payload-only file operations. */
1364
+ private fileOperations;
1072
1365
  /**
1073
- * Execute an async operation with standardized file error handling.
1366
+ * Run a file operation with standard failure handling: log, and record a
1367
+ * typed issue when `context.issueType` (the code for untagged failures)
1368
+ * is given; return `fallback` on failure.
1074
1369
  */
1075
- private withFileErrorHandling;
1370
+ private withFailureHandling;
1076
1371
  /**
1077
1372
  * Process a file through the full pipeline: extract, hash, chunk, embed, upsert.
1078
1373
  *
1079
1374
  * @param filePath - The file to process.
1080
1375
  */
1081
1376
  processFile(filePath: string): Promise<void>;
1377
+ /** {@inheritDoc SourceOperationsProvider.sourceOperations} */
1378
+ sourceOperations(): SourceOperationsInterface;
1082
1379
  /**
1083
1380
  * Delete all chunks for a file from the vector store and remove metadata.
1084
1381
  *
@@ -1086,7 +1383,9 @@ declare class DocumentProcessor implements DocumentProcessorInterface {
1086
1383
  */
1087
1384
  deleteFile(filePath: string): Promise<void>;
1088
1385
  /**
1089
- * Process a metadata update: merge into enrichment store, update Qdrant payloads (no re-embed).
1386
+ * Process a metadata update: merge into enrichment store, update Qdrant
1387
+ * payloads (no re-embed). The stored `file_path` (casing included) and
1388
+ * `matched_rules` are kept.
1090
1389
  *
1091
1390
  * @param filePath - The file whose metadata to update.
1092
1391
  * @param metadata - The new metadata to merge.
@@ -1094,9 +1393,9 @@ declare class DocumentProcessor implements DocumentProcessorInterface {
1094
1393
  */
1095
1394
  processMetadataUpdate(filePath: string, metadata: Record<string, unknown>): Promise<Record<string, unknown> | null>;
1096
1395
  /**
1097
- * Re-apply inference rules to a file without re-embedding.
1098
- * Reads file attributes, applies current rules, merges with enrichment metadata,
1099
- * and updates Qdrant payloads.
1396
+ * Re-apply inference rules to a file without re-embedding (see
1397
+ * `reapplyFileRules`: system fields and the stored `file_path` are
1398
+ * re-asserted; interpolation failures are recorded as an issue).
1100
1399
  *
1101
1400
  * @param filePath - The file to update.
1102
1401
  * @returns The merged metadata, or `null` if the file is not indexed.
@@ -1128,10 +1427,29 @@ declare class DocumentProcessor implements DocumentProcessorInterface {
1128
1427
  updateRules(compiledRules: CompiledRule[], templateEngine?: TemplateEngine, customMapLib?: Record<string, (...args: unknown[]) => unknown>): void;
1129
1428
  }
1130
1429
 
1430
+ /**
1431
+ * @module queue/pausable
1432
+ * 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.
1433
+ */
1434
+ /**
1435
+ * A queue that can stop starting new work, resume, and report when its
1436
+ * in-flight work has finished. Prune uses this to quiesce every writer
1437
+ * before it computes and executes its plan.
1438
+ */
1439
+ interface PausableQueue {
1440
+ /** Stop starting new work; enqueues are still accepted. */
1441
+ pause(): void;
1442
+ /** Resume starting work. */
1443
+ resume(): void;
1444
+ /** Resolve once no work is in flight (queued work may remain). */
1445
+ waitForIdleWorkers(): Promise<void>;
1446
+ }
1447
+
1131
1448
  /**
1132
1449
  * @module queue
1133
- * Debounced, rate-limited, concurrent event queue for file watchers. Manages priority queuing and async callbacks. No direct I/O; orchestrates processing.
1450
+ * 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
1451
  */
1452
+
1135
1453
  /**
1136
1454
  * A watch event.
1137
1455
  */
@@ -1157,27 +1475,22 @@ interface EventQueueOptions {
1157
1475
  debounceMs: number;
1158
1476
  /** Maximum number of concurrent processors. */
1159
1477
  concurrency: number;
1160
- /** Optional max processed events per minute (token bucket). */
1161
- rateLimitPerMinute?: number;
1162
1478
  }
1163
1479
  /**
1164
- * A debounced, rate-limited, concurrent event queue.
1480
+ * A debounced, concurrent event queue.
1165
1481
  */
1166
1482
  declare class EventQueue {
1167
1483
  private readonly debounceMs;
1168
1484
  private readonly concurrency;
1169
- private readonly rateLimitPerMinute?;
1170
1485
  private started;
1171
1486
  private paused;
1487
+ private stopped;
1172
1488
  private active;
1173
1489
  private readonly debounceTimers;
1174
1490
  private readonly latestByKey;
1175
1491
  private readonly normalQueue;
1176
1492
  private readonly lowQueue;
1177
- private tokens;
1178
- private lastRefillMs;
1179
- private drainWaiters;
1180
- private idleWorkerWaiters;
1493
+ private readonly signals;
1181
1494
  /**
1182
1495
  * Create an event queue.
1183
1496
  *
@@ -1185,16 +1498,25 @@ declare class EventQueue {
1185
1498
  */
1186
1499
  constructor(options: EventQueueOptions);
1187
1500
  /**
1188
- * Enqueue an event, debounced per path+priority.
1501
+ * Enqueue an event, debounced per path+priority. Ignored once stopped.
1189
1502
  *
1190
1503
  * @param event - The watch event.
1191
1504
  * @param fn - The processing function to invoke when dequeued.
1192
1505
  */
1193
1506
  enqueue(event: WatchEvent, fn: ProcessFn): void;
1194
1507
  /**
1195
- * Start processing events.
1508
+ * Start processing events (events enqueued earlier are held until now).
1509
+ */
1510
+ start(): void;
1511
+ /**
1512
+ * Alias of {@link EventQueue.start}, kept for existing callers.
1196
1513
  */
1197
1514
  process(): void;
1515
+ /**
1516
+ * Stop: cancel pending debounces, drop queued events, ignore new ones, and
1517
+ * resolve once in-flight work finishes. Drain waiters resolve then too.
1518
+ */
1519
+ stop(): Promise<void>;
1198
1520
  /**
1199
1521
  * Pause processing events. Events can still be enqueued but will not be processed.
1200
1522
  */
@@ -1218,13 +1540,136 @@ declare class EventQueue {
1218
1540
  */
1219
1541
  waitForIdleWorkers(): Promise<void>;
1220
1542
  private push;
1221
- private refillTokens;
1222
- private takeToken;
1223
1543
  private nextItem;
1224
1544
  private pump;
1225
1545
  private isIdle;
1226
- private maybeResolveDrain;
1227
- private maybeResolveIdleWorkers;
1546
+ private settle;
1547
+ }
1548
+
1549
+ /**
1550
+ * @module queue/sourceNotifyTypes
1551
+ * Options, errors and job bookkeeping types of the source notify queue (validated options schema, stopped error, coalesced jobs and their waiters). No I/O.
1552
+ */
1553
+
1554
+ /**
1555
+ * Default number of references processed at once: the core
1556
+ * `embedding.concurrency` default, which the service passes in.
1557
+ */
1558
+ declare const DEFAULT_SOURCE_NOTIFY_CONCURRENCY: number;
1559
+ /** Options for the source notify queue. */
1560
+ declare const sourceNotifyQueueOptionsSchema: z.ZodObject<{
1561
+ concurrency: z.ZodDefault<z.ZodNumber>;
1562
+ }, z.core.$strip>;
1563
+ /** Options for the source notify queue (input form; defaults applied). */
1564
+ type SourceNotifyQueueOptions = z.input<typeof sourceNotifyQueueOptionsSchema>;
1565
+ /** Issues-store operations the queue needs. */
1566
+ type SourceQueueIssues = Pick<IssuesManager, 'record' | 'clear'>;
1567
+ /** Per-run options of `SourceNotifyQueue.processNow`. */
1568
+ interface ProcessNowOptions {
1569
+ /**
1570
+ * Re-embed even when content is unchanged (reindex scope `full`). Merged
1571
+ * as OR into a run it joins.
1572
+ */
1573
+ force?: boolean;
1574
+ }
1575
+ /** Rejection for `SourceNotifyQueue.processNow` after `stop()`. */
1576
+ declare class SourceNotifyQueueStoppedError extends Error {
1577
+ /** Create the error. */
1578
+ constructor();
1579
+ }
1580
+
1581
+ /**
1582
+ * @module queue/SourceNotifyQueue
1583
+ * 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.
1584
+ */
1585
+
1586
+ /** What the queue runs: one reference with its designated rule. */
1587
+ type SourceProcess = Pick<SourceOperationsInterface, 'process'>;
1588
+ /**
1589
+ * Coalescing queue for source-document notifications (Decision 12).
1590
+ *
1591
+ * - A notification for a **pending** reference is merged into it (the latest
1592
+ * rule wins; the reference keeps its place in line).
1593
+ * - One for an **in-flight** reference marks it dirty: when the current run
1594
+ * ends the reference is queued once more (at the back), however many
1595
+ * notifications arrived meanwhile.
1596
+ * - Every run calls `process`, which retrieves current state, so a
1597
+ * burst on one reference costs at most two retrievals and the final state
1598
+ * wins. Runs never overlap for the same reference.
1599
+ *
1600
+ * References are compared exactly (case-sensitive), like source point IDs.
1601
+ * The queue holds work until {@link start}; {@link pause} (prune) stops new
1602
+ * runs without rejecting enqueues. Failures never escape: `process`
1603
+ * records issues itself, and an unexpected rejection becomes a `failed`
1604
+ * result and an `extraction_error` issue (with the designated rule).
1605
+ *
1606
+ * Reindex runs go through {@link processNow} as well, so a notification and
1607
+ * a reindex of one reference never run in parallel and the latest state wins.
1608
+ */
1609
+ declare class SourceNotifyQueue implements PausableQueue {
1610
+ private readonly processor;
1611
+ private readonly logger?;
1612
+ private readonly issues?;
1613
+ private readonly concurrency;
1614
+ private started;
1615
+ private paused;
1616
+ private stopped;
1617
+ private readonly pending;
1618
+ private readonly inFlight;
1619
+ private readonly signals;
1620
+ /**
1621
+ * @param processor - Processes one reference with its designated rule
1622
+ * (source operations).
1623
+ * @param options - Queue options (validated).
1624
+ * @param logger - Logger for unexpected processing rejections.
1625
+ * @param issues - Issues store for unexpected processing rejections.
1626
+ */
1627
+ constructor(processor: SourceProcess, options?: SourceNotifyQueueOptions, logger?: pino.Logger | undefined, issues?: SourceQueueIssues | undefined);
1628
+ /**
1629
+ * Notify that a source document changed (fire and forget).
1630
+ *
1631
+ * @param ref - The exact `<name>://<id>` reference.
1632
+ * @param rule - The designated rule name.
1633
+ * @returns `false` when the queue is stopped and the notification was dropped.
1634
+ */
1635
+ enqueue(ref: string, rule: string): boolean;
1636
+ /**
1637
+ * Process a reference and resolve with the result of a run that started
1638
+ * after this call, so the result reflects the source's state at or after
1639
+ * the call (the `?wait=true` path). Coalesces with other notifications:
1640
+ * if the reference is pending, this joins that run; if it is in flight,
1641
+ * this waits for the current run and then the one dirty re-run.
1642
+ *
1643
+ * @param ref - The exact `<name>://<id>` reference.
1644
+ * @param rule - The designated rule name.
1645
+ * @param options - `force` re-embeds unchanged content.
1646
+ * @returns The per-document result.
1647
+ * @throws {@link SourceNotifyQueueStoppedError} (as a rejection) when the
1648
+ * queue is stopped before the run starts.
1649
+ */
1650
+ processNow(ref: string, rule: string, options?: ProcessNowOptions): Promise<DocumentResult>;
1651
+ /** Start processing (work enqueued earlier is held until now). */
1652
+ start(): void;
1653
+ /** {@inheritDoc PausableQueue.pause} */
1654
+ pause(): void;
1655
+ /** {@inheritDoc PausableQueue.resume} */
1656
+ resume(): void;
1657
+ /** {@inheritDoc PausableQueue.waitForIdleWorkers} */
1658
+ waitForIdleWorkers(): Promise<void>;
1659
+ /** Resolve once nothing is pending, owed (dirty) or in flight. */
1660
+ drain(): Promise<void>;
1661
+ /**
1662
+ * Stop: drop pending and owed runs (their `processNow` callers reject with
1663
+ * {@link SourceNotifyQueueStoppedError}), refuse new work, and resolve once
1664
+ * in-flight runs finish.
1665
+ */
1666
+ stop(): Promise<void>;
1667
+ private schedule;
1668
+ private pump;
1669
+ private run;
1670
+ private execute;
1671
+ private isIdle;
1672
+ private settle;
1228
1673
  }
1229
1674
 
1230
1675
  /**
@@ -1724,24 +2169,30 @@ declare class ReindexTracker {
1724
2169
  }
1725
2170
 
1726
2171
  /**
1727
- * @module api
1728
- * Fastify API server factory. Registers all route handlers and returns an unstarted server instance.
2172
+ * @module api/apiServerOptions
2173
+ * Options accepted by createApiServer: processor, stores, queues, config access, trackers and optional collaborators (virtual rules, VCS, source queue). Types only.
1729
2174
  */
1730
2175
 
1731
2176
  /**
1732
- * Options for {@link createApiServer}.
2177
+ * Options for `createApiServer`.
1733
2178
  */
1734
2179
  interface ApiServerOptions {
2180
+ /**
2181
+ * Queues paused while a prune deletes points. The service passes
2182
+ * `combinePausableQueues(fileQueue, sourceQueue)` (`app/index.ts`), so a
2183
+ * prune quiesces both the file event queue and the source notify queue.
2184
+ */
2185
+ queue: PausableQueue;
2186
+ /** Source notify queue (`POST /documents`); absent in file-only setups. */
2187
+ sourceQueue?: SourceNotifyQueue;
1735
2188
  /** The component descriptor (used for config-apply handler). */
1736
2189
  descriptor: JeevesComponentDescriptor;
1737
- /** The document processor. */
1738
- processor: DocumentProcessorInterface;
2190
+ /** The document processor: file and source operations. */
2191
+ processor: WatcherProcessor;
1739
2192
  /** The vector store client. */
1740
2193
  vectorStore: VectorStoreClient;
1741
2194
  /** The embedding provider. */
1742
2195
  embeddingProvider: EmbeddingProvider;
1743
- /** The event queue. */
1744
- queue: EventQueue;
1745
2196
  /** The application configuration (used as initial/fallback value). */
1746
2197
  config: JeevesWatcherConfig;
1747
2198
  /** Config getter for live config access after hot-reload. */
@@ -1775,16 +2226,58 @@ interface ApiServerOptions {
1775
2226
  /** VCS coordinator for git-backed versioning API routes. */
1776
2227
  vcsCoordinator?: VcsCoordinator;
1777
2228
  }
2229
+
2230
+ /**
2231
+ * @module api
2232
+ * Fastify API server factory. Registers all route handlers (status, query, documents, config, rules, VCS) and returns an unstarted server instance.
2233
+ */
2234
+
1778
2235
  /**
1779
2236
  * Create the Fastify API server with all routes registered.
1780
2237
  *
1781
- * The returned instance is not yet listening — call `server.listen()` to start.
2238
+ * The returned instance is not yet listening; call `server.listen()` to start.
1782
2239
  *
1783
2240
  * @param options - The server options.
1784
2241
  * @returns A configured Fastify instance.
1785
2242
  */
1786
2243
  declare function createApiServer(options: ApiServerOptions): FastifyInstance;
1787
2244
 
2245
+ /**
2246
+ * @module config/warnings
2247
+ * The non-fatal config warning shape shared by config loading (unknown source keys, reserved rule field names) and `POST /config/validate`. Types only.
2248
+ */
2249
+ /** A non-fatal config validation warning. */
2250
+ interface ConfigWarning {
2251
+ /** Config location the warning refers to. */
2252
+ path: string;
2253
+ /** Human-readable warning message. */
2254
+ message: string;
2255
+ }
2256
+
2257
+ /**
2258
+ * @module config/loadConfig
2259
+ * 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.
2260
+ */
2261
+
2262
+ /** Options of {@link loadConfig}. */
2263
+ interface LoadConfigOptions {
2264
+ /**
2265
+ * Receives non-fatal warnings once the config has loaded successfully:
2266
+ * unknown keys under `sources.<name>` (which validation drops), then rule
2267
+ * schema properties named like reserved system fields.
2268
+ */
2269
+ onWarning?: (warning: ConfigWarning) => void;
2270
+ }
2271
+ /**
2272
+ * Load the jeeves-watcher configuration.
2273
+ *
2274
+ * @param configPath - Optional explicit path to a config file.
2275
+ * @param options - Optional warning sink.
2276
+ * @returns The loaded configuration.
2277
+ * @throws If no configuration is found or validation fails.
2278
+ */
2279
+ declare function loadConfig(configPath?: string, options?: LoadConfigOptions): Promise<JeevesWatcherConfig>;
2280
+
1788
2281
  /**
1789
2282
  * @module logger
1790
2283
  * Creates pino logger instances. I/O: optionally writes logs to file via pino/file transport. Defaults to stdout at info level.
@@ -1803,12 +2296,17 @@ declare function createLogger(config?: LoggingConfig): pino.Logger;
1803
2296
  * Component factory interfaces and defaults for {@link JeevesWatcher}. Override in tests to inject mocks.
1804
2297
  */
1805
2298
 
2299
+ /** Runtime options for {@link JeevesWatcher} that aren't serializable in config. */
2300
+ interface JeevesWatcherRuntimeOptions {
2301
+ /** Callback invoked on unrecoverable system error. If not set, throws. */
2302
+ onFatalError?: (error: unknown) => void;
2303
+ }
1806
2304
  /**
1807
2305
  * Component factories for {@link JeevesWatcher}. Override in tests to inject mocks.
1808
2306
  */
1809
2307
  interface JeevesWatcherFactories {
1810
2308
  /** Load and validate a {@link JeevesWatcherConfig} from disk. */
1811
- loadConfig: (configPath?: string) => Promise<JeevesWatcherConfig>;
2309
+ loadConfig: (configPath?: string, options?: LoadConfigOptions) => Promise<JeevesWatcherConfig>;
1812
2310
  /** Create a pino logger instance. */
1813
2311
  createLogger: typeof createLogger;
1814
2312
  /** Create an embedding provider from config. */
@@ -1818,7 +2316,7 @@ interface JeevesWatcherFactories {
1818
2316
  /** Compile inference rules from config. */
1819
2317
  compileRules: typeof compileRules;
1820
2318
  /** Create a document processor for file ingestion. */
1821
- createDocumentProcessor: (deps: ConstructorParameters<typeof DocumentProcessor>[0]) => DocumentProcessorInterface;
2319
+ createDocumentProcessor: (deps: ConstructorParameters<typeof DocumentProcessor>[0]) => WatcherProcessor;
1822
2320
  /** Create an event queue for batching file-system events. */
1823
2321
  createEventQueue: (options: ConstructorParameters<typeof EventQueue>[0]) => EventQueue;
1824
2322
  /** Create a file-system watcher for the configured watch paths. */
@@ -1827,6 +2325,27 @@ interface JeevesWatcherFactories {
1827
2325
  createApiServer: typeof createApiServer;
1828
2326
  }
1829
2327
 
2328
+ /**
2329
+ * @module app/sources
2330
+ * 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.
2331
+ */
2332
+
2333
+ /**
2334
+ * Adapt a custom file-only processor to the {@link WatcherProcessor} the
2335
+ * service runs on. File operations are forwarded unchanged. Its source
2336
+ * operations fail: every notify-queue run returns a `failed` result with
2337
+ * `source_unavailable` (the run's issue, as for a failing callback), and
2338
+ * every other source operation throws the API's `503 not_available`, so
2339
+ * `POST /documents`, `POST /metadata { source }`, `POST /render { source }`
2340
+ * and `POST /reindex { source }` answer as before source support existed.
2341
+ * Use it in a custom `createDocumentProcessor` factory; never wrap a
2342
+ * processor that has source operations of its own (they would be hidden).
2343
+ *
2344
+ * @param processor - The file-only processor.
2345
+ * @returns The processor with failing source operations.
2346
+ */
2347
+ declare function withoutSourceSupport(processor: DocumentProcessorInterface): WatcherProcessor;
2348
+
1830
2349
  /**
1831
2350
  * @module app/startFromConfig
1832
2351
  * Convenience entry point: loads config from disk and starts a {@link JeevesWatcher}.
@@ -1850,11 +2369,6 @@ declare function startFromConfig(configPath?: string, descriptor?: JeevesCompone
1850
2369
  * Main application orchestrator. Wires components, manages lifecycle (start/stop/reload).
1851
2370
  */
1852
2371
 
1853
- /** Runtime options for {@link JeevesWatcher} that aren't serializable in config. */
1854
- interface JeevesWatcherRuntimeOptions {
1855
- /** Callback invoked on unrecoverable system error. If not set, throws. */
1856
- onFatalError?: (error: unknown) => void;
1857
- }
1858
2372
  /**
1859
2373
  * Main application class that wires together all components.
1860
2374
  */
@@ -1867,13 +2381,14 @@ declare class JeevesWatcher {
1867
2381
  private logger;
1868
2382
  private watcher;
1869
2383
  private queue;
2384
+ private sourceQueue;
1870
2385
  private server;
1871
2386
  private processor;
1872
2387
  private configWatcher;
1873
2388
  private issuesManager;
1874
2389
  private valuesManager;
1875
2390
  private helperIntrospection;
1876
- private virtualRuleStore;
2391
+ private readonly virtualRuleStore;
1877
2392
  private vectorStore;
1878
2393
  private embeddingProvider;
1879
2394
  private gitignoreFilter;
@@ -1884,9 +2399,7 @@ declare class JeevesWatcher {
1884
2399
  private readonly version;
1885
2400
  /** Create a new JeevesWatcher instance. */
1886
2401
  constructor(config: JeevesWatcherConfig, configPath?: string, descriptor?: JeevesComponentDescriptor, factories?: Partial<JeevesWatcherFactories>, runtimeOptions?: JeevesWatcherRuntimeOptions);
1887
- /**
1888
- * Start the watcher, API server, and all components.
1889
- */
2402
+ /** Start the watcher, API server, and all components. */
1890
2403
  start(): Promise<void>;
1891
2404
  /** Set up logger, VCS, embedding provider, and vector store. */
1892
2405
  private initInfrastructure;
@@ -1895,24 +2408,15 @@ declare class JeevesWatcher {
1895
2408
  /** Wire up watcher and VCS coordinator, then start all services. */
1896
2409
  private startServicesAndWatcher;
1897
2410
  /**
1898
- * Gracefully stop all components.
2411
+ * Gracefully stop all components: the API server closes first (no new
2412
+ * notifications), then producers stop and queues drain (see
2413
+ * shutdownComponents).
1899
2414
  */
1900
2415
  stop(): Promise<void>;
1901
- private startApiServer;
1902
- private startConfigWatch;
1903
- private stopConfigWatch;
2416
+ private apiServerOptions;
1904
2417
  private reloadConfig;
1905
2418
  }
1906
2419
 
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
2420
  /**
1917
2421
  * @module descriptor
1918
2422
  * Jeeves Component Descriptor for the watcher service. Single source of truth
@@ -2090,5 +2594,5 @@ declare class SquashManager {
2090
2594
  private forcePushIfConfigured;
2091
2595
  }
2092
2596
 
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 };
2597
+ export { CommitMessageGenerator, ContentHashCache, DEFAULT_SOURCE_NOTIFY_CONCURRENCY, DocumentProcessor, EnrichmentStore, EventQueue, FileSystemWatcher, GitignoreFilter, InitialScanTracker, IssuesManager, JeevesWatcher, ReindexTracker, SourceClient, SourceNotifyQueue, SourceNotifyQueueStoppedError, SourceReferenceError, SquashManager, SystemHealth, TemplateEngine, ValuesManager, VcsCoordinator, VcsManager, VectorStoreClient, VirtualRuleStore, applyRules, buildAttributes, buildTemplateEngine, compileRules, contentHash, createApiServer, createEmbeddingProvider, createHandlebarsInstance, createLogger, extractText, loadConfig, loadCustomHelpers, mergeEnrichment, parseSourceReference, parsedSourceReferenceSchema, pointId, registerBuiltinHelpers, resolveTemplateSource, resolvedSourceReferenceSchema, sourceAttributesSchema, sourceErrorCodeSchema, sourceNotifyQueueOptionsSchema, sourceRejectionCodeSchema, sourceRetrievalResultSchema, startFromConfig, watcherDescriptor, withoutSourceSupport };
2598
+ export type { AllHelpersIntrospection, ApiServerOptions, ApplyRulesOptions, ApplyRulesResult, CircuitBreakerSnapshot, CollectionInfo, CommitInfo, CompiledRule, CompiledTemplate, ConfigWarning, DocumentProcessorDeps, DocumentProcessorInterface, EmbedOptions, EmbeddingProvider, EnrichmentStoreInterface, EventQueueOptions, ExtractedText, Extractor, FileAttributes, FileSystemWatcherOptions, HelperModuleIntrospection, IndexOptions, InitialScanStatus, IssuesFile, JeevesWatcherFactories, JeevesWatcherRuntimeOptions, LoadConfigOptions, ParsedSourceReference, PausableQueue, PayloadFieldSchema, PendingReversion, ProcessFn, ProcessNowOptions, ProcessorConfig, ProviderFactory, PushError, ReindexStatus, RenderResult, ResolvedSourceReference, ResolvedWatchRoot, RuleAttributes, RuleLogger, ScrollPageResult, ScrolledPoint, SearchResult, SourceAttributes, SourceErrorCode, SourceNotifyQueueOptions, SourceOperationsInterface, SourceOperationsProvider, SourceProcess, SourceQueueIssues, SourceRejectionCode, SourceRenderOutcome, SourceRetrievalResult, SourceRetriever, SquashManagerOptions, SquashResult, SystemHealthOptions, ValuesIndex, VcsBreakerState, VectorPoint, VectorStore, WatchEvent, WatcherProcessor };