@zhixuan92/multi-model-agent-core 3.11.0 → 3.12.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 (157) hide show
  1. package/README.md +3 -3
  2. package/dist/config/read-only-review-flag.d.ts +1 -1
  3. package/dist/config/read-only-review-flag.d.ts.map +1 -1
  4. package/dist/config/read-only-review-flag.js +1 -0
  5. package/dist/config/read-only-review-flag.js.map +1 -1
  6. package/dist/config/schema.d.ts +47 -0
  7. package/dist/config/schema.d.ts.map +1 -1
  8. package/dist/config/schema.js +102 -0
  9. package/dist/config/schema.js.map +1 -1
  10. package/dist/delegate-with-escalation.d.ts.map +1 -1
  11. package/dist/delegate-with-escalation.js +1 -0
  12. package/dist/delegate-with-escalation.js.map +1 -1
  13. package/dist/escalation/fallback.d.ts +2 -0
  14. package/dist/escalation/fallback.d.ts.map +1 -1
  15. package/dist/escalation/fallback.js +26 -0
  16. package/dist/escalation/fallback.js.map +1 -1
  17. package/dist/executors/audit.js +2 -2
  18. package/dist/executors/audit.js.map +1 -1
  19. package/dist/executors/debug.js +1 -1
  20. package/dist/executors/debug.js.map +1 -1
  21. package/dist/executors/delegate.d.ts.map +1 -1
  22. package/dist/executors/delegate.js +1 -0
  23. package/dist/executors/delegate.js.map +1 -1
  24. package/dist/executors/execute-plan.js +2 -2
  25. package/dist/executors/execute-plan.js.map +1 -1
  26. package/dist/executors/explore.d.ts +13 -0
  27. package/dist/executors/explore.d.ts.map +1 -0
  28. package/dist/executors/explore.js +352 -0
  29. package/dist/executors/explore.js.map +1 -0
  30. package/dist/executors/index.d.ts +1 -0
  31. package/dist/executors/index.d.ts.map +1 -1
  32. package/dist/executors/index.js +1 -0
  33. package/dist/executors/index.js.map +1 -1
  34. package/dist/executors/retry.d.ts.map +1 -1
  35. package/dist/executors/retry.js +1 -0
  36. package/dist/executors/retry.js.map +1 -1
  37. package/dist/executors/review.d.ts.map +1 -1
  38. package/dist/executors/review.js +1 -0
  39. package/dist/executors/review.js.map +1 -1
  40. package/dist/executors/verify.js +2 -2
  41. package/dist/executors/verify.js.map +1 -1
  42. package/dist/intake/compilers/explore.d.ts +29 -0
  43. package/dist/intake/compilers/explore.d.ts.map +1 -0
  44. package/dist/intake/compilers/explore.js +108 -0
  45. package/dist/intake/compilers/explore.js.map +1 -0
  46. package/dist/observability/events.d.ts +96 -4
  47. package/dist/observability/events.d.ts.map +1 -1
  48. package/dist/observability/events.js +49 -0
  49. package/dist/observability/events.js.map +1 -1
  50. package/dist/provider.d.ts.map +1 -1
  51. package/dist/provider.js +1 -0
  52. package/dist/provider.js.map +1 -1
  53. package/dist/reporting/compose-explore-headline.d.ts +14 -0
  54. package/dist/reporting/compose-explore-headline.d.ts.map +1 -0
  55. package/dist/reporting/compose-explore-headline.js +14 -0
  56. package/dist/reporting/compose-explore-headline.js.map +1 -0
  57. package/dist/reporting/derive-explore-status.d.ts +18 -0
  58. package/dist/reporting/derive-explore-status.d.ts.map +1 -0
  59. package/dist/reporting/derive-explore-status.js +19 -0
  60. package/dist/reporting/derive-explore-status.js.map +1 -0
  61. package/dist/reporting/parse-explore-report.d.ts +38 -0
  62. package/dist/reporting/parse-explore-report.d.ts.map +1 -0
  63. package/dist/reporting/parse-explore-report.js +185 -0
  64. package/dist/reporting/parse-explore-report.js.map +1 -0
  65. package/dist/research/adapters/arxiv.d.ts +6 -0
  66. package/dist/research/adapters/arxiv.d.ts.map +1 -0
  67. package/dist/research/adapters/arxiv.js +36 -0
  68. package/dist/research/adapters/arxiv.js.map +1 -0
  69. package/dist/research/adapters/generic-rss.d.ts +8 -0
  70. package/dist/research/adapters/generic-rss.d.ts.map +1 -0
  71. package/dist/research/adapters/generic-rss.js +26 -0
  72. package/dist/research/adapters/generic-rss.js.map +1 -0
  73. package/dist/research/adapters/github-search.d.ts +7 -0
  74. package/dist/research/adapters/github-search.d.ts.map +1 -0
  75. package/dist/research/adapters/github-search.js +95 -0
  76. package/dist/research/adapters/github-search.js.map +1 -0
  77. package/dist/research/adapters/index.d.ts +8 -0
  78. package/dist/research/adapters/index.d.ts.map +1 -0
  79. package/dist/research/adapters/index.js +17 -0
  80. package/dist/research/adapters/index.js.map +1 -0
  81. package/dist/research/adapters/semantic-scholar.d.ts +6 -0
  82. package/dist/research/adapters/semantic-scholar.d.ts.map +1 -0
  83. package/dist/research/adapters/semantic-scholar.js +54 -0
  84. package/dist/research/adapters/semantic-scholar.js.map +1 -0
  85. package/dist/research/adapters/types.d.ts +15 -0
  86. package/dist/research/adapters/types.d.ts.map +1 -0
  87. package/dist/research/adapters/types.js +2 -0
  88. package/dist/research/adapters/types.js.map +1 -0
  89. package/dist/research/allowlist.d.ts +25 -0
  90. package/dist/research/allowlist.d.ts.map +1 -0
  91. package/dist/research/allowlist.js +102 -0
  92. package/dist/research/allowlist.js.map +1 -0
  93. package/dist/research/ssrf-guard.d.ts +12 -0
  94. package/dist/research/ssrf-guard.d.ts.map +1 -0
  95. package/dist/research/ssrf-guard.js +209 -0
  96. package/dist/research/ssrf-guard.js.map +1 -0
  97. package/dist/research/types.d.ts +14 -0
  98. package/dist/research/types.d.ts.map +1 -0
  99. package/dist/research/types.js +2 -0
  100. package/dist/research/types.js.map +1 -0
  101. package/dist/research/untrusted-content.d.ts +13 -0
  102. package/dist/research/untrusted-content.d.ts.map +1 -0
  103. package/dist/research/untrusted-content.js +9 -0
  104. package/dist/research/untrusted-content.js.map +1 -0
  105. package/dist/research/web-fetch.d.ts +50 -0
  106. package/dist/research/web-fetch.d.ts.map +1 -0
  107. package/dist/research/web-fetch.js +411 -0
  108. package/dist/research/web-fetch.js.map +1 -0
  109. package/dist/research/web-search.d.ts +28 -0
  110. package/dist/research/web-search.d.ts.map +1 -0
  111. package/dist/research/web-search.js +134 -0
  112. package/dist/research/web-search.js.map +1 -0
  113. package/dist/review/diff-review.d.ts +1 -1
  114. package/dist/review/diff-review.d.ts.map +1 -1
  115. package/dist/review/quality-reviewer.d.ts +1 -1
  116. package/dist/review/quality-reviewer.d.ts.map +1 -1
  117. package/dist/review/quality-reviewer.js +15 -3
  118. package/dist/review/quality-reviewer.js.map +1 -1
  119. package/dist/run-tasks/execute-task.d.ts.map +1 -1
  120. package/dist/run-tasks/execute-task.js +1 -0
  121. package/dist/run-tasks/execute-task.js.map +1 -1
  122. package/dist/run-tasks/index.d.ts.map +1 -1
  123. package/dist/run-tasks/index.js +1 -0
  124. package/dist/run-tasks/index.js.map +1 -1
  125. package/dist/run-tasks/reviewed-lifecycle.d.ts.map +1 -1
  126. package/dist/run-tasks/reviewed-lifecycle.js +50 -5
  127. package/dist/run-tasks/reviewed-lifecycle.js.map +1 -1
  128. package/dist/runners/base/research-tools.d.ts +47 -0
  129. package/dist/runners/base/research-tools.d.ts.map +1 -0
  130. package/dist/runners/base/research-tools.js +67 -0
  131. package/dist/runners/base/research-tools.js.map +1 -0
  132. package/dist/runners/base/result-builders.d.ts.map +1 -1
  133. package/dist/runners/base/result-builders.js +5 -0
  134. package/dist/runners/base/result-builders.js.map +1 -1
  135. package/dist/runners/claude-runner.d.ts.map +1 -1
  136. package/dist/runners/claude-runner.js +39 -6
  137. package/dist/runners/claude-runner.js.map +1 -1
  138. package/dist/runners/codex-runner.d.ts.map +1 -1
  139. package/dist/runners/codex-runner.js +28 -0
  140. package/dist/runners/codex-runner.js.map +1 -1
  141. package/dist/runners/openai-runner.d.ts.map +1 -1
  142. package/dist/runners/openai-runner.js +79 -2
  143. package/dist/runners/openai-runner.js.map +1 -1
  144. package/dist/runners/types.d.ts +9 -0
  145. package/dist/runners/types.d.ts.map +1 -1
  146. package/dist/telemetry/event-builder.d.ts.map +1 -1
  147. package/dist/telemetry/event-builder.js +5 -2
  148. package/dist/telemetry/event-builder.js.map +1 -1
  149. package/dist/telemetry/types.d.ts +3 -3
  150. package/dist/tool-schemas/explore.d.ts +9 -0
  151. package/dist/tool-schemas/explore.d.ts.map +1 -0
  152. package/dist/tool-schemas/explore.js +64 -0
  153. package/dist/tool-schemas/explore.js.map +1 -0
  154. package/dist/types.d.ts +38 -0
  155. package/dist/types.d.ts.map +1 -1
  156. package/dist/types.js.map +1 -1
  157. package/package.json +16 -1
