@animus-labs/cortex 0.2.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 (293) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +73 -0
  3. package/dist/budget-guard.d.ts +75 -0
  4. package/dist/budget-guard.d.ts.map +1 -0
  5. package/dist/budget-guard.js +142 -0
  6. package/dist/budget-guard.js.map +1 -0
  7. package/dist/compaction/compaction.d.ts +99 -0
  8. package/dist/compaction/compaction.d.ts.map +1 -0
  9. package/dist/compaction/compaction.js +302 -0
  10. package/dist/compaction/compaction.js.map +1 -0
  11. package/dist/compaction/failsafe.d.ts +57 -0
  12. package/dist/compaction/failsafe.d.ts.map +1 -0
  13. package/dist/compaction/failsafe.js +135 -0
  14. package/dist/compaction/failsafe.js.map +1 -0
  15. package/dist/compaction/index.d.ts +381 -0
  16. package/dist/compaction/index.d.ts.map +1 -0
  17. package/dist/compaction/index.js +979 -0
  18. package/dist/compaction/index.js.map +1 -0
  19. package/dist/compaction/microcompaction.d.ts +219 -0
  20. package/dist/compaction/microcompaction.d.ts.map +1 -0
  21. package/dist/compaction/microcompaction.js +536 -0
  22. package/dist/compaction/microcompaction.js.map +1 -0
  23. package/dist/compaction/observational/buffering.d.ts +225 -0
  24. package/dist/compaction/observational/buffering.d.ts.map +1 -0
  25. package/dist/compaction/observational/buffering.js +354 -0
  26. package/dist/compaction/observational/buffering.js.map +1 -0
  27. package/dist/compaction/observational/constants.d.ts +70 -0
  28. package/dist/compaction/observational/constants.d.ts.map +1 -0
  29. package/dist/compaction/observational/constants.js +507 -0
  30. package/dist/compaction/observational/constants.js.map +1 -0
  31. package/dist/compaction/observational/index.d.ts +219 -0
  32. package/dist/compaction/observational/index.d.ts.map +1 -0
  33. package/dist/compaction/observational/index.js +641 -0
  34. package/dist/compaction/observational/index.js.map +1 -0
  35. package/dist/compaction/observational/observer.d.ts +97 -0
  36. package/dist/compaction/observational/observer.d.ts.map +1 -0
  37. package/dist/compaction/observational/observer.js +424 -0
  38. package/dist/compaction/observational/observer.js.map +1 -0
  39. package/dist/compaction/observational/recall-tool.d.ts +27 -0
  40. package/dist/compaction/observational/recall-tool.d.ts.map +1 -0
  41. package/dist/compaction/observational/recall-tool.js +93 -0
  42. package/dist/compaction/observational/recall-tool.js.map +1 -0
  43. package/dist/compaction/observational/reflector.d.ts +94 -0
  44. package/dist/compaction/observational/reflector.d.ts.map +1 -0
  45. package/dist/compaction/observational/reflector.js +167 -0
  46. package/dist/compaction/observational/reflector.js.map +1 -0
  47. package/dist/compaction/observational/types.d.ts +271 -0
  48. package/dist/compaction/observational/types.d.ts.map +1 -0
  49. package/dist/compaction/observational/types.js +15 -0
  50. package/dist/compaction/observational/types.js.map +1 -0
  51. package/dist/context-manager.d.ts +134 -0
  52. package/dist/context-manager.d.ts.map +1 -0
  53. package/dist/context-manager.js +170 -0
  54. package/dist/context-manager.js.map +1 -0
  55. package/dist/cortex-agent.d.ts +1020 -0
  56. package/dist/cortex-agent.d.ts.map +1 -0
  57. package/dist/cortex-agent.js +3589 -0
  58. package/dist/cortex-agent.js.map +1 -0
  59. package/dist/error-classifier.d.ts +48 -0
  60. package/dist/error-classifier.d.ts.map +1 -0
  61. package/dist/error-classifier.js +152 -0
  62. package/dist/error-classifier.js.map +1 -0
  63. package/dist/event-bridge.d.ts +166 -0
  64. package/dist/event-bridge.d.ts.map +1 -0
  65. package/dist/event-bridge.js +381 -0
  66. package/dist/event-bridge.js.map +1 -0
  67. package/dist/index.d.ts +55 -0
  68. package/dist/index.d.ts.map +1 -0
  69. package/dist/index.js +57 -0
  70. package/dist/index.js.map +1 -0
  71. package/dist/mcp-client.d.ts +119 -0
  72. package/dist/mcp-client.d.ts.map +1 -0
  73. package/dist/mcp-client.js +474 -0
  74. package/dist/mcp-client.js.map +1 -0
  75. package/dist/model-wrapper.d.ts +58 -0
  76. package/dist/model-wrapper.d.ts.map +1 -0
  77. package/dist/model-wrapper.js +86 -0
  78. package/dist/model-wrapper.js.map +1 -0
  79. package/dist/noop-logger.d.ts +4 -0
  80. package/dist/noop-logger.d.ts.map +1 -0
  81. package/dist/noop-logger.js +8 -0
  82. package/dist/noop-logger.js.map +1 -0
  83. package/dist/prompt-diagnostics.d.ts +47 -0
  84. package/dist/prompt-diagnostics.d.ts.map +1 -0
  85. package/dist/prompt-diagnostics.js +230 -0
  86. package/dist/prompt-diagnostics.js.map +1 -0
  87. package/dist/provider-manager.d.ts +224 -0
  88. package/dist/provider-manager.d.ts.map +1 -0
  89. package/dist/provider-manager.js +563 -0
  90. package/dist/provider-manager.js.map +1 -0
  91. package/dist/provider-registry.d.ts +115 -0
  92. package/dist/provider-registry.d.ts.map +1 -0
  93. package/dist/provider-registry.js +305 -0
  94. package/dist/provider-registry.js.map +1 -0
  95. package/dist/schema-converter.d.ts +20 -0
  96. package/dist/schema-converter.d.ts.map +1 -0
  97. package/dist/schema-converter.js +48 -0
  98. package/dist/schema-converter.js.map +1 -0
  99. package/dist/skill-preprocessor.d.ts +46 -0
  100. package/dist/skill-preprocessor.d.ts.map +1 -0
  101. package/dist/skill-preprocessor.js +237 -0
  102. package/dist/skill-preprocessor.js.map +1 -0
  103. package/dist/skill-registry.d.ts +107 -0
  104. package/dist/skill-registry.d.ts.map +1 -0
  105. package/dist/skill-registry.js +330 -0
  106. package/dist/skill-registry.js.map +1 -0
  107. package/dist/skill-tool.d.ts +54 -0
  108. package/dist/skill-tool.d.ts.map +1 -0
  109. package/dist/skill-tool.js +88 -0
  110. package/dist/skill-tool.js.map +1 -0
  111. package/dist/sub-agent-manager.d.ts +90 -0
  112. package/dist/sub-agent-manager.d.ts.map +1 -0
  113. package/dist/sub-agent-manager.js +192 -0
  114. package/dist/sub-agent-manager.js.map +1 -0
  115. package/dist/token-estimator.d.ts +23 -0
  116. package/dist/token-estimator.d.ts.map +1 -0
  117. package/dist/token-estimator.js +27 -0
  118. package/dist/token-estimator.js.map +1 -0
  119. package/dist/tool-contract.d.ts +68 -0
  120. package/dist/tool-contract.d.ts.map +1 -0
  121. package/dist/tool-contract.js +35 -0
  122. package/dist/tool-contract.js.map +1 -0
  123. package/dist/tool-result-persistence.d.ts +89 -0
  124. package/dist/tool-result-persistence.d.ts.map +1 -0
  125. package/dist/tool-result-persistence.js +152 -0
  126. package/dist/tool-result-persistence.js.map +1 -0
  127. package/dist/tools/bash/index.d.ts +71 -0
  128. package/dist/tools/bash/index.d.ts.map +1 -0
  129. package/dist/tools/bash/index.js +485 -0
  130. package/dist/tools/bash/index.js.map +1 -0
  131. package/dist/tools/bash/interactive.d.ts +47 -0
  132. package/dist/tools/bash/interactive.d.ts.map +1 -0
  133. package/dist/tools/bash/interactive.js +262 -0
  134. package/dist/tools/bash/interactive.js.map +1 -0
  135. package/dist/tools/bash/safety.d.ts +149 -0
  136. package/dist/tools/bash/safety.d.ts.map +1 -0
  137. package/dist/tools/bash/safety.js +1116 -0
  138. package/dist/tools/bash/safety.js.map +1 -0
  139. package/dist/tools/edit.d.ts +57 -0
  140. package/dist/tools/edit.d.ts.map +1 -0
  141. package/dist/tools/edit.js +310 -0
  142. package/dist/tools/edit.js.map +1 -0
  143. package/dist/tools/glob.d.ts +34 -0
  144. package/dist/tools/glob.d.ts.map +1 -0
  145. package/dist/tools/glob.js +268 -0
  146. package/dist/tools/glob.js.map +1 -0
  147. package/dist/tools/grep.d.ts +53 -0
  148. package/dist/tools/grep.d.ts.map +1 -0
  149. package/dist/tools/grep.js +673 -0
  150. package/dist/tools/grep.js.map +1 -0
  151. package/dist/tools/index.d.ts +62 -0
  152. package/dist/tools/index.d.ts.map +1 -0
  153. package/dist/tools/index.js +52 -0
  154. package/dist/tools/index.js.map +1 -0
  155. package/dist/tools/read.d.ts +43 -0
  156. package/dist/tools/read.d.ts.map +1 -0
  157. package/dist/tools/read.js +459 -0
  158. package/dist/tools/read.js.map +1 -0
  159. package/dist/tools/runtime.d.ts +62 -0
  160. package/dist/tools/runtime.d.ts.map +1 -0
  161. package/dist/tools/runtime.js +116 -0
  162. package/dist/tools/runtime.js.map +1 -0
  163. package/dist/tools/shared/cwd-tracker.d.ts +32 -0
  164. package/dist/tools/shared/cwd-tracker.d.ts.map +1 -0
  165. package/dist/tools/shared/cwd-tracker.js +44 -0
  166. package/dist/tools/shared/cwd-tracker.js.map +1 -0
  167. package/dist/tools/shared/edit-history.d.ts +55 -0
  168. package/dist/tools/shared/edit-history.d.ts.map +1 -0
  169. package/dist/tools/shared/edit-history.js +72 -0
  170. package/dist/tools/shared/edit-history.js.map +1 -0
  171. package/dist/tools/shared/edit-matcher.d.ts +83 -0
  172. package/dist/tools/shared/edit-matcher.d.ts.map +1 -0
  173. package/dist/tools/shared/edit-matcher.js +359 -0
  174. package/dist/tools/shared/edit-matcher.js.map +1 -0
  175. package/dist/tools/shared/file-mutation-lock.d.ts +22 -0
  176. package/dist/tools/shared/file-mutation-lock.d.ts.map +1 -0
  177. package/dist/tools/shared/file-mutation-lock.js +35 -0
  178. package/dist/tools/shared/file-mutation-lock.js.map +1 -0
  179. package/dist/tools/shared/gitignore.d.ts +17 -0
  180. package/dist/tools/shared/gitignore.d.ts.map +1 -0
  181. package/dist/tools/shared/gitignore.js +59 -0
  182. package/dist/tools/shared/gitignore.js.map +1 -0
  183. package/dist/tools/shared/pdf-extractor.d.ts +96 -0
  184. package/dist/tools/shared/pdf-extractor.d.ts.map +1 -0
  185. package/dist/tools/shared/pdf-extractor.js +196 -0
  186. package/dist/tools/shared/pdf-extractor.js.map +1 -0
  187. package/dist/tools/shared/read-registry.d.ts +66 -0
  188. package/dist/tools/shared/read-registry.d.ts.map +1 -0
  189. package/dist/tools/shared/read-registry.js +65 -0
  190. package/dist/tools/shared/read-registry.js.map +1 -0
  191. package/dist/tools/shared/safe-env.d.ts +18 -0
  192. package/dist/tools/shared/safe-env.d.ts.map +1 -0
  193. package/dist/tools/shared/safe-env.js +70 -0
  194. package/dist/tools/shared/safe-env.js.map +1 -0
  195. package/dist/tools/sub-agent.d.ts +91 -0
  196. package/dist/tools/sub-agent.d.ts.map +1 -0
  197. package/dist/tools/sub-agent.js +89 -0
  198. package/dist/tools/sub-agent.js.map +1 -0
  199. package/dist/tools/task-output.d.ts +38 -0
  200. package/dist/tools/task-output.d.ts.map +1 -0
  201. package/dist/tools/task-output.js +186 -0
  202. package/dist/tools/task-output.js.map +1 -0
  203. package/dist/tools/tool-search/index.d.ts +40 -0
  204. package/dist/tools/tool-search/index.d.ts.map +1 -0
  205. package/dist/tools/tool-search/index.js +110 -0
  206. package/dist/tools/tool-search/index.js.map +1 -0
  207. package/dist/tools/tool-search/registry.d.ts +82 -0
  208. package/dist/tools/tool-search/registry.d.ts.map +1 -0
  209. package/dist/tools/tool-search/registry.js +238 -0
  210. package/dist/tools/tool-search/registry.js.map +1 -0
  211. package/dist/tools/undo-edit.d.ts +51 -0
  212. package/dist/tools/undo-edit.d.ts.map +1 -0
  213. package/dist/tools/undo-edit.js +231 -0
  214. package/dist/tools/undo-edit.js.map +1 -0
  215. package/dist/tools/web-fetch/cache.d.ts +49 -0
  216. package/dist/tools/web-fetch/cache.d.ts.map +1 -0
  217. package/dist/tools/web-fetch/cache.js +89 -0
  218. package/dist/tools/web-fetch/cache.js.map +1 -0
  219. package/dist/tools/web-fetch/index.d.ts +53 -0
  220. package/dist/tools/web-fetch/index.d.ts.map +1 -0
  221. package/dist/tools/web-fetch/index.js +513 -0
  222. package/dist/tools/web-fetch/index.js.map +1 -0
  223. package/dist/tools/write.d.ts +59 -0
  224. package/dist/tools/write.d.ts.map +1 -0
  225. package/dist/tools/write.js +316 -0
  226. package/dist/tools/write.js.map +1 -0
  227. package/dist/types.d.ts +881 -0
  228. package/dist/types.d.ts.map +1 -0
  229. package/dist/types.js +16 -0
  230. package/dist/types.js.map +1 -0
  231. package/dist/working-tags.d.ts +44 -0
  232. package/dist/working-tags.d.ts.map +1 -0
  233. package/dist/working-tags.js +103 -0
  234. package/dist/working-tags.js.map +1 -0
  235. package/package.json +87 -0
  236. package/src/budget-guard.ts +170 -0
  237. package/src/compaction/compaction.ts +386 -0
  238. package/src/compaction/failsafe.ts +185 -0
  239. package/src/compaction/index.ts +1199 -0
  240. package/src/compaction/microcompaction.ts +709 -0
  241. package/src/compaction/observational/buffering.ts +430 -0
  242. package/src/compaction/observational/constants.ts +532 -0
  243. package/src/compaction/observational/index.ts +837 -0
  244. package/src/compaction/observational/observer.ts +510 -0
  245. package/src/compaction/observational/recall-tool.ts +130 -0
  246. package/src/compaction/observational/reflector.ts +221 -0
  247. package/src/compaction/observational/types.ts +343 -0
  248. package/src/context-manager.ts +237 -0
  249. package/src/cortex-agent.ts +4297 -0
  250. package/src/error-classifier.ts +199 -0
  251. package/src/event-bridge.ts +508 -0
  252. package/src/index.ts +292 -0
  253. package/src/mcp-client.ts +582 -0
  254. package/src/model-wrapper.ts +128 -0
  255. package/src/noop-logger.ts +9 -0
  256. package/src/prompt-diagnostics.ts +296 -0
  257. package/src/provider-manager.ts +823 -0
  258. package/src/provider-registry.ts +386 -0
  259. package/src/schema-converter.ts +51 -0
  260. package/src/skill-preprocessor.ts +314 -0
  261. package/src/skill-registry.ts +378 -0
  262. package/src/skill-tool.ts +130 -0
  263. package/src/sub-agent-manager.ts +236 -0
  264. package/src/token-estimator.ts +26 -0
  265. package/src/tool-contract.ts +113 -0
  266. package/src/tool-result-persistence.ts +197 -0
  267. package/src/tools/bash/index.ts +633 -0
  268. package/src/tools/bash/interactive.ts +302 -0
  269. package/src/tools/bash/safety.ts +1297 -0
  270. package/src/tools/edit.ts +422 -0
  271. package/src/tools/glob.ts +330 -0
  272. package/src/tools/grep.ts +819 -0
  273. package/src/tools/index.ts +110 -0
  274. package/src/tools/read.ts +580 -0
  275. package/src/tools/runtime.ts +173 -0
  276. package/src/tools/shared/cwd-tracker.ts +50 -0
  277. package/src/tools/shared/edit-history.ts +96 -0
  278. package/src/tools/shared/edit-matcher.ts +457 -0
  279. package/src/tools/shared/file-mutation-lock.ts +40 -0
  280. package/src/tools/shared/gitignore.ts +61 -0
  281. package/src/tools/shared/pdf-extractor.ts +290 -0
  282. package/src/tools/shared/read-registry.ts +93 -0
  283. package/src/tools/shared/safe-env.ts +82 -0
  284. package/src/tools/sub-agent.ts +171 -0
  285. package/src/tools/task-output.ts +236 -0
  286. package/src/tools/tool-search/index.ts +167 -0
  287. package/src/tools/tool-search/registry.ts +278 -0
  288. package/src/tools/undo-edit.ts +314 -0
  289. package/src/tools/web-fetch/cache.ts +112 -0
  290. package/src/tools/web-fetch/index.ts +604 -0
  291. package/src/tools/write.ts +385 -0
  292. package/src/types.ts +1057 -0
  293. package/src/working-tags.ts +118 -0
