@debriefer/core 2.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.
Files changed (98) hide show
  1. package/README.md +86 -0
  2. package/dist/__tests__/base-source.test.d.ts +2 -0
  3. package/dist/__tests__/base-source.test.d.ts.map +1 -0
  4. package/dist/__tests__/base-source.test.js +333 -0
  5. package/dist/__tests__/base-source.test.js.map +1 -0
  6. package/dist/__tests__/batch-runner.test.d.ts +2 -0
  7. package/dist/__tests__/batch-runner.test.d.ts.map +1 -0
  8. package/dist/__tests__/batch-runner.test.js +217 -0
  9. package/dist/__tests__/batch-runner.test.js.map +1 -0
  10. package/dist/__tests__/cache.test.d.ts +2 -0
  11. package/dist/__tests__/cache.test.d.ts.map +1 -0
  12. package/dist/__tests__/cache.test.js +127 -0
  13. package/dist/__tests__/cache.test.js.map +1 -0
  14. package/dist/__tests__/confidence.test.d.ts +2 -0
  15. package/dist/__tests__/confidence.test.d.ts.map +1 -0
  16. package/dist/__tests__/confidence.test.js +81 -0
  17. package/dist/__tests__/confidence.test.js.map +1 -0
  18. package/dist/__tests__/cost-tracker.test.d.ts +2 -0
  19. package/dist/__tests__/cost-tracker.test.d.ts.map +1 -0
  20. package/dist/__tests__/cost-tracker.test.js +149 -0
  21. package/dist/__tests__/cost-tracker.test.js.map +1 -0
  22. package/dist/__tests__/orchestrator.test.d.ts +2 -0
  23. package/dist/__tests__/orchestrator.test.d.ts.map +1 -0
  24. package/dist/__tests__/orchestrator.test.js +751 -0
  25. package/dist/__tests__/orchestrator.test.js.map +1 -0
  26. package/dist/__tests__/rate-limiter.test.d.ts +2 -0
  27. package/dist/__tests__/rate-limiter.test.d.ts.map +1 -0
  28. package/dist/__tests__/rate-limiter.test.js +83 -0
  29. package/dist/__tests__/rate-limiter.test.js.map +1 -0
  30. package/dist/__tests__/reliability.test.d.ts +2 -0
  31. package/dist/__tests__/reliability.test.d.ts.map +1 -0
  32. package/dist/__tests__/reliability.test.js +207 -0
  33. package/dist/__tests__/reliability.test.js.map +1 -0
  34. package/dist/__tests__/synthesizer.test.d.ts +2 -0
  35. package/dist/__tests__/synthesizer.test.d.ts.map +1 -0
  36. package/dist/__tests__/synthesizer.test.js +50 -0
  37. package/dist/__tests__/synthesizer.test.js.map +1 -0
  38. package/dist/__tests__/telemetry.test.d.ts +2 -0
  39. package/dist/__tests__/telemetry.test.d.ts.map +1 -0
  40. package/dist/__tests__/telemetry.test.js +81 -0
  41. package/dist/__tests__/telemetry.test.js.map +1 -0
  42. package/dist/__tests__/types.test.d.ts +2 -0
  43. package/dist/__tests__/types.test.d.ts.map +1 -0
  44. package/dist/__tests__/types.test.js +708 -0
  45. package/dist/__tests__/types.test.js.map +1 -0
  46. package/dist/base-source.d.ts +91 -0
  47. package/dist/base-source.d.ts.map +1 -0
  48. package/dist/base-source.js +144 -0
  49. package/dist/base-source.js.map +1 -0
  50. package/dist/batch-runner.d.ts +40 -0
  51. package/dist/batch-runner.d.ts.map +1 -0
  52. package/dist/batch-runner.js +65 -0
  53. package/dist/batch-runner.js.map +1 -0
  54. package/dist/cache/in-memory.d.ts +26 -0
  55. package/dist/cache/in-memory.d.ts.map +1 -0
  56. package/dist/cache/in-memory.js +51 -0
  57. package/dist/cache/in-memory.js.map +1 -0
  58. package/dist/confidence.d.ts +13 -0
  59. package/dist/confidence.d.ts.map +1 -0
  60. package/dist/confidence.js +29 -0
  61. package/dist/confidence.js.map +1 -0
  62. package/dist/cost-tracker.d.ts +37 -0
  63. package/dist/cost-tracker.d.ts.map +1 -0
  64. package/dist/cost-tracker.js +62 -0
  65. package/dist/cost-tracker.js.map +1 -0
  66. package/dist/index.d.ts +25 -0
  67. package/dist/index.d.ts.map +1 -0
  68. package/dist/index.js +28 -0
  69. package/dist/index.js.map +1 -0
  70. package/dist/orchestrator.d.ts +92 -0
  71. package/dist/orchestrator.d.ts.map +1 -0
  72. package/dist/orchestrator.js +373 -0
  73. package/dist/orchestrator.js.map +1 -0
  74. package/dist/rate-limiter.d.ts +31 -0
  75. package/dist/rate-limiter.d.ts.map +1 -0
  76. package/dist/rate-limiter.js +79 -0
  77. package/dist/rate-limiter.js.map +1 -0
  78. package/dist/reliability.d.ts +49 -0
  79. package/dist/reliability.d.ts.map +1 -0
  80. package/dist/reliability.js +67 -0
  81. package/dist/reliability.js.map +1 -0
  82. package/dist/synthesizer.d.ts +31 -0
  83. package/dist/synthesizer.d.ts.map +1 -0
  84. package/dist/synthesizer.js +47 -0
  85. package/dist/synthesizer.js.map +1 -0
  86. package/dist/telemetry/console.d.ts +7 -0
  87. package/dist/telemetry/console.d.ts.map +1 -0
  88. package/dist/telemetry/console.js +21 -0
  89. package/dist/telemetry/console.js.map +1 -0
  90. package/dist/telemetry/noop.d.ts +7 -0
  91. package/dist/telemetry/noop.d.ts.map +1 -0
  92. package/dist/telemetry/noop.js +12 -0
  93. package/dist/telemetry/noop.js.map +1 -0
  94. package/dist/types.d.ts +417 -0
  95. package/dist/types.d.ts.map +1 -0
  96. package/dist/types.js +102 -0
  97. package/dist/types.js.map +1 -0
  98. package/package.json +46 -0