@@ -0,0 +1,54 @@
1
+ import { request } from 'undici';
2
+ function normalizeRecord(r) {
3
+ const paperId = typeof r.paperId === 'string' && r.paperId.length > 0 ? r.paperId : null;
4
+ const title = typeof r.title === 'string' ? r.title.trim() : '';
5
+ if (!paperId || !title)
6
+ return null;
7
+ const abstract = typeof r.abstract === 'string' ? r.abstract : '';
8
+ const apiUrl = typeof r.url === 'string' && r.url.length > 0 ? r.url : null;
9
+ const year = typeof r.year === 'number' && Number.isFinite(r.year) && r.year > 1900 ? r.year : null;
10
+ return {
11
+ adapterId: 'semantic_scholar',
12
+ recordId: paperId,
13
+ title,
14
+ url: apiUrl ?? `https://www.semanticscholar.org/paper/${paperId}`,
15
+ snippet: abstract.slice(0, 500),
16
+ publishedAt: year ? `${year}-01-01` : undefined,
17
+ raw: r,
18
+ };
19
+ }
20
+ export async function semanticScholarSearch(query, opts = {}) {
21
+ const max = Math.min(25, Math.max(1, opts.maxResults ?? 10));
22
+ const url = new URL('https://api.semanticscholar.org/graph/v1/paper/search');
23
+ url.searchParams.set('query', query);
24
+ url.searchParams.set('limit', String(max));
25
+ url.searchParams.set('fields', 'paperId,title,abstract,year,authors,url');
26
+ let res;
27
+ try {
28
+ res = await request(url.toString(), { method: 'GET' });
29
+ }
30
+ catch (err) {
31
+ throw new Error(`semantic_scholar_request_failed: ${err.message}`);
32
+ }
33
+ if (res.statusCode === 429)
34
+ throw new Error('semantic_scholar_rate_limited');
35
+ if (res.statusCode >= 300 && res.statusCode < 400)
36
+ throw new Error('adapter_unexpected_redirect: semantic_scholar');
37
+ if (res.statusCode !== 200)
38
+ throw new Error(`semantic_scholar_http_${res.statusCode}`);
39
+ let body;
40
+ try {
41
+ body = await res.body.json();
42
+ }
43
+ catch (err) {
44
+ throw new Error(`semantic_scholar_parse_error: ${err.message}`);
45
+ }
46
+ const data = Array.isArray(body?.data)
47
+ ? body.data
48
+ : [];
49
+ return data
50
+ .slice(0, max)
51
+ .map(normalizeRecord)
52
+ .filter((r) => r !== null);
53
+ }
54
+ //# sourceMappingURL=semantic-scholar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"semantic-scholar.js","sourceRoot":"","sources":["../../../src/research/adapters/semantic-scholar.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ export type AdapterId = 'arxiv' | 'semantic_scholar' | 'github_search' | 'rss';
2
+ export interface AdapterResult {
3
+ adapterId: AdapterId;
4
+ recordId: string;
5
+ title: string;
6
+ url: string;
7
+ snippet: string;
8
+ publishedAt?: string;
9
+ raw: unknown;
10
+ }
11
+ export interface AdapterCallContext {
12
+ abortSignal: AbortSignal;
13
+ hostAllowlist?: ReadonlySet<string>;
14
+ }
15
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/research/adapters/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,kBAAkB,GAAG,eAAe,GAAG,KAAK,CAAC;AAE/E,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,SAAS,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,EAAE,OAAO,CAAC;CACd;AAED,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,WAAW,CAAC;IAEzB,aAAa,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CACrC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/research/adapters/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,25 @@
1
+ export declare function extractURLHosts(strings: readonly string[]): string[];
2
+ export interface AllowlistInput {
3
+ fetchAllowlistExtra: readonly string[];
4
+ userSources: readonly string[];
5
+ }
6
+ export type AllowlistProvenance = 'extra' | 'user_source';
7
+ export type HostAllowlist = ReadonlyMap<string, AllowlistProvenance>;
8
+ /**
9
+ * Build the per-task fetch allowlist as a provenance-aware map. Per spec
10
+ * §6.2 / §7.1 step 8, the private-network opt-in is gated on
11
+ * `provenance === 'extra'` — only operator-declared hosts in
12
+ * `fetchAllowlistExtra` are eligible, never hosts harvested from
13
+ * `userSources`. Build order: userSources first (lower precedence), then
14
+ * fetchAllowlistExtra overwrites — so collisions resolve to the operator's
15
+ * deliberate intent.
16
+ *
17
+ * Both sources are validated through canonicalizeHostname; invalid entries
18
+ * (IP literals, single-label names, malformed hostnames, overlong hosts)
19
+ * are silently skipped. This mirrors ResearchConfigSchema's HostString
20
+ * canonicalization as defense-in-depth for callers that have not parsed
21
+ * configuration first; silent skipping preserves URL-extraction behavior
22
+ * for untrusted userSources while keeping this builder non-throwing.
23
+ */
24
+ export declare function buildHostAllowlist(input: AllowlistInput): HostAllowlist;
25
+ //# sourceMappingURL=allowlist.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"allowlist.d.ts","sourceRoot":"","sources":["../../src/research/allowlist.ts"],"names":[],"mappings":"AAyCA,wBAAgB,eAAe,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE,CAsBpE;AAED,MAAM,WAAW,cAAc;IAC7B,mBAAmB,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;CAChC;AAED,MAAM,MAAM,mBAAmB,GAAG,OAAO,GAAG,aAAa,CAAC;AAC1D,MAAM,MAAM,aAAa,GAAG,WAAW,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;AAErE;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,cAAc,GAAG,aAAa,CAYvE"}
@@ -0,0 +1,102 @@
1
+ import { isIP } from 'node:net';
2
+ const URL_REGEX = /\bhttps?:\/\/[^\s'"<>()]+/gi;
3
+ const FORBIDDEN_HOST_CHARS = /[\/:@?#]|:\/\//;
4
+ const MAX_HOSTNAME_LENGTH = 253;
5
+ const TRAILING_URL_PUNCTUATION = /[.,;:!?]+$/;
6
+ /**
7
+ * Validate and canonicalize a hostname string. Returns the canonical
8
+ * (lowercase, IDNA-encoded) form or null if the input is not a valid
9
+ * DNS FQDN. Mirrors the HostString rules in config/schema.ts as a
10
+ * defense-in-depth layer: even though ResearchConfigSchema already
11
+ * validates fetchAllowlistExtra via HostString, this function ensures
12
+ * that any caller of buildHostAllowlist — including callers that bypass
13
+ * schema parsing — cannot inject non-FQDN entries with "extra" provenance.
14
+ */
15
+ function canonicalizeHostname(raw) {
16
+ const trimmed = raw.trim();
17
+ if (trimmed.length === 0 || trimmed.length > MAX_HOSTNAME_LENGTH)
18
+ return null;
19
+ if (FORBIDDEN_HOST_CHARS.test(trimmed))
20
+ return null;
21
+ // Strip trailing dot (DNS root label) — example.com. ≡ example.com
22
+ const stripped = trimmed.endsWith('.') ? trimmed.slice(0, -1) : trimmed;
23
+ if (stripped.length === 0 || stripped.length > MAX_HOSTNAME_LENGTH)
24
+ return null;
25
+ let canonical;
26
+ try {
27
+ canonical = new URL(`https://${stripped}`).hostname;
28
+ }
29
+ catch {
30
+ return null;
31
+ }
32
+ if (canonical.length === 0 || canonical.length > MAX_HOSTNAME_LENGTH)
33
+ return null;
34
+ if (isIP(canonical) !== 0)
35
+ return null;
36
+ const labels = canonical.split('.');
37
+ if (labels.length < 2)
38
+ return null;
39
+ for (const label of labels) {
40
+ if (label.length === 0 || label.length > 63)
41
+ return null;
42
+ if (label.startsWith('-') || label.endsWith('-'))
43
+ return null;
44
+ }
45
+ return canonical;
46
+ }
47
+ export function extractURLHosts(strings) {
48
+ const out = [];
49
+ const seen = new Set();
50
+ for (const s of strings) {
51
+ const matches = s.match(URL_REGEX) ?? [];
52
+ for (const m of matches) {
53
+ try {
54
+ const candidate = m.replace(TRAILING_URL_PUNCTUATION, '');
55
+ const u = new URL(candidate);
56
+ if (!u.hostname)
57
+ continue;
58
+ const canonical = canonicalizeHostname(u.hostname);
59
+ if (canonical === null)
60
+ continue;
61
+ if (!seen.has(canonical)) {
62
+ seen.add(canonical);
63
+ out.push(canonical);
64
+ }
65
+ }
66
+ catch {
67
+ // malformed URL — silently skip
68
+ }
69
+ }
70
+ }
71
+ return out;
72
+ }
73
+ /**
74
+ * Build the per-task fetch allowlist as a provenance-aware map. Per spec
75
+ * §6.2 / §7.1 step 8, the private-network opt-in is gated on
76
+ * `provenance === 'extra'` — only operator-declared hosts in
77
+ * `fetchAllowlistExtra` are eligible, never hosts harvested from
78
+ * `userSources`. Build order: userSources first (lower precedence), then
79
+ * fetchAllowlistExtra overwrites — so collisions resolve to the operator's
80
+ * deliberate intent.
81
+ *
82
+ * Both sources are validated through canonicalizeHostname; invalid entries
83
+ * (IP literals, single-label names, malformed hostnames, overlong hosts)
84
+ * are silently skipped. This mirrors ResearchConfigSchema's HostString
85
+ * canonicalization as defense-in-depth for callers that have not parsed
86
+ * configuration first; silent skipping preserves URL-extraction behavior
87
+ * for untrusted userSources while keeping this builder non-throwing.
88
+ */
89
+ export function buildHostAllowlist(input) {
90
+ const map = new Map();
91
+ for (const h of extractURLHosts(input.userSources)) {
92
+ map.set(h, 'user_source');
93
+ }
94
+ for (const h of input.fetchAllowlistExtra) {
95
+ const canonical = canonicalizeHostname(h);
96
+ if (canonical !== null) {
97
+ map.set(canonical, 'extra');
98
+ }
99
+ }
100
+ return map;
101
+ }
102
+ //# sourceMappingURL=allowlist.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"allowlist.js","sourceRoot":"","sources":["../../src/research/allowlist.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ export type IPClass = 'public' | 'loopback' | 'private' | 'link-local-or-metadata' | 'unspecified' | 'multicast' | 'broadcast-or-reserved';
2
+ export declare class SsrfBlocked extends Error {
3
+ readonly code: string;
4
+ constructor(code: string, message: string);
5
+ }
6
+ export declare function classifyIP(ip: string): IPClass;
7
+ export interface ResolveOptions {
8
+ resolve?: (host: string) => Promise<string[]>;
9
+ allowPrivateForHost: boolean;
10
+ }
11
+ export declare function resolveAndPin(host: string, options: ResolveOptions): Promise<string>;
12
+ //# sourceMappingURL=ssrf-guard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ssrf-guard.d.ts","sourceRoot":"","sources":["../../src/research/ssrf-guard.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,OAAO,GACf,QAAQ,GACR,UAAU,GACV,SAAS,GACT,wBAAwB,GACxB,aAAa,GACb,WAAW,GACX,uBAAuB,CAAC;AAE5B,qBAAa,WAAY,SAAQ,KAAK;aACR,IAAI,EAAE,MAAM;gBAAZ,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;CAI1D;AA8DD,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAyD9C;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC9C,mBAAmB,EAAE,OAAO,CAAC;CAC9B;AA+CD,wBAAsB,aAAa,CACjC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,MAAM,CAAC,CAyCjB"}
@@ -0,0 +1,209 @@
1
+ import { isIP } from 'node:net';
2
+ import { promises as dns } from 'node:dns';
3
+ export class SsrfBlocked extends Error {
4
+ code;
5
+ constructor(code, message) {
6
+ super(message);
7
+ this.code = code;
8
+ this.name = 'SsrfBlocked';
9
+ }
10
+ }
11
+ function ipv4ToInt(ip) {
12
+ const parts = ip.split('.').map(Number);
13
+ if (parts.length !== 4 || parts.some(p => Number.isNaN(p) || p < 0 || p > 255))
14
+ return null;
15
+ return ((parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8) | parts[3]) >>> 0;
16
+ }
17
+ const inRange = (n, base, mask) => {
18
+ const b = ipv4ToInt(base);
19
+ if (b === null)
20
+ return false;
21
+ const m = mask === 0 ? 0 : (~0 << (32 - mask)) >>> 0;
22
+ return (n & m) === (b & m);
23
+ };
24
+ const IPV4_SPECIAL_RANGES = [
25
+ ['0.0.0.0', 8, 'unspecified'],
26
+ ['127.0.0.0', 8, 'loopback'],
27
+ ['10.0.0.0', 8, 'private'],
28
+ ['172.16.0.0', 12, 'private'],
29
+ ['192.168.0.0', 16, 'private'],
30
+ ['100.64.0.0', 10, 'private'], // RFC 6598 CGNAT; opt-in allowable with private hosts.
31
+ ['169.254.0.0', 16, 'link-local-or-metadata'],
32
+ // IANA IPv4 special-purpose ranges that are not normal public internet destinations.
33
+ ['192.0.0.0', 24, 'broadcast-or-reserved'],
34
+ ['192.0.2.0', 24, 'broadcast-or-reserved'], // TEST-NET-1
35
+ ['198.18.0.0', 15, 'broadcast-or-reserved'], // benchmarking
36
+ ['198.51.100.0', 24, 'broadcast-or-reserved'], // TEST-NET-2
37
+ ['203.0.113.0', 24, 'broadcast-or-reserved'], // TEST-NET-3
38
+ ['224.0.0.0', 4, 'multicast'],
39
+ ['240.0.0.0', 4, 'broadcast-or-reserved'],
40
+ ];
41
+ /**
42
+ * Extract a 32-bit unsigned int from a 4-hex-group region of an expanded IPv6
43
+ * address (used for IPv4-mapped and 6to4 embedded-IPv4 extraction).
44
+ *
45
+ * Returns null on malformed input. The caller stringifies back to dotted-quad
46
+ * via classifyIP, so we don't need pretty formatting here.
47
+ */
48
+ function expandIPv6Groups(addr) {
49
+ // Split on '::' (at most once); pad missing groups with '0'.
50
+ const halves = addr.split('::');
51
+ if (halves.length > 2)
52
+ return null;
53
+ const left = halves[0] ? halves[0].split(':') : [];
54
+ const right = halves.length === 2 && halves[1] ? halves[1].split(':') : [];
55
+ const fill = 8 - (left.length + right.length);
56
+ if (fill < 0)
57
+ return null;
58
+ if (halves.length === 1 && left.length !== 8)
59
+ return null;
60
+ return [...left, ...Array(fill).fill('0'), ...right]
61
+ .map((g) => g.padStart(4, '0').toLowerCase());
62
+ }
63
+ function groupsToIPv4(g, startGroup) {
64
+ if (g.length < startGroup + 2)
65
+ return null;
66
+ const hi = parseInt(g[startGroup], 16);
67
+ const lo = parseInt(g[startGroup + 1], 16);
68
+ if (Number.isNaN(hi) || Number.isNaN(lo))
69
+ return null;
70
+ const a = (hi >> 8) & 0xff, b = hi & 0xff, c = (lo >> 8) & 0xff, d = lo & 0xff;
71
+ return `${a}.${b}.${c}.${d}`;
72
+ }
73
+ export function classifyIP(ip) {
74
+ const lower = ip.toLowerCase();
75
+ // Cloud-metadata ULAs (informal cloud-provider conventions; not IANA-registered)
76
+ // Checked before isIP because these patterns may use non-hex tokens like 'gcp'/'az'.
77
+ if (/^fd00:(ec2|gcp|az):/.test(lower))
78
+ return 'link-local-or-metadata';
79
+ const v = isIP(ip);
80
+ if (v === 4) {
81
+ const n = ipv4ToInt(ip);
82
+ if (n === null)
83
+ return 'broadcast-or-reserved';
84
+ if (n === 0xffffffff)
85
+ return 'broadcast-or-reserved';
86
+ for (const [base, mask, klass] of IPV4_SPECIAL_RANGES) {
87
+ if (inRange(n, base, mask))
88
+ return klass;
89
+ }
90
+ return 'public';
91
+ }
92
+ if (v === 6) {
93
+ if (lower === '::')
94
+ return 'unspecified';
95
+ if (lower === '::1')
96
+ return 'loopback';
97
+ // IPv4-mapped IPv6 (::ffff:a.b.c.d or ::ffff:HEXHEX:HEXHEX) — recurse on embedded IPv4
98
+ const v4mapped = lower.match(/^::ffff:(\d+\.\d+\.\d+\.\d+)$/);
99
+ if (v4mapped)
100
+ return classifyIP(v4mapped[1]);
101
+ const groups = expandIPv6Groups(lower);
102
+ if (groups && groups[0] === '0000' && groups[1] === '0000' && groups[2] === '0000'
103
+ && groups[3] === '0000' && groups[4] === '0000' && groups[5] === 'ffff') {
104
+ const embedded = groupsToIPv4(groups, 6);
105
+ if (embedded)
106
+ return classifyIP(embedded);
107
+ }
108
+ // 6to4 (2002::/16) — embeds IPv4 at bits 16–47 (groups 1 + 2). Recurse.
109
+ if (groups && groups[0] === '2002') {
110
+ const embedded = groupsToIPv4(groups, 1);
111
+ if (embedded)
112
+ return classifyIP(embedded);
113
+ }
114
+ // fe80::/10 link-local (covers fe80–febf when interpreted strictly).
115
+ if (groups && /^fe[89ab]/.test(groups[0]))
116
+ return 'link-local-or-metadata';
117
+ // Locally-assigned ULA (fc00::/8) and randomly-assigned ULA (fd00::/8) → 'private'.
118
+ // The opt-in policy in spec §7.1 step 8 distinguishes these two halves;
119
+ // classifyIP only reports membership in the conditional-reject set.
120
+ if (groups && (groups[0].startsWith('fc') || groups[0].startsWith('fd'))) {
121
+ return 'private';
122
+ }
123
+ if (lower.startsWith('ff'))
124
+ return 'multicast';
125
+ // IANA IPv6 special-purpose ranges that are not normal public internet destinations.
126
+ if (groups && groups[0] === '2001' && groups[1] === '0db8')
127
+ return 'broadcast-or-reserved';
128
+ if (groups && groups[0] === '2001' && /^0[0-1]/.test(groups[1] ?? ''))
129
+ return 'broadcast-or-reserved';
130
+ // Note: `fec0::/10` was a deprecated site-local block (RFC 3879). Modern
131
+ // unicast addresses outside fc00::/7 (e.g. `fec1::1`) are **routable**
132
+ // under current IANA allocations — classify as public, NOT link-local.
133
+ return 'public';
134
+ }
135
+ return 'broadcast-or-reserved';
136
+ }
137
+ const isNoRecordsError = (error) => {
138
+ const code = error?.code;
139
+ return code === 'ENODATA' || code === 'ENOTFOUND' || code === 'ESERVFAIL';
140
+ };
141
+ const defaultResolve = async (host) => {
142
+ const [v4, v6] = await Promise.allSettled([
143
+ dns.resolve4(host),
144
+ dns.resolve6(host),
145
+ ]);
146
+ const results = [];
147
+ if (v4.status === 'fulfilled')
148
+ results.push(...v4.value);
149
+ if (v6.status === 'fulfilled')
150
+ results.push(...v6.value);
151
+ if (results.length > 0)
152
+ return results;
153
+ const failures = [v4, v6].filter((r) => r.status === 'rejected');
154
+ if (failures.length > 0 && failures.some((r) => !isNoRecordsError(r.reason))) {
155
+ throw new Error('DNS resolution failed');
156
+ }
157
+ return results;
158
+ };
159
+ const BLOCKED_CLASSES_STRICT = new Set([
160
+ 'loopback',
161
+ 'private',
162
+ 'link-local-or-metadata',
163
+ 'unspecified',
164
+ 'multicast',
165
+ 'broadcast-or-reserved',
166
+ ]);
167
+ const BLOCKED_CLASSES_PERMISSIVE = new Set([
168
+ 'loopback',
169
+ 'link-local-or-metadata',
170
+ 'unspecified',
171
+ 'multicast',
172
+ 'broadcast-or-reserved',
173
+ ]);
174
+ function isLocallyAssignedULA(ip) {
175
+ if (isIP(ip) !== 6)
176
+ return false;
177
+ const groups = expandIPv6Groups(ip.toLowerCase());
178
+ if (!groups)
179
+ return false;
180
+ return groups[0].startsWith('fc');
181
+ }
182
+ export async function resolveAndPin(host, options) {
183
+ const resolve = options.resolve ?? defaultResolve;
184
+ let ips;
185
+ try {
186
+ ips = await resolve(host);
187
+ }
188
+ catch {
189
+ throw new SsrfBlocked('web_fetch_dns_resolution_failed', `web_fetch_dns_resolution_failed: DNS resolution failed for host '${host}'`);
190
+ }
191
+ if (ips.length === 0) {
192
+ throw new SsrfBlocked('web_fetch_no_addresses', `web_fetch_no_addresses: no addresses resolved for host '${host}'`);
193
+ }
194
+ const blocked = options.allowPrivateForHost
195
+ ? BLOCKED_CLASSES_PERMISSIVE
196
+ : BLOCKED_CLASSES_STRICT;
197
+ for (const ip of ips) {
198
+ const klass = classifyIP(ip);
199
+ if (blocked.has(klass)) {
200
+ throw new SsrfBlocked('web_fetch_private_ip_blocked', `web_fetch_private_ip_blocked: resolved IP class '${klass}' is not allowed for host '${host}'`);
201
+ }
202
+ // fc00::/8 locally-assigned ULA is always-reject, even in permissive mode
203
+ if (isLocallyAssignedULA(ip)) {
204
+ throw new SsrfBlocked('web_fetch_private_ip_blocked', `web_fetch_private_ip_blocked: resolved IP is locally-assigned ULA (fc00::/8), which is never allowed for host '${host}'`);
205
+ }
206
+ }
207
+ return ips[0];
208
+ }
209
+ //# sourceMappingURL=ssrf-guard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ssrf-guard.js","sourceRoot":"","sources":["../../src/research/ssrf-guard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAAE,QAAQ,IAAI,GAAG,EAAE,MAAM,UAAU,CAAC;AAW3C,MAAM,OAAO,WAAY,SAAQ,KAAK;IACR;IAA5B,YAA4B,IAAY,EAAE,OAAe;QACvD,KAAK,CAAC,OAAO,CAAC,CAAC;QADW,SAAI,GAAJ,IAAI,CAAQ;QAEtC,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;IAC5B,CAAC;CACF;AAED,SAAS,SAAS,CAAC,EAAU;IAC3B,MAAM,KAAK,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACxC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAC5F,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;AAClF,CAAC;AAED,MAAM,OAAO,GAAG,CAAC,CAAS,EAAE,IAAY,EAAE,IAAY,EAAW,EAAE;IACjE,MAAM,CAAC,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAC1B,IAAI,CAAC,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAC7B,MAAM,CAAC,GAAG,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC;IACrD,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7B,CAAC,CAAC;AAEF,MAAM,mBAAmB,GAAwD;IAC/E,CAAC,SAAS,EAAE,CAAC,EAAE,aAAa,CAAC;IAC7B,CAAC,WAAW,EAAE,CAAC,EAAE,UAAU,CAAC;IAC5B,CAAC,UAAU,EAAE,CAAC,EAAE,SAAS,CAAC;IAC1B,CAAC,YAAY,EAAE,EAAE,EAAE,SAAS,CAAC;IAC7B,CAAC,aAAa,EAAE,EAAE,EAAE,SAAS,CAAC;IAC9B,CAAC,YAAY,EAAE,EAAE,EAAE,SAAS,CAAC,EAAE,uDAAuD;IACtF,CAAC,aAAa,EAAE,EAAE,EAAE,wBAAwB,CAAC;IAC7C,qFAAqF;IACrF,CAAC,WAAW,EAAE,EAAE,EAAE,uBAAuB,CAAC;IAC1C,CAAC,WAAW,EAAE,EAAE,EAAE,uBAAuB,CAAC,EAAE,aAAa;IACzD,CAAC,YAAY,EAAE,EAAE,EAAE,uBAAuB,CAAC,EAAE,eAAe;IAC5D,CAAC,cAAc,EAAE,EAAE,EAAE,uBAAuB,CAAC,EAAE,aAAa;IAC5D,CAAC,aAAa,EAAE,EAAE,EAAE,uBAAuB,CAAC,EAAE,aAAa;IAC3D,CAAC,WAAW,EAAE,CAAC,EAAE,WAAW,CAAC;IAC7B,CAAC,WAAW,EAAE,CAAC,EAAE,uBAAuB,CAAC;CAC1C,CAAC;AAEF;;;;;;GAMG;AACH,SAAS,gBAAgB,CAAC,IAAY;IACpC,6DAA6D;IAC7D,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAChC,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IACnC,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACnD,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,KAAK,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC3E,MAAM,IAAI,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;IAC9C,IAAI,IAAI,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAC1B,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAC1D,OAAO,CAAC,GAAG,IAAI,EAAE,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,KAAK,CAAC;SACjD,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;AAClD,CAAC;AAED,SAAS,YAAY,CAAC,CAAW,EAAE,UAAkB;IACnD,IAAI,CAAC,CAAC,MAAM,GAAG,UAAU,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAC3C,MAAM,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAE,EAAE,EAAE,CAAC,CAAC;IACxC,MAAM,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,CAAE,EAAE,EAAE,CAAC,CAAC;IAC5C,IAAI,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;QAAE,OAAO,IAAI,CAAC;IACtD,MAAM,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,IAAI,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,IAAI,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;IAC/E,OAAO,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,EAAU;IACnC,MAAM,KAAK,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC;IAE/B,iFAAiF;IACjF,qFAAqF;IACrF,IAAI,qBAAqB,CAAC,IAAI,CAAC,KAAK,CAAC;QAAQ,OAAO,wBAAwB,CAAC;IAE7E,MAAM,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC;IACnB,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACZ,MAAM,CAAC,GAAG,SAAS,CAAC,EAAE,CAAC,CAAC;QACxB,IAAI,CAAC,KAAK,IAAI;YAAE,OAAO,uBAAuB,CAAC;QAC/C,IAAI,CAAC,KAAK,UAAU;YAAE,OAAO,uBAAuB,CAAC;QACrD,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,mBAAmB,EAAE,CAAC;YACtD,IAAI,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC;gBAAE,OAAO,KAAK,CAAC;QAC3C,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACZ,IAAI,KAAK,KAAK,IAAI;YAA2B,OAAO,aAAa,CAAC;QAClE,IAAI,KAAK,KAAK,KAAK;YAA0B,OAAO,UAAU,CAAC;QAE/D,uFAAuF;QACvF,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAC;QAC9D,IAAI,QAAQ;YAAE,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAE,CAAC,CAAC;QAC9C,MAAM,MAAM,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC;QACvC,IAAI,MAAM,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,MAAM,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,MAAM,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,MAAM;eAC3E,MAAM,CAAC,CAAC,CAAC,KAAK,MAAM,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,MAAM,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,CAAC;YAC5E,MAAM,QAAQ,GAAG,YAAY,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YACzC,IAAI,QAAQ;gBAAE,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC;QAC5C,CAAC;QAED,wEAAwE;QACxE,IAAI,MAAM,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,CAAC;YACnC,MAAM,QAAQ,GAAG,YAAY,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YACzC,IAAI,QAAQ;gBAAE,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC;QAC5C,CAAC;QAED,qEAAqE;QACrE,IAAI,MAAM,IAAI,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC;YAAG,OAAO,wBAAwB,CAAC;QAE7E,oFAAoF;QACpF,wEAAwE;QACxE,oEAAoE;QACpE,IAAI,MAAM,IAAI,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,CAAC,CAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;YAC3E,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,IAAI,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC;YAAmB,OAAO,WAAW,CAAC;QAChE,qFAAqF;QACrF,IAAI,MAAM,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,MAAM,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,MAAM;YAAE,OAAO,uBAAuB,CAAC;QAC3F,IAAI,MAAM,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,MAAM,IAAI,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YAAE,OAAO,uBAAuB,CAAC;QACtG,yEAAyE;QACzE,uEAAuE;QACvE,uEAAuE;QACvE,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,OAAO,uBAAuB,CAAC;AACjC,CAAC;AAOD,MAAM,gBAAgB,GAAG,CAAC,KAAc,EAAW,EAAE;IACnD,MAAM,IAAI,GAAI,KAA4B,EAAE,IAAI,CAAC;IACjD,OAAO,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,WAAW,IAAI,IAAI,KAAK,WAAW,CAAC;AAC5E,CAAC,CAAC;AAEF,MAAM,cAAc,GAAG,KAAK,EAAE,IAAY,EAAqB,EAAE;IAC/D,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC;QACxC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC;QAClB,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC;KACnB,CAAC,CAAC;IACH,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,IAAI,EAAE,CAAC,MAAM,KAAK,WAAW;QAAE,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC;IACzD,IAAI,EAAE,CAAC,MAAM,KAAK,WAAW;QAAE,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC;IACzD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,OAAO,CAAC;IACvC,MAAM,QAAQ,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAA8B,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC;IAC7F,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;QAC7E,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAC3C,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC,CAAC;AAEF,MAAM,sBAAsB,GAAG,IAAI,GAAG,CAAU;IAC9C,UAAU;IACV,SAAS;IACT,wBAAwB;IACxB,aAAa;IACb,WAAW;IACX,uBAAuB;CACxB,CAAC,CAAC;AAEH,MAAM,0BAA0B,GAAG,IAAI,GAAG,CAAU;IAClD,UAAU;IACV,wBAAwB;IACxB,aAAa;IACb,WAAW;IACX,uBAAuB;CACxB,CAAC,CAAC;AAEH,SAAS,oBAAoB,CAAC,EAAU;IACtC,IAAI,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACjC,MAAM,MAAM,GAAG,gBAAgB,CAAC,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;IAClD,IAAI,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IAC1B,OAAO,MAAM,CAAC,CAAC,CAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;AACrC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,IAAY,EACZ,OAAuB;IAEvB,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,cAAc,CAAC;IAClD,IAAI,GAAa,CAAC;IAClB,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,WAAW,CACnB,iCAAiC,EACjC,oEAAoE,IAAI,GAAG,CAC5E,CAAC;IACJ,CAAC;IAED,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrB,MAAM,IAAI,WAAW,CACnB,wBAAwB,EACxB,2DAA2D,IAAI,GAAG,CACnE,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAG,OAAO,CAAC,mBAAmB;QACzC,CAAC,CAAC,0BAA0B;QAC5B,CAAC,CAAC,sBAAsB,CAAC;IAE3B,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE,CAAC;QACrB,MAAM,KAAK,GAAG,UAAU,CAAC,EAAE,CAAC,CAAC;QAC7B,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YACvB,MAAM,IAAI,WAAW,CACnB,8BAA8B,EAC9B,oDAAoD,KAAK,8BAA8B,IAAI,GAAG,CAC/F,CAAC;QACJ,CAAC;QACD,0EAA0E;QAC1E,IAAI,oBAAoB,CAAC,EAAE,CAAC,EAAE,CAAC;YAC7B,MAAM,IAAI,WAAW,CACnB,8BAA8B,EAC9B,kHAAkH,IAAI,GAAG,CAC1H,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO,GAAG,CAAC,CAAC,CAAE,CAAC;AACjB,CAAC"}
@@ -0,0 +1,14 @@
1
+ export type { AdapterId, AdapterResult, AdapterCallContext } from './adapters/types.js';
2
+ /**
3
+ * Tool definition shape that runner adapters consume. The explore executor
4
+ * builds an array of these for the external worker (taskIndex=1) and sets
5
+ * them on `TaskSpec.customToolset`. Runner adapters merge with the standard
6
+ * surface when present.
7
+ */
8
+ export interface ResearchToolDefinition {
9
+ name: 'web_search' | 'web_fetch' | 'arxiv' | 'semantic_scholar' | 'github_search' | 'rss';
10
+ description: string;
11
+ inputSchema: unknown;
12
+ invoke(input: unknown): Promise<unknown>;
13
+ }
14
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/research/types.ts"],"names":[],"mappings":"AACA,YAAY,EAAE,SAAS,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAExF;;;;;GAKG;AACH,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,YAAY,GAAG,WAAW,GAAG,OAAO,GAAG,kBAAkB,GAAG,eAAe,GAAG,KAAK,CAAC;IAC1F,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,OAAO,CAAC;IACrB,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC1C"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/research/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,13 @@
1
+ export interface FetchedContent {
2
+ url: string;
3
+ host: string;
4
+ content: string;
5
+ }
6
+ export declare function wrapFetchedContent(c: FetchedContent): string;
7
+ export interface SearchHit {
8
+ title: string;
9
+ url: string;
10
+ snippet: string;
11
+ }
12
+ export declare function wrapSearchResults(hits: readonly SearchHit[]): string;
13
+ //# sourceMappingURL=untrusted-content.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"untrusted-content.d.ts","sourceRoot":"","sources":["../../src/research/untrusted-content.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,cAAc,GAAG,MAAM,CAE5D;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,SAAS,SAAS,EAAE,GAAG,MAAM,CAEpE"}
@@ -0,0 +1,9 @@
1
+ const escapeAttr = (s) => s.replace(/&/g, '&amp;').replace(/"/g, '&quot;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
2
+ const escapeBody = (s) => s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
3
+ export function wrapFetchedContent(c) {
4
+ return `<external-content url="${escapeAttr(c.url)}" host="${escapeAttr(c.host)}" trustLevel="untrusted">${escapeBody(c.content)}</external-content>`;
5
+ }
6
+ export function wrapSearchResults(hits) {
7
+ return `<external-search-results trustLevel="untrusted">${escapeBody(JSON.stringify(hits))}</external-search-results>`;
8
+ }
9
+ //# sourceMappingURL=untrusted-content.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"untrusted-content.js","sourceRoot":"","sources":["../../src/research/untrusted-content.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,GAAG,CAAC,CAAS,EAAE,EAAE,CAC/B,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AAE/F,MAAM,UAAU,GAAG,CAAC,CAAS,EAAE,EAAE,CAC/B,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AAQvE,MAAM,UAAU,kBAAkB,CAAC,CAAiB;IAClD,OAAO,0BAA0B,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,WAAW,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,4BAA4B,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,qBAAqB,CAAC;AACxJ,CAAC;AAQD,MAAM,UAAU,iBAAiB,CAAC,IAA0B;IAC1D,OAAO,mDAAmD,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,4BAA4B,CAAC;AACzH,CAAC"}
@@ -0,0 +1,50 @@
1
+ import { Agent } from 'undici';
2
+ import type { ResearchConfig } from '../config/schema.js';
3
+ export interface WebFetchInput {
4
+ url: string;
5
+ cfg: ResearchConfig['fetch'];
6
+ hostAllowlist: ReadonlySet<string>;
7
+ /** Hosts in this set may resolve to RFC1918 private addresses (still rejects loopback/metadata). */
8
+ privateNetworkHosts?: ReadonlySet<string>;
9
+ /** Test seam — replaces DNS resolution. */
10
+ resolveIP?: (host: string) => Promise<string>;
11
+ /**
12
+ * Test seam — return undefined to let undici use the global dispatcher (so
13
+ * MockAgent intercepts in tests). Default in prod builds an IP-pinning Agent
14
+ * per spec §7.1.10 with TLS SNI on the original hostname.
15
+ *
16
+ * Ownership: dispatchers returned by this hook are caller-owned/shared and
17
+ * will not be closed or destroyed by webFetch. The default dispatcher created
18
+ * by webFetch is one-shot and is disposed after its request completes.
19
+ */
20
+ createDispatcher?: (host: string, pinnedIP: string, cfg: ResearchConfig['fetch']) => import('undici').Dispatcher | undefined;
21
+ }
22
+ export declare const defaultIPPinningDispatcher: (host: string, pinnedIP: string, cfg: ResearchConfig["fetch"]) => Agent;
23
+ export type WebFetchOk = {
24
+ status: 'ok';
25
+ /** Worker-facing string: <external-content …>extracted-text</external-content> */
26
+ body: string;
27
+ /** Adapter-facing raw text (HTML stripped to main-text for HTML; raw bytes for XML/JSON). NOT wrapped. */
28
+ rawText: string;
29
+ host: string;
30
+ bytesReturned: number;
31
+ /** True if the wire-level read was capped by cfg.maxBodyBytes (raw response truncated). */
32
+ truncated: boolean;
33
+ /**
34
+ * True if the post-extraction text was capped by RETURNED_TEXT_CAP (default 64 KiB).
35
+ * Adapters that parse rawText (e.g. rss) MUST inspect this flag — a true value
36
+ * means the XML/JSON body may be syntactically incomplete and parsing should be skipped.
37
+ * This is independent of truncated; both can be true if both caps tripped.
38
+ */
39
+ textTruncated: boolean;
40
+ credentialsStripped: boolean;
41
+ };
42
+ export type WebFetchErr = {
43
+ status: 'error';
44
+ reasonCode: string;
45
+ host?: string;
46
+ credentialsStripped: boolean;
47
+ };
48
+ export type WebFetchResult = WebFetchOk | WebFetchErr;
49
+ export declare function webFetch(input: WebFetchInput): Promise<WebFetchResult>;
50
+ //# sourceMappingURL=web-fetch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web-fetch.d.ts","sourceRoot":"","sources":["../../src/research/web-fetch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,KAAK,EAAE,MAAM,QAAQ,CAAC;AAIxC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAI1D,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,cAAc,CAAC,OAAO,CAAC,CAAC;IAC7B,aAAa,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACnC,oGAAoG;IACpG,mBAAmB,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC1C,2CAA2C;IAC3C,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC9C;;;;;;;;OAQG;IACH,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,cAAc,CAAC,OAAO,CAAC,KAAK,OAAO,QAAQ,EAAE,UAAU,GAAG,SAAS,CAAC;CAC9H;AAED,eAAO,MAAM,0BAA0B,GAAI,MAAM,MAAM,EAAE,UAAU,MAAM,EAAE,KAAK,cAAc,CAAC,OAAO,CAAC,UAQnG,CAAC;AAEL,MAAM,MAAM,UAAU,GAAG;IACvB,MAAM,EAAE,IAAI,CAAC;IACb,kFAAkF;IAClF,IAAI,EAAE,MAAM,CAAC;IACb,0GAA0G;IAC1G,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,2FAA2F;IAC3F,SAAS,EAAE,OAAO,CAAC;IACnB;;;;;OAKG;IACH,aAAa,EAAE,OAAO,CAAC;IACvB,mBAAmB,EAAE,OAAO,CAAC;CAC9B,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,MAAM,EAAE,OAAO,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,mBAAmB,EAAE,OAAO,CAAC;CAC9B,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,UAAU,GAAG,WAAW,CAAC;AA4QtD,wBAAsB,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC,CA+K5E"}