@fortressllm/sybil 0.0.3

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 (288) hide show
  1. package/.env copy +91 -0
  2. package/.env.example +139 -0
  3. package/BROWSER_CONTROL.md +354 -0
  4. package/CLI_CHAT_FEATURE.md +224 -0
  5. package/CLI_GUIDE.md +359 -0
  6. package/DYNAMIC_SKILLS.md +345 -0
  7. package/DockerFile.sandbox +14 -0
  8. package/PROGRESS.md +249 -0
  9. package/README.md +281 -0
  10. package/RENAME_LOG.md +62 -0
  11. package/SIMPLIFIED_TELEGRAM_UX.md +273 -0
  12. package/SYBIL_SUMMARY.md +360 -0
  13. package/TASK11_NETWORK.md +202 -0
  14. package/TASK14_CLI.md +432 -0
  15. package/TASK8_SAFETY.md +317 -0
  16. package/TASK9_COMPLETION.md +186 -0
  17. package/TASK9_SUMMARY.md +201 -0
  18. package/TELEGRAM_OTP_AUTH.md +359 -0
  19. package/VECTOR_MEMORY.md +163 -0
  20. package/assets/logo.png +0 -0
  21. package/cypfq_code_search.md +287 -0
  22. package/cypfq_driver_search.md +297 -0
  23. package/cypfq_github_search.md +297 -0
  24. package/cypfq_repo_search.md +370 -0
  25. package/dist/agents/autonomous-agent.d.ts +61 -0
  26. package/dist/agents/autonomous-agent.d.ts.map +1 -0
  27. package/dist/agents/autonomous-agent.js +536 -0
  28. package/dist/agents/autonomous-agent.js.map +1 -0
  29. package/dist/agents/network.d.ts +1006 -0
  30. package/dist/agents/network.d.ts.map +1 -0
  31. package/dist/agents/network.js +1266 -0
  32. package/dist/agents/network.js.map +1 -0
  33. package/dist/cli/commands/backup.d.ts +3 -0
  34. package/dist/cli/commands/backup.d.ts.map +1 -0
  35. package/dist/cli/commands/backup.js +63 -0
  36. package/dist/cli/commands/backup.js.map +1 -0
  37. package/dist/cli/commands/config.d.ts +3 -0
  38. package/dist/cli/commands/config.d.ts.map +1 -0
  39. package/dist/cli/commands/config.js +163 -0
  40. package/dist/cli/commands/config.js.map +1 -0
  41. package/dist/cli/commands/doctor.d.ts +3 -0
  42. package/dist/cli/commands/doctor.d.ts.map +1 -0
  43. package/dist/cli/commands/doctor.js +107 -0
  44. package/dist/cli/commands/doctor.js.map +1 -0
  45. package/dist/cli/commands/init.d.ts +3 -0
  46. package/dist/cli/commands/init.d.ts.map +1 -0
  47. package/dist/cli/commands/init.js +138 -0
  48. package/dist/cli/commands/init.js.map +1 -0
  49. package/dist/cli/commands/logs.d.ts +3 -0
  50. package/dist/cli/commands/logs.d.ts.map +1 -0
  51. package/dist/cli/commands/logs.js +81 -0
  52. package/dist/cli/commands/logs.js.map +1 -0
  53. package/dist/cli/commands/otp.d.ts +3 -0
  54. package/dist/cli/commands/otp.d.ts.map +1 -0
  55. package/dist/cli/commands/otp.js +142 -0
  56. package/dist/cli/commands/otp.js.map +1 -0
  57. package/dist/cli/commands/restore.d.ts +3 -0
  58. package/dist/cli/commands/restore.d.ts.map +1 -0
  59. package/dist/cli/commands/restore.js +99 -0
  60. package/dist/cli/commands/restore.js.map +1 -0
  61. package/dist/cli/commands/start.d.ts +3 -0
  62. package/dist/cli/commands/start.d.ts.map +1 -0
  63. package/dist/cli/commands/start.js +65 -0
  64. package/dist/cli/commands/start.js.map +1 -0
  65. package/dist/cli/commands/status.d.ts +3 -0
  66. package/dist/cli/commands/status.d.ts.map +1 -0
  67. package/dist/cli/commands/status.js +68 -0
  68. package/dist/cli/commands/status.js.map +1 -0
  69. package/dist/cli/commands/stop.d.ts +3 -0
  70. package/dist/cli/commands/stop.d.ts.map +1 -0
  71. package/dist/cli/commands/stop.js +62 -0
  72. package/dist/cli/commands/stop.js.map +1 -0
  73. package/dist/cli/commands/update.d.ts +3 -0
  74. package/dist/cli/commands/update.d.ts.map +1 -0
  75. package/dist/cli/commands/update.js +49 -0
  76. package/dist/cli/commands/update.js.map +1 -0
  77. package/dist/cli/commands/whatsapp.d.ts +3 -0
  78. package/dist/cli/commands/whatsapp.d.ts.map +1 -0
  79. package/dist/cli/commands/whatsapp.js +281 -0
  80. package/dist/cli/commands/whatsapp.js.map +1 -0
  81. package/dist/cli/index.d.ts +7 -0
  82. package/dist/cli/index.d.ts.map +1 -0
  83. package/dist/cli/index.js +58 -0
  84. package/dist/cli/index.js.map +1 -0
  85. package/dist/cli.d.ts +9 -0
  86. package/dist/cli.d.ts.map +1 -0
  87. package/dist/cli.js +750 -0
  88. package/dist/cli.js.map +1 -0
  89. package/dist/index.d.ts +2 -0
  90. package/dist/index.d.ts.map +1 -0
  91. package/dist/index.js +109 -0
  92. package/dist/index.js.map +1 -0
  93. package/dist/mastra/index.d.ts +4 -0
  94. package/dist/mastra/index.d.ts.map +1 -0
  95. package/dist/mastra/index.js +37 -0
  96. package/dist/mastra/index.js.map +1 -0
  97. package/dist/mastra/memory.d.ts +9 -0
  98. package/dist/mastra/memory.d.ts.map +1 -0
  99. package/dist/mastra/memory.js +92 -0
  100. package/dist/mastra/memory.js.map +1 -0
  101. package/dist/processors/index.d.ts +74 -0
  102. package/dist/processors/index.d.ts.map +1 -0
  103. package/dist/processors/index.js +153 -0
  104. package/dist/processors/index.js.map +1 -0
  105. package/dist/processors/semantic-recall.d.ts +63 -0
  106. package/dist/processors/semantic-recall.d.ts.map +1 -0
  107. package/dist/processors/semantic-recall.js +216 -0
  108. package/dist/processors/semantic-recall.js.map +1 -0
  109. package/dist/processors/tool-search.d.ts +26 -0
  110. package/dist/processors/tool-search.d.ts.map +1 -0
  111. package/dist/processors/tool-search.js +41 -0
  112. package/dist/processors/tool-search.js.map +1 -0
  113. package/dist/skills/dynamic/skill-generator.d.ts +169 -0
  114. package/dist/skills/dynamic/skill-generator.d.ts.map +1 -0
  115. package/dist/skills/dynamic/skill-generator.js +488 -0
  116. package/dist/skills/dynamic/skill-generator.js.map +1 -0
  117. package/dist/tools/agent-delegation-tools.d.ts +142 -0
  118. package/dist/tools/agent-delegation-tools.d.ts.map +1 -0
  119. package/dist/tools/agent-delegation-tools.js +263 -0
  120. package/dist/tools/agent-delegation-tools.js.map +1 -0
  121. package/dist/tools/browser-tools.d.ts +374 -0
  122. package/dist/tools/browser-tools.d.ts.map +1 -0
  123. package/dist/tools/browser-tools.js +752 -0
  124. package/dist/tools/browser-tools.js.map +1 -0
  125. package/dist/tools/dynamic/registry.d.ts +61 -0
  126. package/dist/tools/dynamic/registry.d.ts.map +1 -0
  127. package/dist/tools/dynamic/registry.js +121 -0
  128. package/dist/tools/dynamic/registry.js.map +1 -0
  129. package/dist/tools/dynamic/tool-generator.d.ts +99 -0
  130. package/dist/tools/dynamic/tool-generator.d.ts.map +1 -0
  131. package/dist/tools/dynamic/tool-generator.js +367 -0
  132. package/dist/tools/dynamic/tool-generator.js.map +1 -0
  133. package/dist/tools/extended-tools.d.ts +176 -0
  134. package/dist/tools/extended-tools.d.ts.map +1 -0
  135. package/dist/tools/extended-tools.js +464 -0
  136. package/dist/tools/extended-tools.js.map +1 -0
  137. package/dist/tools/library/calendar/index.d.ts +134 -0
  138. package/dist/tools/library/calendar/index.d.ts.map +1 -0
  139. package/dist/tools/library/calendar/index.js +160 -0
  140. package/dist/tools/library/calendar/index.js.map +1 -0
  141. package/dist/tools/podman-workspace-mcp-cli.d.ts +3 -0
  142. package/dist/tools/podman-workspace-mcp-cli.d.ts.map +1 -0
  143. package/dist/tools/podman-workspace-mcp-cli.js +12 -0
  144. package/dist/tools/podman-workspace-mcp-cli.js.map +1 -0
  145. package/dist/tools/podman-workspace-mcp.d.ts +247 -0
  146. package/dist/tools/podman-workspace-mcp.d.ts.map +1 -0
  147. package/dist/tools/podman-workspace-mcp.js +1093 -0
  148. package/dist/tools/podman-workspace-mcp.js.map +1 -0
  149. package/dist/tools/podman-workspace.d.ts +148 -0
  150. package/dist/tools/podman-workspace.d.ts.map +1 -0
  151. package/dist/tools/podman-workspace.js +682 -0
  152. package/dist/tools/podman-workspace.js.map +1 -0
  153. package/dist/tools/telegram-file-tools.d.ts +78 -0
  154. package/dist/tools/telegram-file-tools.d.ts.map +1 -0
  155. package/dist/tools/telegram-file-tools.js +294 -0
  156. package/dist/tools/telegram-file-tools.js.map +1 -0
  157. package/dist/tools/tool-registry.d.ts +467 -0
  158. package/dist/tools/tool-registry.d.ts.map +1 -0
  159. package/dist/tools/tool-registry.js +156 -0
  160. package/dist/tools/tool-registry.js.map +1 -0
  161. package/dist/tools/web-tools.d.ts +77 -0
  162. package/dist/tools/web-tools.d.ts.map +1 -0
  163. package/dist/tools/web-tools.js +416 -0
  164. package/dist/tools/web-tools.js.map +1 -0
  165. package/dist/tools/whatsapp-autoreply-tools.d.ts +118 -0
  166. package/dist/tools/whatsapp-autoreply-tools.d.ts.map +1 -0
  167. package/dist/tools/whatsapp-autoreply-tools.js +503 -0
  168. package/dist/tools/whatsapp-autoreply-tools.js.map +1 -0
  169. package/dist/tools/whatsapp-tools.d.ts +175 -0
  170. package/dist/tools/whatsapp-tools.d.ts.map +1 -0
  171. package/dist/tools/whatsapp-tools.js +566 -0
  172. package/dist/tools/whatsapp-tools.js.map +1 -0
  173. package/dist/utils/logger.d.ts +65 -0
  174. package/dist/utils/logger.d.ts.map +1 -0
  175. package/dist/utils/logger.js +307 -0
  176. package/dist/utils/logger.js.map +1 -0
  177. package/dist/utils/model-config.d.ts +73 -0
  178. package/dist/utils/model-config.d.ts.map +1 -0
  179. package/dist/utils/model-config.js +366 -0
  180. package/dist/utils/model-config.js.map +1 -0
  181. package/dist/utils/semantic-memory.d.ts +82 -0
  182. package/dist/utils/semantic-memory.d.ts.map +1 -0
  183. package/dist/utils/semantic-memory.js +189 -0
  184. package/dist/utils/semantic-memory.js.map +1 -0
  185. package/dist/utils/system.d.ts +2 -0
  186. package/dist/utils/system.d.ts.map +1 -0
  187. package/dist/utils/system.js +24 -0
  188. package/dist/utils/system.js.map +1 -0
  189. package/dist/utils/telegram-auth.d.ts +54 -0
  190. package/dist/utils/telegram-auth.d.ts.map +1 -0
  191. package/dist/utils/telegram-auth.js +146 -0
  192. package/dist/utils/telegram-auth.js.map +1 -0
  193. package/dist/utils/telegram.d.ts +7 -0
  194. package/dist/utils/telegram.d.ts.map +1 -0
  195. package/dist/utils/telegram.js +1494 -0
  196. package/dist/utils/telegram.js.map +1 -0
  197. package/dist/utils/whatsapp-client.d.ts +166 -0
  198. package/dist/utils/whatsapp-client.d.ts.map +1 -0
  199. package/dist/utils/whatsapp-client.js +722 -0
  200. package/dist/utils/whatsapp-client.js.map +1 -0
  201. package/dist/workflows/planner-workflow.d.ts +39 -0
  202. package/dist/workflows/planner-workflow.d.ts.map +1 -0
  203. package/dist/workflows/planner-workflow.js +165 -0
  204. package/dist/workflows/planner-workflow.js.map +1 -0
  205. package/dist/workflows/skill-builder-workflow.d.ts +16 -0
  206. package/dist/workflows/skill-builder-workflow.d.ts.map +1 -0
  207. package/dist/workflows/skill-builder-workflow.js +157 -0
  208. package/dist/workflows/skill-builder-workflow.js.map +1 -0
  209. package/dist/workspace/index.d.ts +23 -0
  210. package/dist/workspace/index.d.ts.map +1 -0
  211. package/dist/workspace/index.js +64 -0
  212. package/dist/workspace/index.js.map +1 -0
  213. package/docs/README.md +140 -0
  214. package/docs/api/agents.md +481 -0
  215. package/docs/api/browser-tools.md +469 -0
  216. package/docs/api/memory.md +629 -0
  217. package/docs/architecture/agent-networks.md +586 -0
  218. package/docs/architecture/memory.md +579 -0
  219. package/docs/architecture/overview.md +436 -0
  220. package/docs/architecture/tools.md +637 -0
  221. package/docs/cli-tui.md +367 -0
  222. package/docs/guides/environment-variables.md +502 -0
  223. package/docs/guides/troubleshooting.md +882 -0
  224. package/docs/tutorials/agent-networks.md +432 -0
  225. package/docs/tutorials/dynamic-tools.md +469 -0
  226. package/docs/tutorials/getting-started.md +263 -0
  227. package/docs/tutorials/skills.md +561 -0
  228. package/docs/tutorials/web-browsing.md +329 -0
  229. package/mastra.db-shm +0 -0
  230. package/mastra.db-wal +0 -0
  231. package/package.json +71 -0
  232. package/plan.md +601 -0
  233. package/skills/code-review/SKILL.md +48 -0
  234. package/skills/task-planning/SKILL.md +55 -0
  235. package/skills/web-research/SKILL.md +79 -0
  236. package/skills/whatsapp-management/SKILL.md +78 -0
  237. package/src/agents/autonomous-agent.ts +626 -0
  238. package/src/agents/network.ts +1307 -0
  239. package/src/cli/commands/backup.ts +78 -0
  240. package/src/cli/commands/config.ts +176 -0
  241. package/src/cli/commands/doctor.ts +111 -0
  242. package/src/cli/commands/init.ts +150 -0
  243. package/src/cli/commands/logs.ts +94 -0
  244. package/src/cli/commands/otp.ts +162 -0
  245. package/src/cli/commands/restore.ts +118 -0
  246. package/src/cli/commands/start.ts +76 -0
  247. package/src/cli/commands/status.ts +81 -0
  248. package/src/cli/commands/stop.ts +68 -0
  249. package/src/cli/commands/update.ts +61 -0
  250. package/src/cli/commands/whatsapp.ts +322 -0
  251. package/src/cli/index.ts +69 -0
  252. package/src/cli.ts +830 -0
  253. package/src/index.ts +124 -0
  254. package/src/mastra/index.ts +49 -0
  255. package/src/mastra/memory.ts +99 -0
  256. package/src/mastra/public/workspace/plan.md +115 -0
  257. package/src/mastra/public/workspace/research/react-tailwind/skill.md +47 -0
  258. package/src/processors/index.ts +170 -0
  259. package/src/processors/semantic-recall.ts +277 -0
  260. package/src/processors/tool-search.ts +46 -0
  261. package/src/skills/dynamic/skill-generator.ts +568 -0
  262. package/src/tools/agent-delegation-tools.ts +301 -0
  263. package/src/tools/browser-tools.ts +792 -0
  264. package/src/tools/dynamic/registry.ts +144 -0
  265. package/src/tools/dynamic/tool-generator.ts +406 -0
  266. package/src/tools/extended-tools.ts +498 -0
  267. package/src/tools/library/calendar/index.ts +172 -0
  268. package/src/tools/podman-workspace-mcp-cli.ts +14 -0
  269. package/src/tools/podman-workspace-mcp.ts +1290 -0
  270. package/src/tools/podman-workspace.ts +858 -0
  271. package/src/tools/telegram-file-tools.ts +320 -0
  272. package/src/tools/tool-registry.ts +233 -0
  273. package/src/tools/web-tools.ts +461 -0
  274. package/src/tools/whatsapp-autoreply-tools.ts +616 -0
  275. package/src/tools/whatsapp-tools.ts +602 -0
  276. package/src/utils/logger.ts +368 -0
  277. package/src/utils/model-config.ts +437 -0
  278. package/src/utils/semantic-memory.ts +230 -0
  279. package/src/utils/system.ts +25 -0
  280. package/src/utils/telegram-auth.ts +201 -0
  281. package/src/utils/telegram.ts +1847 -0
  282. package/src/utils/whatsapp-client.ts +808 -0
  283. package/src/workflows/planner-workflow.ts +178 -0
  284. package/src/workflows/skill-builder-workflow.ts +175 -0
  285. package/src/workspace/index.ts +69 -0
  286. package/tsconfig.json +22 -0
  287. package/view-logs.sh +116 -0
  288. package/whatsapp-session.sh +197 -0