@@ -0,0 +1,513 @@
1
+ /**
2
+ * WebFetch tool: fetch a web page and return its content as processed text.
3
+ *
4
+ * Two-model architecture:
5
+ * 1. Fetch: HTTP request via Node built-in fetch
6
+ * 2. Convert: HTML to markdown via Turndown
7
+ * 3. Summarize: utility model answers the prompt using the page content
8
+ *
9
+ * The main agent never sees raw page content.
10
+ *
11
+ * Reference: docs/cortex/tools/web-fetch.md
12
+ */
13
+ import { promises as dns } from 'node:dns';
14
+ import { isIPv4, isIPv6 } from 'node:net';
15
+ import { Type } from 'typebox';
16
+ import { WebFetchCache } from './cache.js';
17
+ import { attachRuntimeAwareTool } from '../runtime.js';
18
+ // ---------------------------------------------------------------------------
19
+ // Schema
20
+ // ---------------------------------------------------------------------------
21
+ export const WebFetchParams = Type.Object({
22
+ url: Type.String({ description: 'The URL to fetch. HTTP auto-upgraded to HTTPS.' }),
23
+ prompt: Type.String({ description: 'A question or instruction about what to extract from the page.' }),
24
+ });
25
+ // ---------------------------------------------------------------------------
26
+ // Constants
27
+ // ---------------------------------------------------------------------------
28
+ const REQUEST_TIMEOUT = 30_000;
29
+ const DEFAULT_MAX_PER_LOOP = 300;
30
+ const USER_AGENT = 'Cortex/1.0 (web-fetch tool)';
31
+ /**
32
+ * Maximum tokens of page content sent to the utility model for summarization.
33
+ *
34
+ * Distinct from the agent-side result-persistence interceptor: this cap is
35
+ * about cost/latency on the summarization step, not main-agent context. We
36
+ * pick a value generous enough to let the utility model see most of a page
37
+ * (utility models typically have 200K+ context windows) while preventing
38
+ * pathological cases where a 1MB page burns excessive tokens on every fetch.
39
+ */
40
+ const MAX_UTILITY_MODEL_INPUT_TOKENS = 100_000;
41
+ /**
42
+ * Hostname strings that always resolve to private/local addresses.
43
+ * Checked before DNS resolution as a fast-path reject.
44
+ *
45
+ * Note: this list is a fast-path optimization, not the security boundary.
46
+ * The actual SSRF protection comes from validateResolvedIp(), which checks
47
+ * the DNS-resolved IP against private ranges before every fetch. A TOCTOU
48
+ * window exists between our DNS check and Node's internal fetch DNS lookup;
49
+ * mitigating DNS rebinding fully would require socket-level interception.
50
+ */
51
+ const PRIVATE_HOSTNAME_PATTERNS = [
52
+ /^localhost$/i,
53
+ /^0\.0\.0\.0$/,
54
+ /^127\.\d+\.\d+\.\d+$/,
55
+ /^\[?::1\]?$/,
56
+ ];
57
+ /**
58
+ * Check whether an IP address (v4 or v6) belongs to a private, loopback,
59
+ * link-local, or otherwise non-routable range. Handles IPv4-mapped IPv6
60
+ * addresses (::ffff:x.x.x.x) and parses octets numerically to catch
61
+ * alternate encodings (decimal IPs, zero-padded, etc.).
62
+ */
63
+ export function isPrivateIp(ip) {
64
+ let normalized = ip;
65
+ // Normalize IPv4-mapped IPv6 (::ffff:127.0.0.1 -> 127.0.0.1)
66
+ if (normalized.toLowerCase().startsWith('::ffff:')) {
67
+ normalized = normalized.slice(7);
68
+ }
69
+ if (isIPv4(normalized)) {
70
+ const octets = normalized.split('.').map(Number);
71
+ if (octets.length !== 4 || octets.some(o => isNaN(o) || o < 0 || o > 255)) {
72
+ // Malformed, treat as private (fail-safe)
73
+ return true;
74
+ }
75
+ // 127.0.0.0/8 (loopback)
76
+ if (octets[0] === 127)
77
+ return true;
78
+ // 10.0.0.0/8
79
+ if (octets[0] === 10)
80
+ return true;
81
+ // 172.16.0.0/12
82
+ if (octets[0] === 172 && octets[1] >= 16 && octets[1] <= 31)
83
+ return true;
84
+ // 192.168.0.0/16
85
+ if (octets[0] === 192 && octets[1] === 168)
86
+ return true;
87
+ // 169.254.0.0/16 (link-local, cloud metadata)
88
+ if (octets[0] === 169 && octets[1] === 254)
89
+ return true;
90
+ // 0.0.0.0/8
91
+ if (octets[0] === 0)
92
+ return true;
93
+ return false;
94
+ }
95
+ if (isIPv6(ip)) {
96
+ const lower = ip.toLowerCase();
97
+ // ::1 (loopback)
98
+ if (lower === '::1' || lower === '0:0:0:0:0:0:0:1')
99
+ return true;
100
+ // fe80::/10 (link-local)
101
+ if (lower.startsWith('fe80:'))
102
+ return true;
103
+ // fc00::/7 (unique local, includes fd00::/8)
104
+ const firstSegment = lower.split(':')[0] ?? '';
105
+ const firstVal = parseInt(firstSegment, 16);
106
+ if (!isNaN(firstVal) && (firstVal & 0xfe00) === 0xfc00)
107
+ return true;
108
+ // :: (unspecified)
109
+ if (lower === '::' || lower === '0:0:0:0:0:0:0:0')
110
+ return true;
111
+ return false;
112
+ }
113
+ // Unrecognized format, fail-safe: treat as private
114
+ return true;
115
+ }
116
+ /**
117
+ * Resolve a hostname via DNS and validate that the resolved IP is not private.
118
+ * Throws if the hostname resolves to a private/loopback/link-local address.
119
+ */
120
+ async function validateResolvedIp(hostname) {
121
+ // If the hostname is already a literal IP, validate directly
122
+ if (isIPv4(hostname) || isIPv6(hostname)) {
123
+ if (isPrivateIp(hostname)) {
124
+ throw new Error(`URL resolves to private IP ${hostname}`);
125
+ }
126
+ return;
127
+ }
128
+ const { address } = await dns.lookup(hostname);
129
+ if (isPrivateIp(address)) {
130
+ throw new Error(`URL resolves to private IP ${address}`);
131
+ }
132
+ }
133
+ let turndownServicePromise;
134
+ function getTurndownService() {
135
+ return (turndownServicePromise ??= import('turndown').then(m => {
136
+ const Turndown = m.default;
137
+ return new Turndown({
138
+ headingStyle: 'atx',
139
+ codeBlockStyle: 'fenced',
140
+ bulletListMarker: '-',
141
+ });
142
+ }));
143
+ }
144
+ // ---------------------------------------------------------------------------
145
+ // Helpers
146
+ // ---------------------------------------------------------------------------
147
+ /**
148
+ * Validate a URL, rejecting dangerous schemes, private hostnames, and literal private IPs.
149
+ * This is the first-pass check (hostname/literal IP only). DNS resolution is done
150
+ * separately before each fetch to catch DNS rebinding attacks.
151
+ */
152
+ function validateUrl(urlStr) {
153
+ let url;
154
+ try {
155
+ url = new URL(urlStr);
156
+ }
157
+ catch {
158
+ return { valid: false, reason: 'Invalid URL format' };
159
+ }
160
+ // Reject non-HTTP(S) schemes
161
+ if (url.protocol !== 'http:' && url.protocol !== 'https:') {
162
+ return { valid: false, reason: `URL scheme "${url.protocol}" is not allowed. Only http: and https: are supported.` };
163
+ }
164
+ // Auto-upgrade HTTP to HTTPS
165
+ if (url.protocol === 'http:') {
166
+ url = new URL(urlStr.replace(/^http:/, 'https:'));
167
+ }
168
+ const hostname = url.hostname;
169
+ // Check hostname-level blocklist (localhost, etc.)
170
+ for (const pattern of PRIVATE_HOSTNAME_PATTERNS) {
171
+ if (pattern.test(hostname)) {
172
+ return { valid: false, reason: `URL rejected: private/local network address (${hostname})` };
173
+ }
174
+ }
175
+ // If the hostname is a literal IP, validate it structurally
176
+ if (isIPv4(hostname) || isIPv6(hostname)) {
177
+ if (isPrivateIp(hostname)) {
178
+ return { valid: false, reason: `URL rejected: private/local network address (${hostname})` };
179
+ }
180
+ }
181
+ return { valid: true, url };
182
+ }
183
+ /**
184
+ * Strip HTML elements that are not useful for content extraction.
185
+ * This is a simple regex-based approach for removing script, style,
186
+ * nav, footer, and header elements before Turndown conversion.
187
+ */
188
+ function stripBoilerplateHtml(html) {
189
+ // Remove script, style, nav, footer, header, aside, noscript
190
+ const tagsToRemove = ['script', 'style', 'nav', 'footer', 'header', 'aside', 'noscript', 'svg'];
191
+ let cleaned = html;
192
+ for (const tag of tagsToRemove) {
193
+ const regex = new RegExp(`<${tag}[^>]*>[\\s\\S]*?</${tag}>`, 'gi');
194
+ cleaned = cleaned.replace(regex, '');
195
+ // Also remove self-closing variants
196
+ cleaned = cleaned.replace(new RegExp(`<${tag}[^>]*/>`, 'gi'), '');
197
+ }
198
+ return cleaned;
199
+ }
200
+ // ---------------------------------------------------------------------------
201
+ // Tool factory
202
+ // ---------------------------------------------------------------------------
203
+ export function createWebFetchTool(config) {
204
+ const runtimeWebFetch = config.runtime?.webFetch;
205
+ const cache = runtimeWebFetch?.getCache() ?? new WebFetchCache();
206
+ const maxPerLoop = config.maxPerLoop ?? DEFAULT_MAX_PER_LOOP;
207
+ let fetchesThisLoop = 0;
208
+ const tool = {
209
+ name: 'WebFetch',
210
+ description: 'Fetch a web page and return a summarized answer to your question about its content.',
211
+ parameters: WebFetchParams,
212
+ resetRateLimit() {
213
+ if (runtimeWebFetch) {
214
+ runtimeWebFetch.resetLoop();
215
+ return;
216
+ }
217
+ fetchesThisLoop = 0;
218
+ },
219
+ getCache() {
220
+ return cache;
221
+ },
222
+ async execute(params) {
223
+ // URL validation
224
+ const validation = validateUrl(params.url);
225
+ if (!validation.valid) {
226
+ return {
227
+ content: [{ type: 'text', text: `URL rejected: ${validation.reason}` }],
228
+ details: {
229
+ finalUrl: params.url,
230
+ statusCode: 0,
231
+ cacheHit: false,
232
+ rawSize: 0,
233
+ markdownSize: 0,
234
+ },
235
+ };
236
+ }
237
+ const url = validation.url;
238
+ const urlStr = url.toString();
239
+ // Check cache (cached responses don't count against rate limit)
240
+ const cached = cache.get(urlStr);
241
+ if (cached) {
242
+ // Still need to summarize with the user's prompt
243
+ const summary = await summarize(cached.content, params.prompt, config.utilityComplete);
244
+ return {
245
+ content: [{ type: 'text', text: summary }],
246
+ details: {
247
+ finalUrl: cached.finalUrl,
248
+ statusCode: cached.statusCode,
249
+ cacheHit: true,
250
+ rawSize: 0,
251
+ markdownSize: cached.content.length,
252
+ },
253
+ };
254
+ }
255
+ // Rate limit check (only for non-cached fetches)
256
+ const currentFetchCount = runtimeWebFetch?.fetchCount ?? fetchesThisLoop;
257
+ if (currentFetchCount >= maxPerLoop) {
258
+ return {
259
+ content: [{ type: 'text', text: `WebFetch rate limit reached (${maxPerLoop} per loop). Wait for the next loop or use Bash with curl for direct access.` }],
260
+ details: {
261
+ finalUrl: urlStr,
262
+ statusCode: 0,
263
+ cacheHit: false,
264
+ rawSize: 0,
265
+ markdownSize: 0,
266
+ },
267
+ };
268
+ }
269
+ if (runtimeWebFetch) {
270
+ runtimeWebFetch.incrementFetchCount();
271
+ }
272
+ else {
273
+ fetchesThisLoop++;
274
+ }
275
+ // DNS pre-resolution: resolve hostname and validate the IP is not private.
276
+ // This prevents DNS rebinding attacks where a domain initially resolves to
277
+ // a public IP during validation but resolves to 127.0.0.1 at fetch time.
278
+ try {
279
+ await validateResolvedIp(url.hostname);
280
+ }
281
+ catch (err) {
282
+ const msg = err instanceof Error ? err.message : String(err);
283
+ return {
284
+ content: [{ type: 'text', text: `URL rejected: ${msg}` }],
285
+ details: {
286
+ finalUrl: urlStr,
287
+ statusCode: 0,
288
+ cacheHit: false,
289
+ rawSize: 0,
290
+ markdownSize: 0,
291
+ },
292
+ };
293
+ }
294
+ // Fetch the URL (manual redirect to detect cross-host redirects)
295
+ let response;
296
+ let currentUrl = urlStr;
297
+ const maxRedirects = 10;
298
+ let redirectCount = 0;
299
+ // eslint-disable-next-line no-constant-condition
300
+ while (true) {
301
+ try {
302
+ const controller = new AbortController();
303
+ const timeoutId = setTimeout(() => controller.abort(), REQUEST_TIMEOUT);
304
+ response = await fetch(currentUrl, {
305
+ signal: controller.signal,
306
+ headers: {
307
+ 'User-Agent': USER_AGENT,
308
+ 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
309
+ },
310
+ redirect: 'manual',
311
+ });
312
+ clearTimeout(timeoutId);
313
+ }
314
+ catch (err) {
315
+ const msg = err instanceof Error ? err.message : String(err);
316
+ if (msg.includes('abort')) {
317
+ return {
318
+ content: [{ type: 'text', text: `Request timed out: ${currentUrl}` }],
319
+ details: { finalUrl: currentUrl, statusCode: 0, cacheHit: false, rawSize: 0, markdownSize: 0 },
320
+ };
321
+ }
322
+ if (msg.includes('ENOTFOUND') || msg.includes('getaddrinfo')) {
323
+ const hostname = url.hostname;
324
+ return {
325
+ content: [{ type: 'text', text: `Could not resolve host: ${hostname}` }],
326
+ details: { finalUrl: currentUrl, statusCode: 0, cacheHit: false, rawSize: 0, markdownSize: 0 },
327
+ };
328
+ }
329
+ if (msg.includes('certificate') || msg.includes('SSL') || msg.includes('TLS')) {
330
+ return {
331
+ content: [{ type: 'text', text: `SSL certificate error for ${currentUrl}` }],
332
+ details: { finalUrl: currentUrl, statusCode: 0, cacheHit: false, rawSize: 0, markdownSize: 0 },
333
+ };
334
+ }
335
+ return {
336
+ content: [{ type: 'text', text: `Failed to fetch ${currentUrl}: ${msg}` }],
337
+ details: { finalUrl: currentUrl, statusCode: 0, cacheHit: false, rawSize: 0, markdownSize: 0 },
338
+ };
339
+ }
340
+ // Handle redirects (3xx status)
341
+ const status = response.status;
342
+ if (status >= 300 && status < 400) {
343
+ const location = response.headers.get('location');
344
+ if (!location)
345
+ break; // No Location header, treat as final response
346
+ // Resolve relative redirect URLs
347
+ const redirectUrl = new URL(location, currentUrl).toString();
348
+ const currentHost = new URL(currentUrl).hostname;
349
+ const redirectHost = new URL(redirectUrl).hostname;
350
+ // Cross-host redirect: inform the model instead of following
351
+ if (redirectHost !== currentHost) {
352
+ return {
353
+ content: [{ type: 'text', text: `This URL redirects to ${redirectUrl}. Make a new WebFetch request with this URL.` }],
354
+ details: {
355
+ finalUrl: redirectUrl,
356
+ statusCode: status,
357
+ cacheHit: false,
358
+ rawSize: 0,
359
+ markdownSize: 0,
360
+ },
361
+ };
362
+ }
363
+ // Same-host redirect: validate the redirect URL's resolved IP before following
364
+ try {
365
+ await validateResolvedIp(redirectHost);
366
+ }
367
+ catch (err) {
368
+ const msg = err instanceof Error ? err.message : String(err);
369
+ return {
370
+ content: [{ type: 'text', text: `Redirect URL rejected: ${msg}` }],
371
+ details: { finalUrl: redirectUrl, statusCode: status, cacheHit: false, rawSize: 0, markdownSize: 0 },
372
+ };
373
+ }
374
+ redirectCount++;
375
+ if (redirectCount > maxRedirects) {
376
+ return {
377
+ content: [{ type: 'text', text: `Too many redirects (${maxRedirects}) for ${urlStr}` }],
378
+ details: { finalUrl: currentUrl, statusCode: status, cacheHit: false, rawSize: 0, markdownSize: 0 },
379
+ };
380
+ }
381
+ currentUrl = redirectUrl;
382
+ continue;
383
+ }
384
+ // Not a redirect, break out of the loop
385
+ break;
386
+ }
387
+ const finalUrl = currentUrl;
388
+ const statusCode = response.status;
389
+ // Handle HTTP errors
390
+ if (statusCode === 404) {
391
+ return {
392
+ content: [{ type: 'text', text: `Page not found: ${urlStr}` }],
393
+ details: { finalUrl, statusCode, cacheHit: false, rawSize: 0, markdownSize: 0 },
394
+ };
395
+ }
396
+ if (statusCode === 403) {
397
+ return {
398
+ content: [{ type: 'text', text: `Access forbidden: ${urlStr}. This may require authentication. Check if an MCP tool provides access.` }],
399
+ details: { finalUrl, statusCode, cacheHit: false, rawSize: 0, markdownSize: 0 },
400
+ };
401
+ }
402
+ if (statusCode >= 500) {
403
+ return {
404
+ content: [{ type: 'text', text: `Server error (${statusCode}): ${urlStr}` }],
405
+ details: { finalUrl, statusCode, cacheHit: false, rawSize: 0, markdownSize: 0 },
406
+ };
407
+ }
408
+ // Read body
409
+ const rawBody = await response.text();
410
+ const rawSize = rawBody.length;
411
+ // Determine content type
412
+ const contentType = response.headers.get('content-type') ?? '';
413
+ let markdown;
414
+ if (contentType.includes('application/json')) {
415
+ // JSON: return as-is
416
+ markdown = rawBody;
417
+ }
418
+ else if (contentType.includes('text/plain')) {
419
+ // Plain text: return as-is
420
+ markdown = rawBody;
421
+ }
422
+ else {
423
+ // HTML: strip boilerplate and convert via Turndown
424
+ const cleaned = stripBoilerplateHtml(rawBody);
425
+ markdown = (await getTurndownService()).turndown(cleaned);
426
+ }
427
+ // Check for JavaScript-only pages
428
+ if (markdown.trim().length < 100 && rawBody.includes('<script')) {
429
+ return {
430
+ content: [{ type: 'text', text: 'The page appears to require JavaScript to render. No extractable content found.' }],
431
+ details: { finalUrl, statusCode, cacheHit: false, rawSize, markdownSize: markdown.length },
432
+ };
433
+ }
434
+ // Cache the result
435
+ cache.set(urlStr, {
436
+ content: markdown,
437
+ fetchedAt: Date.now(),
438
+ statusCode,
439
+ finalUrl,
440
+ });
441
+ // Summarize with utility model
442
+ const summary = await summarize(markdown, params.prompt, config.utilityComplete);
443
+ return {
444
+ content: [{ type: 'text', text: summary }],
445
+ details: {
446
+ finalUrl,
447
+ statusCode,
448
+ cacheHit: false,
449
+ rawSize,
450
+ markdownSize: markdown.length,
451
+ },
452
+ };
453
+ },
454
+ };
455
+ return attachRuntimeAwareTool(tool, {
456
+ toolKind: 'WebFetch',
457
+ cloneForRuntime: (runtime) => createWebFetchTool({
458
+ ...config,
459
+ runtime,
460
+ }),
461
+ });
462
+ }
463
+ // ---------------------------------------------------------------------------
464
+ // Summarization
465
+ // ---------------------------------------------------------------------------
466
+ /**
467
+ * Summarize page content using the utility model.
468
+ * Falls back to truncated content if the utility model is unavailable.
469
+ */
470
+ /**
471
+ * Cap content sent to the utility model. This is purely a cost/latency
472
+ * guard for the summarization step and is independent of the agent-side
473
+ * result-persistence interceptor (which protects main-agent context).
474
+ */
475
+ function capForUtilityModel(content) {
476
+ const maxChars = MAX_UTILITY_MODEL_INPUT_TOKENS * 4;
477
+ if (content.length <= maxChars)
478
+ return content;
479
+ return content.slice(0, maxChars) + '\n\n[Content truncated for summarization input]';
480
+ }
481
+ async function summarize(content, prompt, utilityComplete) {
482
+ if (!utilityComplete) {
483
+ // No utility model available; return raw content. The agent's
484
+ // result-persistence interceptor will bookend/persist if oversized.
485
+ return `[WebFetch: utility model not available. Returning raw content.]\n\n${content}`;
486
+ }
487
+ const summarizationInput = capForUtilityModel(content);
488
+ try {
489
+ const result = await utilityComplete({
490
+ systemPrompt: 'You are a web content analyst. Answer the user\'s question based on the provided web page content. Be concise and focused. If the content doesn\'t contain the answer, say so.',
491
+ messages: [
492
+ {
493
+ role: 'user',
494
+ content: `Question: ${prompt}\n\nWeb page content:\n${summarizationInput}`,
495
+ },
496
+ ],
497
+ });
498
+ if (typeof result === 'string')
499
+ return result;
500
+ if (result && typeof result === 'object' && 'text' in result) {
501
+ const textValue = result['text'];
502
+ if (typeof textValue === 'string')
503
+ return textValue;
504
+ }
505
+ return `[Summarization produced unexpected result type]\n\n${content.slice(0, 2000)}`;
506
+ }
507
+ catch {
508
+ // Summarization failed, return raw content. The agent's
509
+ // result-persistence interceptor will bookend/persist if oversized.
510
+ return `[WebFetch: summarization failed. Returning raw content.]\n\n${content}`;
511
+ }
512
+ }
513
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tools/web-fetch/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Write tool: create a new file or overwrite an existing file.
3
+ *
4
+ * Enforces the read-before-write contract via ReadRegistry.
5
+ * Performs atomic writes (write to temp, then rename) to prevent
6
+ * partial writes on crash. Creates parent directories as needed.
7
+ *
8
+ * Reference: docs/cortex/tools/write.md
9
+ */
10
+ import { Type, type Static } from 'typebox';
11
+ import type { EditHistory } from './shared/edit-history.js';
12
+ import type { FileMutationLock } from './shared/file-mutation-lock.js';
13
+ import type { ReadRegistry } from './shared/read-registry.js';
14
+ import type { ToolContentDetails } from '../types.js';
15
+ import type { CortexToolRuntime } from './runtime.js';
16
+ export declare const WriteParams: Type.TObject<{
17
+ file_path: Type.TString;
18
+ content: Type.TString;
19
+ }>;
20
+ export type WriteParamsType = Static<typeof WriteParams>;
21
+ export interface DiffHunk {
22
+ oldStart: number;
23
+ oldLines: number;
24
+ newStart: number;
25
+ newLines: number;
26
+ lines: string[];
27
+ }
28
+ export interface WriteDetails {
29
+ filePath: string;
30
+ isCreate: boolean;
31
+ bytesWritten: number;
32
+ diff: DiffHunk[] | null;
33
+ originalContent: string | null;
34
+ }
35
+ export interface WriteToolConfig {
36
+ runtime?: CortexToolRuntime | undefined;
37
+ readRegistry?: ReadRegistry | undefined;
38
+ fileMutationLock?: FileMutationLock | undefined;
39
+ /**
40
+ * Undo stack. When provided, every successful write pushes a
41
+ * pre-mutation snapshot (or `null` when the file did not exist) so
42
+ * `UndoEdit` can restore the prior state.
43
+ */
44
+ editHistory?: EditHistory | undefined;
45
+ }
46
+ /**
47
+ * Compute a safe line-level diff between two strings.
48
+ *
49
+ * This intentionally emits at most one changed hunk. The UI only needs a
50
+ * compact, deterministic summary of the mutation, not a minimal diff.
51
+ */
52
+ export declare function computeDiff(oldContent: string, newContent: string): DiffHunk[];
53
+ export declare function createWriteTool(config: WriteToolConfig): {
54
+ name: string;
55
+ description: string;
56
+ parameters: typeof WriteParams;
57
+ execute: (params: WriteParamsType) => Promise<ToolContentDetails<WriteDetails>>;
58
+ };
59
+ //# sourceMappingURL=write.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"write.d.ts","sourceRoot":"","sources":["../../src/tools/write.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,EAAE,IAAI,EAAE,KAAK,MAAM,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAOtD,eAAO,MAAM,WAAW;;;EAGtB,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,OAAO,WAAW,CAAC,CAAC;AAMzD,MAAM,WAAW,QAAQ;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;IACxB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAMD,MAAM,WAAW,eAAe;IAC9B,OAAO,CAAC,EAAE,iBAAiB,GAAG,SAAS,CAAC;IACxC,YAAY,CAAC,EAAE,YAAY,GAAG,SAAS,CAAC;IACxC,gBAAgB,CAAC,EAAE,gBAAgB,GAAG,SAAS,CAAC;IAChD;;;;OAIG;IACH,WAAW,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;CACvC;AAMD;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,QAAQ,EAAE,CA0C9E;AAMD,wBAAgB,eAAe,CAAC,MAAM,EAAE,eAAe,GAAG;IACxD,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,OAAO,WAAW,CAAC;IAC/B,OAAO,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,OAAO,CAAC,kBAAkB,CAAC,YAAY,CAAC,CAAC,CAAC;CACjF,CA6PA"}