atena-cli 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (475) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +210 -0
  3. package/dist/agent.d.ts +44 -0
  4. package/dist/agent.d.ts.map +1 -0
  5. package/dist/agent.js +731 -0
  6. package/dist/agent.js.map +1 -0
  7. package/dist/agents.d.ts +33 -0
  8. package/dist/agents.d.ts.map +1 -0
  9. package/dist/agents.js +162 -0
  10. package/dist/agents.js.map +1 -0
  11. package/dist/autocomplete.d.ts +4 -0
  12. package/dist/autocomplete.d.ts.map +1 -0
  13. package/dist/autocomplete.js +96 -0
  14. package/dist/autocomplete.js.map +1 -0
  15. package/dist/cli/commands/connect.d.ts +3 -0
  16. package/dist/cli/commands/connect.d.ts.map +1 -0
  17. package/dist/cli/commands/connect.js +31 -0
  18. package/dist/cli/commands/connect.js.map +1 -0
  19. package/dist/cli/commands/deploy.d.ts +3 -0
  20. package/dist/cli/commands/deploy.d.ts.map +1 -0
  21. package/dist/cli/commands/deploy.js +26 -0
  22. package/dist/cli/commands/deploy.js.map +1 -0
  23. package/dist/cli/commands/login.d.ts +3 -0
  24. package/dist/cli/commands/login.d.ts.map +1 -0
  25. package/dist/cli/commands/login.js +46 -0
  26. package/dist/cli/commands/login.js.map +1 -0
  27. package/dist/cli/commands/vault.d.ts +3 -0
  28. package/dist/cli/commands/vault.d.ts.map +1 -0
  29. package/dist/cli/commands/vault.js +73 -0
  30. package/dist/cli/commands/vault.js.map +1 -0
  31. package/dist/cli/index.d.ts +3 -0
  32. package/dist/cli/index.d.ts.map +1 -0
  33. package/dist/cli/index.js +309 -0
  34. package/dist/cli/index.js.map +1 -0
  35. package/dist/cli/init/setup.d.ts +3 -0
  36. package/dist/cli/init/setup.d.ts.map +1 -0
  37. package/dist/cli/init/setup.js +74 -0
  38. package/dist/cli/init/setup.js.map +1 -0
  39. package/dist/cli/menus.d.ts +2 -0
  40. package/dist/cli/menus.d.ts.map +1 -0
  41. package/dist/cli/menus.js +111 -0
  42. package/dist/cli/menus.js.map +1 -0
  43. package/dist/cli/postinstall.d.ts +9 -0
  44. package/dist/cli/postinstall.d.ts.map +1 -0
  45. package/dist/cli/postinstall.js +81 -0
  46. package/dist/cli/postinstall.js.map +1 -0
  47. package/dist/cli/realtime-input.d.ts +4 -0
  48. package/dist/cli/realtime-input.d.ts.map +1 -0
  49. package/dist/cli/realtime-input.js +268 -0
  50. package/dist/cli/realtime-input.js.map +1 -0
  51. package/dist/cli/setup.d.ts +26 -0
  52. package/dist/cli/setup.d.ts.map +1 -0
  53. package/dist/cli/setup.js +202 -0
  54. package/dist/cli/setup.js.map +1 -0
  55. package/dist/cli/themes.d.ts +30 -0
  56. package/dist/cli/themes.d.ts.map +1 -0
  57. package/dist/cli/themes.js +225 -0
  58. package/dist/cli/themes.js.map +1 -0
  59. package/dist/cli/ui.d.ts +70 -0
  60. package/dist/cli/ui.d.ts.map +1 -0
  61. package/dist/cli/ui.js +455 -0
  62. package/dist/cli/ui.js.map +1 -0
  63. package/dist/commands.d.ts +16 -0
  64. package/dist/commands.d.ts.map +1 -0
  65. package/dist/commands.js +230 -0
  66. package/dist/commands.js.map +1 -0
  67. package/dist/config.d.ts +42 -0
  68. package/dist/config.d.ts.map +1 -0
  69. package/dist/config.js +140 -0
  70. package/dist/config.js.map +1 -0
  71. package/dist/context.d.ts +23 -0
  72. package/dist/context.d.ts.map +1 -0
  73. package/dist/context.js +80 -0
  74. package/dist/context.js.map +1 -0
  75. package/dist/core/agent.d.ts +94 -0
  76. package/dist/core/agent.d.ts.map +1 -0
  77. package/dist/core/agent.js +1280 -0
  78. package/dist/core/agent.js.map +1 -0
  79. package/dist/core/agents/enterprise/backend.d.ts +3 -0
  80. package/dist/core/agents/enterprise/backend.d.ts.map +1 -0
  81. package/dist/core/agents/enterprise/backend.js +35 -0
  82. package/dist/core/agents/enterprise/backend.js.map +1 -0
  83. package/dist/core/agents/enterprise/cloud.d.ts +3 -0
  84. package/dist/core/agents/enterprise/cloud.d.ts.map +1 -0
  85. package/dist/core/agents/enterprise/cloud.js +35 -0
  86. package/dist/core/agents/enterprise/cloud.js.map +1 -0
  87. package/dist/core/agents/enterprise/datascience.d.ts +3 -0
  88. package/dist/core/agents/enterprise/datascience.d.ts.map +1 -0
  89. package/dist/core/agents/enterprise/datascience.js +35 -0
  90. package/dist/core/agents/enterprise/datascience.js.map +1 -0
  91. package/dist/core/agents/enterprise/design.d.ts +3 -0
  92. package/dist/core/agents/enterprise/design.d.ts.map +1 -0
  93. package/dist/core/agents/enterprise/design.js +35 -0
  94. package/dist/core/agents/enterprise/design.js.map +1 -0
  95. package/dist/core/agents/enterprise/devops.d.ts +3 -0
  96. package/dist/core/agents/enterprise/devops.d.ts.map +1 -0
  97. package/dist/core/agents/enterprise/devops.js +35 -0
  98. package/dist/core/agents/enterprise/devops.js.map +1 -0
  99. package/dist/core/agents/enterprise/finance.d.ts +3 -0
  100. package/dist/core/agents/enterprise/finance.d.ts.map +1 -0
  101. package/dist/core/agents/enterprise/finance.js +35 -0
  102. package/dist/core/agents/enterprise/finance.js.map +1 -0
  103. package/dist/core/agents/enterprise/frontend.d.ts +3 -0
  104. package/dist/core/agents/enterprise/frontend.d.ts.map +1 -0
  105. package/dist/core/agents/enterprise/frontend.js +35 -0
  106. package/dist/core/agents/enterprise/frontend.js.map +1 -0
  107. package/dist/core/agents/enterprise/hr.d.ts +3 -0
  108. package/dist/core/agents/enterprise/hr.d.ts.map +1 -0
  109. package/dist/core/agents/enterprise/hr.js +35 -0
  110. package/dist/core/agents/enterprise/hr.js.map +1 -0
  111. package/dist/core/agents/enterprise/index.d.ts +4 -0
  112. package/dist/core/agents/enterprise/index.d.ts.map +1 -0
  113. package/dist/core/agents/enterprise/index.js +44 -0
  114. package/dist/core/agents/enterprise/index.js.map +1 -0
  115. package/dist/core/agents/enterprise/legal.d.ts +3 -0
  116. package/dist/core/agents/enterprise/legal.d.ts.map +1 -0
  117. package/dist/core/agents/enterprise/legal.js +35 -0
  118. package/dist/core/agents/enterprise/legal.js.map +1 -0
  119. package/dist/core/agents/enterprise/marketing.d.ts +3 -0
  120. package/dist/core/agents/enterprise/marketing.d.ts.map +1 -0
  121. package/dist/core/agents/enterprise/marketing.js +35 -0
  122. package/dist/core/agents/enterprise/marketing.js.map +1 -0
  123. package/dist/core/agents/enterprise/pm.d.ts +3 -0
  124. package/dist/core/agents/enterprise/pm.d.ts.map +1 -0
  125. package/dist/core/agents/enterprise/pm.js +35 -0
  126. package/dist/core/agents/enterprise/pm.js.map +1 -0
  127. package/dist/core/agents/enterprise/product.d.ts +3 -0
  128. package/dist/core/agents/enterprise/product.d.ts.map +1 -0
  129. package/dist/core/agents/enterprise/product.js +35 -0
  130. package/dist/core/agents/enterprise/product.js.map +1 -0
  131. package/dist/core/agents/enterprise/qa.d.ts +3 -0
  132. package/dist/core/agents/enterprise/qa.d.ts.map +1 -0
  133. package/dist/core/agents/enterprise/qa.js +35 -0
  134. package/dist/core/agents/enterprise/qa.js.map +1 -0
  135. package/dist/core/agents/enterprise/sales.d.ts +3 -0
  136. package/dist/core/agents/enterprise/sales.d.ts.map +1 -0
  137. package/dist/core/agents/enterprise/sales.js +35 -0
  138. package/dist/core/agents/enterprise/sales.js.map +1 -0
  139. package/dist/core/agents/enterprise/security.d.ts +3 -0
  140. package/dist/core/agents/enterprise/security.d.ts.map +1 -0
  141. package/dist/core/agents/enterprise/security.js +36 -0
  142. package/dist/core/agents/enterprise/security.js.map +1 -0
  143. package/dist/core/agents/enterprise/support.d.ts +3 -0
  144. package/dist/core/agents/enterprise/support.d.ts.map +1 -0
  145. package/dist/core/agents/enterprise/support.js +35 -0
  146. package/dist/core/agents/enterprise/support.js.map +1 -0
  147. package/dist/core/agents.d.ts +84 -0
  148. package/dist/core/agents.d.ts.map +1 -0
  149. package/dist/core/agents.js +266 -0
  150. package/dist/core/agents.js.map +1 -0
  151. package/dist/core/analytics.d.ts +21 -0
  152. package/dist/core/analytics.d.ts.map +1 -0
  153. package/dist/core/analytics.js +57 -0
  154. package/dist/core/analytics.js.map +1 -0
  155. package/dist/core/auth.d.ts +43 -0
  156. package/dist/core/auth.d.ts.map +1 -0
  157. package/dist/core/auth.js +110 -0
  158. package/dist/core/auth.js.map +1 -0
  159. package/dist/core/code_indexer.d.ts +14 -0
  160. package/dist/core/code_indexer.d.ts.map +1 -0
  161. package/dist/core/code_indexer.js +52 -0
  162. package/dist/core/code_indexer.js.map +1 -0
  163. package/dist/core/commands.d.ts +16 -0
  164. package/dist/core/commands.d.ts.map +1 -0
  165. package/dist/core/commands.js +285 -0
  166. package/dist/core/commands.js.map +1 -0
  167. package/dist/core/consensus.d.ts +25 -0
  168. package/dist/core/consensus.d.ts.map +1 -0
  169. package/dist/core/consensus.js +49 -0
  170. package/dist/core/consensus.js.map +1 -0
  171. package/dist/core/context.d.ts +23 -0
  172. package/dist/core/context.d.ts.map +1 -0
  173. package/dist/core/context.js +82 -0
  174. package/dist/core/context.js.map +1 -0
  175. package/dist/core/eden-ai-sdk.d.ts +11 -0
  176. package/dist/core/eden-ai-sdk.d.ts.map +1 -0
  177. package/dist/core/eden-ai-sdk.js +158 -0
  178. package/dist/core/eden-ai-sdk.js.map +1 -0
  179. package/dist/core/events.d.ts +64 -0
  180. package/dist/core/events.d.ts.map +1 -0
  181. package/dist/core/events.js +18 -0
  182. package/dist/core/events.js.map +1 -0
  183. package/dist/core/groq-client.d.ts +7 -0
  184. package/dist/core/groq-client.d.ts.map +1 -0
  185. package/dist/core/groq-client.js +112 -0
  186. package/dist/core/groq-client.js.map +1 -0
  187. package/dist/core/mcp.d.ts +51 -0
  188. package/dist/core/mcp.d.ts.map +1 -0
  189. package/dist/core/mcp.js +201 -0
  190. package/dist/core/mcp.js.map +1 -0
  191. package/dist/core/memory.d.ts +20 -0
  192. package/dist/core/memory.d.ts.map +1 -0
  193. package/dist/core/memory.js +61 -0
  194. package/dist/core/memory.js.map +1 -0
  195. package/dist/core/model-profiles.d.ts +62 -0
  196. package/dist/core/model-profiles.d.ts.map +1 -0
  197. package/dist/core/model-profiles.js +841 -0
  198. package/dist/core/model-profiles.js.map +1 -0
  199. package/dist/core/moonshot-client.d.ts +7 -0
  200. package/dist/core/moonshot-client.d.ts.map +1 -0
  201. package/dist/core/moonshot-client.js +102 -0
  202. package/dist/core/moonshot-client.js.map +1 -0
  203. package/dist/core/nexus.d.ts +16 -0
  204. package/dist/core/nexus.d.ts.map +1 -0
  205. package/dist/core/nexus.js +31 -0
  206. package/dist/core/nexus.js.map +1 -0
  207. package/dist/core/notifications.d.ts +16 -0
  208. package/dist/core/notifications.d.ts.map +1 -0
  209. package/dist/core/notifications.js +26 -0
  210. package/dist/core/notifications.js.map +1 -0
  211. package/dist/core/ollama-client.d.ts +16 -0
  212. package/dist/core/ollama-client.d.ts.map +1 -0
  213. package/dist/core/ollama-client.js +138 -0
  214. package/dist/core/ollama-client.js.map +1 -0
  215. package/dist/core/orchestrator.d.ts +96 -0
  216. package/dist/core/orchestrator.d.ts.map +1 -0
  217. package/dist/core/orchestrator.js +801 -0
  218. package/dist/core/orchestrator.js.map +1 -0
  219. package/dist/core/permissions.d.ts +34 -0
  220. package/dist/core/permissions.d.ts.map +1 -0
  221. package/dist/core/permissions.js +224 -0
  222. package/dist/core/permissions.js.map +1 -0
  223. package/dist/core/providers.d.ts +22 -0
  224. package/dist/core/providers.d.ts.map +1 -0
  225. package/dist/core/providers.js +81 -0
  226. package/dist/core/providers.js.map +1 -0
  227. package/dist/core/researcher.d.ts +24 -0
  228. package/dist/core/researcher.d.ts.map +1 -0
  229. package/dist/core/researcher.js +97 -0
  230. package/dist/core/researcher.js.map +1 -0
  231. package/dist/core/sandbox.d.ts +22 -0
  232. package/dist/core/sandbox.d.ts.map +1 -0
  233. package/dist/core/sandbox.js +79 -0
  234. package/dist/core/sandbox.js.map +1 -0
  235. package/dist/core/scavenger.d.ts +5 -0
  236. package/dist/core/scavenger.d.ts.map +1 -0
  237. package/dist/core/scavenger.js +51 -0
  238. package/dist/core/scavenger.js.map +1 -0
  239. package/dist/core/server.d.ts +21 -0
  240. package/dist/core/server.d.ts.map +1 -0
  241. package/dist/core/server.js +776 -0
  242. package/dist/core/server.js.map +1 -0
  243. package/dist/core/sessions.d.ts +54 -0
  244. package/dist/core/sessions.d.ts.map +1 -0
  245. package/dist/core/sessions.js +182 -0
  246. package/dist/core/sessions.js.map +1 -0
  247. package/dist/core/setup.d.ts +12 -0
  248. package/dist/core/setup.d.ts.map +1 -0
  249. package/dist/core/setup.js +70 -0
  250. package/dist/core/setup.js.map +1 -0
  251. package/dist/core/skills.d.ts +17 -0
  252. package/dist/core/skills.d.ts.map +1 -0
  253. package/dist/core/skills.js +123 -0
  254. package/dist/core/skills.js.map +1 -0
  255. package/dist/core/stats.d.ts +54 -0
  256. package/dist/core/stats.d.ts.map +1 -0
  257. package/dist/core/stats.js +221 -0
  258. package/dist/core/stats.js.map +1 -0
  259. package/dist/core/swarm_manager.d.ts +20 -0
  260. package/dist/core/swarm_manager.d.ts.map +1 -0
  261. package/dist/core/swarm_manager.js +48 -0
  262. package/dist/core/swarm_manager.js.map +1 -0
  263. package/dist/core/system.d.ts +39 -0
  264. package/dist/core/system.d.ts.map +1 -0
  265. package/dist/core/system.js +129 -0
  266. package/dist/core/system.js.map +1 -0
  267. package/dist/core/tasks.d.ts +24 -0
  268. package/dist/core/tasks.d.ts.map +1 -0
  269. package/dist/core/tasks.js +66 -0
  270. package/dist/core/tasks.js.map +1 -0
  271. package/dist/core/telegram.d.ts +9 -0
  272. package/dist/core/telegram.d.ts.map +1 -0
  273. package/dist/core/telegram.js +49 -0
  274. package/dist/core/telegram.js.map +1 -0
  275. package/dist/core/tools/acquire_skill.d.ts +3 -0
  276. package/dist/core/tools/acquire_skill.d.ts.map +1 -0
  277. package/dist/core/tools/acquire_skill.js +30 -0
  278. package/dist/core/tools/acquire_skill.js.map +1 -0
  279. package/dist/core/tools/agent_tools.d.ts +4 -0
  280. package/dist/core/tools/agent_tools.d.ts.map +1 -0
  281. package/dist/core/tools/agent_tools.js +117 -0
  282. package/dist/core/tools/agent_tools.js.map +1 -0
  283. package/dist/core/tools/code_search.d.ts +3 -0
  284. package/dist/core/tools/code_search.d.ts.map +1 -0
  285. package/dist/core/tools/code_search.js +43 -0
  286. package/dist/core/tools/code_search.js.map +1 -0
  287. package/dist/core/tools/craft_tool.d.ts +3 -0
  288. package/dist/core/tools/craft_tool.d.ts.map +1 -0
  289. package/dist/core/tools/craft_tool.js +32 -0
  290. package/dist/core/tools/craft_tool.js.map +1 -0
  291. package/dist/core/tools/discord.d.ts +3 -0
  292. package/dist/core/tools/discord.d.ts.map +1 -0
  293. package/dist/core/tools/discord.js +206 -0
  294. package/dist/core/tools/discord.js.map +1 -0
  295. package/dist/core/tools/dynamic/registry.d.ts +15 -0
  296. package/dist/core/tools/dynamic/registry.d.ts.map +1 -0
  297. package/dist/core/tools/dynamic/registry.js +59 -0
  298. package/dist/core/tools/dynamic/registry.js.map +1 -0
  299. package/dist/core/tools/github.d.ts +3 -0
  300. package/dist/core/tools/github.d.ts.map +1 -0
  301. package/dist/core/tools/github.js +357 -0
  302. package/dist/core/tools/github.js.map +1 -0
  303. package/dist/core/tools/google.d.ts +3 -0
  304. package/dist/core/tools/google.d.ts.map +1 -0
  305. package/dist/core/tools/google.js +409 -0
  306. package/dist/core/tools/google.js.map +1 -0
  307. package/dist/core/tools/index.d.ts +4 -0
  308. package/dist/core/tools/index.d.ts.map +1 -0
  309. package/dist/core/tools/index.js +2338 -0
  310. package/dist/core/tools/index.js.map +1 -0
  311. package/dist/core/tools/optimize_prompt.d.ts +3 -0
  312. package/dist/core/tools/optimize_prompt.d.ts.map +1 -0
  313. package/dist/core/tools/optimize_prompt.js +43 -0
  314. package/dist/core/tools/optimize_prompt.js.map +1 -0
  315. package/dist/core/tools/predict_healing.d.ts +3 -0
  316. package/dist/core/tools/predict_healing.d.ts.map +1 -0
  317. package/dist/core/tools/predict_healing.js +34 -0
  318. package/dist/core/tools/predict_healing.js.map +1 -0
  319. package/dist/core/tools/sage_memory.d.ts +3 -0
  320. package/dist/core/tools/sage_memory.d.ts.map +1 -0
  321. package/dist/core/tools/sage_memory.js +29 -0
  322. package/dist/core/tools/sage_memory.js.map +1 -0
  323. package/dist/core/tools/self_heal.d.ts +3 -0
  324. package/dist/core/tools/self_heal.d.ts.map +1 -0
  325. package/dist/core/tools/self_heal.js +46 -0
  326. package/dist/core/tools/self_heal.js.map +1 -0
  327. package/dist/core/tools/send_briefing.d.ts +3 -0
  328. package/dist/core/tools/send_briefing.d.ts.map +1 -0
  329. package/dist/core/tools/send_briefing.js +31 -0
  330. package/dist/core/tools/send_briefing.js.map +1 -0
  331. package/dist/core/tools/slack.d.ts +3 -0
  332. package/dist/core/tools/slack.d.ts.map +1 -0
  333. package/dist/core/tools/slack.js +256 -0
  334. package/dist/core/tools/slack.js.map +1 -0
  335. package/dist/core/tools/telegram.d.ts +3 -0
  336. package/dist/core/tools/telegram.d.ts.map +1 -0
  337. package/dist/core/tools/telegram.js +211 -0
  338. package/dist/core/tools/telegram.js.map +1 -0
  339. package/dist/core/tools/vox.d.ts +3 -0
  340. package/dist/core/tools/vox.d.ts.map +1 -0
  341. package/dist/core/tools/vox.js +29 -0
  342. package/dist/core/tools/vox.js.map +1 -0
  343. package/dist/core/types/index.d.ts +164 -0
  344. package/dist/core/types/index.d.ts.map +1 -0
  345. package/dist/core/types/index.js +3 -0
  346. package/dist/core/types/index.js.map +1 -0
  347. package/dist/core/vault.d.ts +20 -0
  348. package/dist/core/vault.d.ts.map +1 -0
  349. package/dist/core/vault.js +91 -0
  350. package/dist/core/vault.js.map +1 -0
  351. package/dist/core/verify_v3.d.ts +2 -0
  352. package/dist/core/verify_v3.d.ts.map +1 -0
  353. package/dist/core/verify_v3.js +38 -0
  354. package/dist/core/verify_v3.js.map +1 -0
  355. package/dist/core/verify_v3_5.d.ts +2 -0
  356. package/dist/core/verify_v3_5.d.ts.map +1 -0
  357. package/dist/core/verify_v3_5.js +56 -0
  358. package/dist/core/verify_v3_5.js.map +1 -0
  359. package/dist/core/verify_v4.d.ts +2 -0
  360. package/dist/core/verify_v4.d.ts.map +1 -0
  361. package/dist/core/verify_v4.js +42 -0
  362. package/dist/core/verify_v4.js.map +1 -0
  363. package/dist/core/verify_v5.d.ts +2 -0
  364. package/dist/core/verify_v5.d.ts.map +1 -0
  365. package/dist/core/verify_v5.js +53 -0
  366. package/dist/core/verify_v5.js.map +1 -0
  367. package/dist/core/verify_v6.d.ts +2 -0
  368. package/dist/core/verify_v6.d.ts.map +1 -0
  369. package/dist/core/verify_v6.js +42 -0
  370. package/dist/core/verify_v6.js.map +1 -0
  371. package/dist/core/verify_v7.d.ts +2 -0
  372. package/dist/core/verify_v7.d.ts.map +1 -0
  373. package/dist/core/verify_v7.js +29 -0
  374. package/dist/core/verify_v7.js.map +1 -0
  375. package/dist/core/verify_v8.d.ts +2 -0
  376. package/dist/core/verify_v8.d.ts.map +1 -0
  377. package/dist/core/verify_v8.js +32 -0
  378. package/dist/core/verify_v8.js.map +1 -0
  379. package/dist/core/workflows.d.ts +24 -0
  380. package/dist/core/workflows.d.ts.map +1 -0
  381. package/dist/core/workflows.js +47 -0
  382. package/dist/core/workflows.js.map +1 -0
  383. package/dist/core/workspaces.d.ts +13 -0
  384. package/dist/core/workspaces.d.ts.map +1 -0
  385. package/dist/core/workspaces.js +45 -0
  386. package/dist/core/workspaces.js.map +1 -0
  387. package/dist/enquirer-input.d.ts +3 -0
  388. package/dist/enquirer-input.d.ts.map +1 -0
  389. package/dist/enquirer-input.js +112 -0
  390. package/dist/enquirer-input.js.map +1 -0
  391. package/dist/index.d.ts +3 -0
  392. package/dist/index.d.ts.map +1 -0
  393. package/dist/index.js +241 -0
  394. package/dist/index.js.map +1 -0
  395. package/dist/mcp.d.ts +51 -0
  396. package/dist/mcp.d.ts.map +1 -0
  397. package/dist/mcp.js +201 -0
  398. package/dist/mcp.js.map +1 -0
  399. package/dist/ollama-client.d.ts +15 -0
  400. package/dist/ollama-client.d.ts.map +1 -0
  401. package/dist/ollama-client.js +95 -0
  402. package/dist/ollama-client.js.map +1 -0
  403. package/dist/permissions.d.ts +34 -0
  404. package/dist/permissions.d.ts.map +1 -0
  405. package/dist/permissions.js +224 -0
  406. package/dist/permissions.js.map +1 -0
  407. package/dist/realtime-input.d.ts +2 -0
  408. package/dist/realtime-input.d.ts.map +1 -0
  409. package/dist/realtime-input.js +308 -0
  410. package/dist/realtime-input.js.map +1 -0
  411. package/dist/server.d.ts +20 -0
  412. package/dist/server.d.ts.map +1 -0
  413. package/dist/server.js +203 -0
  414. package/dist/server.js.map +1 -0
  415. package/dist/sessions.d.ts +50 -0
  416. package/dist/sessions.d.ts.map +1 -0
  417. package/dist/sessions.js +181 -0
  418. package/dist/sessions.js.map +1 -0
  419. package/dist/simple-input.d.ts +2 -0
  420. package/dist/simple-input.d.ts.map +1 -0
  421. package/dist/simple-input.js +83 -0
  422. package/dist/simple-input.js.map +1 -0
  423. package/dist/skills.d.ts +17 -0
  424. package/dist/skills.d.ts.map +1 -0
  425. package/dist/skills.js +194 -0
  426. package/dist/skills.js.map +1 -0
  427. package/dist/stats.d.ts +54 -0
  428. package/dist/stats.d.ts.map +1 -0
  429. package/dist/stats.js +220 -0
  430. package/dist/stats.js.map +1 -0
  431. package/dist/tools/discord.d.ts +3 -0
  432. package/dist/tools/discord.d.ts.map +1 -0
  433. package/dist/tools/discord.js +206 -0
  434. package/dist/tools/discord.js.map +1 -0
  435. package/dist/tools/github.d.ts +3 -0
  436. package/dist/tools/github.d.ts.map +1 -0
  437. package/dist/tools/github.js +357 -0
  438. package/dist/tools/github.js.map +1 -0
  439. package/dist/tools/google.d.ts +3 -0
  440. package/dist/tools/google.d.ts.map +1 -0
  441. package/dist/tools/google.js +409 -0
  442. package/dist/tools/google.js.map +1 -0
  443. package/dist/tools/index.d.ts +4 -0
  444. package/dist/tools/index.d.ts.map +1 -0
  445. package/dist/tools/index.js +2139 -0
  446. package/dist/tools/index.js.map +1 -0
  447. package/dist/tools/slack.d.ts +3 -0
  448. package/dist/tools/slack.d.ts.map +1 -0
  449. package/dist/tools/slack.js +256 -0
  450. package/dist/tools/slack.js.map +1 -0
  451. package/dist/tools/telegram.d.ts +3 -0
  452. package/dist/tools/telegram.d.ts.map +1 -0
  453. package/dist/tools/telegram.js +211 -0
  454. package/dist/tools/telegram.js.map +1 -0
  455. package/dist/types/index.d.ts +152 -0
  456. package/dist/types/index.d.ts.map +1 -0
  457. package/dist/types/index.js +3 -0
  458. package/dist/types/index.js.map +1 -0
  459. package/dist/ui.d.ts +101 -0
  460. package/dist/ui.d.ts.map +1 -0
  461. package/dist/ui.js +317 -0
  462. package/dist/ui.js.map +1 -0
  463. package/dist/web/src/lib/utils.d.ts +3 -0
  464. package/dist/web/src/lib/utils.d.ts.map +1 -0
  465. package/dist/web/src/lib/utils.js +6 -0
  466. package/dist/web/src/lib/utils.js.map +1 -0
  467. package/dist/web/src/main.d.ts +2 -0
  468. package/dist/web/src/main.d.ts.map +1 -0
  469. package/dist/web/src/main.js +5 -0
  470. package/dist/web/src/main.js.map +1 -0
  471. package/dist/web/vite.config.d.ts +3 -0
  472. package/dist/web/vite.config.d.ts.map +1 -0
  473. package/dist/web/vite.config.js +12 -0
  474. package/dist/web/vite.config.js.map +1 -0
  475. package/package.json +83 -0