@@ -0,0 +1,461 @@
1
+ import { createTool } from "@mastra/core/tools";
2
+ import { z } from "zod";
3
+ import axios from "axios";
4
+ import * as cheerio from "cheerio";
5
+ import { logger } from "../utils/logger.js";
6
+
7
+ /**
8
+ * Tool: Fetch Web Page Content
9
+ * Fetches and extracts content from a web page URL
10
+ */
11
+ export const fetchWebContentTool = createTool({
12
+ id: "fetch-web-content",
13
+ description: `
14
+ Fetches and extracts the main content from a web page URL.
15
+ Use this when you need to read articles, documentation, or any web content.
16
+ Returns the content in a clean, readable format with title and main text.
17
+ `,
18
+ inputSchema: z.object({
19
+ url: z.string().url().describe("The URL of the web page to fetch"),
20
+ extractLinks: z.boolean().optional().default(false).describe("Whether to also extract links from the page"),
21
+ }),
22
+ outputSchema: z.object({
23
+ success: z.boolean(),
24
+ url: z.string(),
25
+ title: z.string(),
26
+ content: z.string(),
27
+ excerpt: z.string(),
28
+ links: z.array(z.object({
29
+ text: z.string(),
30
+ url: z.string(),
31
+ })).optional(),
32
+ error: z.string().optional(),
33
+ }),
34
+ execute: async (inputData) => {
35
+ const startTime = Date.now();
36
+ const { url, extractLinks } = inputData;
37
+
38
+ logger.info("WEB_TOOL", `Fetching web content: ${url}`, {
39
+ extractLinks,
40
+ });
41
+
42
+ try {
43
+ // Fetch the HTML with proper headers
44
+ const response = await axios.get(url, {
45
+ timeout: 15000,
46
+ headers: {
47
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
48
+ "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
49
+ "Accept-Language": "en-US,en;q=0.5",
50
+ },
51
+ maxRedirects: 5,
52
+ });
53
+
54
+ const html = response.data;
55
+ const $ = cheerio.load(html);
56
+
57
+ // Remove script and style elements
58
+ $("script, style, nav, footer, iframe, noscript").remove();
59
+
60
+ // Extract title
61
+ const title = $("title").text().trim() || $("h1").first().text().trim() || "Untitled";
62
+
63
+ // Try to find main content area
64
+ let contentArea = $("article, main, [role='main'], .content, #content, .post, .entry").first();
65
+ if (contentArea.length === 0) {
66
+ contentArea = $("body");
67
+ }
68
+
69
+ // Extract text content
70
+ let content = contentArea.text()
71
+ .replace(/\s+/g, " ")
72
+ .replace(/\n+/g, "\n")
73
+ .trim();
74
+
75
+ // Limit content length
76
+ const maxLength = 8000;
77
+ if (content.length > maxLength) {
78
+ content = content.substring(0, maxLength) + "... [content truncated]";
79
+ }
80
+
81
+ // Generate excerpt
82
+ const excerpt = content.substring(0, 200) + (content.length > 200 ? "..." : "");
83
+
84
+ // Extract links if requested
85
+ let links: Array<{ text: string; url: string }> | undefined;
86
+ if (extractLinks) {
87
+ links = [];
88
+ contentArea.find("a[href]").each((_, elem) => {
89
+ const linkUrl = $(elem).attr("href");
90
+ const linkText = $(elem).text().trim();
91
+ if (linkUrl && linkText && links && links.length < 20) {
92
+ // Resolve relative URLs
93
+ const absoluteUrl = new URL(linkUrl, url).href;
94
+ links.push({ text: linkText, url: absoluteUrl });
95
+ }
96
+ });
97
+ }
98
+
99
+ const result = {
100
+ success: true,
101
+ url,
102
+ title,
103
+ content,
104
+ excerpt,
105
+ links: extractLinks ? links : undefined,
106
+ };
107
+
108
+ const duration = Date.now() - startTime;
109
+ logger.info("WEB_TOOL", `Fetched web content successfully`, {
110
+ url,
111
+ title,
112
+ contentLength: content.length,
113
+ linksCount: links?.length || 0,
114
+ duration: `${duration}ms`,
115
+ });
116
+
117
+ return result;
118
+ } catch (error) {
119
+ const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
120
+ const duration = Date.now() - startTime;
121
+
122
+ logger.error("WEB_TOOL", `Failed to fetch web content: ${errorMessage}`, {
123
+ url,
124
+ error: errorMessage,
125
+ duration: `${duration}ms`,
126
+ });
127
+
128
+ return {
129
+ success: false,
130
+ url: inputData.url,
131
+ title: "Error",
132
+ content: "",
133
+ excerpt: "",
134
+ error: errorMessage,
135
+ };
136
+ }
137
+ },
138
+ });
139
+
140
+ /**
141
+ * Tool: Search the Web
142
+ * Performs a web search using DuckDuckGo (no API key required)
143
+ */
144
+ export const searchWebTool = createTool({
145
+ id: "search-web",
146
+ description: `
147
+ Searches the web for information on a given query.
148
+ Use this when you need to find current information, research topics, or discover web pages.
149
+ Returns search results with titles, snippets, and URLs.
150
+ `,
151
+ inputSchema: z.object({
152
+ query: z.string().describe("The search query"),
153
+ numResults: z.number().min(1).max(10).optional().describe("Number of results to return (1-10)"),
154
+ }),
155
+ outputSchema: z.object({
156
+ success: z.boolean(),
157
+ query: z.string(),
158
+ results: z.array(z.object({
159
+ title: z.string(),
160
+ snippet: z.string(),
161
+ url: z.string(),
162
+ })),
163
+ error: z.string().optional(),
164
+ }),
165
+ execute: async (inputData) => {
166
+ const startTime = Date.now();
167
+ const { query, numResults } = inputData;
168
+ const limit = Math.min(Math.max(numResults ?? 5, 1), 10);
169
+
170
+ logger.info("WEB_TOOL", `Searching web: "${query}"`, {
171
+ numResults: limit,
172
+ });
173
+
174
+ try {
175
+ // Use DuckDuckGo HTML search
176
+ const searchUrl = `https://html.duckduckgo.com/html/?q=${encodeURIComponent(query)}`;
177
+
178
+ const response = await axios.get(searchUrl, {
179
+ timeout: 10000,
180
+ headers: {
181
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
182
+ },
183
+ });
184
+
185
+ const $ = cheerio.load(response.data);
186
+ const results: Array<{ title: string; snippet: string; url: string }> = [];
187
+
188
+ // Parse search results
189
+ $(".result").each((i, elem) => {
190
+ if (results.length >= limit) return;
191
+
192
+ const titleElem = $(elem).find(".result__a").first();
193
+ const snippetElem = $(elem).find(".result__snippet").first();
194
+ const urlElem = $(elem).find(".result__url").first();
195
+
196
+ const title = titleElem.text().trim();
197
+ const snippet = snippetElem.text().trim();
198
+ let url = urlElem.text().trim();
199
+
200
+ // If URL not found in result__url, try to get from title link
201
+ if (!url && titleElem.length) {
202
+ const href = titleElem.attr("href");
203
+ if (href) {
204
+ // DuckDuckGo uses redirects, extract actual URL
205
+ const match = href.match(/uddg=([^&]+)/);
206
+ if (match) {
207
+ url = decodeURIComponent(match[1]);
208
+ }
209
+ }
210
+ }
211
+
212
+ if (title && url) {
213
+ results.push({ title, snippet, url });
214
+ }
215
+ });
216
+
217
+ const duration = Date.now() - startTime;
218
+ logger.info("WEB_TOOL", `Web search completed`, {
219
+ query,
220
+ resultsCount: results.length,
221
+ duration: `${duration}ms`,
222
+ });
223
+
224
+ return {
225
+ success: true,
226
+ query,
227
+ results,
228
+ };
229
+ } catch (error) {
230
+ const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
231
+ const duration = Date.now() - startTime;
232
+
233
+ logger.error("WEB_TOOL", `Web search failed: ${errorMessage}`, {
234
+ query,
235
+ error: errorMessage,
236
+ duration: `${duration}ms`,
237
+ });
238
+
239
+ return {
240
+ success: false,
241
+ query: inputData.query,
242
+ results: [],
243
+ error: errorMessage,
244
+ };
245
+ }
246
+ },
247
+ });
248
+
249
+ /**
250
+ * Tool: Extract Structured Data from Web Page
251
+ * Extracts specific data from a web page using CSS selectors
252
+ */
253
+ export const extractStructuredDataTool = createTool({
254
+ id: "extract-structured-data",
255
+ description: `
256
+ Extracts structured data from a web page using CSS selectors.
257
+ Use this when you need to scrape specific elements like prices, ratings, product info, etc.
258
+ Specify the URL and a map of fields with their CSS selectors.
259
+ `,
260
+ inputSchema: z.object({
261
+ url: z.string().url().describe("The URL of the web page to scrape"),
262
+ fields: z.record(z.object({
263
+ selector: z.string().describe("CSS selector to extract the field"),
264
+ attribute: z.string().optional().describe("Attribute to extract (e.g., 'href', 'src'). Leave empty for text content"),
265
+ multiple: z.boolean().optional().default(false).describe("Whether to extract multiple values"),
266
+ })).describe("Map of field names to extraction rules"),
267
+ }),
268
+ outputSchema: z.object({
269
+ success: z.boolean(),
270
+ url: z.string(),
271
+ data: z.record(z.any()),
272
+ error: z.string().optional(),
273
+ }),
274
+ execute: async (inputData) => {
275
+ const startTime = Date.now();
276
+ const { url, fields } = inputData;
277
+
278
+ logger.info("WEB_TOOL", `Extracting structured data from: ${url}`, {
279
+ fields: Object.keys(fields),
280
+ });
281
+
282
+ try {
283
+ const response = await axios.get(url, {
284
+ timeout: 15000,
285
+ headers: {
286
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
287
+ },
288
+ });
289
+
290
+ const $ = cheerio.load(response.data);
291
+ const data: Record<string, any> = {};
292
+
293
+ for (const [fieldName, config] of Object.entries(fields)) {
294
+ const { selector, attribute, multiple } = config;
295
+
296
+ if (multiple) {
297
+ // Extract multiple values
298
+ const values: string[] = [];
299
+ $(selector).each((_, elem) => {
300
+ const value = attribute
301
+ ? $(elem).attr(attribute)
302
+ : $(elem).text().trim();
303
+ if (value) values.push(value);
304
+ });
305
+ data[fieldName] = values;
306
+ } else {
307
+ // Extract single value
308
+ const elem = $(selector).first();
309
+ const value = attribute
310
+ ? elem.attr(attribute)
311
+ : elem.text().trim();
312
+ data[fieldName] = value || null;
313
+ }
314
+ }
315
+
316
+ const duration = Date.now() - startTime;
317
+ logger.info("WEB_TOOL", `Structured data extraction completed`, {
318
+ url,
319
+ fieldsCount: Object.keys(data).length,
320
+ duration: `${duration}ms`,
321
+ });
322
+
323
+ return {
324
+ success: true,
325
+ url,
326
+ data,
327
+ };
328
+ } catch (error) {
329
+ const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
330
+ const duration = Date.now() - startTime;
331
+
332
+ logger.error("WEB_TOOL", `Structured data extraction failed: ${errorMessage}`, {
333
+ url,
334
+ error: errorMessage,
335
+ duration: `${duration}ms`,
336
+ });
337
+
338
+ return {
339
+ success: false,
340
+ url: inputData.url,
341
+ data: {},
342
+ error: errorMessage,
343
+ };
344
+ }
345
+ },
346
+ });
347
+
348
+ /**
349
+ * Tool: Deep Web Research
350
+ * Performs comprehensive research by searching and reading multiple pages
351
+ */
352
+ export const deepResearchTool = createTool({
353
+ id: "deep-research",
354
+ description: `
355
+ Performs comprehensive web research on a topic.
356
+ This tool searches the web, reads relevant pages, and synthesizes information.
357
+ Use this for thorough research on any topic.
358
+ `,
359
+ inputSchema: z.object({
360
+ topic: z.string().describe("The research topic or question"),
361
+ depth: z.enum(["basic", "standard", "deep"]).optional().default("standard").describe("Research depth"),
362
+ }),
363
+ outputSchema: z.object({
364
+ success: z.boolean(),
365
+ topic: z.string(),
366
+ summary: z.string(),
367
+ sources: z.array(z.object({
368
+ title: z.string(),
369
+ url: z.string(),
370
+ relevance: z.string(),
371
+ })),
372
+ error: z.string().optional(),
373
+ }),
374
+ execute: async (inputData) => {
375
+ const startTime = Date.now();
376
+ const { topic, depth } = inputData;
377
+ const numSources = depth === "basic" ? 3 : depth === "standard" ? 5 : 8;
378
+
379
+ logger.info("WEB_TOOL", `Starting deep research on: "${topic}"`, {
380
+ depth,
381
+ targetSources: numSources,
382
+ });
383
+
384
+ try {
385
+ // Search for the topic
386
+ const searchUrl = `https://html.duckduckgo.com/html/?q=${encodeURIComponent(topic)}`;
387
+ const response = await axios.get(searchUrl, {
388
+ timeout: 10000,
389
+ headers: {
390
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
391
+ },
392
+ });
393
+
394
+ const $ = cheerio.load(response.data);
395
+ const sources: Array<{ title: string; url: string; relevance: string }> = [];
396
+
397
+ $(".result").each((i, elem) => {
398
+ if (sources.length >= numSources) return;
399
+
400
+ const titleElem = $(elem).find(".result__a").first();
401
+ const snippetElem = $(elem).find(".result__snippet").first();
402
+
403
+ const title = titleElem.text().trim();
404
+ const snippet = snippetElem.text().trim();
405
+
406
+ let url = "";
407
+ const href = titleElem.attr("href");
408
+ if (href) {
409
+ const match = href.match(/uddg=([^&]+)/);
410
+ if (match) {
411
+ url = decodeURIComponent(match[1]);
412
+ }
413
+ }
414
+
415
+ if (title && url) {
416
+ sources.push({
417
+ title,
418
+ url,
419
+ relevance: snippet.substring(0, 150),
420
+ });
421
+ }
422
+ });
423
+
424
+ // Create summary
425
+ const summary = `Found ${sources.length} relevant sources for "${topic}". ` +
426
+ `These sources include ${sources.map(s => s.title).slice(0, 3).join(", ")}` +
427
+ (sources.length > 3 ? ` and ${sources.length - 3} others.` : ".");
428
+
429
+ const duration = Date.now() - startTime;
430
+ logger.info("WEB_TOOL", `Deep research completed`, {
431
+ topic,
432
+ sourcesFound: sources.length,
433
+ duration: `${duration}ms`,
434
+ });
435
+
436
+ return {
437
+ success: true,
438
+ topic,
439
+ summary,
440
+ sources,
441
+ };
442
+ } catch (error) {
443
+ const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
444
+ const duration = Date.now() - startTime;
445
+
446
+ logger.error("WEB_TOOL", `Deep research failed: ${errorMessage}`, {
447
+ topic,
448
+ error: errorMessage,
449
+ duration: `${duration}ms`,
450
+ });
451
+
452
+ return {
453
+ success: false,
454
+ topic: inputData.topic,
455
+ summary: "",
456
+ sources: [],
457
+ error: errorMessage,
458
+ };
459
+ }
460
+ },
461
+ });