@defai.digital/research-domain 13.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,38 @@
1
+ Business Source License 1.1
2
+
3
+ Parameters
4
+
5
+ Licensor: DEFAI Private Limited
6
+ Licensed Work: AutomatosX
7
+ The Licensed Work is (c) 2024-2025 DEFAI Private Limited
8
+ Additional Use Grant: You may make production use of the Licensed Work,
9
+ provided that your organization has less than US$2,000,000 in annual gross
10
+ revenue in the prior fiscal year. "Production use" means use in a live
11
+ production environment to support business or operational activities for end
12
+ users.
13
+ Change Date: Four years after the release date of the Licensed Work version
14
+ Change License: Apache License, Version 2.0
15
+
16
+ Terms
17
+
18
+ The Licensor hereby grants you the right to copy, modify, create derivative
19
+ works, redistribute, and make non-production use of the Licensed Work. The
20
+ Licensor may make an Additional Use Grant, above, permitting other uses of the
21
+ Licensed Work. The rights granted to you under this license are subject to the
22
+ following condition.
23
+
24
+ If you make any use of the Licensed Work, you must ensure that the Licensed
25
+ Work, or any modified version of it, carries prominent notices stating that
26
+ you have modified the Licensed Work.
27
+
28
+ This license does not grant permission to use the Licensor's trademarks.
29
+
30
+ The Licensed Work is provided "as is", without warranty of any kind, express
31
+ or implied, including but not limited to the warranties of merchantability,
32
+ fitness for a particular purpose and noninfringement. In no event shall the
33
+ Licensor be liable for any claim, damages or other liability, whether in an
34
+ action of contract, tort or otherwise, arising from, out of or in connection
35
+ with the Licensed Work or the use or other dealings in the Licensed Work.
36
+
37
+ On the Change Date, the Licensed Work will be made available under the Change
38
+ License.
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Research Domain
3
+ *
4
+ * Deep research agent with live documentation fetching and knowledge synthesis.
5
+ */
6
+ export type { WebFetcherPort, SynthesizerPort, ResearchCachePort, ResearchAgentOptions, ResearchAgent, } from './types.js';
7
+ export { createStubWebFetcher, createWebFetcher } from './web-fetcher.js';
8
+ export { createStubSynthesizer, detectConflicts, validateUrls } from './synthesizer.js';
9
+ export { createResearchAgent } from './research-agent.js';
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,YAAY,EACV,cAAc,EACd,eAAe,EACf,iBAAiB,EACjB,oBAAoB,EACpB,aAAa,GACd,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAG1E,OAAO,EAAE,qBAAqB,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAGxF,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Research Domain
3
+ *
4
+ * Deep research agent with live documentation fetching and knowledge synthesis.
5
+ */
6
+ // Web Fetcher
7
+ export { createStubWebFetcher, createWebFetcher } from './web-fetcher.js';
8
+ // Synthesizer
9
+ export { createStubSynthesizer, detectConflicts, validateUrls } from './synthesizer.js';
10
+ // Research Agent
11
+ export { createResearchAgent } from './research-agent.js';
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAWH,cAAc;AACd,OAAO,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAE1E,cAAc;AACd,OAAO,EAAE,qBAAqB,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAExF,iBAAiB;AACjB,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Research Agent
3
+ *
4
+ * Main research agent implementation.
5
+ *
6
+ * Invariants:
7
+ * - INV-RSH-001: All sources cited in synthesis
8
+ * - INV-RSH-002: Confidence reflects source reliability
9
+ * - INV-RSH-003: Stale data flagged with warning
10
+ */
11
+ import type { ResearchAgent, ResearchAgentOptions } from './types.js';
12
+ /**
13
+ * Create a research agent
14
+ */
15
+ export declare function createResearchAgent(options?: Partial<ResearchAgentOptions>): ResearchAgent;
16
+ //# sourceMappingURL=research-agent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"research-agent.d.ts","sourceRoot":"","sources":["../src/research-agent.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAcH,OAAO,KAAK,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAItE;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,GAAE,OAAO,CAAC,oBAAoB,CAAM,GAC1C,aAAa,CA+Ff"}
@@ -0,0 +1,154 @@
1
+ /**
2
+ * Research Agent
3
+ *
4
+ * Main research agent implementation.
5
+ *
6
+ * Invariants:
7
+ * - INV-RSH-001: All sources cited in synthesis
8
+ * - INV-RSH-002: Confidence reflects source reliability
9
+ * - INV-RSH-003: Stale data flagged with warning
10
+ */
11
+ import { calculateConfidence, hasStaleDataWarning, } from '@defai.digital/contracts';
12
+ import { createStubWebFetcher } from './web-fetcher.js';
13
+ import { createStubSynthesizer, detectConflicts } from './synthesizer.js';
14
+ /**
15
+ * Create a research agent
16
+ */
17
+ export function createResearchAgent(options = {}) {
18
+ const { webFetcher = createStubWebFetcher(), synthesizer = createStubSynthesizer(), cache, defaultTimeout = 60000, } = options;
19
+ return {
20
+ async research(request) {
21
+ const startTime = Date.now();
22
+ const resultId = crypto.randomUUID();
23
+ // Check cache
24
+ if (cache) {
25
+ const queryHash = hashQuery(request.query);
26
+ const cached = await cache.get(queryHash);
27
+ if (cached) {
28
+ return cached;
29
+ }
30
+ }
31
+ // Fetch sources
32
+ const sources = await fetchSources(request, webFetcher, defaultTimeout);
33
+ // Calculate warnings
34
+ const warnings = [];
35
+ // INV-RSH-003: Check for stale data
36
+ if (sources.length > 0) {
37
+ const tempResult = {
38
+ resultId,
39
+ query: request.query,
40
+ sources,
41
+ synthesis: '',
42
+ codeExamples: [],
43
+ confidence: 0,
44
+ warnings: [],
45
+ durationMs: 0,
46
+ completedAt: new Date().toISOString(),
47
+ };
48
+ if (hasStaleDataWarning(tempResult)) {
49
+ warnings.push('Some sources may contain outdated information (>24 hours old)');
50
+ }
51
+ }
52
+ // Detect conflicts
53
+ // INV-RSH-202: Note conflicting information
54
+ const conflicts = detectConflicts(sources);
55
+ warnings.push(...conflicts);
56
+ // Synthesize results
57
+ let synthesis = '';
58
+ if (request.synthesize && sources.length > 0) {
59
+ synthesis = await synthesizer.synthesize({
60
+ query: request.query,
61
+ sources,
62
+ style: 'detailed',
63
+ includeCode: request.includeCode,
64
+ maxLength: 10000,
65
+ });
66
+ }
67
+ // INV-RSH-002: Calculate confidence based on source reliability
68
+ const confidence = calculateConfidence(sources);
69
+ const result = {
70
+ resultId,
71
+ query: request.query,
72
+ sources,
73
+ synthesis,
74
+ codeExamples: extractCodeExamples(sources),
75
+ confidence,
76
+ warnings,
77
+ durationMs: Date.now() - startTime,
78
+ completedAt: new Date().toISOString(),
79
+ };
80
+ // Cache result
81
+ if (cache) {
82
+ const queryHash = hashQuery(request.query);
83
+ await cache.set(queryHash, result, 3600000); // 1 hour TTL
84
+ }
85
+ return result;
86
+ },
87
+ async fetch(request) {
88
+ return webFetcher.fetch(request);
89
+ },
90
+ async synthesize(request) {
91
+ return synthesizer.synthesize(request);
92
+ },
93
+ };
94
+ }
95
+ /**
96
+ * Fetch sources for a research query
97
+ * INV-RSH-102: Failed sources don't block
98
+ */
99
+ async function fetchSources(request, webFetcher, timeout) {
100
+ const sources = [];
101
+ // INV-RSH-100: Enforce timeout
102
+ const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error('Research timeout')), request.timeout ?? timeout));
103
+ try {
104
+ // Search for sources
105
+ const searchResults = await Promise.race([
106
+ webFetcher.search(request.query, request.maxSources),
107
+ timeoutPromise,
108
+ ]);
109
+ sources.push(...searchResults);
110
+ }
111
+ catch (error) {
112
+ // Log but don't fail
113
+ console.warn('[research-agent] Search failed:', error);
114
+ }
115
+ return sources;
116
+ }
117
+ /**
118
+ * Extract code examples from sources
119
+ */
120
+ function extractCodeExamples(sources) {
121
+ const examples = [];
122
+ for (const source of sources) {
123
+ if (source.content) {
124
+ const codeBlockRegex = /```(\w+)?\n([\s\S]*?)```/g;
125
+ let match;
126
+ while ((match = codeBlockRegex.exec(source.content)) !== null) {
127
+ const code = match[2]?.trim();
128
+ if (code && code.length > 10) {
129
+ examples.push({
130
+ code,
131
+ language: match[1] ?? 'text',
132
+ source: source.url,
133
+ tested: false,
134
+ });
135
+ }
136
+ }
137
+ }
138
+ }
139
+ return examples.slice(0, 10); // Limit to 10 examples
140
+ }
141
+ /**
142
+ * Hash a query for caching
143
+ */
144
+ function hashQuery(query) {
145
+ const normalized = query.toLowerCase().trim();
146
+ let hash = 0;
147
+ for (let i = 0; i < normalized.length; i++) {
148
+ const char = normalized.charCodeAt(i);
149
+ hash = (hash << 5) - hash + char;
150
+ hash = hash & hash;
151
+ }
152
+ return Math.abs(hash).toString(36);
153
+ }
154
+ //# sourceMappingURL=research-agent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"research-agent.js","sourceRoot":"","sources":["../src/research-agent.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Synthesizer
3
+ *
4
+ * Combine multiple research sources into a coherent answer.
5
+ *
6
+ * Invariants:
7
+ * - INV-RSH-200: Source attribution included
8
+ * - INV-RSH-201: Code examples attributed
9
+ * - INV-RSH-202: Conflicting information noted
10
+ * - INV-RSH-203: No hallucinated URLs
11
+ */
12
+ import type { ResearchSource } from '@defai.digital/contracts';
13
+ import type { SynthesizerPort } from './types.js';
14
+ /**
15
+ * Create a stub synthesizer
16
+ */
17
+ export declare function createStubSynthesizer(): SynthesizerPort;
18
+ /**
19
+ * Detect conflicting information between sources
20
+ * INV-RSH-202: Conflicting information noted
21
+ */
22
+ export declare function detectConflicts(sources: ResearchSource[]): string[];
23
+ /**
24
+ * Validate all URLs in synthesis come from sources
25
+ * INV-RSH-203: No hallucinated URLs
26
+ */
27
+ export declare function validateUrls(synthesis: string, sources: ResearchSource[]): boolean;
28
+ //# sourceMappingURL=synthesizer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"synthesizer.d.ts","sourceRoot":"","sources":["../src/synthesizer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAEV,cAAc,EAEf,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,eAAe,CAYvD;AAwGD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,cAAc,EAAE,GAAG,MAAM,EAAE,CA2BnE;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE,GAAG,OAAO,CAwBlF"}
@@ -0,0 +1,159 @@
1
+ /**
2
+ * Synthesizer
3
+ *
4
+ * Combine multiple research sources into a coherent answer.
5
+ *
6
+ * Invariants:
7
+ * - INV-RSH-200: Source attribution included
8
+ * - INV-RSH-201: Code examples attributed
9
+ * - INV-RSH-202: Conflicting information noted
10
+ * - INV-RSH-203: No hallucinated URLs
11
+ */
12
+ /**
13
+ * Create a stub synthesizer
14
+ */
15
+ export function createStubSynthesizer() {
16
+ return {
17
+ async synthesize(request) {
18
+ console.warn('[research-domain] Using stub synthesizer - no AI synthesis. ' +
19
+ 'Inject a real SynthesizerPort for production use.');
20
+ // Create a simple concatenation-based synthesis
21
+ return createSimpleSynthesis(request);
22
+ },
23
+ };
24
+ }
25
+ /**
26
+ * Create a simple template-based synthesis
27
+ * Used as fallback when no AI synthesizer is available
28
+ */
29
+ function createSimpleSynthesis(request) {
30
+ const { query, sources, includeCode } = request;
31
+ const lines = [];
32
+ lines.push(`# Research: ${query}\n`);
33
+ // Summary section
34
+ lines.push('## Summary\n');
35
+ lines.push(`Based on ${sources.length} source(s):\n`);
36
+ // Source summaries
37
+ for (const source of sources) {
38
+ const reliability = formatReliability(source.reliability);
39
+ lines.push(`### ${source.title} ${reliability}`);
40
+ lines.push(`*Source: ${source.url}*\n`);
41
+ lines.push(truncateText(source.snippet, 500));
42
+ lines.push('');
43
+ }
44
+ // Code examples
45
+ if (includeCode) {
46
+ const allCode = collectCodeExamples(sources);
47
+ if (allCode.length > 0) {
48
+ lines.push('\n## Code Examples\n');
49
+ for (const example of allCode.slice(0, 5)) {
50
+ lines.push(`\`\`\`${example.language}`);
51
+ lines.push(example.code);
52
+ lines.push('```');
53
+ if (example.source) {
54
+ lines.push(`*Source: ${example.source}*`);
55
+ }
56
+ lines.push('');
57
+ }
58
+ }
59
+ }
60
+ // References
61
+ lines.push('\n## References\n');
62
+ for (let i = 0; i < sources.length; i++) {
63
+ lines.push(`${i + 1}. [${sources[i].title}](${sources[i].url})`);
64
+ }
65
+ return lines.join('\n');
66
+ }
67
+ /**
68
+ * Format reliability badge
69
+ */
70
+ function formatReliability(reliability) {
71
+ switch (reliability) {
72
+ case 'official':
73
+ return '[Official]';
74
+ case 'community':
75
+ return '[Community]';
76
+ case 'generated':
77
+ return '[AI Generated]';
78
+ default:
79
+ return '';
80
+ }
81
+ }
82
+ /**
83
+ * Truncate text to max length
84
+ */
85
+ function truncateText(text, maxLength) {
86
+ if (text.length <= maxLength) {
87
+ return text;
88
+ }
89
+ return text.slice(0, maxLength - 3) + '...';
90
+ }
91
+ /**
92
+ * Collect code examples from all sources
93
+ * INV-RSH-201: Code examples attributed
94
+ */
95
+ function collectCodeExamples(sources) {
96
+ const examples = [];
97
+ for (const source of sources) {
98
+ if (source.content) {
99
+ // Extract code blocks from content
100
+ const codeBlockRegex = /```(\w+)?\n([\s\S]*?)```/g;
101
+ let match;
102
+ while ((match = codeBlockRegex.exec(source.content)) !== null) {
103
+ examples.push({
104
+ code: match[2]?.trim() ?? '',
105
+ language: match[1] ?? 'text',
106
+ source: source.url,
107
+ tested: false,
108
+ });
109
+ }
110
+ }
111
+ }
112
+ return examples;
113
+ }
114
+ /**
115
+ * Detect conflicting information between sources
116
+ * INV-RSH-202: Conflicting information noted
117
+ */
118
+ export function detectConflicts(sources) {
119
+ const conflicts = [];
120
+ // Simple heuristic: check for contradictory keywords
121
+ const contradictoryPairs = [
122
+ ['deprecated', 'recommended'],
123
+ ['avoid', 'best practice'],
124
+ ['not recommended', 'should use'],
125
+ ['legacy', 'modern'],
126
+ ];
127
+ for (const [word1, word2] of contradictoryPairs) {
128
+ const hasWord1 = sources.some((s) => s.snippet.toLowerCase().includes(word1));
129
+ const hasWord2 = sources.some((s) => s.snippet.toLowerCase().includes(word2));
130
+ if (hasWord1 && hasWord2) {
131
+ conflicts.push(`Sources have conflicting views: some mention "${word1}" while others suggest "${word2}"`);
132
+ }
133
+ }
134
+ return conflicts;
135
+ }
136
+ /**
137
+ * Validate all URLs in synthesis come from sources
138
+ * INV-RSH-203: No hallucinated URLs
139
+ */
140
+ export function validateUrls(synthesis, sources) {
141
+ const urlRegex = /https?:\/\/[^\s\)]+/g;
142
+ const urls = synthesis.match(urlRegex) ?? [];
143
+ const sourceUrls = new Set(sources.map((s) => s.url));
144
+ for (const url of urls) {
145
+ // Allow URLs that are from our sources
146
+ if (sourceUrls.has(url)) {
147
+ continue;
148
+ }
149
+ // Allow URLs that are subpaths of source URLs
150
+ const isSubpath = Array.from(sourceUrls).some((sourceUrl) => url.startsWith(sourceUrl.replace(/\/$/, '')));
151
+ if (isSubpath) {
152
+ continue;
153
+ }
154
+ // URL not from sources - this is a hallucination
155
+ return false;
156
+ }
157
+ return true;
158
+ }
159
+ //# sourceMappingURL=synthesizer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"synthesizer.js","sourceRoot":"","sources":["../src/synthesizer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Research Domain Types
3
+ *
4
+ * Port interfaces for the research agent.
5
+ */
6
+ import type { ResearchRequest, ResearchResult, ResearchSource, FetchRequest, FetchResponse, SynthesisRequest } from '@defai.digital/contracts';
7
+ /**
8
+ * Port for fetching web content
9
+ */
10
+ export interface WebFetcherPort {
11
+ /**
12
+ * Fetch content from a URL
13
+ */
14
+ fetch(request: FetchRequest): Promise<FetchResponse>;
15
+ /**
16
+ * Search the web for a query
17
+ */
18
+ search(query: string, maxResults: number): Promise<ResearchSource[]>;
19
+ }
20
+ /**
21
+ * Port for synthesizing research results
22
+ */
23
+ export interface SynthesizerPort {
24
+ /**
25
+ * Synthesize sources into a coherent answer
26
+ */
27
+ synthesize(request: SynthesisRequest): Promise<string>;
28
+ }
29
+ /**
30
+ * Port for caching research results
31
+ */
32
+ export interface ResearchCachePort {
33
+ /**
34
+ * Get cached result for query
35
+ */
36
+ get(queryHash: string): Promise<ResearchResult | null>;
37
+ /**
38
+ * Cache a result
39
+ */
40
+ set(queryHash: string, result: ResearchResult, ttlMs: number): Promise<void>;
41
+ /**
42
+ * Invalidate cache entry
43
+ */
44
+ invalidate(queryHash: string): Promise<void>;
45
+ }
46
+ /**
47
+ * Research agent options
48
+ */
49
+ export interface ResearchAgentOptions {
50
+ /**
51
+ * Web fetcher port
52
+ */
53
+ webFetcher: WebFetcherPort;
54
+ /**
55
+ * Synthesizer port
56
+ */
57
+ synthesizer: SynthesizerPort;
58
+ /**
59
+ * Optional cache port
60
+ */
61
+ cache?: ResearchCachePort;
62
+ /**
63
+ * Default timeout for operations
64
+ */
65
+ defaultTimeout?: number;
66
+ /**
67
+ * Maximum concurrent fetches
68
+ * INV-RSH-101: Limited to 5
69
+ */
70
+ maxConcurrentFetches?: number;
71
+ }
72
+ /**
73
+ * Research agent interface
74
+ */
75
+ export interface ResearchAgent {
76
+ /**
77
+ * Execute a research query
78
+ */
79
+ research(request: ResearchRequest): Promise<ResearchResult>;
80
+ /**
81
+ * Fetch a single URL
82
+ */
83
+ fetch(request: FetchRequest): Promise<FetchResponse>;
84
+ /**
85
+ * Synthesize existing sources
86
+ */
87
+ synthesize(request: SynthesisRequest): Promise<string>;
88
+ }
89
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EACV,eAAe,EACf,cAAc,EACd,cAAc,EACd,YAAY,EACZ,aAAa,EACb,gBAAgB,EACjB,MAAM,0BAA0B,CAAC;AAElC;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B;;OAEG;IACH,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IAErD;;OAEG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;CACtE;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B;;OAEG;IACH,UAAU,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACxD;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC;;OAEG;IACH,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IAEvD;;OAEG;IACH,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE7E;;OAEG;IACH,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9C;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC;;OAEG;IACH,UAAU,EAAE,cAAc,CAAC;IAE3B;;OAEG;IACH,WAAW,EAAE,eAAe,CAAC;IAE7B;;OAEG;IACH,KAAK,CAAC,EAAE,iBAAiB,CAAC;IAE1B;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;;OAGG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B;;OAEG;IACH,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IAE5D;;OAEG;IACH,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IAErD;;OAEG;IACH,UAAU,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACxD"}
package/dist/types.js ADDED
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Research Domain Types
3
+ *
4
+ * Port interfaces for the research agent.
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Web Fetcher
3
+ *
4
+ * Fetch and parse web content for research.
5
+ *
6
+ * Invariants:
7
+ * - INV-RSH-100: Timeout enforced
8
+ * - INV-RSH-101: Concurrent fetches limited
9
+ * - INV-RSH-102: Failed sources don't block
10
+ */
11
+ import type { WebFetcherPort } from './types.js';
12
+ /**
13
+ * Create a stub web fetcher
14
+ */
15
+ export declare function createStubWebFetcher(): WebFetcherPort;
16
+ /**
17
+ * Create a web fetcher with rate limiting
18
+ */
19
+ export declare function createWebFetcher(options: {
20
+ maxConcurrent?: number;
21
+ defaultTimeout?: number;
22
+ userAgent?: string;
23
+ }): WebFetcherPort;
24
+ //# sourceMappingURL=web-fetcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web-fetcher.d.ts","sourceRoot":"","sources":["../src/web-fetcher.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AASH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAsCjD;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,cAAc,CA4BrD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE;IACxC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,cAAc,CAkFjB"}