@farukada/langchain-ts-rms 0.1.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 (175) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +446 -0
  3. package/dist/app/freshness/evaluator.d.ts +23 -0
  4. package/dist/app/freshness/evaluator.d.ts.map +1 -0
  5. package/dist/app/freshness/evaluator.js +72 -0
  6. package/dist/app/freshness/evaluator.js.map +1 -0
  7. package/dist/app/governance/guardrails.d.ts +51 -0
  8. package/dist/app/governance/guardrails.d.ts.map +1 -0
  9. package/dist/app/governance/guardrails.js +68 -0
  10. package/dist/app/governance/guardrails.js.map +1 -0
  11. package/dist/app/graph/workflow.d.ts +1159 -0
  12. package/dist/app/graph/workflow.d.ts.map +1 -0
  13. package/dist/app/graph/workflow.js +468 -0
  14. package/dist/app/graph/workflow.js.map +1 -0
  15. package/dist/app/queryPlanning/planner.d.ts +18 -0
  16. package/dist/app/queryPlanning/planner.d.ts.map +1 -0
  17. package/dist/app/queryPlanning/planner.js +80 -0
  18. package/dist/app/queryPlanning/planner.js.map +1 -0
  19. package/dist/app/queryRewriting/rewriter.d.ts +32 -0
  20. package/dist/app/queryRewriting/rewriter.d.ts.map +1 -0
  21. package/dist/app/queryRewriting/rewriter.js +111 -0
  22. package/dist/app/queryRewriting/rewriter.js.map +1 -0
  23. package/dist/app/reranking/reranker.d.ts +27 -0
  24. package/dist/app/reranking/reranker.d.ts.map +1 -0
  25. package/dist/app/reranking/reranker.js +67 -0
  26. package/dist/app/reranking/reranker.js.map +1 -0
  27. package/dist/app/state/schema.d.ts +121 -0
  28. package/dist/app/state/schema.d.ts.map +1 -0
  29. package/dist/app/state/schema.js +88 -0
  30. package/dist/app/state/schema.js.map +1 -0
  31. package/dist/app/summarization/summarizationSchema.d.ts +34 -0
  32. package/dist/app/summarization/summarizationSchema.d.ts.map +1 -0
  33. package/dist/app/summarization/summarizationSchema.js +65 -0
  34. package/dist/app/summarization/summarizationSchema.js.map +1 -0
  35. package/dist/app/summarization/summarizer.d.ts +51 -0
  36. package/dist/app/summarization/summarizer.d.ts.map +1 -0
  37. package/dist/app/summarization/summarizer.js +181 -0
  38. package/dist/app/summarization/summarizer.js.map +1 -0
  39. package/dist/app/summarization/synthesisSchema.d.ts +16 -0
  40. package/dist/app/summarization/synthesisSchema.d.ts.map +1 -0
  41. package/dist/app/summarization/synthesisSchema.js +43 -0
  42. package/dist/app/summarization/synthesisSchema.js.map +1 -0
  43. package/dist/app/summarization/synthesizer.d.ts +21 -0
  44. package/dist/app/summarization/synthesizer.d.ts.map +1 -0
  45. package/dist/app/summarization/synthesizer.js +86 -0
  46. package/dist/app/summarization/synthesizer.js.map +1 -0
  47. package/dist/config/env.d.ts +49 -0
  48. package/dist/config/env.d.ts.map +1 -0
  49. package/dist/config/env.js +54 -0
  50. package/dist/config/env.js.map +1 -0
  51. package/dist/domain/contracts.d.ts +59 -0
  52. package/dist/domain/contracts.d.ts.map +1 -0
  53. package/dist/domain/contracts.js +52 -0
  54. package/dist/domain/contracts.js.map +1 -0
  55. package/dist/domain/ports.d.ts +63 -0
  56. package/dist/domain/ports.d.ts.map +1 -0
  57. package/dist/domain/ports.js +2 -0
  58. package/dist/domain/ports.js.map +1 -0
  59. package/dist/domain/researchUtils.d.ts +51 -0
  60. package/dist/domain/researchUtils.d.ts.map +1 -0
  61. package/dist/domain/researchUtils.js +85 -0
  62. package/dist/domain/researchUtils.js.map +1 -0
  63. package/dist/infra/chat/chatModelProvider.d.ts +4 -0
  64. package/dist/infra/chat/chatModelProvider.d.ts.map +1 -0
  65. package/dist/infra/chat/chatModelProvider.js +13 -0
  66. package/dist/infra/chat/chatModelProvider.js.map +1 -0
  67. package/dist/infra/checkpoint/checkpointerFactory.d.ts +38 -0
  68. package/dist/infra/checkpoint/checkpointerFactory.d.ts.map +1 -0
  69. package/dist/infra/checkpoint/checkpointerFactory.js +54 -0
  70. package/dist/infra/checkpoint/checkpointerFactory.js.map +1 -0
  71. package/dist/infra/content/contentExtractor.d.ts +58 -0
  72. package/dist/infra/content/contentExtractor.d.ts.map +1 -0
  73. package/dist/infra/content/contentExtractor.js +296 -0
  74. package/dist/infra/content/contentExtractor.js.map +1 -0
  75. package/dist/infra/embeddings/embeddingProvider.d.ts +4 -0
  76. package/dist/infra/embeddings/embeddingProvider.d.ts.map +1 -0
  77. package/dist/infra/embeddings/embeddingProvider.js +11 -0
  78. package/dist/infra/embeddings/embeddingProvider.js.map +1 -0
  79. package/dist/infra/healthCheck.d.ts +23 -0
  80. package/dist/infra/healthCheck.d.ts.map +1 -0
  81. package/dist/infra/healthCheck.js +57 -0
  82. package/dist/infra/healthCheck.js.map +1 -0
  83. package/dist/infra/observability/tokenCounter.d.ts +30 -0
  84. package/dist/infra/observability/tokenCounter.d.ts.map +1 -0
  85. package/dist/infra/observability/tokenCounter.js +46 -0
  86. package/dist/infra/observability/tokenCounter.js.map +1 -0
  87. package/dist/infra/observability/tracing.d.ts +38 -0
  88. package/dist/infra/observability/tracing.d.ts.map +1 -0
  89. package/dist/infra/observability/tracing.js +92 -0
  90. package/dist/infra/observability/tracing.js.map +1 -0
  91. package/dist/infra/rateLimit/circuitBreaker.d.ts +54 -0
  92. package/dist/infra/rateLimit/circuitBreaker.d.ts.map +1 -0
  93. package/dist/infra/rateLimit/circuitBreaker.js +97 -0
  94. package/dist/infra/rateLimit/circuitBreaker.js.map +1 -0
  95. package/dist/infra/rateLimit/rateLimiter.d.ts +42 -0
  96. package/dist/infra/rateLimit/rateLimiter.d.ts.map +1 -0
  97. package/dist/infra/rateLimit/rateLimiter.js +89 -0
  98. package/dist/infra/rateLimit/rateLimiter.js.map +1 -0
  99. package/dist/infra/search/searxngClient.d.ts +29 -0
  100. package/dist/infra/search/searxngClient.d.ts.map +1 -0
  101. package/dist/infra/search/searxngClient.js +85 -0
  102. package/dist/infra/search/searxngClient.js.map +1 -0
  103. package/dist/infra/search/urlBlocklist.d.ts +28 -0
  104. package/dist/infra/search/urlBlocklist.d.ts.map +1 -0
  105. package/dist/infra/search/urlBlocklist.js +78 -0
  106. package/dist/infra/search/urlBlocklist.js.map +1 -0
  107. package/dist/infra/vector/qdrantClient.d.ts +18 -0
  108. package/dist/infra/vector/qdrantClient.d.ts.map +1 -0
  109. package/dist/infra/vector/qdrantClient.js +82 -0
  110. package/dist/infra/vector/qdrantClient.js.map +1 -0
  111. package/dist/infra/vector/researchRepository.d.ts +39 -0
  112. package/dist/infra/vector/researchRepository.d.ts.map +1 -0
  113. package/dist/infra/vector/researchRepository.js +294 -0
  114. package/dist/infra/vector/researchRepository.js.map +1 -0
  115. package/dist/lib/helpers.d.ts +50 -0
  116. package/dist/lib/helpers.d.ts.map +1 -0
  117. package/dist/lib/helpers.js +124 -0
  118. package/dist/lib/helpers.js.map +1 -0
  119. package/dist/lib/index.d.ts +65 -0
  120. package/dist/lib/index.d.ts.map +1 -0
  121. package/dist/lib/index.js +61 -0
  122. package/dist/lib/index.js.map +1 -0
  123. package/dist/lib/rmsTool.d.ts +28 -0
  124. package/dist/lib/rmsTool.d.ts.map +1 -0
  125. package/dist/lib/rmsTool.js +79 -0
  126. package/dist/lib/rmsTool.js.map +1 -0
  127. package/dist/lib/schemas/lifecycleSchemas.d.ts +42 -0
  128. package/dist/lib/schemas/lifecycleSchemas.d.ts.map +1 -0
  129. package/dist/lib/schemas/lifecycleSchemas.js +176 -0
  130. package/dist/lib/schemas/lifecycleSchemas.js.map +1 -0
  131. package/dist/lib/schemas/researchSchemas.d.ts +23 -0
  132. package/dist/lib/schemas/researchSchemas.d.ts.map +1 -0
  133. package/dist/lib/schemas/researchSchemas.js +83 -0
  134. package/dist/lib/schemas/researchSchemas.js.map +1 -0
  135. package/dist/lib/tools/deleteResearch.d.ts +19 -0
  136. package/dist/lib/tools/deleteResearch.d.ts.map +1 -0
  137. package/dist/lib/tools/deleteResearch.js +37 -0
  138. package/dist/lib/tools/deleteResearch.js.map +1 -0
  139. package/dist/lib/tools/getDatetime.d.ts +7 -0
  140. package/dist/lib/tools/getDatetime.d.ts.map +1 -0
  141. package/dist/lib/tools/getDatetime.js +26 -0
  142. package/dist/lib/tools/getDatetime.js.map +1 -0
  143. package/dist/lib/tools/getResearch.d.ts +19 -0
  144. package/dist/lib/tools/getResearch.d.ts.map +1 -0
  145. package/dist/lib/tools/getResearch.js +32 -0
  146. package/dist/lib/tools/getResearch.js.map +1 -0
  147. package/dist/lib/tools/listResearch.d.ts +25 -0
  148. package/dist/lib/tools/listResearch.d.ts.map +1 -0
  149. package/dist/lib/tools/listResearch.js +41 -0
  150. package/dist/lib/tools/listResearch.js.map +1 -0
  151. package/dist/lib/tools/refreshResearch.d.ts +27 -0
  152. package/dist/lib/tools/refreshResearch.d.ts.map +1 -0
  153. package/dist/lib/tools/refreshResearch.js +81 -0
  154. package/dist/lib/tools/refreshResearch.js.map +1 -0
  155. package/dist/lib/tools/research.d.ts +108 -0
  156. package/dist/lib/tools/research.d.ts.map +1 -0
  157. package/dist/lib/tools/research.js +273 -0
  158. package/dist/lib/tools/research.js.map +1 -0
  159. package/dist/lib/tools/searchResearch.d.ts +25 -0
  160. package/dist/lib/tools/searchResearch.d.ts.map +1 -0
  161. package/dist/lib/tools/searchResearch.js +45 -0
  162. package/dist/lib/tools/searchResearch.js.map +1 -0
  163. package/dist/lib/types.d.ts +51 -0
  164. package/dist/lib/types.d.ts.map +1 -0
  165. package/dist/lib/types.js +2 -0
  166. package/dist/lib/types.js.map +1 -0
  167. package/dist/mcp/index.d.ts +12 -0
  168. package/dist/mcp/index.d.ts.map +1 -0
  169. package/dist/mcp/index.js +12 -0
  170. package/dist/mcp/index.js.map +1 -0
  171. package/dist/mcp/server.d.ts +45 -0
  172. package/dist/mcp/server.d.ts.map +1 -0
  173. package/dist/mcp/server.js +440 -0
  174. package/dist/mcp/server.js.map +1 -0
  175. package/package.json +132 -0