@@ -0,0 +1,417 @@
1
+ /**
2
+ * Core type definitions for the debriefer research orchestration engine.
3
+ *
4
+ * These types are generalized from deadonfilm's death-sources/types.ts and
5
+ * biography-sources/types.ts. They define the contracts for subjects, findings,
6
+ * sources, synthesis, configuration, lifecycle hooks, and error types that
7
+ * the orchestrator and all source implementations share.
8
+ *
9
+ * Domain-specific types (e.g., ActorForEnrichment, BiographyData) live in
10
+ * consumer code, not here. Consumers extend ResearchSubject and provide their
11
+ * own TOutput type to the orchestrator.
12
+ */
13
+ import type { ReliabilityTier } from "./reliability.js";
14
+ /**
15
+ * A research subject is the entity being investigated across multiple sources.
16
+ *
17
+ * Consumers extend this with domain-specific fields via the `context` bag.
18
+ * For example, deadonfilm adds `birthday`, `deathday`, `tmdbId`, etc.
19
+ *
20
+ * @example
21
+ * ```typescript
22
+ * const actor: ResearchSubject = {
23
+ * id: 2157,
24
+ * name: "John Wayne",
25
+ * context: { deathday: "1979-06-11", tmdbId: 2157 },
26
+ * }
27
+ * ```
28
+ */
29
+ export interface ResearchSubject {
30
+ /** Unique identifier — string or number depending on domain */
31
+ id: string | number;
32
+ /** Display name used in search queries and logging */
33
+ name: string;
34
+ /** Domain-specific metadata (birthday, deathday, external IDs, etc.) */
35
+ context?: Record<string, unknown>;
36
+ }
37
+ /**
38
+ * Raw data extracted from a single source lookup, before reliability scoring.
39
+ *
40
+ * This is what a source returns from its `lookup()` method. The orchestrator
41
+ * then tags it with source reliability info to produce a ScoredFinding.
42
+ */
43
+ export interface RawFinding {
44
+ /** Extracted text content from the source */
45
+ text: string;
46
+ /** URL of the source page, if applicable */
47
+ url?: string;
48
+ /** Publisher name (e.g., "The Guardian", "Wikipedia") */
49
+ publication?: string;
50
+ /** Article or page title */
51
+ articleTitle?: string;
52
+ /**
53
+ * Content confidence (0-1): how well does this page answer the research question?
54
+ * This is independent of source reliability — a Reuters page about weather
55
+ * has high reliability but zero confidence for death research.
56
+ */
57
+ confidence: number;
58
+ /** Cost in USD incurred for this lookup (API fees, etc.) */
59
+ costUsd: number;
60
+ /** Arbitrary metadata for debugging or downstream processing */
61
+ metadata?: Record<string, unknown>;
62
+ }
63
+ /**
64
+ * A finding tagged with source reliability information.
65
+ *
66
+ * Created by the orchestrator after a source returns a RawFinding.
67
+ * The reliability fields come from the source's declared tier, not
68
+ * from analyzing the content.
69
+ */
70
+ export interface ScoredFinding extends RawFinding {
71
+ /** Source type identifier (e.g., "wikipedia", "google_search") */
72
+ sourceType: string;
73
+ /** Human-readable source name (e.g., "Wikipedia", "Google Search") */
74
+ sourceName: string;
75
+ /** Reliability tier from the ReliabilityTier enum */
76
+ reliabilityTier: ReliabilityTier;
77
+ /**
78
+ * Numeric reliability score (0-1): how trustworthy is this publisher?
79
+ * Based on Wikipedia's Reliable Sources Perennial list (RSP).
80
+ */
81
+ reliabilityScore: number;
82
+ }
83
+ /**
84
+ * Options for AI synthesis of accumulated findings.
85
+ */
86
+ export interface SynthesisOptions {
87
+ /** AI model identifier (e.g., "claude-sonnet-4-20250514") */
88
+ model?: string;
89
+ /** Maximum tokens for the AI response */
90
+ maxTokens?: number;
91
+ /** System prompt guiding the synthesis */
92
+ systemPrompt?: string;
93
+ }
94
+ /**
95
+ * Result of AI synthesis, including the structured output and cost metadata.
96
+ */
97
+ export interface SynthesisResult<TOutput> {
98
+ /** The structured output produced by the AI */
99
+ data: TOutput;
100
+ /** Cost in USD for this synthesis call */
101
+ costUsd: number;
102
+ /** Number of input tokens consumed */
103
+ inputTokens: number;
104
+ /** Number of output tokens generated */
105
+ outputTokens: number;
106
+ /** Model identifier used for synthesis */
107
+ model: string;
108
+ }
109
+ /**
110
+ * Interface for AI synthesizers that distill findings into structured output.
111
+ *
112
+ * Ships with ClaudeSynthesizer. Consumers can implement for OpenAI, Gemini,
113
+ * local models, or skip AI entirely with a pass-through implementation.
114
+ */
115
+ export interface Synthesizer<TSubject extends ResearchSubject, TOutput> {
116
+ synthesize(subject: TSubject, findings: ScoredFinding[], options: SynthesisOptions): Promise<SynthesisResult<TOutput>>;
117
+ }
118
+ /**
119
+ * Minimal source interface used in SourcePhaseGroup to avoid circular
120
+ * dependency with BaseResearchSource (which imports from this file).
121
+ *
122
+ * BaseResearchSource implements this interface. The orchestrator works
123
+ * with BaseResearchSource instances but the type system only needs this
124
+ * minimal contract for phase group definitions.
125
+ */
126
+ export interface MinimalSource<TSubject extends ResearchSubject> {
127
+ /** Machine-readable source identifier (e.g., "wikipedia", "google_search") */
128
+ readonly name: string;
129
+ /** Source type string matching a registry key */
130
+ readonly type: string;
131
+ /** Reliability tier from the ReliabilityTier enum */
132
+ readonly reliabilityTier: ReliabilityTier;
133
+ /** Numeric reliability score (0-1) */
134
+ readonly reliabilityScore: number;
135
+ /** Whether this source is free to query */
136
+ readonly isFree: boolean;
137
+ /** Estimated cost per query in USD */
138
+ readonly estimatedCostPerQuery: number;
139
+ /** Domain for rate limiting coordination (e.g., "en.wikipedia.org") */
140
+ readonly domain: string;
141
+ /** Check if this source is available (API key configured, etc.) */
142
+ isAvailable(): boolean;
143
+ /**
144
+ * Look up information about a subject.
145
+ * Returns null if no relevant information was found.
146
+ */
147
+ lookup(subject: TSubject, signal: AbortSignal): Promise<RawFinding | null>;
148
+ }
149
+ /**
150
+ * A group of sources that execute together in a single phase.
151
+ *
152
+ * The orchestrator processes phases sequentially. Within each phase,
153
+ * sources run concurrently via Promise.allSettled() by default. When
154
+ * `sequential` is true, sources run one at a time in order, stopping
155
+ * at the first source that returns a non-null finding.
156
+ */
157
+ export interface SourcePhaseGroup<TSubject extends ResearchSubject> {
158
+ /** Phase number — determines execution order (lower = earlier) */
159
+ phase: number;
160
+ /** Human-readable phase name for logging (e.g., "Structured Data", "Web Search") */
161
+ name?: string;
162
+ /** Sources to execute within this phase (concurrently by default, or sequentially when `sequential: true`) */
163
+ sources: ReadonlyArray<MinimalSource<TSubject>>;
164
+ /**
165
+ * If true, execute sources sequentially within this phase instead of
166
+ * concurrently. Stops at the first source that returns a non-null finding.
167
+ * Useful for AI model sources where you want cheapest-first with early exit.
168
+ */
169
+ sequential?: boolean;
170
+ }
171
+ /**
172
+ * Complete result of debriefing (researching) a single subject.
173
+ *
174
+ * Contains the synthesized output, all collected findings, cost tracking,
175
+ * and execution metadata.
176
+ */
177
+ export interface DebriefResult<TOutput> {
178
+ /** The subject that was researched */
179
+ subject: ResearchSubject;
180
+ /** Synthesized output, or null if synthesis failed or was skipped */
181
+ data: TOutput | null;
182
+ /** All scored findings collected across all phases */
183
+ findings: ScoredFinding[];
184
+ /** Synthesis result with token counts and cost, if synthesis ran */
185
+ synthesisResult?: SynthesisResult<TOutput>;
186
+ /** Total cost in USD across all source lookups and synthesis */
187
+ totalCostUsd: number;
188
+ /** Number of sources that were attempted */
189
+ sourcesAttempted: number;
190
+ /** Number of sources that returned findings */
191
+ sourcesSucceeded: number;
192
+ /** Phase number where early stopping occurred, if applicable */
193
+ stoppedAtPhase?: number;
194
+ /** Total wall-clock time in milliseconds */
195
+ durationMs: number;
196
+ }
197
+ /**
198
+ * Configuration for the research orchestrator.
199
+ *
200
+ * All fields are optional — the orchestrator provides sensible defaults.
201
+ */
202
+ export interface ResearchConfig {
203
+ /**
204
+ * Source category flags (e.g., { free: true, news: true, ai: false }).
205
+ * Categories are domain-specific — consumer code uses these when constructing
206
+ * phase groups to decide which sources to include. The orchestrator stores
207
+ * this config for lifecycle hooks but does not filter sources itself.
208
+ */
209
+ categories?: Record<string, boolean>;
210
+ /** Number of subjects to process concurrently in batch mode (default: 5, range: 1-20) */
211
+ concurrency?: number;
212
+ /** Minimum content confidence to count as a quality finding (default: 0.6) */
213
+ confidenceThreshold?: number;
214
+ /** Minimum source reliability to count as a quality finding (default: 0.6) */
215
+ reliabilityThreshold?: number;
216
+ /**
217
+ * Number of high-quality source families needed before early stopping (default: 3).
218
+ * A "source family" is a unique sourceType — multiple findings from the same
219
+ * source type count as one family.
220
+ */
221
+ earlyStopThreshold?: number;
222
+ /** Cost limits to prevent runaway spending */
223
+ costLimits?: {
224
+ /** Maximum cost per subject in USD — stops processing that subject */
225
+ maxCostPerSubject?: number;
226
+ /** Maximum total cost for the entire batch in USD — stops the batch */
227
+ maxTotalCost?: number;
228
+ };
229
+ /** AI synthesis options */
230
+ synthesis?: SynthesisOptions;
231
+ /** Cache provider for source-level result caching */
232
+ cache?: CacheProvider;
233
+ /** Telemetry provider for events, spans, and error recording */
234
+ telemetry?: TelemetryProvider;
235
+ }
236
+ /**
237
+ * Interface for caching source lookup results.
238
+ *
239
+ * Ships with InMemoryCache. Consumers can provide RedisCache, SqliteCache,
240
+ * or any other implementation.
241
+ */
242
+ export interface CacheProvider {
243
+ /** Get a cached value by key. Returns null on cache miss. */
244
+ get(key: string): Promise<string | null>;
245
+ /** Set a cached value with optional TTL in seconds. */
246
+ set(key: string, value: string, ttlSeconds?: number): Promise<void>;
247
+ /** Delete a cached value. */
248
+ delete(key: string): Promise<void>;
249
+ }
250
+ /**
251
+ * A telemetry span for timing operations.
252
+ */
253
+ export interface TelemetrySpan {
254
+ /** End the span timing. */
255
+ end(): void;
256
+ /** Attach attributes to the span (e.g., source name, cost). */
257
+ setAttributes(attrs: Record<string, string | number | boolean>): void;
258
+ }
259
+ /**
260
+ * Interface for recording telemetry events, spans, and errors.
261
+ *
262
+ * Ships with ConsoleTelemetry and NoopTelemetry. Consumers can provide
263
+ * OpenTelemetryProvider, New Relic, Datadog, etc.
264
+ */
265
+ export interface TelemetryProvider {
266
+ /** Record a named event with arbitrary data. */
267
+ recordEvent(name: string, data: Record<string, unknown>): void;
268
+ /** Start a named timing span. Call span.end() when done. */
269
+ startSpan(name: string): TelemetrySpan;
270
+ /** Record an error with optional context. */
271
+ recordError(error: Error, context?: Record<string, unknown>): void;
272
+ }
273
+ /**
274
+ * Progress stats emitted during batch processing.
275
+ */
276
+ export interface BatchProgressStats {
277
+ /** Number of subjects completed so far */
278
+ completed: number;
279
+ /** Total number of subjects in the batch */
280
+ total: number;
281
+ /** Total cost in USD so far */
282
+ costUsd: number;
283
+ /** Elapsed time in milliseconds since batch start */
284
+ elapsedMs: number;
285
+ }
286
+ /**
287
+ * Final stats after a batch completes.
288
+ */
289
+ export interface BatchStats extends BatchProgressStats {
290
+ /** Number of subjects that produced a result */
291
+ succeeded: number;
292
+ /** Number of subjects that failed */
293
+ failed: number;
294
+ /** Average cost per subject in USD */
295
+ avgCostPerSubject: number;
296
+ /** Average duration per subject in milliseconds */
297
+ avgDurationMs: number;
298
+ }
299
+ /**
300
+ * Lifecycle hooks for observability and integration during batch processing.
301
+ *
302
+ * All hooks are optional. Consumers wire up what they need: database writes,
303
+ * progress bars, logging, monitoring dashboards, etc.
304
+ *
305
+ * Hook naming follows the pattern: on{Event}{Timing}
306
+ * - Start/Complete for paired begin/end events
307
+ * - No suffix for point-in-time events
308
+ */
309
+ export interface LifecycleHooks<TSubject extends ResearchSubject, TOutput> {
310
+ /** Fired once at the start of a batch run */
311
+ onRunStart?(subjectCount: number, config: ResearchConfig): void;
312
+ /** Fired before processing each subject */
313
+ onSubjectStart?(subject: TSubject, index: number, total: number): void;
314
+ /** Fired before each source lookup */
315
+ onSourceAttempt?(subject: TSubject, sourceName: string, phase: number): void;
316
+ /** Fired after each source lookup completes (success or failure) */
317
+ onSourceComplete?(subject: TSubject, sourceName: string, finding: RawFinding | null, costUsd: number): void;
318
+ /** Fired after all sources in a phase complete */
319
+ onPhaseComplete?(subject: TSubject, phase: number, findingsInPhase: ScoredFinding[]): void;
320
+ /** Fired when early stopping is triggered */
321
+ onEarlyStop?(subject: TSubject, phase: number, reason: string): void;
322
+ /** Fired before AI synthesis begins */
323
+ onSynthesisStart?(subject: TSubject, findingCount: number): void;
324
+ /** Fired after AI synthesis completes */
325
+ onSynthesisComplete?(subject: TSubject, result: SynthesisResult<TOutput>): void;
326
+ /** Fired after processing each subject (success or failure) */
327
+ onSubjectComplete?(subject: TSubject, result: DebriefResult<TOutput>): void;
328
+ /** Fired periodically during batch processing with progress stats */
329
+ onBatchProgress?(stats: BatchProgressStats): void;
330
+ /** Fired when a cost limit is reached */
331
+ onCostLimitReached?(subject: TSubject, costUsd: number, limit: number): void;
332
+ /** Fired once when the batch run completes successfully */
333
+ onRunComplete?(stats: BatchStats): void;
334
+ /** Fired if the batch run fails with an unrecoverable error */
335
+ onRunFailed?(error: Error): void;
336
+ }
337
+ /**
338
+ * Error thrown when a cost limit is exceeded during research.
339
+ *
340
+ * Can be thrown for per-subject limits (stops that subject) or total batch
341
+ * limits (stops the entire batch).
342
+ *
343
+ * @example
344
+ * ```typescript
345
+ * try {
346
+ * await orchestrator.debriefBatch(subjects)
347
+ * } catch (error) {
348
+ * if (error instanceof CostLimitExceededError) {
349
+ * console.log(`Cost limit: $${error.costUsd.toFixed(4)} > $${error.limit.toFixed(4)}`)
350
+ * }
351
+ * }
352
+ * ```
353
+ */
354
+ export declare class CostLimitExceededError extends Error {
355
+ /** ID of the subject being processed when the limit was hit */
356
+ readonly subjectId: string | number;
357
+ /** The cost in USD that triggered the limit */
358
+ readonly costUsd: number;
359
+ /** The configured limit that was exceeded in USD */
360
+ readonly limit: number;
361
+ readonly name = "CostLimitExceededError";
362
+ constructor(
363
+ /** ID of the subject being processed when the limit was hit */
364
+ subjectId: string | number,
365
+ /** The cost in USD that triggered the limit */
366
+ costUsd: number,
367
+ /** The configured limit that was exceeded in USD */
368
+ limit: number);
369
+ }
370
+ /**
371
+ * Error thrown when a source request times out.
372
+ *
373
+ * The orchestrator catches this and continues with remaining sources.
374
+ * High-priority source timeouts may be logged for investigation.
375
+ *
376
+ * @example
377
+ * ```typescript
378
+ * throw new SourceTimeoutError("Wikipedia", 30000)
379
+ * ```
380
+ */
381
+ export declare class SourceTimeoutError extends Error {
382
+ /** Name of the source that timed out */
383
+ readonly sourceName: string;
384
+ /** Timeout duration in milliseconds */
385
+ readonly timeoutMs: number;
386
+ readonly name = "SourceTimeoutError";
387
+ constructor(
388
+ /** Name of the source that timed out */
389
+ sourceName: string,
390
+ /** Timeout duration in milliseconds */
391
+ timeoutMs: number);
392
+ }
393
+ /**
394
+ * Error thrown when a source access is blocked (403, 429, etc.).
395
+ *
396
+ * The orchestrator catches this and caches the blocked status to avoid
397
+ * re-hitting the same source. Blocked sources should be investigated
398
+ * for alternative access methods (browser automation, API access, etc.).
399
+ *
400
+ * @example
401
+ * ```typescript
402
+ * throw new SourceAccessBlockedError("NYTimes", 403)
403
+ * ```
404
+ */
405
+ export declare class SourceAccessBlockedError extends Error {
406
+ /** Name of the source that blocked access */
407
+ readonly sourceName: string;
408
+ /** HTTP status code (403, 429, etc.) */
409
+ readonly statusCode: number;
410
+ readonly name = "SourceAccessBlockedError";
411
+ constructor(
412
+ /** Name of the source that blocked access */
413
+ sourceName: string,
414
+ /** HTTP status code (403, 429, etc.) */
415
+ statusCode: number);
416
+ }
417
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Core type definitions for the debriefer research orchestration engine.
3
+ *
4
+ * These types are generalized from deadonfilm's death-sources/types.ts and
5
+ * biography-sources/types.ts. They define the contracts for subjects, findings,
6
+ * sources, synthesis, configuration, lifecycle hooks, and error types that
7
+ * the orchestrator and all source implementations share.
8
+ *
9
+ * Domain-specific types (e.g., ActorForEnrichment, BiographyData) live in
10
+ * consumer code, not here. Consumers extend ResearchSubject and provide their
11
+ * own TOutput type to the orchestrator.
12
+ */
13
+ // ============================================================================
14
+ // Error Types
15
+ // ============================================================================
16
+ /**
17
+ * Error thrown when a cost limit is exceeded during research.
18
+ *
19
+ * Can be thrown for per-subject limits (stops that subject) or total batch
20
+ * limits (stops the entire batch).
21
+ *
22
+ * @example
23
+ * ```typescript
24
+ * try {
25
+ * await orchestrator.debriefBatch(subjects)
26
+ * } catch (error) {
27
+ * if (error instanceof CostLimitExceededError) {
28
+ * console.log(`Cost limit: $${error.costUsd.toFixed(4)} > $${error.limit.toFixed(4)}`)
29
+ * }
30
+ * }
31
+ * ```
32
+ */
33
+ export class CostLimitExceededError extends Error {
34
+ subjectId;
35
+ costUsd;
36
+ limit;
37
+ name = "CostLimitExceededError";
38
+ constructor(
39
+ /** ID of the subject being processed when the limit was hit */
40
+ subjectId,
41
+ /** The cost in USD that triggered the limit */
42
+ costUsd,
43
+ /** The configured limit that was exceeded in USD */
44
+ limit) {
45
+ super(`Cost limit exceeded for subject ${subjectId}: $${costUsd.toFixed(4)} > $${limit.toFixed(4)}`);
46
+ this.subjectId = subjectId;
47
+ this.costUsd = costUsd;
48
+ this.limit = limit;
49
+ }
50
+ }
51
+ /**
52
+ * Error thrown when a source request times out.
53
+ *
54
+ * The orchestrator catches this and continues with remaining sources.
55
+ * High-priority source timeouts may be logged for investigation.
56
+ *
57
+ * @example
58
+ * ```typescript
59
+ * throw new SourceTimeoutError("Wikipedia", 30000)
60
+ * ```
61
+ */
62
+ export class SourceTimeoutError extends Error {
63
+ sourceName;
64
+ timeoutMs;
65
+ name = "SourceTimeoutError";
66
+ constructor(
67
+ /** Name of the source that timed out */
68
+ sourceName,
69
+ /** Timeout duration in milliseconds */
70
+ timeoutMs) {
71
+ super(`Source ${sourceName} timed out after ${timeoutMs}ms`);
72
+ this.sourceName = sourceName;
73
+ this.timeoutMs = timeoutMs;
74
+ }
75
+ }
76
+ /**
77
+ * Error thrown when a source access is blocked (403, 429, etc.).
78
+ *
79
+ * The orchestrator catches this and caches the blocked status to avoid
80
+ * re-hitting the same source. Blocked sources should be investigated
81
+ * for alternative access methods (browser automation, API access, etc.).
82
+ *
83
+ * @example
84
+ * ```typescript
85
+ * throw new SourceAccessBlockedError("NYTimes", 403)
86
+ * ```
87
+ */
88
+ export class SourceAccessBlockedError extends Error {
89
+ sourceName;
90
+ statusCode;
91
+ name = "SourceAccessBlockedError";
92
+ constructor(
93
+ /** Name of the source that blocked access */
94
+ sourceName,
95
+ /** HTTP status code (403, 429, etc.) */
96
+ statusCode) {
97
+ super(`Source ${sourceName} blocked with status ${statusCode}`);
98
+ this.sourceName = sourceName;
99
+ this.statusCode = statusCode;
100
+ }
101
+ }
102
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAwYH,+EAA+E;AAC/E,cAAc;AACd,+EAA+E;AAE/E;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,OAAO,sBAAuB,SAAQ,KAAK;IAK7B;IAEA;IAEA;IART,IAAI,GAAG,wBAAwB,CAAA;IAExC;IACE,+DAA+D;IAC/C,SAA0B;IAC1C,+CAA+C;IAC/B,OAAe;IAC/B,oDAAoD;IACpC,KAAa;QAE7B,KAAK,CACH,mCAAmC,SAAS,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAC9F,CAAA;QARe,cAAS,GAAT,SAAS,CAAiB;QAE1B,YAAO,GAAP,OAAO,CAAQ;QAEf,UAAK,GAAL,KAAK,CAAQ;IAK/B,CAAC;CACF;AAED;;;;;;;;;;GAUG;AACH,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IAKzB;IAEA;IANT,IAAI,GAAG,oBAAoB,CAAA;IAEpC;IACE,wCAAwC;IACxB,UAAkB;IAClC,uCAAuC;IACvB,SAAiB;QAEjC,KAAK,CAAC,UAAU,UAAU,oBAAoB,SAAS,IAAI,CAAC,CAAA;QAJ5C,eAAU,GAAV,UAAU,CAAQ;QAElB,cAAS,GAAT,SAAS,CAAQ;IAGnC,CAAC;CACF;AAED;;;;;;;;;;;GAWG;AACH,MAAM,OAAO,wBAAyB,SAAQ,KAAK;IAK/B;IAEA;IANT,IAAI,GAAG,0BAA0B,CAAA;IAE1C;IACE,6CAA6C;IAC7B,UAAkB;IAClC,wCAAwC;IACxB,UAAkB;QAElC,KAAK,CAAC,UAAU,UAAU,wBAAwB,UAAU,EAAE,CAAC,CAAA;QAJ/C,eAAU,GAAV,UAAU,CAAQ;QAElB,eAAU,GAAV,UAAU,CAAQ;IAGpC,CAAC;CACF"}
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "@debriefer/core",
3
+ "version": "2.0.0",
4
+ "description": "Multi-source research orchestration engine with reliability scoring, phase-based execution, and pluggable synthesis",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ }
13
+ },
14
+ "scripts": {
15
+ "build": "tsc",
16
+ "test": "vitest run",
17
+ "lint": "eslint src/",
18
+ "type-check": "tsc --noEmit"
19
+ },
20
+ "files": [
21
+ "dist"
22
+ ],
23
+ "keywords": [
24
+ "research",
25
+ "orchestration",
26
+ "multi-source",
27
+ "reliability",
28
+ "web-scraping",
29
+ "ai",
30
+ "enrichment"
31
+ ],
32
+ "author": "Chris Henderson",
33
+ "license": "MIT",
34
+ "repository": {
35
+ "type": "git",
36
+ "url": "https://github.com/chenders/debriefer.git",
37
+ "directory": "packages/core"
38
+ },
39
+ "homepage": "https://github.com/chenders/debriefer#readme",
40
+ "bugs": {
41
+ "url": "https://github.com/chenders/debriefer/issues"
42
+ },
43
+ "dependencies": {
44
+ "p-limit": "^6"
45
+ }
46
+ }