@@ -0,0 +1,2338 @@
1
+ import { promises as fs } from 'node:fs';
2
+ import { spawn } from 'node:child_process';
3
+ import path from 'node:path';
4
+ import { execSync } from 'node:child_process';
5
+ import { slackTools } from './slack.js';
6
+ import { googleTools } from './google.js';
7
+ import { githubTools } from './github.js';
8
+ import { discordTools } from './discord.js';
9
+ import { telegramTools } from './telegram.js';
10
+ import { createAgentTool, listAgentsTool } from './agent_tools.js';
11
+ import { codeSearchTool } from './code_search.js';
12
+ import { selfHealTool } from './self_heal.js';
13
+ import { sageMemoryTool } from './sage_memory.js';
14
+ import { sendBriefingTool } from './send_briefing.js';
15
+ import { craftTool } from './craft_tool.js';
16
+ import { optimizePromptTool } from './optimize_prompt.js';
17
+ import { predictHealingTool } from './predict_healing.js';
18
+ import { acquireSkillTool } from './acquire_skill.js';
19
+ import { voxTool } from './vox.js';
20
+ import { dynamicToolRegistry } from './dynamic/registry.js';
21
+ import { colors } from '../../cli/ui.js';
22
+ // Multi-Agent Orchestration tool
23
+ const delegateTasksTool = {
24
+ definition: {
25
+ name: 'delegate_tasks',
26
+ description: 'Delegate multiple sub-tasks to specialized worker agents. Use this to orchestrate parallel execution.',
27
+ parameters: {
28
+ type: 'object',
29
+ properties: {
30
+ tasks: {
31
+ type: 'array',
32
+ description: 'List of tasks to delegate to workers.',
33
+ items: {
34
+ type: 'object',
35
+ properties: {
36
+ role: { type: 'string', description: 'Agent ID (build, plan, explore, debug)' },
37
+ prompt: { type: 'string', description: 'Detailed instruction' }
38
+ },
39
+ required: ['role', 'prompt']
40
+ }
41
+ }
42
+ },
43
+ required: ['tasks']
44
+ }
45
+ },
46
+ handler: async (args) => {
47
+ try {
48
+ const { EdenAgent } = await import('../agent.js');
49
+ const tasks = args.tasks;
50
+ const results = await Promise.all(tasks.map(async (task) => {
51
+ const workerOptions = {
52
+ model: 'eden:latest', // Ensure we use the best model
53
+ ollamaUrl: 'http://localhost:11434',
54
+ cwd: process.cwd(),
55
+ interactive: false,
56
+ debug: false
57
+ };
58
+ const worker = new EdenAgent(workerOptions);
59
+ worker.switchAgent(task.role);
60
+ await worker.runSingleTurn(task.prompt);
61
+ const transcript = worker.getTranscript();
62
+ const finalAnswer = transcript.filter(t => t.kind === 'assistant').pop();
63
+ return {
64
+ role: task.role,
65
+ output: finalAnswer?.text || 'No output'
66
+ };
67
+ }));
68
+ return {
69
+ status: 'success',
70
+ output: JSON.stringify(results, null, 2)
71
+ };
72
+ }
73
+ catch (err) {
74
+ return { status: 'error', error: String(err) };
75
+ }
76
+ }
77
+ };
78
+ // File operations tool
79
+ const readFileTool = {
80
+ definition: {
81
+ name: 'read_file',
82
+ description: 'Read the contents of a file at the specified path. Returns the file content as text.',
83
+ parameters: {
84
+ type: 'object',
85
+ properties: {
86
+ file_path: {
87
+ type: 'string',
88
+ description: 'The absolute path to the file to read',
89
+ },
90
+ offset: {
91
+ type: 'number',
92
+ description: 'Optional line offset to start reading from (1-indexed)',
93
+ },
94
+ limit: {
95
+ type: 'number',
96
+ description: 'Optional maximum number of lines to read',
97
+ },
98
+ },
99
+ required: ['file_path'],
100
+ },
101
+ },
102
+ handler: async (args, agent) => {
103
+ try {
104
+ const agentCwd = agent?.options?.cwd;
105
+ let filePath = String(args.file_path);
106
+ // Resolve relative paths against agent's cwd
107
+ if (agentCwd && !filePath.startsWith('/')) {
108
+ filePath = path.join(agentCwd, filePath);
109
+ }
110
+ const offset = args.offset ? Number(args.offset) : undefined;
111
+ const limit = args.limit ? Number(args.limit) : undefined;
112
+ let content = await fs.readFile(filePath, 'utf8');
113
+ if (offset !== undefined || limit !== undefined) {
114
+ const lines = content.split('\n');
115
+ const start = offset ? Math.max(0, offset - 1) : 0;
116
+ const end = limit ? Math.min(lines.length, start + limit) : lines.length;
117
+ content = lines.slice(start, end).join('\n');
118
+ }
119
+ return {
120
+ status: 'success',
121
+ output: content,
122
+ metadata: { file_path: filePath },
123
+ };
124
+ }
125
+ catch (err) {
126
+ return {
127
+ status: 'error',
128
+ error: err instanceof Error ? err.message : String(err),
129
+ };
130
+ }
131
+ },
132
+ };
133
+ // Write file tool
134
+ const writeFileTool = {
135
+ definition: {
136
+ name: 'write_file',
137
+ description: 'Write content to a file at the specified path. Creates the file if it does not exist.',
138
+ parameters: {
139
+ type: 'object',
140
+ properties: {
141
+ file_path: {
142
+ type: 'string',
143
+ description: 'The absolute path to the file to write',
144
+ },
145
+ content: {
146
+ type: 'string',
147
+ description: 'The content to write to the file',
148
+ },
149
+ },
150
+ required: ['file_path', 'content'],
151
+ },
152
+ },
153
+ handler: async (args, agent) => {
154
+ try {
155
+ const agentCwd = agent?.options?.cwd || process.cwd();
156
+ let filePath = String(args.file_path);
157
+ // Resolve relative paths or hallucinated absolute paths (like /app/...)
158
+ // If it's absolute but not within the workspace or home, force it into workspace
159
+ const isWorkspacePath = filePath.startsWith(agentCwd);
160
+ const isHomePath = filePath.startsWith('/home');
161
+ if (!filePath.startsWith('/') || (!isWorkspacePath && !isHomePath)) {
162
+ const basename = path.basename(filePath) || 'file.txt';
163
+ filePath = path.join(agentCwd, basename);
164
+ }
165
+ const content = String(args.content);
166
+ // Ensure directory exists
167
+ const dir = path.dirname(filePath);
168
+ try {
169
+ await fs.mkdir(dir, { recursive: true });
170
+ }
171
+ catch (mkdirErr) {
172
+ // If we can't create the directory, fallback to current directory
173
+ if (mkdirErr.code === 'EACCES' || mkdirErr.code === 'EPERM') {
174
+ const basename = path.basename(filePath);
175
+ filePath = path.join(process.cwd(), basename);
176
+ }
177
+ }
178
+ await fs.writeFile(filePath, content, 'utf8');
179
+ return {
180
+ status: 'success',
181
+ output: `File written successfully: ${filePath}`,
182
+ metadata: { file_path: filePath, bytes: content.length },
183
+ };
184
+ }
185
+ catch (err) {
186
+ return {
187
+ status: 'error',
188
+ error: err instanceof Error ? err.message : String(err),
189
+ };
190
+ }
191
+ },
192
+ };
193
+ // Edit file tool (search and replace)
194
+ const editFileTool = {
195
+ definition: {
196
+ name: 'edit_file',
197
+ description: 'Edit a file by replacing occurrences of old_string with new_string.',
198
+ parameters: {
199
+ type: 'object',
200
+ properties: {
201
+ file_path: {
202
+ type: 'string',
203
+ description: 'The absolute path to the file to edit',
204
+ },
205
+ old_string: {
206
+ type: 'string',
207
+ description: 'The text to search for and replace',
208
+ },
209
+ new_string: {
210
+ type: 'string',
211
+ description: 'The replacement text',
212
+ },
213
+ replace_all: {
214
+ type: 'boolean',
215
+ description: 'If true, replace all occurrences instead of just the first one',
216
+ },
217
+ },
218
+ required: ['file_path', 'old_string', 'new_string'],
219
+ },
220
+ },
221
+ handler: async (args, agent) => {
222
+ try {
223
+ const agentCwd = agent?.options?.cwd;
224
+ let filePath = String(args.file_path);
225
+ // Resolve relative paths against agent's cwd
226
+ if (agentCwd && !filePath.startsWith('/')) {
227
+ filePath = path.join(agentCwd, filePath);
228
+ }
229
+ const oldString = String(args.old_string);
230
+ const newString = String(args.new_string);
231
+ const replaceAll = Boolean(args.replace_all);
232
+ const content = await fs.readFile(filePath, 'utf8');
233
+ if (!content.includes(oldString)) {
234
+ return {
235
+ status: 'error',
236
+ error: `Could not find the string to replace in ${filePath}`,
237
+ };
238
+ }
239
+ const newContent = replaceAll
240
+ ? content.split(oldString).join(newString)
241
+ : content.replace(oldString, newString);
242
+ await fs.writeFile(filePath, newContent, 'utf8');
243
+ return {
244
+ status: 'success',
245
+ output: `File edited successfully: ${filePath}`,
246
+ metadata: { file_path: filePath, replacements: replaceAll ? 'all' : 'first' },
247
+ };
248
+ }
249
+ catch (err) {
250
+ return {
251
+ status: 'error',
252
+ error: err instanceof Error ? err.message : String(err),
253
+ };
254
+ }
255
+ },
256
+ };
257
+ // List directory tool
258
+ const listDirTool = {
259
+ definition: {
260
+ name: 'list_dir',
261
+ description: 'List files and directories at the specified path. Returns file names, sizes, and modification times.',
262
+ parameters: {
263
+ type: 'object',
264
+ properties: {
265
+ directory_path: {
266
+ type: 'string',
267
+ description: 'The absolute path to the directory to list',
268
+ },
269
+ recursive: {
270
+ type: 'boolean',
271
+ description: 'If true, list recursively',
272
+ },
273
+ },
274
+ required: ['directory_path'],
275
+ },
276
+ },
277
+ handler: async (args, agent) => {
278
+ try {
279
+ const agentCwd = agent?.options?.cwd || process.cwd();
280
+ let dirPath = String(args.directory_path || '.');
281
+ // Resolve relative paths or hallucinated absolute paths
282
+ const isWorkspacePath = dirPath.startsWith(agentCwd);
283
+ const isHomePath = dirPath.startsWith('/home');
284
+ if (!dirPath.startsWith('/') || (!isWorkspacePath && !isHomePath)) {
285
+ dirPath = path.join(agentCwd, dirPath === '.' ? '' : dirPath);
286
+ }
287
+ const recursive = Boolean(args.recursive);
288
+ const entries = [];
289
+ if (recursive) {
290
+ const walk = async (currentPath, prefix) => {
291
+ const items = await fs.readdir(currentPath, { withFileTypes: true });
292
+ for (const item of items) {
293
+ const fullPath = path.join(currentPath, item.name);
294
+ const stat = await fs.stat(fullPath);
295
+ const size = stat.isFile() ? ` (${stat.size} bytes)` : ' (dir)';
296
+ entries.push(`${prefix}${item.name}${size}`);
297
+ if (item.isDirectory()) {
298
+ await walk(fullPath, prefix + ' ');
299
+ }
300
+ }
301
+ };
302
+ await walk(dirPath, '');
303
+ }
304
+ else {
305
+ const items = await fs.readdir(dirPath, { withFileTypes: true });
306
+ for (const item of items) {
307
+ const fullPath = path.join(dirPath, item.name);
308
+ const stat = await fs.stat(fullPath);
309
+ const size = stat.isFile() ? ` (${stat.size} bytes)` : ' (dir)';
310
+ entries.push(`${item.name}${size}`);
311
+ }
312
+ }
313
+ return {
314
+ status: 'success',
315
+ output: entries.join('\n'),
316
+ metadata: { directory: dirPath, count: entries.length },
317
+ };
318
+ }
319
+ catch (err) {
320
+ return {
321
+ status: 'error',
322
+ error: err instanceof Error ? err.message : String(err),
323
+ };
324
+ }
325
+ },
326
+ };
327
+ // Grep search tool
328
+ const grepSearchTool = {
329
+ definition: {
330
+ name: 'grep_search',
331
+ description: 'Search for text patterns in files using ripgrep-style matching.',
332
+ parameters: {
333
+ type: 'object',
334
+ properties: {
335
+ query: {
336
+ type: 'string',
337
+ description: 'The search pattern or text to find',
338
+ },
339
+ path: {
340
+ type: 'string',
341
+ description: 'The directory or file path to search in',
342
+ },
343
+ file_pattern: {
344
+ type: 'string',
345
+ description: 'Optional glob pattern to filter files (e.g., "*.ts", "*.js")',
346
+ },
347
+ case_sensitive: {
348
+ type: 'boolean',
349
+ description: 'If false, perform case-insensitive search',
350
+ },
351
+ fixed_strings: {
352
+ type: 'boolean',
353
+ description: 'If true, treat query as literal string instead of regex',
354
+ },
355
+ },
356
+ required: ['query', 'path'],
357
+ },
358
+ },
359
+ handler: async (args, agent) => {
360
+ try {
361
+ const agentCwd = agent?.options?.cwd;
362
+ const query = String(args.query);
363
+ let searchPath = String(args.path);
364
+ // Resolve relative paths against agent's cwd
365
+ if (agentCwd && !searchPath.startsWith('/')) {
366
+ searchPath = path.join(agentCwd, searchPath);
367
+ }
368
+ const filePattern = args.file_pattern ? String(args.file_pattern) : undefined;
369
+ const caseSensitive = args.case_sensitive !== false;
370
+ const fixedStrings = Boolean(args.fixed_strings);
371
+ // Build grep/ripgrep command
372
+ const args_list = [];
373
+ if (!caseSensitive)
374
+ args_list.push('-i');
375
+ if (fixedStrings)
376
+ args_list.push('-F');
377
+ if (filePattern) {
378
+ args_list.push('--include', filePattern);
379
+ }
380
+ args_list.push(query, searchPath);
381
+ const result = execSync(`rg ${args_list.join(' ')} 2>/dev/null || grep -r ${args_list.join(' ')} 2>/dev/null || echo "No matches found"`, {
382
+ encoding: 'utf8',
383
+ maxBuffer: 1024 * 1024,
384
+ });
385
+ const lines = result.trim().split('\n').filter(Boolean);
386
+ const truncated = lines.length > 50;
387
+ const output = truncated ? lines.slice(0, 50).join('\n') + '\n... (truncated)' : result;
388
+ return {
389
+ status: 'success',
390
+ output,
391
+ metadata: {
392
+ matches: lines.length,
393
+ truncated,
394
+ },
395
+ };
396
+ }
397
+ catch (err) {
398
+ return {
399
+ status: 'error',
400
+ error: err instanceof Error ? err.message : String(err),
401
+ };
402
+ }
403
+ },
404
+ };
405
+ // Run command tool - improved with better output handling and suggestions
406
+ const runCommandTool = {
407
+ definition: {
408
+ name: 'run_command',
409
+ description: 'Execute a shell command. Returns stdout and stderr output. Shows suggestions if command fails or has no output.',
410
+ parameters: {
411
+ type: 'object',
412
+ properties: {
413
+ command: {
414
+ type: 'string',
415
+ description: 'The command to execute',
416
+ },
417
+ cwd: {
418
+ type: 'string',
419
+ description: 'Optional working directory for the command',
420
+ },
421
+ timeout_sec: {
422
+ type: 'number',
423
+ description: 'Optional timeout in seconds (default: 60)',
424
+ },
425
+ },
426
+ required: ['command'],
427
+ },
428
+ },
429
+ handler: async (args, agent) => {
430
+ try {
431
+ const command = String(args.command);
432
+ const agentCwd = agent?.options?.cwd;
433
+ let cwd = args.cwd ? String(args.cwd) : agentCwd || process.cwd();
434
+ // If cwd is relative, resolve against agent's cwd
435
+ if (agentCwd && !cwd.startsWith('/')) {
436
+ cwd = path.join(agentCwd, cwd);
437
+ }
438
+ const timeoutSec = args.timeout_sec ? Number(args.timeout_sec) : 60;
439
+ return new Promise((resolve) => {
440
+ // Stop spinner so we don't clobber live output
441
+ console.log(); // Add a newline before output
442
+ const child = spawn('bash', ['-c', command], {
443
+ cwd,
444
+ stdio: ['pipe', 'pipe', 'pipe'],
445
+ detached: false, // Ensure process is attached and can be killed
446
+ });
447
+ let stdout = '';
448
+ let stderr = '';
449
+ let timeout = null;
450
+ let isResolved = false;
451
+ let serverCheckTimeout = null;
452
+ // Detect if this is a long-running server command
453
+ const serverPatterns = [
454
+ 'http.server', 'python3 -m http', 'python -m http',
455
+ 'nodemon', 'npm start', 'npm run dev',
456
+ 'node.*server', 'flask run', 'django',
457
+ 'uvicorn', 'fastapi', 'rails server',
458
+ 'php -S', 'live-server', 'vite'
459
+ ];
460
+ const isServerCommand = serverPatterns.some(p => command.toLowerCase().includes(p.toLowerCase()));
461
+ const safeResolve = (result) => {
462
+ if (!isResolved) {
463
+ isResolved = true;
464
+ if (timeout)
465
+ clearTimeout(timeout);
466
+ if (serverCheckTimeout)
467
+ clearTimeout(serverCheckTimeout);
468
+ resolve(result);
469
+ }
470
+ };
471
+ // Increase timeout for server commands to give them time to start
472
+ const effectiveTimeout = isServerCommand ? Math.max(timeoutSec, 30) : timeoutSec;
473
+ if (effectiveTimeout > 0) {
474
+ timeout = setTimeout(() => {
475
+ console.log(colors.warning(`\n⚠ Timeout después de ${effectiveTimeout}s, terminando proceso...`));
476
+ child.kill('SIGTERM');
477
+ setTimeout(() => {
478
+ if (!child.killed) {
479
+ child.kill('SIGKILL');
480
+ }
481
+ // Resolve with timeout error if process still hasn't closed
482
+ safeResolve({
483
+ status: 'error',
484
+ output: stdout,
485
+ error: `Command timed out after ${effectiveTimeout}s`,
486
+ metadata: { timeout: effectiveTimeout, killed: true }
487
+ });
488
+ }, 3000);
489
+ }, effectiveTimeout * 1000);
490
+ }
491
+ // Close stdin immediately to prevent hanging on input prompts
492
+ child.stdin?.end();
493
+ child.stdin?.destroy();
494
+ // Fallback for server commands: if no startup output after 10s, assume success
495
+ if (isServerCommand) {
496
+ serverCheckTimeout = setTimeout(() => {
497
+ if (!isResolved && stdout.length > 0) {
498
+ // Got some output but no clear startup message, assume server started
499
+ safeResolve({
500
+ status: 'success',
501
+ output: `✓ Servidor iniciado (output capturado)\n\n${stdout}\n(Proceso continúa ejecutándose en segundo plano)`,
502
+ metadata: { server: true, command: command.slice(0, 100), fallback: true }
503
+ });
504
+ }
505
+ else if (!isResolved) {
506
+ // No output at all, but assume server started for common patterns
507
+ safeResolve({
508
+ status: 'success',
509
+ output: `✓ Servidor iniciado (sin output visible)\n\n(Proceso continúa ejecutándose en segundo plano)`,
510
+ metadata: { server: true, command: command.slice(0, 100), fallback: true }
511
+ });
512
+ }
513
+ }, 10000); // 10 second fallback
514
+ }
515
+ child.stdout?.on('data', (data) => {
516
+ const str = String(data);
517
+ process.stdout.write(colors.muted(str));
518
+ stdout += str;
519
+ // For server commands, check if server started successfully
520
+ if (isServerCommand && !isResolved) {
521
+ const serverStartedPatterns = [
522
+ /serving http/i,
523
+ /serving at/i,
524
+ /server started/i,
525
+ /listening on port/i,
526
+ /running on.*http/i,
527
+ /ready in.*ms/i,
528
+ /compiled successfully/i,
529
+ /webpack.*compiled/i,
530
+ /.*:\/\/localhost:\d+/i,
531
+ /http server started/i,
532
+ /httpd started/i,
533
+ /development server/i,
534
+ /local:/i
535
+ ];
536
+ if (serverStartedPatterns.some(p => p.test(str))) {
537
+ // Server started successfully, resolve immediately
538
+ setTimeout(() => {
539
+ safeResolve({
540
+ status: 'success',
541
+ output: `✓ Servidor iniciado exitosamente\n\n${stdout}\n(Proceso continúa ejecutándose en segundo plano)`,
542
+ metadata: { server: true, command: command.slice(0, 100) }
543
+ });
544
+ }, 500); // Small delay to capture more startup output
545
+ }
546
+ }
547
+ });
548
+ child.stderr?.on('data', (data) => {
549
+ const str = String(data);
550
+ process.stderr.write(colors.error(str));
551
+ stderr += str;
552
+ });
553
+ child.on('close', (code, signal) => {
554
+ if (timeout)
555
+ clearTimeout(timeout);
556
+ console.log(); // End visual block of command stream
557
+ const isError = code !== 0;
558
+ const hasStdout = stdout.trim().length > 0;
559
+ const hasStderr = stderr.trim().length > 0;
560
+ // Build comprehensive output
561
+ let output = '';
562
+ let suggestions = [];
563
+ if (hasStdout) {
564
+ output += stdout;
565
+ }
566
+ if (hasStderr) {
567
+ if (output)
568
+ output += '\n\n';
569
+ output += `STDERR:\n${stderr}`;
570
+ }
571
+ // Handle silent success cases (mkdir, touch, etc.)
572
+ if (!isError && !hasStdout && !hasStderr) {
573
+ // Check what command was run and provide context
574
+ const cmdBase = command.trim().split(' ')[0];
575
+ const silentCommands = ['mkdir', 'touch', 'rm', 'cp', 'mv', 'chmod', 'chown'];
576
+ if (silentCommands.includes(cmdBase)) {
577
+ output = `✓ Comando ejecutado exitosamente (sin output)`;
578
+ // Show what was created/modified
579
+ if (cmdBase === 'mkdir') {
580
+ const match = command.match(/mkdir\s+-?p?\s+(.*)/);
581
+ if (match) {
582
+ output += `\nDirectorios creados: ${match[1]}`;
583
+ }
584
+ }
585
+ }
586
+ else {
587
+ output = '(comando completado sin output)';
588
+ }
589
+ }
590
+ // Generate suggestions for common errors
591
+ if (isError) {
592
+ const errorText = stderr.toLowerCase();
593
+ if (errorText.includes('command not found') || errorText.includes('no such file')) {
594
+ suggestions.push('Verifica que el comando esté instalado: `which <comando>`');
595
+ suggestions.push('Alternativa: Instala con tu package manager (apt, npm, etc.)');
596
+ }
597
+ if (errorText.includes('permission denied') || errorText.includes('eacces')) {
598
+ suggestions.push('Intenta con sudo o verifica permisos: `ls -la`');
599
+ suggestions.push('Alternativa: Cambia permisos con `chmod` o cambia de directorio');
600
+ }
601
+ if (errorText.includes('file exists') || errorText.includes('eexist')) {
602
+ suggestions.push('El archivo/directorio ya existe');
603
+ suggestions.push('Alternativa: Usa `-f` (force) o elimina primero con `rm`');
604
+ }
605
+ if (errorText.includes('no such file or directory')) {
606
+ suggestions.push('Verifica que la ruta existe con `ls -la`');
607
+ suggestions.push('Alternativa: Crea directorios padre primero con `mkdir -p`');
608
+ }
609
+ if (errorText.includes('connection refused') || errorText.includes('timeout')) {
610
+ suggestions.push('Verifica conectividad de red');
611
+ suggestions.push('Alternativa: Revisa firewall o intenta más tarde');
612
+ }
613
+ if (suggestions.length === 0) {
614
+ suggestions.push('Verifica el comando con `--help` o man pages');
615
+ suggestions.push('Alternativa: Busca ejemplos en documentación oficial');
616
+ }
617
+ }
618
+ // Build final response
619
+ let finalOutput = output;
620
+ if (suggestions.length > 0) {
621
+ finalOutput += '\n\n💡 Sugerencias:\n' + suggestions.map(s => ` • ${s}`).join('\n');
622
+ }
623
+ safeResolve({
624
+ status: isError ? 'error' : 'success',
625
+ output: finalOutput || '(no output)',
626
+ error: isError ? `Exit code: ${code}` : undefined,
627
+ metadata: {
628
+ exit_code: code,
629
+ stdout_length: stdout.length,
630
+ stderr_length: stderr.length,
631
+ command: command.slice(0, 100), // Truncate for safety
632
+ suggestions_count: suggestions.length,
633
+ },
634
+ });
635
+ });
636
+ child.on('error', (err) => {
637
+ if (timeout)
638
+ clearTimeout(timeout);
639
+ safeResolve({
640
+ status: 'error',
641
+ output: '',
642
+ error: `Failed to execute: ${err.message}\n\n💡 Sugerencias:\n • Verifica que el shell esté disponible\n • Alternativa: Intenta con el comando completo (ej: /bin/ls)`,
643
+ });
644
+ });
645
+ });
646
+ }
647
+ catch (err) {
648
+ return {
649
+ status: 'error',
650
+ output: '',
651
+ error: err instanceof Error ? err.message : String(err),
652
+ };
653
+ }
654
+ },
655
+ };
656
+ // Find files by name tool
657
+ const findByNameTool = {
658
+ definition: {
659
+ name: 'find_by_name',
660
+ description: 'Find files and directories by name pattern.',
661
+ parameters: {
662
+ type: 'object',
663
+ properties: {
664
+ pattern: {
665
+ type: 'string',
666
+ description: 'The glob pattern to match (e.g., "*.ts", "package.json")',
667
+ },
668
+ directory: {
669
+ type: 'string',
670
+ description: 'The directory to search in',
671
+ },
672
+ max_depth: {
673
+ type: 'number',
674
+ description: 'Maximum directory depth to search',
675
+ },
676
+ },
677
+ required: ['pattern', 'directory'],
678
+ },
679
+ },
680
+ handler: async (args, agent) => {
681
+ try {
682
+ const pattern = String(args.pattern);
683
+ const maxDepth = args.max_depth ? Number(args.max_depth) : undefined;
684
+ // Use agent's cwd if available, otherwise default to current directory
685
+ const agentCwd = agent?.options?.cwd;
686
+ let directory = String(args.directory);
687
+ // If directory is relative, resolve it against agent's cwd
688
+ if (agentCwd && !directory.startsWith('/')) {
689
+ directory = path.join(agentCwd, directory);
690
+ }
691
+ let command = `find "${directory}" -name "${pattern}" -type f`;
692
+ if (maxDepth) {
693
+ command += ` -maxdepth ${maxDepth}`;
694
+ }
695
+ const result = execSync(command, { encoding: 'utf8' });
696
+ const files = result.trim().split('\n').filter(Boolean);
697
+ return {
698
+ status: 'success',
699
+ output: files.join('\n') || '(no files found)',
700
+ metadata: { count: files.length },
701
+ };
702
+ }
703
+ catch (err) {
704
+ return {
705
+ status: 'error',
706
+ error: err instanceof Error ? err.message : String(err),
707
+ };
708
+ }
709
+ },
710
+ };
711
+ // View URL content tool
712
+ const viewUrlTool = {
713
+ definition: {
714
+ name: 'view_url',
715
+ description: 'Fetch and view content from a URL.',
716
+ parameters: {
717
+ type: 'object',
718
+ properties: {
719
+ url: {
720
+ type: 'string',
721
+ description: 'The URL to fetch',
722
+ },
723
+ },
724
+ required: ['url'],
725
+ },
726
+ },
727
+ handler: async (args) => {
728
+ try {
729
+ const url = String(args.url);
730
+ const response = await fetch(url);
731
+ if (!response.ok) {
732
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
733
+ }
734
+ const content = await response.text();
735
+ const truncated = content.length > 10000;
736
+ const output = truncated ? content.slice(0, 10000) + '\n... (truncated)' : content;
737
+ return {
738
+ status: 'success',
739
+ output,
740
+ metadata: {
741
+ url,
742
+ content_type: response.headers.get('content-type'),
743
+ content_length: content.length,
744
+ truncated,
745
+ },
746
+ };
747
+ }
748
+ catch (err) {
749
+ return {
750
+ status: 'error',
751
+ error: err instanceof Error ? err.message : String(err),
752
+ };
753
+ }
754
+ },
755
+ };
756
+ // Ask user question tool
757
+ const askUserTool = {
758
+ definition: {
759
+ name: 'ask_user',
760
+ description: 'Ask the user a question with predefined options.',
761
+ parameters: {
762
+ type: 'object',
763
+ properties: {
764
+ question: {
765
+ type: 'string',
766
+ description: 'The question to ask',
767
+ },
768
+ options: {
769
+ type: 'array',
770
+ description: 'Array of option objects with label and description',
771
+ items: {
772
+ type: 'object',
773
+ properties: {
774
+ label: { type: 'string' },
775
+ description: { type: 'string' },
776
+ },
777
+ },
778
+ },
779
+ allow_multiple: {
780
+ type: 'boolean',
781
+ description: 'Allow selecting multiple options',
782
+ },
783
+ },
784
+ required: ['question', 'options'],
785
+ },
786
+ },
787
+ handler: (args) => {
788
+ const question = String(args.question);
789
+ const options = Array.isArray(args.options) ? args.options : [];
790
+ const allowMultiple = Boolean(args.allow_multiple);
791
+ const formatted = options.map((opt, i) => {
792
+ const o = opt;
793
+ return `${i + 1}. ${o.label || '?'}: ${o.description || ''}`;
794
+ }).join('\n');
795
+ return {
796
+ status: 'success',
797
+ output: `USER QUESTION: ${question}\n\nOptions (${allowMultiple ? 'select multiple' : 'select one'}):\n${formatted}\n\nPlease respond with the number(s) of your choice.`,
798
+ metadata: { requires_user_input: true },
799
+ };
800
+ },
801
+ };
802
+ // Create memory tool
803
+ const createMemoryTool = {
804
+ definition: {
805
+ name: 'create_memory',
806
+ description: 'Save important context to the memory database.',
807
+ parameters: {
808
+ type: 'object',
809
+ properties: {
810
+ content: {
811
+ type: 'string',
812
+ description: 'The content to remember',
813
+ },
814
+ tags: {
815
+ type: 'array',
816
+ description: 'Tags to associate with the memory',
817
+ items: { type: 'string' },
818
+ },
819
+ title: {
820
+ type: 'string',
821
+ description: 'Title for the memory',
822
+ },
823
+ },
824
+ required: ['content', 'title'],
825
+ },
826
+ },
827
+ handler: (args) => {
828
+ const content = String(args.content);
829
+ const title = String(args.title);
830
+ const tags = Array.isArray(args.tags) ? args.tags : [];
831
+ // In a real implementation, this would write to a database
832
+ // For now, we just acknowledge the memory was created
833
+ return {
834
+ status: 'success',
835
+ output: `Memory saved: "${title}"\n\n${content}\n\nTags: ${tags.join(', ') || 'none'}`,
836
+ metadata: { title, tags },
837
+ };
838
+ },
839
+ };
840
+ // Vision/Image analysis tool - analyze images using Ollama vision models
841
+ const analyzeImageTool = {
842
+ definition: {
843
+ name: 'analyze_image',
844
+ description: 'Analyze an image file using vision AI. Returns a description of what the image contains.',
845
+ parameters: {
846
+ type: 'object',
847
+ properties: {
848
+ image_path: {
849
+ type: 'string',
850
+ description: 'The absolute path to the image file',
851
+ },
852
+ prompt: {
853
+ type: 'string',
854
+ description: 'Optional specific question about the image (default: "Describe this image in detail")',
855
+ },
856
+ },
857
+ required: ['image_path'],
858
+ },
859
+ },
860
+ handler: async (args) => {
861
+ try {
862
+ const imagePath = String(args.image_path);
863
+ const prompt = args.prompt ? String(args.prompt) : 'Describe this image in detail';
864
+ // Read image as base64
865
+ const imageBuffer = await fs.readFile(imagePath);
866
+ const base64Image = imageBuffer.toString('base64');
867
+ // Determine mime type from extension
868
+ const ext = path.extname(imagePath).toLowerCase();
869
+ const mimeType = ext === '.png' ? 'image/png' :
870
+ ext === '.gif' ? 'image/gif' :
871
+ ext === '.webp' ? 'image/webp' : 'image/jpeg';
872
+ // Call Ollama with vision capabilities
873
+ const ollamaUrl = process.env.OLLAMA_HOST || 'http://localhost:11434';
874
+ const model = process.env.VISION_MODEL || 'llava';
875
+ const response = await fetch(`${ollamaUrl}/api/generate`, {
876
+ method: 'POST',
877
+ headers: { 'Content-Type': 'application/json' },
878
+ body: JSON.stringify({
879
+ model,
880
+ prompt,
881
+ images: [base64Image],
882
+ stream: false,
883
+ }),
884
+ });
885
+ if (!response.ok) {
886
+ throw new Error(`Ollama API error: ${response.status}`);
887
+ }
888
+ const result = await response.json();
889
+ return {
890
+ status: 'success',
891
+ output: result.response,
892
+ metadata: { image_path: imagePath, model, prompt },
893
+ };
894
+ }
895
+ catch (err) {
896
+ return {
897
+ status: 'error',
898
+ error: err instanceof Error ? err.message : String(err),
899
+ };
900
+ }
901
+ },
902
+ };
903
+ // Text embedding tool - generate embeddings for text similarity
904
+ const embeddingTool = {
905
+ definition: {
906
+ name: 'generate_embedding',
907
+ description: 'Generate vector embeddings for text using Ollama. Useful for semantic search and similarity comparisons.',
908
+ parameters: {
909
+ type: 'object',
910
+ properties: {
911
+ text: {
912
+ type: 'string',
913
+ description: 'The text to generate embeddings for',
914
+ },
915
+ model: {
916
+ type: 'string',
917
+ description: 'Embedding model to use (default: nomic-embed-text)',
918
+ },
919
+ },
920
+ required: ['text'],
921
+ },
922
+ },
923
+ handler: async (args) => {
924
+ try {
925
+ const text = String(args.text);
926
+ const model = args.model ? String(args.model) : 'nomic-embed-text';
927
+ const ollamaUrl = process.env.OLLAMA_HOST || 'http://localhost:11434';
928
+ const response = await fetch(`${ollamaUrl}/api/embeddings`, {
929
+ method: 'POST',
930
+ headers: { 'Content-Type': 'application/json' },
931
+ body: JSON.stringify({
932
+ model,
933
+ prompt: text,
934
+ }),
935
+ });
936
+ if (!response.ok) {
937
+ throw new Error(`Ollama API error: ${response.status}`);
938
+ }
939
+ const result = await response.json();
940
+ return {
941
+ status: 'success',
942
+ output: `Generated ${result.embedding.length} dimensional embedding`,
943
+ metadata: {
944
+ embedding: result.embedding,
945
+ dimensions: result.embedding.length,
946
+ model,
947
+ text_preview: text.slice(0, 100) + (text.length > 100 ? '...' : ''),
948
+ },
949
+ };
950
+ }
951
+ catch (err) {
952
+ return {
953
+ status: 'error',
954
+ error: err instanceof Error ? err.message : String(err),
955
+ };
956
+ }
957
+ },
958
+ };
959
+ // Web search/research tool - search the web using various search APIs
960
+ const webSearchTool = {
961
+ definition: {
962
+ name: 'web_search',
963
+ description: 'Search the web for information. Uses DuckDuckGo or other search providers.',
964
+ parameters: {
965
+ type: 'object',
966
+ properties: {
967
+ query: {
968
+ type: 'string',
969
+ description: 'The search query',
970
+ },
971
+ num_results: {
972
+ type: 'number',
973
+ description: 'Number of results to return (default: 5, max: 10)',
974
+ },
975
+ },
976
+ required: ['query'],
977
+ },
978
+ },
979
+ handler: async (args) => {
980
+ try {
981
+ const query = encodeURIComponent(String(args.query));
982
+ const numResults = Math.min(args.num_results ? Number(args.num_results) : 5, 10);
983
+ // Try DuckDuckGo HTML first
984
+ try {
985
+ const response = await fetch(`https://html.duckduckgo.com/html/?q=${query}`, {
986
+ headers: {
987
+ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
988
+ },
989
+ });
990
+ if (response.ok) {
991
+ const html = await response.text();
992
+ // Parse results from HTML
993
+ const results = [];
994
+ // Simple regex-based extraction
995
+ const resultBlocks = html.match(/<div class="result[^"]*">[\s\S]*?<\/div>/g) || [];
996
+ for (const block of resultBlocks.slice(0, numResults)) {
997
+ const titleMatch = block.match(/<a[^>]*class="result__a"[^>]*>([\s\S]*?)<\/a>/);
998
+ const urlMatch = block.match(/<a[^>]*href="([^"]*)"/);
999
+ const snippetMatch = block.match(/<a[^>]*class="result__snippet"[^>]*>([\s\S]*?)<\/a>/);
1000
+ if (titleMatch && urlMatch) {
1001
+ results.push({
1002
+ title: titleMatch[1].replace(/<[^>]*>/g, '').trim(),
1003
+ url: urlMatch[1],
1004
+ snippet: snippetMatch ? snippetMatch[1].replace(/<[^>]*>/g, '').trim() : '',
1005
+ });
1006
+ }
1007
+ }
1008
+ if (results.length > 0) {
1009
+ const formatted = results.map((r, i) => `${i + 1}. ${r.title}\n URL: ${r.url}\n ${r.snippet}`).join('\n\n');
1010
+ return {
1011
+ status: 'success',
1012
+ output: formatted,
1013
+ metadata: { results_count: results.length, source: 'duckduckgo' },
1014
+ };
1015
+ }
1016
+ }
1017
+ }
1018
+ catch {
1019
+ // Fallback to alternative search or error
1020
+ }
1021
+ return {
1022
+ status: 'error',
1023
+ error: 'Web search failed. The search service may be unavailable or rate-limited.',
1024
+ };
1025
+ }
1026
+ catch (err) {
1027
+ return {
1028
+ status: 'error',
1029
+ error: err instanceof Error ? err.message : String(err),
1030
+ };
1031
+ }
1032
+ },
1033
+ };
1034
+ // Browser automation tool - fetch and extract content from web pages
1035
+ const browserTool = {
1036
+ definition: {
1037
+ name: 'browse_webpage',
1038
+ description: 'Fetch a webpage and extract its main content, removing ads and navigation. Useful for reading articles.',
1039
+ parameters: {
1040
+ type: 'object',
1041
+ properties: {
1042
+ url: {
1043
+ type: 'string',
1044
+ description: 'The URL to browse',
1045
+ },
1046
+ extract_main_content: {
1047
+ type: 'boolean',
1048
+ description: 'Extract main content only (default: true)',
1049
+ },
1050
+ },
1051
+ required: ['url'],
1052
+ },
1053
+ },
1054
+ handler: async (args) => {
1055
+ try {
1056
+ const url = String(args.url);
1057
+ const extractMain = args.extract_main_content !== false;
1058
+ const response = await fetch(url, {
1059
+ headers: {
1060
+ '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',
1061
+ 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
1062
+ 'Accept-Language': 'en-US,en;q=0.5',
1063
+ },
1064
+ });
1065
+ if (!response.ok) {
1066
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
1067
+ }
1068
+ const html = await response.text();
1069
+ if (!extractMain) {
1070
+ // Return raw HTML (truncated)
1071
+ const truncated = html.length > 10000 ? html.slice(0, 10000) + '\n... (truncated)' : html;
1072
+ return {
1073
+ status: 'success',
1074
+ output: truncated,
1075
+ metadata: { url, content_length: html.length, truncated: html.length > 10000 },
1076
+ };
1077
+ }
1078
+ // Extract title
1079
+ const titleMatch = html.match(/<title[^>]*>([\s\S]*?)<\/title>/i);
1080
+ const title = titleMatch ? titleMatch[1].trim() : 'No title';
1081
+ // Extract main content - remove scripts, styles, nav, etc.
1082
+ let content = html
1083
+ .replace(/<script[^>]*>[\s\S]*?<\/script>/gi, '')
1084
+ .replace(/<style[^>]*>[\s\S]*?<\/style>/gi, '')
1085
+ .replace(/<nav[^>]*>[\s\S]*?<\/nav>/gi, '')
1086
+ .replace(/<header[^>]*>[\s\S]*?<\/header>/gi, '')
1087
+ .replace(/<footer[^>]*>[\s\S]*?<\/footer>/gi, '')
1088
+ .replace(/<aside[^>]*>[\s\S]*?<\/aside>/gi, '')
1089
+ .replace(/<[^>]*>/g, ' ') // Remove remaining tags
1090
+ .replace(/\s+/g, ' ') // Normalize whitespace
1091
+ .trim();
1092
+ // Truncate if too long
1093
+ const maxLength = 8000;
1094
+ const truncated = content.length > maxLength;
1095
+ if (truncated) {
1096
+ content = content.slice(0, maxLength) + '\n... (content truncated)';
1097
+ }
1098
+ return {
1099
+ status: 'success',
1100
+ output: `Title: ${title}\n\nContent:\n${content}`,
1101
+ metadata: {
1102
+ url,
1103
+ title,
1104
+ content_length: content.length,
1105
+ truncated,
1106
+ },
1107
+ };
1108
+ }
1109
+ catch (err) {
1110
+ return {
1111
+ status: 'error',
1112
+ error: err instanceof Error ? err.message : String(err),
1113
+ };
1114
+ }
1115
+ },
1116
+ };
1117
+ // Code execution tool - run code in various languages
1118
+ const codeExecutionTool = {
1119
+ definition: {
1120
+ name: 'execute_code',
1121
+ description: 'Execute code in various programming languages (JavaScript, Python, Bash). Returns stdout, stderr, and exit code.',
1122
+ parameters: {
1123
+ type: 'object',
1124
+ properties: {
1125
+ code: {
1126
+ type: 'string',
1127
+ description: 'The code to execute',
1128
+ },
1129
+ language: {
1130
+ type: 'string',
1131
+ description: 'Programming language (javascript, python, bash/shell)',
1132
+ enum: ['javascript', 'python', 'bash', 'shell'],
1133
+ },
1134
+ timeout_sec: {
1135
+ type: 'number',
1136
+ description: 'Timeout in seconds (default: 30)',
1137
+ },
1138
+ },
1139
+ required: ['code', 'language'],
1140
+ },
1141
+ },
1142
+ handler: async (args) => {
1143
+ try {
1144
+ const code = String(args.code);
1145
+ const language = String(args.language).toLowerCase();
1146
+ const timeoutSec = args.timeout_sec ? Number(args.timeout_sec) : 30;
1147
+ let command;
1148
+ let args_list;
1149
+ switch (language) {
1150
+ case 'javascript':
1151
+ case 'js':
1152
+ command = 'node';
1153
+ args_list = ['-e', code];
1154
+ break;
1155
+ case 'python':
1156
+ case 'py':
1157
+ command = 'python3';
1158
+ args_list = ['-c', code];
1159
+ break;
1160
+ case 'bash':
1161
+ case 'shell':
1162
+ case 'sh':
1163
+ command = 'bash';
1164
+ args_list = ['-c', code];
1165
+ break;
1166
+ default:
1167
+ return {
1168
+ status: 'error',
1169
+ error: `Unsupported language: ${language}. Supported: javascript, python, bash`,
1170
+ };
1171
+ }
1172
+ return new Promise((resolve) => {
1173
+ const child = spawn(command, args_list, {
1174
+ stdio: ['ignore', 'pipe', 'pipe'],
1175
+ });
1176
+ let stdout = '';
1177
+ let stderr = '';
1178
+ let timeout = null;
1179
+ if (timeoutSec > 0) {
1180
+ timeout = setTimeout(() => {
1181
+ child.kill('SIGTERM');
1182
+ setTimeout(() => {
1183
+ if (!child.killed)
1184
+ child.kill('SIGKILL');
1185
+ }, 5000);
1186
+ }, timeoutSec * 1000);
1187
+ }
1188
+ child.stdout?.on('data', (data) => {
1189
+ stdout += String(data);
1190
+ });
1191
+ child.stderr?.on('data', (data) => {
1192
+ stderr += String(data);
1193
+ });
1194
+ child.on('close', (code) => {
1195
+ if (timeout)
1196
+ clearTimeout(timeout);
1197
+ const output = stdout || stderr || '(no output)';
1198
+ const isError = code !== 0;
1199
+ resolve({
1200
+ status: isError ? 'error' : 'success',
1201
+ output,
1202
+ error: isError ? `Exit code: ${code}${stderr ? '\n' + stderr : ''}` : undefined,
1203
+ metadata: {
1204
+ language,
1205
+ exit_code: code,
1206
+ stdout_length: stdout.length,
1207
+ stderr_length: stderr.length,
1208
+ },
1209
+ });
1210
+ });
1211
+ child.on('error', (err) => {
1212
+ if (timeout)
1213
+ clearTimeout(timeout);
1214
+ resolve({
1215
+ status: 'error',
1216
+ error: `Failed to execute: ${err.message}`,
1217
+ });
1218
+ });
1219
+ });
1220
+ }
1221
+ catch (err) {
1222
+ return {
1223
+ status: 'error',
1224
+ error: err instanceof Error ? err.message : String(err),
1225
+ };
1226
+ }
1227
+ },
1228
+ };
1229
+ // Semantic search tool - search within files using embeddings
1230
+ const semanticSearchTool = {
1231
+ definition: {
1232
+ name: 'semantic_search',
1233
+ description: 'Search for semantically similar content in files. Uses embeddings to find conceptually related content, not just keyword matches.',
1234
+ parameters: {
1235
+ type: 'object',
1236
+ properties: {
1237
+ query: {
1238
+ type: 'string',
1239
+ description: 'The semantic query (what concept you are looking for)',
1240
+ },
1241
+ directory: {
1242
+ type: 'string',
1243
+ description: 'Directory to search in',
1244
+ },
1245
+ file_pattern: {
1246
+ type: 'string',
1247
+ description: 'File pattern to limit search (e.g., "*.md", "*.txt")',
1248
+ },
1249
+ top_k: {
1250
+ type: 'number',
1251
+ description: 'Number of top results to return (default: 5)',
1252
+ },
1253
+ },
1254
+ required: ['query', 'directory'],
1255
+ },
1256
+ },
1257
+ handler: async (args) => {
1258
+ try {
1259
+ const query = String(args.query);
1260
+ const directory = String(args.directory);
1261
+ const filePattern = args.file_pattern ? String(args.file_pattern) : '*';
1262
+ const topK = args.top_k ? Number(args.top_k) : 5;
1263
+ // Using Eden's Researcher Module for true Semantic Search (NVIDIA NIM Embeddings)
1264
+ try {
1265
+ const { researcher } = await import('../researcher.js');
1266
+ const { execSync } = await import('child_process');
1267
+ // Find files matching pattern
1268
+ const command = `find "${directory}" -name "${filePattern}" -type f 2>/dev/null | head -50`;
1269
+ const files = execSync(command, { encoding: 'utf8', timeout: 30000 }).trim().split('\n').filter(Boolean);
1270
+ if (files.length === 0) {
1271
+ return {
1272
+ status: 'success',
1273
+ output: 'No files found matching the pattern.',
1274
+ metadata: { query, directory, matches: 0 },
1275
+ };
1276
+ }
1277
+ // Index all found files
1278
+ const fs = await import('fs/promises');
1279
+ for (const file of files) {
1280
+ try {
1281
+ const content = await fs.readFile(file, 'utf8');
1282
+ await researcher.indexFile(file, content);
1283
+ }
1284
+ catch (e) {
1285
+ // Ignore unreadable files
1286
+ }
1287
+ }
1288
+ // Search the knowledge base
1289
+ const results = await researcher.search(query, topK);
1290
+ if (results.length === 0) {
1291
+ return {
1292
+ status: 'success',
1293
+ output: 'No semantic matches found.',
1294
+ metadata: { query, directory, matches: 0 },
1295
+ };
1296
+ }
1297
+ const formattedResults = results.map(r => `File: ${r.filePath}\nContent:\n${r.content}\n---`);
1298
+ return {
1299
+ status: 'success',
1300
+ output: formattedResults.join('\n\n'),
1301
+ metadata: {
1302
+ query,
1303
+ directory,
1304
+ files_searched: files.length,
1305
+ results_returned: results.length,
1306
+ },
1307
+ };
1308
+ }
1309
+ catch (err) {
1310
+ return {
1311
+ status: 'error',
1312
+ error: `Search failed: ${err instanceof Error ? err.message : String(err)}`,
1313
+ };
1314
+ }
1315
+ }
1316
+ catch (err) {
1317
+ return {
1318
+ status: 'error',
1319
+ error: err instanceof Error ? err.message : String(err),
1320
+ };
1321
+ }
1322
+ },
1323
+ };
1324
+ // Git tools - various git operations
1325
+ const gitStatusTool = {
1326
+ definition: {
1327
+ name: 'git_status',
1328
+ description: 'Check git repository status. Shows modified, staged, and untracked files.',
1329
+ parameters: {
1330
+ type: 'object',
1331
+ properties: {
1332
+ repository_path: {
1333
+ type: 'string',
1334
+ description: 'Path to the git repository (default: current directory)',
1335
+ },
1336
+ },
1337
+ required: [],
1338
+ },
1339
+ },
1340
+ handler: async (args) => {
1341
+ try {
1342
+ const repoPath = args.repository_path ? String(args.repository_path) : process.cwd();
1343
+ const result = execSync('git status -sb', {
1344
+ cwd: repoPath,
1345
+ encoding: 'utf8',
1346
+ timeout: 10000,
1347
+ });
1348
+ return {
1349
+ status: 'success',
1350
+ output: result.trim() || 'No changes',
1351
+ metadata: { repository: repoPath },
1352
+ };
1353
+ }
1354
+ catch (err) {
1355
+ return {
1356
+ status: 'error',
1357
+ error: `Not a git repository or git not available: ${err instanceof Error ? err.message : String(err)}`,
1358
+ };
1359
+ }
1360
+ },
1361
+ };
1362
+ const gitDiffTool = {
1363
+ definition: {
1364
+ name: 'git_diff',
1365
+ description: 'Show git diff for modified files. Can show staged or unstaged changes.',
1366
+ parameters: {
1367
+ type: 'object',
1368
+ properties: {
1369
+ repository_path: {
1370
+ type: 'string',
1371
+ description: 'Path to the git repository',
1372
+ },
1373
+ staged: {
1374
+ type: 'boolean',
1375
+ description: 'Show staged changes instead of unstaged',
1376
+ },
1377
+ file_path: {
1378
+ type: 'string',
1379
+ description: 'Show diff for specific file only',
1380
+ },
1381
+ },
1382
+ required: [],
1383
+ },
1384
+ },
1385
+ handler: async (args) => {
1386
+ try {
1387
+ const repoPath = args.repository_path ? String(args.repository_path) : process.cwd();
1388
+ const staged = Boolean(args.staged);
1389
+ const filePath = args.file_path ? String(args.file_path) : undefined;
1390
+ let command = 'git diff';
1391
+ if (staged)
1392
+ command += ' --cached';
1393
+ if (filePath)
1394
+ command += ` -- "${filePath}"`;
1395
+ const result = execSync(command, {
1396
+ cwd: repoPath,
1397
+ encoding: 'utf8',
1398
+ timeout: 10000,
1399
+ });
1400
+ return {
1401
+ status: 'success',
1402
+ output: result.trim() || 'No changes',
1403
+ metadata: { repository: repoPath, staged, file: filePath },
1404
+ };
1405
+ }
1406
+ catch (err) {
1407
+ return {
1408
+ status: 'error',
1409
+ error: err instanceof Error ? err.message : String(err),
1410
+ };
1411
+ }
1412
+ },
1413
+ };
1414
+ const gitLogTool = {
1415
+ definition: {
1416
+ name: 'git_log',
1417
+ description: 'Show git commit history with customizable format.',
1418
+ parameters: {
1419
+ type: 'object',
1420
+ properties: {
1421
+ repository_path: {
1422
+ type: 'string',
1423
+ description: 'Path to the git repository',
1424
+ },
1425
+ num_commits: {
1426
+ type: 'number',
1427
+ description: 'Number of commits to show (default: 10)',
1428
+ },
1429
+ oneline: {
1430
+ type: 'boolean',
1431
+ description: 'Show one line per commit',
1432
+ },
1433
+ },
1434
+ required: [],
1435
+ },
1436
+ },
1437
+ handler: async (args) => {
1438
+ try {
1439
+ const repoPath = args.repository_path ? String(args.repository_path) : process.cwd();
1440
+ const numCommits = args.num_commits ? Number(args.num_commits) : 10;
1441
+ const oneline = Boolean(args.oneline);
1442
+ let command = `git log -n ${numCommits}`;
1443
+ if (oneline)
1444
+ command += ' --oneline';
1445
+ const result = execSync(command, {
1446
+ cwd: repoPath,
1447
+ encoding: 'utf8',
1448
+ timeout: 10000,
1449
+ });
1450
+ return {
1451
+ status: 'success',
1452
+ output: result.trim(),
1453
+ metadata: { repository: repoPath, commits_shown: numCommits },
1454
+ };
1455
+ }
1456
+ catch (err) {
1457
+ return {
1458
+ status: 'error',
1459
+ error: err instanceof Error ? err.message : String(err),
1460
+ };
1461
+ }
1462
+ },
1463
+ };
1464
+ // HTTP API tool - make HTTP requests
1465
+ const httpRequestTool = {
1466
+ definition: {
1467
+ name: 'http_request',
1468
+ description: 'Make HTTP requests (GET, POST, PUT, DELETE, PATCH). Supports JSON body and custom headers.',
1469
+ parameters: {
1470
+ type: 'object',
1471
+ properties: {
1472
+ url: {
1473
+ type: 'string',
1474
+ description: 'The URL to request',
1475
+ },
1476
+ method: {
1477
+ type: 'string',
1478
+ description: 'HTTP method',
1479
+ enum: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'],
1480
+ },
1481
+ headers: {
1482
+ type: 'object',
1483
+ description: 'Custom headers as key-value pairs',
1484
+ },
1485
+ body: {
1486
+ type: 'string',
1487
+ description: 'Request body (for POST, PUT, PATCH)',
1488
+ },
1489
+ body_json: {
1490
+ type: 'object',
1491
+ description: 'JSON body as object (will be serialized)',
1492
+ },
1493
+ },
1494
+ required: ['url'],
1495
+ },
1496
+ },
1497
+ handler: async (args) => {
1498
+ try {
1499
+ const url = String(args.url);
1500
+ const method = args.method ? String(args.method).toUpperCase() : 'GET';
1501
+ const headers = args.headers || {};
1502
+ let body;
1503
+ if (args.body_json) {
1504
+ body = JSON.stringify(args.body_json);
1505
+ headers['Content-Type'] = headers['Content-Type'] || 'application/json';
1506
+ }
1507
+ else if (args.body) {
1508
+ body = String(args.body);
1509
+ }
1510
+ const response = await fetch(url, {
1511
+ method,
1512
+ headers,
1513
+ body: body && method !== 'GET' && method !== 'HEAD' ? body : undefined,
1514
+ });
1515
+ const responseBody = await response.text();
1516
+ const truncated = responseBody.length > 10000;
1517
+ const output = truncated ? responseBody.slice(0, 10000) + '\n... (truncated)' : responseBody;
1518
+ // Try to parse as JSON for metadata
1519
+ let jsonBody = null;
1520
+ try {
1521
+ jsonBody = JSON.parse(responseBody);
1522
+ }
1523
+ catch {
1524
+ // Not JSON
1525
+ }
1526
+ // Collect headers
1527
+ const headersObj = {};
1528
+ response.headers.forEach((value, key) => {
1529
+ headersObj[key] = value;
1530
+ });
1531
+ return {
1532
+ status: response.ok ? 'success' : 'error',
1533
+ output,
1534
+ error: response.ok ? undefined : `HTTP ${response.status}: ${response.statusText}`,
1535
+ metadata: {
1536
+ status: response.status,
1537
+ statusText: response.statusText,
1538
+ headers: headersObj,
1539
+ body_truncated: truncated,
1540
+ body_length: responseBody.length,
1541
+ json_parsed: jsonBody !== null,
1542
+ },
1543
+ };
1544
+ }
1545
+ catch (err) {
1546
+ return {
1547
+ status: 'error',
1548
+ error: err instanceof Error ? err.message : String(err),
1549
+ };
1550
+ }
1551
+ },
1552
+ };
1553
+ // JSON/YAML tools - parsing and conversion
1554
+ const parseJsonTool = {
1555
+ definition: {
1556
+ name: 'parse_json',
1557
+ description: 'Parse and validate JSON. Returns formatted JSON or error details.',
1558
+ parameters: {
1559
+ type: 'object',
1560
+ properties: {
1561
+ text: {
1562
+ type: 'string',
1563
+ description: 'JSON text to parse',
1564
+ },
1565
+ file_path: {
1566
+ type: 'string',
1567
+ description: 'Path to JSON file (alternative to text)',
1568
+ },
1569
+ format_output: {
1570
+ type: 'boolean',
1571
+ description: 'Format output with indentation (default: true)',
1572
+ },
1573
+ },
1574
+ required: [],
1575
+ },
1576
+ },
1577
+ handler: async (args) => {
1578
+ try {
1579
+ let text;
1580
+ if (args.file_path) {
1581
+ text = await fs.readFile(String(args.file_path), 'utf8');
1582
+ }
1583
+ else if (args.text) {
1584
+ text = String(args.text);
1585
+ }
1586
+ else {
1587
+ return {
1588
+ status: 'error',
1589
+ error: 'Either text or file_path must be provided',
1590
+ };
1591
+ }
1592
+ const parsed = JSON.parse(text);
1593
+ const formatOutput = args.format_output !== false;
1594
+ const output = formatOutput ? JSON.stringify(parsed, null, 2) : JSON.stringify(parsed);
1595
+ // Get type info
1596
+ const type = Array.isArray(parsed) ? 'array' : typeof parsed;
1597
+ const keys = type === 'object' && parsed !== null ? Object.keys(parsed) : null;
1598
+ return {
1599
+ status: 'success',
1600
+ output,
1601
+ metadata: {
1602
+ type,
1603
+ keys: keys,
1604
+ length: Array.isArray(parsed) ? parsed.length : undefined,
1605
+ },
1606
+ };
1607
+ }
1608
+ catch (err) {
1609
+ return {
1610
+ status: 'error',
1611
+ error: `Invalid JSON: ${err instanceof Error ? err.message : String(err)}`,
1612
+ };
1613
+ }
1614
+ },
1615
+ };
1616
+ const jsonToYamlTool = {
1617
+ definition: {
1618
+ name: 'convert_json_yaml',
1619
+ description: 'Convert between JSON and YAML formats.',
1620
+ parameters: {
1621
+ type: 'object',
1622
+ properties: {
1623
+ input: {
1624
+ type: 'string',
1625
+ description: 'Input text (JSON or YAML)',
1626
+ },
1627
+ file_path: {
1628
+ type: 'string',
1629
+ description: 'Path to file (alternative to input)',
1630
+ },
1631
+ to: {
1632
+ type: 'string',
1633
+ description: 'Target format',
1634
+ enum: ['json', 'yaml'],
1635
+ },
1636
+ },
1637
+ required: ['to'],
1638
+ },
1639
+ },
1640
+ handler: async (args) => {
1641
+ try {
1642
+ const targetFormat = String(args.to).toLowerCase();
1643
+ let input;
1644
+ if (args.file_path) {
1645
+ input = await fs.readFile(String(args.file_path), 'utf8');
1646
+ }
1647
+ else if (args.input) {
1648
+ input = String(args.input);
1649
+ }
1650
+ else {
1651
+ return {
1652
+ status: 'error',
1653
+ error: 'Either input or file_path must be provided',
1654
+ };
1655
+ }
1656
+ // Detect input format and parse
1657
+ let data;
1658
+ try {
1659
+ data = JSON.parse(input);
1660
+ }
1661
+ catch {
1662
+ // Try YAML-like parsing (simplified - just handles basic cases)
1663
+ // For full YAML support, would need js-yaml library
1664
+ const lines = input.split('\n');
1665
+ data = {};
1666
+ let currentKey = '';
1667
+ for (const line of lines) {
1668
+ const match = line.match(/^(\w+):\s*(.*)$/);
1669
+ if (match) {
1670
+ currentKey = match[1];
1671
+ data[currentKey] = match[2] || '';
1672
+ }
1673
+ }
1674
+ }
1675
+ let output;
1676
+ if (targetFormat === 'json') {
1677
+ output = JSON.stringify(data, null, 2);
1678
+ }
1679
+ else {
1680
+ // Simple YAML serialization
1681
+ output = Object.entries(data)
1682
+ .map(([k, v]) => `${k}: ${typeof v === 'string' ? v : JSON.stringify(v)}`)
1683
+ .join('\n');
1684
+ }
1685
+ return {
1686
+ status: 'success',
1687
+ output,
1688
+ metadata: { source_format: targetFormat === 'json' ? 'yaml' : 'json', target_format: targetFormat },
1689
+ };
1690
+ }
1691
+ catch (err) {
1692
+ return {
1693
+ status: 'error',
1694
+ error: err instanceof Error ? err.message : String(err),
1695
+ };
1696
+ }
1697
+ },
1698
+ };
1699
+ // File diff tool - compare two files
1700
+ const diffFilesTool = {
1701
+ definition: {
1702
+ name: 'diff_files',
1703
+ description: 'Compare two files and show differences. Uses unified diff format.',
1704
+ parameters: {
1705
+ type: 'object',
1706
+ properties: {
1707
+ file1: {
1708
+ type: 'string',
1709
+ description: 'Path to first file',
1710
+ },
1711
+ file2: {
1712
+ type: 'string',
1713
+ description: 'Path to second file',
1714
+ },
1715
+ unified_lines: {
1716
+ type: 'number',
1717
+ description: 'Number of context lines (default: 3)',
1718
+ },
1719
+ },
1720
+ required: ['file1', 'file2'],
1721
+ },
1722
+ },
1723
+ handler: async (args) => {
1724
+ try {
1725
+ const file1 = String(args.file1);
1726
+ const file2 = String(args.file2);
1727
+ const context = args.unified_lines ? Number(args.unified_lines) : 3;
1728
+ const content1 = await fs.readFile(file1, 'utf8');
1729
+ const content2 = await fs.readFile(file2, 'utf8');
1730
+ // Simple line-by-line diff
1731
+ const lines1 = content1.split('\n');
1732
+ const lines2 = content2.split('\n');
1733
+ const diff = [];
1734
+ const maxLen = Math.max(lines1.length, lines2.length);
1735
+ for (let i = 0; i < maxLen; i++) {
1736
+ const line1 = lines1[i];
1737
+ const line2 = lines2[i];
1738
+ if (line1 !== line2) {
1739
+ if (line1 !== undefined)
1740
+ diff.push(`-${line1}`);
1741
+ if (line2 !== undefined)
1742
+ diff.push(`+${line2}`);
1743
+ }
1744
+ else {
1745
+ diff.push(` ${line1}`);
1746
+ }
1747
+ }
1748
+ const output = diff.slice(0, 200).join('\n'); // Limit output
1749
+ const truncated = diff.length > 200;
1750
+ return {
1751
+ status: 'success',
1752
+ output: truncated ? output + '\n... (truncated)' : output,
1753
+ metadata: { file1, file2, differences: diff.length },
1754
+ };
1755
+ }
1756
+ catch (err) {
1757
+ return {
1758
+ status: 'error',
1759
+ error: err instanceof Error ? err.message : String(err),
1760
+ };
1761
+ }
1762
+ },
1763
+ };
1764
+ // Compression tools - create/extract archives
1765
+ const createArchiveTool = {
1766
+ definition: {
1767
+ name: 'create_archive',
1768
+ description: 'Create a zip or tar archive from files or directories.',
1769
+ parameters: {
1770
+ type: 'object',
1771
+ properties: {
1772
+ output_path: {
1773
+ type: 'string',
1774
+ description: 'Path for the output archive',
1775
+ },
1776
+ source_paths: {
1777
+ type: 'array',
1778
+ description: 'Array of file or directory paths to include',
1779
+ items: { type: 'string' },
1780
+ },
1781
+ format: {
1782
+ type: 'string',
1783
+ description: 'Archive format',
1784
+ enum: ['zip', 'tar', 'tar.gz', 'tgz'],
1785
+ },
1786
+ },
1787
+ required: ['output_path', 'source_paths'],
1788
+ },
1789
+ },
1790
+ handler: async (args) => {
1791
+ try {
1792
+ const outputPath = String(args.output_path);
1793
+ const sourcePaths = Array.isArray(args.source_paths) ? args.source_paths.map(String) : [];
1794
+ const format = args.format ? String(args.format) : 'zip';
1795
+ let command;
1796
+ const sources = sourcePaths.map(p => `"${p}"`).join(' ');
1797
+ switch (format) {
1798
+ case 'zip':
1799
+ command = `zip -r "${outputPath}" ${sources}`;
1800
+ break;
1801
+ case 'tar':
1802
+ command = `tar -cf "${outputPath}" ${sources}`;
1803
+ break;
1804
+ case 'tar.gz':
1805
+ case 'tgz':
1806
+ command = `tar -czf "${outputPath}" ${sources}`;
1807
+ break;
1808
+ default:
1809
+ return {
1810
+ status: 'error',
1811
+ error: `Unsupported format: ${format}`,
1812
+ };
1813
+ }
1814
+ execSync(command, { timeout: 60000 });
1815
+ const stats = await fs.stat(outputPath);
1816
+ return {
1817
+ status: 'success',
1818
+ output: `Archive created: ${outputPath} (${(stats.size / 1024).toFixed(2)} KB)`,
1819
+ metadata: { output_path: outputPath, format, files_included: sourcePaths.length, size_bytes: stats.size },
1820
+ };
1821
+ }
1822
+ catch (err) {
1823
+ return {
1824
+ status: 'error',
1825
+ error: err instanceof Error ? err.message : String(err),
1826
+ };
1827
+ }
1828
+ },
1829
+ };
1830
+ const extractArchiveTool = {
1831
+ definition: {
1832
+ name: 'extract_archive',
1833
+ description: 'Extract a zip or tar archive.',
1834
+ parameters: {
1835
+ type: 'object',
1836
+ properties: {
1837
+ archive_path: {
1838
+ type: 'string',
1839
+ description: 'Path to the archive file',
1840
+ },
1841
+ output_directory: {
1842
+ type: 'string',
1843
+ description: 'Directory to extract to (default: same as archive)',
1844
+ },
1845
+ },
1846
+ required: ['archive_path'],
1847
+ },
1848
+ },
1849
+ handler: async (args) => {
1850
+ try {
1851
+ const archivePath = String(args.archive_path);
1852
+ const outputDir = args.output_directory ? String(args.output_directory) : path.dirname(archivePath);
1853
+ // Detect format from extension
1854
+ const ext = path.extname(archivePath).toLowerCase();
1855
+ const baseName = path.basename(archivePath);
1856
+ let command;
1857
+ if (ext === '.zip') {
1858
+ command = `unzip -o "${archivePath}" -d "${outputDir}"`;
1859
+ }
1860
+ else if (ext === '.gz' || baseName.endsWith('.tar.gz') || baseName.endsWith('.tgz')) {
1861
+ command = `tar -xzf "${archivePath}" -C "${outputDir}"`;
1862
+ }
1863
+ else if (ext === '.tar') {
1864
+ command = `tar -xf "${archivePath}" -C "${outputDir}"`;
1865
+ }
1866
+ else {
1867
+ return {
1868
+ status: 'error',
1869
+ error: `Could not detect archive format from: ${archivePath}`,
1870
+ };
1871
+ }
1872
+ execSync(command, { timeout: 60000 });
1873
+ return {
1874
+ status: 'success',
1875
+ output: `Archive extracted to: ${outputDir}`,
1876
+ metadata: { archive: archivePath, output_directory: outputDir },
1877
+ };
1878
+ }
1879
+ catch (err) {
1880
+ return {
1881
+ status: 'error',
1882
+ error: err instanceof Error ? err.message : String(err),
1883
+ };
1884
+ }
1885
+ },
1886
+ };
1887
+ // PDF text extraction tool
1888
+ const extractPdfTool = {
1889
+ definition: {
1890
+ name: 'extract_pdf_text',
1891
+ description: 'Extract text content from a PDF file. Requires pdftotext or similar tool.',
1892
+ parameters: {
1893
+ type: 'object',
1894
+ properties: {
1895
+ pdf_path: {
1896
+ type: 'string',
1897
+ description: 'Path to the PDF file',
1898
+ },
1899
+ page_range: {
1900
+ type: 'string',
1901
+ description: 'Page range to extract (e.g., "1-5" or "1,3,5", default: all)',
1902
+ },
1903
+ },
1904
+ required: ['pdf_path'],
1905
+ },
1906
+ },
1907
+ handler: async (args) => {
1908
+ try {
1909
+ const pdfPath = String(args.pdf_path);
1910
+ const pageRange = args.page_range ? String(args.page_range) : undefined;
1911
+ let command = `pdftotext -layout`;
1912
+ if (pageRange) {
1913
+ command += ` -f ${pageRange.split('-')[0]} -l ${pageRange.split('-')[1] || pageRange.split('-')[0]}`;
1914
+ }
1915
+ command += ` "${pdfPath}" -`; // Output to stdout
1916
+ const output = execSync(command, { encoding: 'utf8', timeout: 30000 });
1917
+ const truncated = output.length > 15000;
1918
+ return {
1919
+ status: 'success',
1920
+ output: truncated ? output.slice(0, 15000) + '\n... (truncated)' : output,
1921
+ metadata: { pdf_path: pdfPath, page_range: pageRange, text_length: output.length, truncated },
1922
+ };
1923
+ }
1924
+ catch (err) {
1925
+ // Fallback: try Python with PyPDF2
1926
+ try {
1927
+ const pythonScript = `
1928
+ import sys
1929
+ from PyPDF2 import PdfReader
1930
+ reader = PdfReader("${args.pdf_path}")
1931
+ text = ""
1932
+ for page in reader.pages:
1933
+ text += page.extract_text() + "\\n"
1934
+ print(text)
1935
+ `;
1936
+ const output = execSync(`python3 -c "${pythonScript}"`, { encoding: 'utf8', timeout: 30000 });
1937
+ return {
1938
+ status: 'success',
1939
+ output,
1940
+ metadata: { pdf_path: args.pdf_path, method: 'pypdf2' },
1941
+ };
1942
+ }
1943
+ catch {
1944
+ return {
1945
+ status: 'error',
1946
+ error: `Failed to extract PDF text. Ensure pdftotext (poppler-utils) or PyPDF2 is installed. Original error: ${err instanceof Error ? err.message : String(err)}`,
1947
+ };
1948
+ }
1949
+ }
1950
+ },
1951
+ };
1952
+ // Network tools - ping, port check, DNS
1953
+ const pingTool = {
1954
+ definition: {
1955
+ name: 'ping_host',
1956
+ description: 'Ping a host to check network connectivity.',
1957
+ parameters: {
1958
+ type: 'object',
1959
+ properties: {
1960
+ host: {
1961
+ type: 'string',
1962
+ description: 'Hostname or IP to ping',
1963
+ },
1964
+ count: {
1965
+ type: 'number',
1966
+ description: 'Number of pings (default: 4)',
1967
+ },
1968
+ },
1969
+ required: ['host'],
1970
+ },
1971
+ },
1972
+ handler: async (args) => {
1973
+ try {
1974
+ const host = String(args.host);
1975
+ const count = args.count ? Number(args.count) : 4;
1976
+ const output = execSync(`ping -c ${count} "${host}"`, {
1977
+ encoding: 'utf8',
1978
+ timeout: 30000,
1979
+ });
1980
+ return {
1981
+ status: 'success',
1982
+ output,
1983
+ metadata: { host, count },
1984
+ };
1985
+ }
1986
+ catch (err) {
1987
+ // ping returns non-zero on some failures but still has output
1988
+ const output = err.stdout;
1989
+ if (output) {
1990
+ return {
1991
+ status: 'error',
1992
+ output,
1993
+ error: 'Host unreachable or ping failed',
1994
+ metadata: { host: args.host },
1995
+ };
1996
+ }
1997
+ return {
1998
+ status: 'error',
1999
+ error: err instanceof Error ? err.message : String(err),
2000
+ };
2001
+ }
2002
+ },
2003
+ };
2004
+ const checkPortTool = {
2005
+ definition: {
2006
+ name: 'check_port',
2007
+ description: 'Check if a port is open on a host.',
2008
+ parameters: {
2009
+ type: 'object',
2010
+ properties: {
2011
+ host: {
2012
+ type: 'string',
2013
+ description: 'Hostname or IP',
2014
+ },
2015
+ port: {
2016
+ type: 'number',
2017
+ description: 'Port number to check',
2018
+ },
2019
+ timeout_sec: {
2020
+ type: 'number',
2021
+ description: 'Timeout in seconds (default: 5)',
2022
+ },
2023
+ },
2024
+ required: ['host', 'port'],
2025
+ },
2026
+ },
2027
+ handler: async (args) => {
2028
+ try {
2029
+ const host = String(args.host);
2030
+ const port = Number(args.port);
2031
+ const timeout = args.timeout_sec ? Number(args.timeout_sec) : 5;
2032
+ // Try using nc (netcat)
2033
+ try {
2034
+ execSync(`nc -z -w ${timeout} "${host}" ${port}`, { timeout: timeout * 1000 + 1000 });
2035
+ return {
2036
+ status: 'success',
2037
+ output: `Port ${port} on ${host} is OPEN`,
2038
+ metadata: { host, port, open: true },
2039
+ };
2040
+ }
2041
+ catch {
2042
+ return {
2043
+ status: 'success',
2044
+ output: `Port ${port} on ${host} is CLOSED or filtered`,
2045
+ metadata: { host, port, open: false },
2046
+ };
2047
+ }
2048
+ }
2049
+ catch (err) {
2050
+ return {
2051
+ status: 'error',
2052
+ error: err instanceof Error ? err.message : String(err),
2053
+ };
2054
+ }
2055
+ },
2056
+ };
2057
+ // Docker tool - manage containers
2058
+ const dockerTool = {
2059
+ definition: {
2060
+ name: 'docker',
2061
+ description: 'Run Docker commands. Supports ps, images, logs, exec, run, build.',
2062
+ parameters: {
2063
+ type: 'object',
2064
+ properties: {
2065
+ command: {
2066
+ type: 'string',
2067
+ description: 'Docker command (ps, images, logs, exec, run, build, stop, rm)',
2068
+ enum: ['ps', 'images', 'logs', 'exec', 'run', 'build', 'stop', 'rm', 'compose-up', 'compose-down'],
2069
+ },
2070
+ container: {
2071
+ type: 'string',
2072
+ description: 'Container name or ID (for logs, exec, stop, rm)',
2073
+ },
2074
+ args: {
2075
+ type: 'string',
2076
+ description: 'Additional arguments',
2077
+ },
2078
+ },
2079
+ required: ['command'],
2080
+ },
2081
+ },
2082
+ handler: async (args) => {
2083
+ try {
2084
+ const command = String(args.command);
2085
+ const container = args.container ? String(args.container) : '';
2086
+ const extraArgs = args.args ? String(args.args) : '';
2087
+ let dockerCmd;
2088
+ switch (command) {
2089
+ case 'ps':
2090
+ dockerCmd = 'docker ps -a';
2091
+ break;
2092
+ case 'images':
2093
+ dockerCmd = 'docker images';
2094
+ break;
2095
+ case 'logs':
2096
+ if (!container)
2097
+ return { status: 'error', error: 'Container name required for logs' };
2098
+ dockerCmd = `docker logs --tail 100 ${container}`;
2099
+ break;
2100
+ case 'exec':
2101
+ if (!container)
2102
+ return { status: 'error', error: 'Container name required for exec' };
2103
+ dockerCmd = `docker exec ${container} ${extraArgs || 'sh'}`;
2104
+ break;
2105
+ case 'stop':
2106
+ if (!container)
2107
+ return { status: 'error', error: 'Container name required for stop' };
2108
+ dockerCmd = `docker stop ${container}`;
2109
+ break;
2110
+ case 'rm':
2111
+ if (!container)
2112
+ return { status: 'error', error: 'Container name required for rm' };
2113
+ dockerCmd = `docker rm ${container}`;
2114
+ break;
2115
+ case 'compose-up':
2116
+ dockerCmd = 'docker compose up -d';
2117
+ break;
2118
+ case 'compose-down':
2119
+ dockerCmd = 'docker compose down';
2120
+ break;
2121
+ default:
2122
+ dockerCmd = `docker ${command} ${extraArgs}`;
2123
+ }
2124
+ const output = execSync(dockerCmd, { encoding: 'utf8', timeout: 60000 });
2125
+ return {
2126
+ status: 'success',
2127
+ output: output.trim(),
2128
+ metadata: { command: dockerCmd },
2129
+ };
2130
+ }
2131
+ catch (err) {
2132
+ return {
2133
+ status: 'error',
2134
+ error: err instanceof Error ? err.message : String(err),
2135
+ };
2136
+ }
2137
+ },
2138
+ };
2139
+ // CSV processing tool
2140
+ const csvTool = {
2141
+ definition: {
2142
+ name: 'process_csv',
2143
+ description: 'Process CSV files - view, filter, convert to JSON, get statistics.',
2144
+ parameters: {
2145
+ type: 'object',
2146
+ properties: {
2147
+ file_path: {
2148
+ type: 'string',
2149
+ description: 'Path to CSV file',
2150
+ },
2151
+ action: {
2152
+ type: 'string',
2153
+ description: 'Action to perform',
2154
+ enum: ['view', 'head', 'stats', 'to_json'],
2155
+ },
2156
+ limit: {
2157
+ type: 'number',
2158
+ description: 'Number of rows to show (default: 10)',
2159
+ },
2160
+ },
2161
+ required: ['file_path', 'action'],
2162
+ },
2163
+ },
2164
+ handler: async (args) => {
2165
+ try {
2166
+ const filePath = String(args.file_path);
2167
+ const action = String(args.action);
2168
+ const limit = args.limit ? Number(args.limit) : 10;
2169
+ const content = await fs.readFile(filePath, 'utf8');
2170
+ const lines = content.split('\n').filter(l => l.trim());
2171
+ if (lines.length === 0) {
2172
+ return { status: 'error', error: 'Empty CSV file' };
2173
+ }
2174
+ const headers = lines[0].split(',').map(h => h.trim());
2175
+ switch (action) {
2176
+ case 'head':
2177
+ case 'view': {
2178
+ const rows = lines.slice(1, limit + 1).map(line => {
2179
+ const cells = line.split(',').map(c => c.trim());
2180
+ return cells.map((c, i) => `${headers[i]}: ${c}`).join(' | ');
2181
+ });
2182
+ return {
2183
+ status: 'success',
2184
+ output: `Headers: ${headers.join(', ')}\n\n${rows.join('\n')}`,
2185
+ metadata: { total_rows: lines.length - 1, shown: rows.length },
2186
+ };
2187
+ }
2188
+ case 'stats': {
2189
+ const colStats = {};
2190
+ headers.forEach(h => colStats[h] = { count: 0, unique: new Set(), numeric: [] });
2191
+ for (const line of lines.slice(1)) {
2192
+ const cells = line.split(',').map(c => c.trim());
2193
+ cells.forEach((cell, i) => {
2194
+ const h = headers[i];
2195
+ colStats[h].count++;
2196
+ colStats[h].unique.add(cell);
2197
+ const num = parseFloat(cell);
2198
+ if (!isNaN(num))
2199
+ colStats[h].numeric.push(num);
2200
+ });
2201
+ }
2202
+ const stats = headers.map(h => {
2203
+ const s = colStats[h];
2204
+ const numericInfo = s.numeric.length > 0
2205
+ ? ` | min: ${Math.min(...s.numeric)} | max: ${Math.max(...s.numeric)} | avg: ${(s.numeric.reduce((a, b) => a + b, 0) / s.numeric.length).toFixed(2)}`
2206
+ : '';
2207
+ return `${h}: ${s.count} rows, ${s.unique.size} unique${numericInfo}`;
2208
+ });
2209
+ return {
2210
+ status: 'success',
2211
+ output: stats.join('\n'),
2212
+ metadata: { columns: headers.length, rows: lines.length - 1 },
2213
+ };
2214
+ }
2215
+ case 'to_json': {
2216
+ const rows = lines.slice(1).map(line => {
2217
+ const cells = line.split(',').map(c => c.trim());
2218
+ const obj = {};
2219
+ headers.forEach((h, i) => obj[h] = cells[i] || '');
2220
+ return obj;
2221
+ });
2222
+ return {
2223
+ status: 'success',
2224
+ output: JSON.stringify(rows, null, 2),
2225
+ metadata: { rows: rows.length },
2226
+ };
2227
+ }
2228
+ default:
2229
+ return { status: 'error', error: `Unknown action: ${action}` };
2230
+ }
2231
+ }
2232
+ catch (err) {
2233
+ return {
2234
+ status: 'error',
2235
+ error: err instanceof Error ? err.message : String(err),
2236
+ };
2237
+ }
2238
+ },
2239
+ };
2240
+ // SQLite database tool
2241
+ const sqliteTool = {
2242
+ definition: {
2243
+ name: 'query_sqlite',
2244
+ description: 'Execute SQL queries on SQLite databases.',
2245
+ parameters: {
2246
+ type: 'object',
2247
+ properties: {
2248
+ database_path: {
2249
+ type: 'string',
2250
+ description: 'Path to SQLite database file',
2251
+ },
2252
+ query: {
2253
+ type: 'string',
2254
+ description: 'SQL query to execute',
2255
+ },
2256
+ },
2257
+ required: ['database_path', 'query'],
2258
+ },
2259
+ },
2260
+ handler: async (args) => {
2261
+ try {
2262
+ const dbPath = String(args.database_path);
2263
+ const query = String(args.query);
2264
+ const output = execSync(`sqlite3 "${dbPath}" "${query.replace(/"/g, '""')}"`, {
2265
+ encoding: 'utf8',
2266
+ timeout: 30000,
2267
+ });
2268
+ return {
2269
+ status: 'success',
2270
+ output: output.trim(),
2271
+ metadata: { database: dbPath, query },
2272
+ };
2273
+ }
2274
+ catch (err) {
2275
+ return {
2276
+ status: 'error',
2277
+ error: err instanceof Error ? err.message : String(err),
2278
+ };
2279
+ }
2280
+ },
2281
+ };
2282
+ // Export all tools
2283
+ export const tools = [
2284
+ // Core file/system tools
2285
+ readFileTool,
2286
+ writeFileTool,
2287
+ editFileTool,
2288
+ listDirTool,
2289
+ grepSearchTool,
2290
+ runCommandTool,
2291
+ findByNameTool,
2292
+ viewUrlTool,
2293
+ askUserTool,
2294
+ createMemoryTool,
2295
+ analyzeImageTool,
2296
+ embeddingTool,
2297
+ webSearchTool,
2298
+ browserTool,
2299
+ codeExecutionTool,
2300
+ semanticSearchTool,
2301
+ gitStatusTool,
2302
+ gitDiffTool,
2303
+ gitLogTool,
2304
+ httpRequestTool,
2305
+ parseJsonTool,
2306
+ jsonToYamlTool,
2307
+ diffFilesTool,
2308
+ createArchiveTool,
2309
+ extractArchiveTool,
2310
+ extractPdfTool,
2311
+ pingTool,
2312
+ checkPortTool,
2313
+ dockerTool,
2314
+ csvTool,
2315
+ sqliteTool,
2316
+ delegateTasksTool,
2317
+ // API integrations
2318
+ ...slackTools,
2319
+ ...googleTools,
2320
+ ...githubTools,
2321
+ ...discordTools,
2322
+ ...telegramTools,
2323
+ listAgentsTool,
2324
+ createAgentTool,
2325
+ codeSearchTool,
2326
+ selfHealTool,
2327
+ sageMemoryTool,
2328
+ sendBriefingTool,
2329
+ craftTool,
2330
+ optimizePromptTool,
2331
+ predictHealingTool,
2332
+ acquireSkillTool,
2333
+ voxTool,
2334
+ ...dynamicToolRegistry.getTools()
2335
+ ];
2336
+ // Create a map for quick lookup
2337
+ export const toolMap = new Map(tools.map(t => [t.definition.name, t]));
2338
+ //# sourceMappingURL=index.js.map