@@ -0,0 +1,296 @@
1
+ import * as cheerio from "cheerio";
2
+ import { extract as articleExtract } from "@extractus/article-extractor";
3
+ import { logInfo, logWarn, logDebug } from "../observability/tracing.js";
4
+ import { contentLimiter } from "../rateLimit/rateLimiter.js";
5
+ import { contentBreaker } from "../rateLimit/circuitBreaker.js";
6
+ import { loadEnv } from "../../config/env.js";
7
+ /** Elements to strip before extracting text — not useful for research. */
8
+ const STRIP_SELECTORS = [
9
+ "script",
10
+ "style",
11
+ "nav",
12
+ "footer",
13
+ "header",
14
+ "aside",
15
+ "iframe",
16
+ "noscript",
17
+ ".sidebar",
18
+ ".navigation",
19
+ ".menu",
20
+ ".ads",
21
+ ".advertisement",
22
+ ".cookie-banner",
23
+ ".popup",
24
+ "[role='navigation']",
25
+ "[role='banner']",
26
+ "[role='contentinfo']",
27
+ ];
28
+ /**
29
+ * Extracts readable text content from an HTML page.
30
+ *
31
+ * Strips navigation, ads, scripts, and other non-content elements.
32
+ * Collapses whitespace and truncates to `maxChars`.
33
+ */
34
+ export function extractTextFromHtml(html, maxChars) {
35
+ const $ = cheerio.load(html);
36
+ // Remove non-content elements
37
+ for (const selector of STRIP_SELECTORS) {
38
+ $(selector).remove();
39
+ }
40
+ // Prefer <article> or <main> if present; otherwise use <body>
41
+ let contentRoot = $("article").first();
42
+ if (contentRoot.length === 0)
43
+ contentRoot = $("main").first();
44
+ if (contentRoot.length === 0)
45
+ contentRoot = $("body").first();
46
+ // Get text, collapse whitespace
47
+ const rawText = contentRoot.text();
48
+ const cleaned = rawText
49
+ .replace(/\s+/g, " ")
50
+ .replace(/\n{3,}/g, "\n\n")
51
+ .trim();
52
+ return cleaned.slice(0, maxChars);
53
+ }
54
+ /**
55
+ * Maximum number of bytes to download from a page before aborting.
56
+ * Protects against bloated SPAs, PDFs, and other large payloads that would
57
+ * cause OOM when fed to Cheerio. 100KB of HTML is more than enough for
58
+ * article-length content.
59
+ */
60
+ const MAX_DOWNLOAD_BYTES = 100_000;
61
+ /**
62
+ * Realistic Chrome User-Agent string.
63
+ * Using the bot-identifying UA caused widespread 403 blocks.
64
+ */
65
+ const CHROME_USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36";
66
+ /** Minimum content length to consider an extraction successful (chars). */
67
+ const MIN_USEFUL_CONTENT_LENGTH = 200;
68
+ /**
69
+ * Streams an HTTP response body, accumulating chunks into a string.
70
+ * Aborts the request as soon as `maxBytes` is consumed, guaranteeing
71
+ * bounded memory usage regardless of how large the remote payload is.
72
+ */
73
+ async function streamWithByteLimit(body, maxBytes) {
74
+ const reader = body.getReader();
75
+ const decoder = new TextDecoder("utf-8", { fatal: false });
76
+ let accumulated = "";
77
+ let totalBytes = 0;
78
+ try {
79
+ while (true) {
80
+ const { done, value } = await reader.read();
81
+ if (done)
82
+ break;
83
+ totalBytes += value.byteLength;
84
+ accumulated += decoder.decode(value, { stream: true });
85
+ if (totalBytes >= maxBytes) {
86
+ logDebug("Byte limit reached, aborting stream", { totalBytes, maxBytes });
87
+ break;
88
+ }
89
+ }
90
+ }
91
+ finally {
92
+ reader.cancel().catch(() => {
93
+ /* best-effort cancellation */
94
+ });
95
+ }
96
+ // Flush any remaining bytes in the decoder
97
+ accumulated += decoder.decode();
98
+ return accumulated;
99
+ }
100
+ /**
101
+ * Primary extraction: uses `@extractus/article-extractor` which handles
102
+ * its own HTTP fetch with smart content detection and boilerplate removal.
103
+ * Returns clean text content or `null` if extraction fails.
104
+ */
105
+ async function extractWithArticleExtractor(url, maxChars, userAgent, timeoutMs) {
106
+ try {
107
+ const article = await articleExtract(url, {
108
+ contentLengthThreshold: 100,
109
+ }, {
110
+ headers: {
111
+ "User-Agent": userAgent,
112
+ Accept: "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
113
+ "Accept-Language": "en-US,en;q=0.9",
114
+ },
115
+ signal: AbortSignal.timeout(timeoutMs),
116
+ });
117
+ if (!article?.content) {
118
+ logInfo("Article extractor returned no content", { url });
119
+ return null;
120
+ }
121
+ // article.content is HTML — strip tags to get plain text
122
+ const $ = cheerio.load(article.content);
123
+ const text = $.text()
124
+ .replace(/\s+/g, " ")
125
+ .replace(/\n{3,}/g, "\n\n")
126
+ .trim()
127
+ .slice(0, maxChars);
128
+ if (text.length < MIN_USEFUL_CONTENT_LENGTH) {
129
+ logInfo("Article extractor text too short", { url, length: text.length });
130
+ return null;
131
+ }
132
+ logInfo("Article extractor succeeded", { url, extractedLength: text.length });
133
+ return text;
134
+ }
135
+ catch (err) {
136
+ logWarn("Article extractor failed", {
137
+ url,
138
+ error: err instanceof Error ? err.message : String(err),
139
+ });
140
+ return null;
141
+ }
142
+ }
143
+ /**
144
+ * Fetches a web page and extracts readable text content.
145
+ *
146
+ * Uses a tiered extraction strategy:
147
+ * 1. `@extractus/article-extractor` — smart article detection with its own fetch
148
+ * 2. Direct fetch + Cheerio — fallback HTML parsing pipeline
149
+ * 3. SearXNG snippet — final fallback when both extraction methods fail
150
+ *
151
+ * Each tier only fires when the previous one didn't produce enough content.
152
+ */
153
+ export async function extractContent(url, fallbackSnippet, options) {
154
+ const maxChars = options?.maxChars ?? 8000;
155
+ const timeoutMs = options?.timeoutMs ?? 10_000;
156
+ const userAgent = options?.userAgent ?? loadEnv().RMS_USER_AGENT ?? CHROME_USER_AGENT;
157
+ const limiter = options?.limiter ?? contentLimiter;
158
+ const breaker = options?.breaker ?? contentBreaker;
159
+ // ── Tier 1: Article extractor (smart fetch + extraction) ──
160
+ const articleText = await extractWithArticleExtractor(url, maxChars, userAgent, timeoutMs);
161
+ if (articleText) {
162
+ logInfo("Content extracted via article-extractor", {
163
+ url,
164
+ extractedLength: articleText.length,
165
+ });
166
+ return {
167
+ text: articleText,
168
+ extractedLength: articleText.length,
169
+ wasExtracted: true,
170
+ extractionMethod: "article-extractor",
171
+ };
172
+ }
173
+ // ── Tier 2: Direct fetch + Cheerio (existing pipeline) ──
174
+ try {
175
+ await limiter.acquire();
176
+ const resp = await breaker.execute(() => fetch(url, {
177
+ method: "GET",
178
+ headers: {
179
+ "User-Agent": userAgent,
180
+ Accept: "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
181
+ "Accept-Language": "en-US,en;q=0.9",
182
+ },
183
+ signal: AbortSignal.timeout(timeoutMs),
184
+ redirect: "follow",
185
+ }));
186
+ if (!resp.ok) {
187
+ logInfo("Content fetch returned non-OK status", { url, status: resp.status });
188
+ return {
189
+ text: fallbackSnippet,
190
+ extractedLength: fallbackSnippet.length,
191
+ wasExtracted: false,
192
+ extractionMethod: "snippet",
193
+ };
194
+ }
195
+ const contentType = resp.headers.get("content-type") ?? "";
196
+ if (!contentType.includes("text/html") && !contentType.includes("application/xhtml")) {
197
+ logInfo("Non-HTML content type, using snippet fallback", { url, contentType });
198
+ return {
199
+ text: fallbackSnippet,
200
+ extractedLength: fallbackSnippet.length,
201
+ wasExtracted: false,
202
+ extractionMethod: "snippet",
203
+ };
204
+ }
205
+ if (!resp.body) {
206
+ logInfo("Response has no body, using snippet fallback", { url });
207
+ return {
208
+ text: fallbackSnippet,
209
+ extractedLength: fallbackSnippet.length,
210
+ wasExtracted: false,
211
+ extractionMethod: "snippet",
212
+ };
213
+ }
214
+ // Stream the response with a byte limit instead of downloading the full payload
215
+ const html = await streamWithByteLimit(resp.body, MAX_DOWNLOAD_BYTES);
216
+ const text = extractTextFromHtml(html, maxChars);
217
+ // If extracted text is too short, the page might be JS-rendered — fall back
218
+ if (text.length < 100) {
219
+ logInfo("Cheerio extracted content too short, using snippet fallback", {
220
+ url,
221
+ extractedLength: text.length,
222
+ });
223
+ return {
224
+ text: fallbackSnippet,
225
+ extractedLength: fallbackSnippet.length,
226
+ wasExtracted: false,
227
+ extractionMethod: "snippet",
228
+ };
229
+ }
230
+ logInfo("Content extracted via cheerio", { url, extractedLength: text.length });
231
+ return { text, extractedLength: text.length, wasExtracted: true, extractionMethod: "cheerio" };
232
+ }
233
+ catch (err) {
234
+ logWarn("Cheerio extraction failed, using snippet fallback", {
235
+ url,
236
+ error: err instanceof Error ? err.message : String(err),
237
+ });
238
+ return {
239
+ text: fallbackSnippet,
240
+ extractedLength: fallbackSnippet.length,
241
+ wasExtracted: false,
242
+ extractionMethod: "snippet",
243
+ };
244
+ }
245
+ }
246
+ /**
247
+ * Batch-extracts content from multiple URLs with concurrency limiting.
248
+ *
249
+ * Returns results in the same order as input URLs. Failed extractions
250
+ * fall back to the provided snippets.
251
+ */
252
+ export async function batchExtractContent(sources, options) {
253
+ const concurrency = options?.concurrency ?? 3;
254
+ const results = Array.from({ length: sources.length });
255
+ logInfo("Batch content extraction starting", {
256
+ node: "contentExtractor",
257
+ sourceCount: sources.length,
258
+ concurrency,
259
+ });
260
+ // Process in batches of `concurrency`
261
+ for (let i = 0; i < sources.length; i += concurrency) {
262
+ const batch = sources.slice(i, i + concurrency);
263
+ const batchResults = await Promise.all(batch.map((s) => extractContent(s.url, s.snippet, options)));
264
+ for (let j = 0; j < batchResults.length; j++) {
265
+ results[i + j] = batchResults[j];
266
+ }
267
+ // Delay between batches to avoid IP-level throttling by target websites
268
+ if (i + concurrency < sources.length) {
269
+ await new Promise((resolve) => setTimeout(resolve, 500));
270
+ }
271
+ }
272
+ const methodCounts = { "article-extractor": 0, cheerio: 0, snippet: 0 };
273
+ for (const r of results) {
274
+ methodCounts[r.extractionMethod]++;
275
+ }
276
+ logInfo("Batch content extraction complete", {
277
+ node: "contentExtractor",
278
+ total: sources.length,
279
+ articleExtractor: methodCounts["article-extractor"],
280
+ cheerio: methodCounts.cheerio,
281
+ snippet: methodCounts.snippet,
282
+ });
283
+ // Per-URL breakdown for debugging extraction quality
284
+ for (let i = 0; i < results.length; i++) {
285
+ const r = results[i];
286
+ const s = sources[i];
287
+ logInfo(`Extraction result [${String(i + 1)}/${String(sources.length)}]`, {
288
+ url: s.url,
289
+ method: r.extractionMethod,
290
+ extractedLength: r.extractedLength,
291
+ wasExtracted: r.wasExtracted,
292
+ });
293
+ }
294
+ return results;
295
+ }
296
+ //# sourceMappingURL=contentExtractor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contentExtractor.js","sourceRoot":"","sources":["../../../src/infra/content/contentExtractor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { EmbeddingsInterface } from "@langchain/core/embeddings";
2
+ /** Creates an Ollama embedding model from environment configuration. */
3
+ export declare function createEmbeddingProvider(): EmbeddingsInterface;
4
+ //# sourceMappingURL=embeddingProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embeddingProvider.d.ts","sourceRoot":"","sources":["../../../src/infra/embeddings/embeddingProvider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAItE,wEAAwE;AACxE,wBAAgB,uBAAuB,IAAI,mBAAmB,CAM7D"}
@@ -0,0 +1,11 @@
1
+ import { OllamaEmbeddings } from "@langchain/ollama";
2
+ import { loadEnv } from "../../config/env.js";
3
+ /** Creates an Ollama embedding model from environment configuration. */
4
+ export function createEmbeddingProvider() {
5
+ const env = loadEnv();
6
+ return new OllamaEmbeddings({
7
+ baseUrl: env.OLLAMA_HOST,
8
+ model: env.RMS_OLLAMA_EMBEDDING_MODEL ?? env.OLLAMA_EMBEDDING_MODEL,
9
+ });
10
+ }
11
+ //# sourceMappingURL=embeddingProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embeddingProvider.js","sourceRoot":"","sources":["../../../src/infra/embeddings/embeddingProvider.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAE9C,wEAAwE;AACxE,MAAM,UAAU,uBAAuB;IACrC,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;IACtB,OAAO,IAAI,gBAAgB,CAAC;QAC1B,OAAO,EAAE,GAAG,CAAC,WAAW;QACxB,KAAK,EAAE,GAAG,CAAC,0BAA0B,IAAI,GAAG,CAAC,sBAAsB;KACpE,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,23 @@
1
+ /** Health status for a single backend service. */
2
+ export interface ServiceHealth {
3
+ ok: boolean;
4
+ latencyMs: number;
5
+ error?: string | undefined;
6
+ }
7
+ /** Aggregate health status for all RMS backend dependencies. */
8
+ export interface HealthStatus {
9
+ qdrant: ServiceHealth;
10
+ ollama: ServiceHealth;
11
+ searxng: ServiceHealth;
12
+ }
13
+ /**
14
+ * Non-destructive health check for all RMS backend services.
15
+ *
16
+ * - **Qdrant**: calls `GET /collections`
17
+ * - **Ollama**: calls `GET /api/tags`
18
+ * - **SearxNG**: calls `GET /`
19
+ *
20
+ * @returns Structured health status with per-service latency.
21
+ */
22
+ export declare function checkHealth(): Promise<HealthStatus>;
23
+ //# sourceMappingURL=healthCheck.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"healthCheck.d.ts","sourceRoot":"","sources":["../../src/infra/healthCheck.ts"],"names":[],"mappings":"AAOA,kDAAkD;AAClD,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,OAAO,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5B;AAED,gEAAgE;AAChE,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,aAAa,CAAC;IACtB,MAAM,EAAE,aAAa,CAAC;IACtB,OAAO,EAAE,aAAa,CAAC;CACxB;AAED;;;;;;;;GAQG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,YAAY,CAAC,CA8CzD"}
@@ -0,0 +1,57 @@
1
+ import { loadEnv } from "../config/env.js";
2
+ import { logInfo, logError } from "./observability/tracing.js";
3
+ /**
4
+ * Non-destructive health check for all RMS backend services.
5
+ *
6
+ * - **Qdrant**: calls `GET /collections`
7
+ * - **Ollama**: calls `GET /api/tags`
8
+ * - **SearxNG**: calls `GET /`
9
+ *
10
+ * @returns Structured health status with per-service latency.
11
+ */
12
+ export async function checkHealth() {
13
+ const env = loadEnv();
14
+ const probe = async (url) => {
15
+ const start = Date.now();
16
+ try {
17
+ const resp = await fetch(url, {
18
+ method: "GET",
19
+ signal: AbortSignal.timeout(5000),
20
+ });
21
+ const latencyMs = Date.now() - start;
22
+ if (!resp.ok) {
23
+ return { ok: false, latencyMs, error: `HTTP ${resp.status}` };
24
+ }
25
+ return { ok: true, latencyMs };
26
+ }
27
+ catch (err) {
28
+ return {
29
+ ok: false,
30
+ latencyMs: Date.now() - start,
31
+ error: err instanceof Error ? err.message : String(err),
32
+ };
33
+ }
34
+ };
35
+ const [qdrant, ollama, searxng] = await Promise.all([
36
+ probe(`${env.QDRANT_URL}/collections`),
37
+ probe(`${env.OLLAMA_HOST}/api/tags`),
38
+ probe(`${env.SEARXNG_API_BASE}/`),
39
+ ]);
40
+ const allOk = qdrant.ok && ollama.ok && searxng.ok;
41
+ if (allOk) {
42
+ logInfo("Health check passed", {
43
+ qdrantMs: qdrant.latencyMs,
44
+ ollamaMs: ollama.latencyMs,
45
+ searxngMs: searxng.latencyMs,
46
+ });
47
+ }
48
+ else {
49
+ logError("Health check failed", {
50
+ qdrant: qdrant.ok ? "ok" : qdrant.error,
51
+ ollama: ollama.ok ? "ok" : ollama.error,
52
+ searxng: searxng.ok ? "ok" : searxng.error,
53
+ });
54
+ }
55
+ return { qdrant, ollama, searxng };
56
+ }
57
+ //# sourceMappingURL=healthCheck.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"healthCheck.js","sourceRoot":"","sources":["../../src/infra/healthCheck.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC3C,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAoB/D;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;IAEtB,MAAM,KAAK,GAAG,KAAK,EAAE,GAAW,EAA0B,EAAE;QAC1D,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACzB,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;gBAC5B,MAAM,EAAE,KAAK;gBACb,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC;aAClC,CAAC,CAAC;YACH,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;YACrC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;gBACb,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;YAChE,CAAC;YACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;QACjC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK;gBAC7B,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;aACxD,CAAC;QACJ,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAClD,KAAK,CAAC,GAAG,GAAG,CAAC,UAAU,cAAc,CAAC;QACtC,KAAK,CAAC,GAAG,GAAG,CAAC,WAAW,WAAW,CAAC;QACpC,KAAK,CAAC,GAAG,GAAG,CAAC,gBAAgB,GAAG,CAAC;KAClC,CAAC,CAAC;IAEH,MAAM,KAAK,GAAG,MAAM,CAAC,EAAE,IAAI,MAAM,CAAC,EAAE,IAAI,OAAO,CAAC,EAAE,CAAC;IACnD,IAAI,KAAK,EAAE,CAAC;QACV,OAAO,CAAC,qBAAqB,EAAE;YAC7B,QAAQ,EAAE,MAAM,CAAC,SAAS;YAC1B,QAAQ,EAAE,MAAM,CAAC,SAAS;YAC1B,SAAS,EAAE,OAAO,CAAC,SAAS;SAC7B,CAAC,CAAC;IACL,CAAC;SAAM,CAAC;QACN,QAAQ,CAAC,qBAAqB,EAAE;YAC9B,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK;YACvC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK;YACvC,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK;SAC3C,CAAC,CAAC;IACL,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;AACrC,CAAC"}
@@ -0,0 +1,30 @@
1
+ import { BaseCallbackHandler } from "@langchain/core/callbacks/base";
2
+ import type { LLMResult } from "@langchain/core/outputs";
3
+ /**
4
+ * LangChain callback handler that accumulates LLM token usage across
5
+ * multiple invocations within a single workflow run.
6
+ *
7
+ * Attach to chat model calls via `chatModel.bind({ callbacks: [collector] })`
8
+ * or pass as part of the call options.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * const collector = new TokenUsageCollector();
13
+ * await chatModel.invoke(messages, { callbacks: [collector] });
14
+ * console.log(collector.usage); // { promptTokens: 512, completionTokens: 128 }
15
+ * ```
16
+ */
17
+ export declare class TokenUsageCollector extends BaseCallbackHandler {
18
+ name: string;
19
+ private _promptTokens;
20
+ private _completionTokens;
21
+ handleLLMEnd(output: LLMResult): void;
22
+ /** Accumulated token usage from all LLM calls observed by this collector. */
23
+ get usage(): {
24
+ promptTokens: number;
25
+ completionTokens: number;
26
+ };
27
+ /** Reset accumulated counters (for reuse across separate runs). */
28
+ reset(): void;
29
+ }
30
+ //# sourceMappingURL=tokenCounter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokenCounter.d.ts","sourceRoot":"","sources":["../../../src/infra/observability/tokenCounter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAMzD;;;;;;;;;;;;;GAaG;AACH,qBAAa,mBAAoB,SAAQ,mBAAmB;IAC1D,IAAI,SAAyB;IAE7B,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,iBAAiB,CAAK;IAErB,YAAY,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI;IAc9C,6EAA6E;IAC7E,IAAI,KAAK,IAAI;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,gBAAgB,EAAE,MAAM,CAAA;KAAE,CAK9D;IAED,mEAAmE;IACnE,KAAK,IAAI,IAAI;CAId"}
@@ -0,0 +1,46 @@
1
+ import { BaseCallbackHandler } from "@langchain/core/callbacks/base";
2
+ // ---------------------------------------------------------------------------
3
+ // Token Usage Collector
4
+ // ---------------------------------------------------------------------------
5
+ /**
6
+ * LangChain callback handler that accumulates LLM token usage across
7
+ * multiple invocations within a single workflow run.
8
+ *
9
+ * Attach to chat model calls via `chatModel.bind({ callbacks: [collector] })`
10
+ * or pass as part of the call options.
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * const collector = new TokenUsageCollector();
15
+ * await chatModel.invoke(messages, { callbacks: [collector] });
16
+ * console.log(collector.usage); // { promptTokens: 512, completionTokens: 128 }
17
+ * ```
18
+ */
19
+ export class TokenUsageCollector extends BaseCallbackHandler {
20
+ name = "TokenUsageCollector";
21
+ _promptTokens = 0;
22
+ _completionTokens = 0;
23
+ handleLLMEnd(output) {
24
+ // LangChain stores token usage in `llmOutput.tokenUsage` or
25
+ // in the generation's `message.usage_metadata` depending on provider.
26
+ // For Ollama via @langchain/ollama, usage is in `llmOutput.tokenUsage`.
27
+ const usage = output.llmOutput;
28
+ if (usage?.tokenUsage) {
29
+ this._promptTokens += usage.tokenUsage.promptTokens ?? 0;
30
+ this._completionTokens += usage.tokenUsage.completionTokens ?? 0;
31
+ }
32
+ }
33
+ /** Accumulated token usage from all LLM calls observed by this collector. */
34
+ get usage() {
35
+ return {
36
+ promptTokens: this._promptTokens,
37
+ completionTokens: this._completionTokens,
38
+ };
39
+ }
40
+ /** Reset accumulated counters (for reuse across separate runs). */
41
+ reset() {
42
+ this._promptTokens = 0;
43
+ this._completionTokens = 0;
44
+ }
45
+ }
46
+ //# sourceMappingURL=tokenCounter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokenCounter.js","sourceRoot":"","sources":["../../../src/infra/observability/tokenCounter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAGrE,8EAA8E;AAC9E,wBAAwB;AACxB,8EAA8E;AAE9E;;;;;;;;;;;;;GAaG;AACH,MAAM,OAAO,mBAAoB,SAAQ,mBAAmB;IAC1D,IAAI,GAAG,qBAAqB,CAAC;IAErB,aAAa,GAAG,CAAC,CAAC;IAClB,iBAAiB,GAAG,CAAC,CAAC;IAErB,YAAY,CAAC,MAAiB;QACrC,4DAA4D;QAC5D,sEAAsE;QACtE,wEAAwE;QACxE,MAAM,KAAK,GAAG,MAAM,CAAC,SAER,CAAC;QAEd,IAAI,KAAK,EAAE,UAAU,EAAE,CAAC;YACtB,IAAI,CAAC,aAAa,IAAI,KAAK,CAAC,UAAU,CAAC,YAAY,IAAI,CAAC,CAAC;YACzD,IAAI,CAAC,iBAAiB,IAAI,KAAK,CAAC,UAAU,CAAC,gBAAgB,IAAI,CAAC,CAAC;QACnE,CAAC;IACH,CAAC;IAED,6EAA6E;IAC7E,IAAI,KAAK;QACP,OAAO;YACL,YAAY,EAAE,IAAI,CAAC,aAAa;YAChC,gBAAgB,EAAE,IAAI,CAAC,iBAAiB;SACzC,CAAC;IACJ,CAAC;IAED,mEAAmE;IACnE,KAAK;QACH,IAAI,CAAC,aAAa,GAAG,CAAC,CAAC;QACvB,IAAI,CAAC,iBAAiB,GAAG,CAAC,CAAC;IAC7B,CAAC;CACF"}
@@ -0,0 +1,38 @@
1
+ export interface LogContext {
2
+ traceId?: string | undefined;
3
+ researchId?: string | undefined;
4
+ node?: string | undefined;
5
+ errorCode?: string | undefined;
6
+ error?: string | undefined;
7
+ durationMs?: number | undefined;
8
+ [key: string]: unknown;
9
+ }
10
+ export interface StructuredLog {
11
+ level: "info" | "warn" | "error" | "debug";
12
+ msg: string;
13
+ ts: string;
14
+ [key: string]: unknown;
15
+ }
16
+ /** Replace the default `console.log` writer with a custom sink. */
17
+ export declare function setLogWriter(writer: (json: string) => void): void;
18
+ export declare function setLogSilent(value: boolean): void;
19
+ /** Set the minimum log level (e.g. from env config). */
20
+ export declare function setLogLevel(level: StructuredLog["level"]): void;
21
+ /**
22
+ * Emits structured JSON logs for observability. Use traceId for correlation across nodes.
23
+ */
24
+ export declare function log(level: StructuredLog["level"], msg: string, context?: LogContext): void;
25
+ export declare function logInfo(msg: string, context?: LogContext): void;
26
+ export declare function logWarn(msg: string, context?: LogContext): void;
27
+ export declare function logError(msg: string, context?: LogContext): void;
28
+ export declare function logDebug(msg: string, context?: LogContext): void;
29
+ export declare const ErrorCodes: {
30
+ readonly RESEARCH_NOT_FOUND: "RMS_RESEARCH_NOT_FOUND";
31
+ readonly INVALID_INPUT: "RMS_INVALID_INPUT";
32
+ readonly SEARCH_FAILED: "RMS_SEARCH_FAILED";
33
+ readonly SUMMARIZATION_FAILED: "RMS_SUMMARIZATION_FAILED";
34
+ readonly INFRA_RETRIABLE: "RMS_INFRA_RETRIABLE";
35
+ readonly STALE_CACHE: "RMS_STALE_CACHE";
36
+ };
37
+ export declare function withNodeTiming<T>(node: string, traceId: string | undefined, researchId: string, fn: () => T | Promise<T>): Promise<T>;
38
+ //# sourceMappingURL=tracing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tracing.d.ts","sourceRoot":"","sources":["../../../src/infra/observability/tracing.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;IAC3C,GAAG,EAAE,MAAM,CAAC;IACZ,EAAE,EAAE,MAAM,CAAC;IACX,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAKD,mEAAmE;AACnE,wBAAgB,YAAY,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAEjE;AAID,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAEjD;AAcD,wDAAwD;AACxD,wBAAgB,WAAW,CAAC,KAAK,EAAE,aAAa,CAAC,OAAO,CAAC,GAAG,IAAI,CAG/D;AAED;;GAEG;AACH,wBAAgB,GAAG,CAAC,KAAK,EAAE,aAAa,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,UAAe,GAAG,IAAI,CAmB9F;AAED,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,IAAI,CAE/D;AAED,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,IAAI,CAE/D;AAED,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,IAAI,CAEhE;AAED,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,IAAI,CAEhE;AAED,eAAO,MAAM,UAAU;;;;;;;CAOb,CAAC;AAEX,wBAAsB,cAAc,CAAC,CAAC,EACpC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,UAAU,EAAE,MAAM,EAClB,EAAE,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GACvB,OAAO,CAAC,CAAC,CAAC,CAiBZ"}
@@ -0,0 +1,92 @@
1
+ /** Pluggable log writer. Override with `setLogWriter` to route structured logs externally. */
2
+ let _writer = (json) => console.log(json);
3
+ /** Replace the default `console.log` writer with a custom sink. */
4
+ export function setLogWriter(writer) {
5
+ _writer = writer;
6
+ }
7
+ /** When true, all structured logging is suppressed (useful in tests). */
8
+ let _silent = false;
9
+ export function setLogSilent(value) {
10
+ _silent = value;
11
+ }
12
+ /** Numeric log level ordering for filtering (lower = more verbose). */
13
+ const LOG_LEVEL_ORDER = {
14
+ debug: 0,
15
+ info: 1,
16
+ warn: 2,
17
+ error: 3,
18
+ };
19
+ /** The minimum log level to emit. Messages below this level are suppressed. */
20
+ let _minLevel = "info";
21
+ let _levelInitialized = false;
22
+ /** Set the minimum log level (e.g. from env config). */
23
+ export function setLogLevel(level) {
24
+ _minLevel = level;
25
+ _levelInitialized = true;
26
+ }
27
+ /**
28
+ * Emits structured JSON logs for observability. Use traceId for correlation across nodes.
29
+ */
30
+ export function log(level, msg, context = {}) {
31
+ if (_silent)
32
+ return;
33
+ if (!_levelInitialized) {
34
+ _levelInitialized = true;
35
+ const envLevel = process.env["LOG_LEVEL"];
36
+ if (envLevel && envLevel in LOG_LEVEL_ORDER) {
37
+ _minLevel = envLevel;
38
+ }
39
+ }
40
+ if (LOG_LEVEL_ORDER[level] < LOG_LEVEL_ORDER[_minLevel])
41
+ return;
42
+ const entry = {
43
+ level,
44
+ msg,
45
+ ts: new Date().toISOString(),
46
+ };
47
+ for (const [k, v] of Object.entries(context)) {
48
+ if (v !== undefined)
49
+ entry[k] = v;
50
+ }
51
+ _writer(JSON.stringify(entry));
52
+ }
53
+ export function logInfo(msg, context) {
54
+ log("info", msg, context);
55
+ }
56
+ export function logWarn(msg, context) {
57
+ log("warn", msg, context);
58
+ }
59
+ export function logError(msg, context) {
60
+ log("error", msg, context);
61
+ }
62
+ export function logDebug(msg, context) {
63
+ log("debug", msg, context);
64
+ }
65
+ export const ErrorCodes = {
66
+ RESEARCH_NOT_FOUND: "RMS_RESEARCH_NOT_FOUND",
67
+ INVALID_INPUT: "RMS_INVALID_INPUT",
68
+ SEARCH_FAILED: "RMS_SEARCH_FAILED",
69
+ SUMMARIZATION_FAILED: "RMS_SUMMARIZATION_FAILED",
70
+ INFRA_RETRIABLE: "RMS_INFRA_RETRIABLE",
71
+ STALE_CACHE: "RMS_STALE_CACHE",
72
+ };
73
+ export async function withNodeTiming(node, traceId, researchId, fn) {
74
+ const start = Date.now();
75
+ logDebug("Node start", { node, traceId, researchId });
76
+ try {
77
+ const out = await fn();
78
+ logInfo("Node complete", { node, traceId, researchId, durationMs: Date.now() - start });
79
+ return out;
80
+ }
81
+ catch (err) {
82
+ logError("Node failed", {
83
+ node,
84
+ traceId,
85
+ researchId,
86
+ durationMs: Date.now() - start,
87
+ error: err instanceof Error ? err.message : String(err),
88
+ });
89
+ throw err;
90
+ }
91
+ }
92
+ //# sourceMappingURL=tracing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tracing.js","sourceRoot":"","sources":["../../../src/infra/observability/tracing.ts"],"names":[],"mappings":"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"}