@defai.digital/ax-cli 3.2.0 → 3.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (239) hide show
  1. package/.ax-cli/memory.json +8 -1
  2. package/README.md +118 -2
  3. package/config/models.yaml +13 -0
  4. package/config/settings.yaml +6 -0
  5. package/dist/agent/context-manager.d.ts +5 -5
  6. package/dist/agent/context-manager.js +19 -9
  7. package/dist/agent/context-manager.js.map +1 -1
  8. package/dist/agent/dependency-resolver.js +2 -1
  9. package/dist/agent/dependency-resolver.js.map +1 -1
  10. package/dist/agent/llm-agent.d.ts +3 -2
  11. package/dist/agent/llm-agent.js +64 -58
  12. package/dist/agent/llm-agent.js.map +1 -1
  13. package/dist/agent/subagent.js +2 -1
  14. package/dist/agent/subagent.js.map +1 -1
  15. package/dist/analyzers/architecture/anti-pattern-detectors/god-object-detector.d.ts +29 -0
  16. package/dist/analyzers/architecture/anti-pattern-detectors/god-object-detector.js +103 -0
  17. package/dist/analyzers/architecture/anti-pattern-detectors/god-object-detector.js.map +1 -0
  18. package/dist/analyzers/architecture/architecture-analyzer.d.ts +58 -0
  19. package/dist/analyzers/architecture/architecture-analyzer.js +276 -0
  20. package/dist/analyzers/architecture/architecture-analyzer.js.map +1 -0
  21. package/dist/analyzers/architecture/index.d.ts +12 -0
  22. package/dist/analyzers/architecture/index.js +14 -0
  23. package/dist/analyzers/architecture/index.js.map +1 -0
  24. package/dist/analyzers/architecture/pattern-detectors/base-detector.d.ts +27 -0
  25. package/dist/analyzers/architecture/pattern-detectors/base-detector.js +31 -0
  26. package/dist/analyzers/architecture/pattern-detectors/base-detector.js.map +1 -0
  27. package/dist/analyzers/architecture/pattern-detectors/clean-architecture-detector.d.ts +11 -0
  28. package/dist/analyzers/architecture/pattern-detectors/clean-architecture-detector.js +57 -0
  29. package/dist/analyzers/architecture/pattern-detectors/clean-architecture-detector.js.map +1 -0
  30. package/dist/analyzers/architecture/pattern-detectors/mvc-detector.d.ts +11 -0
  31. package/dist/analyzers/architecture/pattern-detectors/mvc-detector.js +43 -0
  32. package/dist/analyzers/architecture/pattern-detectors/mvc-detector.js.map +1 -0
  33. package/dist/analyzers/architecture/pattern-detectors/repository-detector.d.ts +11 -0
  34. package/dist/analyzers/architecture/pattern-detectors/repository-detector.js +49 -0
  35. package/dist/analyzers/architecture/pattern-detectors/repository-detector.js.map +1 -0
  36. package/dist/analyzers/architecture/project-structure-scanner.d.ts +54 -0
  37. package/dist/analyzers/architecture/project-structure-scanner.js +200 -0
  38. package/dist/analyzers/architecture/project-structure-scanner.js.map +1 -0
  39. package/dist/analyzers/best-practices/base-rule.d.ts +45 -0
  40. package/dist/analyzers/best-practices/base-rule.js +45 -0
  41. package/dist/analyzers/best-practices/base-rule.js.map +1 -0
  42. package/dist/analyzers/best-practices/best-practice-validator.d.ts +35 -0
  43. package/dist/analyzers/best-practices/best-practice-validator.js +181 -0
  44. package/dist/analyzers/best-practices/best-practice-validator.js.map +1 -0
  45. package/dist/analyzers/best-practices/rules/index.d.ts +7 -0
  46. package/dist/analyzers/best-practices/rules/index.js +56 -0
  47. package/dist/analyzers/best-practices/rules/index.js.map +1 -0
  48. package/dist/analyzers/best-practices/rules/typescript/consistent-naming.d.ts +17 -0
  49. package/dist/analyzers/best-practices/rules/typescript/consistent-naming.js +41 -0
  50. package/dist/analyzers/best-practices/rules/typescript/consistent-naming.js.map +1 -0
  51. package/dist/analyzers/best-practices/rules/typescript/function-complexity.d.ts +27 -0
  52. package/dist/analyzers/best-practices/rules/typescript/function-complexity.js +76 -0
  53. package/dist/analyzers/best-practices/rules/typescript/function-complexity.js.map +1 -0
  54. package/dist/analyzers/best-practices/rules/typescript/index.d.ts +15 -0
  55. package/dist/analyzers/best-practices/rules/typescript/index.js +16 -0
  56. package/dist/analyzers/best-practices/rules/typescript/index.js.map +1 -0
  57. package/dist/analyzers/best-practices/rules/typescript/max-file-length.d.ts +18 -0
  58. package/dist/analyzers/best-practices/rules/typescript/max-file-length.js +25 -0
  59. package/dist/analyzers/best-practices/rules/typescript/max-file-length.js.map +1 -0
  60. package/dist/analyzers/best-practices/rules/typescript/no-any-type.d.ts +17 -0
  61. package/dist/analyzers/best-practices/rules/typescript/no-any-type.js +27 -0
  62. package/dist/analyzers/best-practices/rules/typescript/no-any-type.js.map +1 -0
  63. package/dist/analyzers/best-practices/rules/typescript/no-implicit-any.d.ts +18 -0
  64. package/dist/analyzers/best-practices/rules/typescript/no-implicit-any.js +39 -0
  65. package/dist/analyzers/best-practices/rules/typescript/no-implicit-any.js.map +1 -0
  66. package/dist/analyzers/best-practices/rules/typescript/no-magic-numbers.d.ts +17 -0
  67. package/dist/analyzers/best-practices/rules/typescript/no-magic-numbers.js +32 -0
  68. package/dist/analyzers/best-practices/rules/typescript/no-magic-numbers.js.map +1 -0
  69. package/dist/analyzers/best-practices/rules/typescript/no-unused-vars.d.ts +17 -0
  70. package/dist/analyzers/best-practices/rules/typescript/no-unused-vars.js +36 -0
  71. package/dist/analyzers/best-practices/rules/typescript/no-unused-vars.js.map +1 -0
  72. package/dist/analyzers/best-practices/rules/typescript/prefer-const.d.ts +17 -0
  73. package/dist/analyzers/best-practices/rules/typescript/prefer-const.js +33 -0
  74. package/dist/analyzers/best-practices/rules/typescript/prefer-const.js.map +1 -0
  75. package/dist/analyzers/best-practices/rules/typescript/prefer-readonly.d.ts +17 -0
  76. package/dist/analyzers/best-practices/rules/typescript/prefer-readonly.js +34 -0
  77. package/dist/analyzers/best-practices/rules/typescript/prefer-readonly.js.map +1 -0
  78. package/dist/analyzers/best-practices/rules/typescript/proper-error-handling.d.ts +17 -0
  79. package/dist/analyzers/best-practices/rules/typescript/proper-error-handling.js +27 -0
  80. package/dist/analyzers/best-practices/rules/typescript/proper-error-handling.js.map +1 -0
  81. package/dist/analyzers/best-practices/types.d.ts +86 -0
  82. package/dist/analyzers/best-practices/types.js +7 -0
  83. package/dist/analyzers/best-practices/types.js.map +1 -0
  84. package/dist/analyzers/cache/analysis-cache.d.ts +41 -0
  85. package/dist/analyzers/cache/analysis-cache.js +84 -0
  86. package/dist/analyzers/cache/analysis-cache.js.map +1 -0
  87. package/dist/analyzers/errors.d.ts +51 -0
  88. package/dist/analyzers/errors.js +79 -0
  89. package/dist/analyzers/errors.js.map +1 -0
  90. package/dist/commands/doctor.js +3 -2
  91. package/dist/commands/doctor.js.map +1 -1
  92. package/dist/commands/frontend.d.ts +9 -0
  93. package/dist/commands/frontend.js +645 -0
  94. package/dist/commands/frontend.js.map +1 -0
  95. package/dist/commands/mcp.js +652 -3
  96. package/dist/commands/mcp.js.map +1 -1
  97. package/dist/commands/models.js +2 -2
  98. package/dist/commands/models.js.map +1 -1
  99. package/dist/commands/setup.js +100 -41
  100. package/dist/commands/setup.js.map +1 -1
  101. package/dist/constants.d.ts +4 -0
  102. package/dist/constants.js +4 -0
  103. package/dist/constants.js.map +1 -1
  104. package/dist/hooks/use-enhanced-input.js +16 -3
  105. package/dist/hooks/use-enhanced-input.js.map +1 -1
  106. package/dist/hooks/use-input-handler.js +9 -4
  107. package/dist/hooks/use-input-handler.js.map +1 -1
  108. package/dist/index.js +5 -2
  109. package/dist/index.js.map +1 -1
  110. package/dist/llm/client.d.ts +1 -0
  111. package/dist/llm/tools.js +86 -0
  112. package/dist/llm/tools.js.map +1 -1
  113. package/dist/llm/types.d.ts +49 -22
  114. package/dist/llm/types.js +12 -8
  115. package/dist/llm/types.js.map +1 -1
  116. package/dist/mcp/client.d.ts +5 -0
  117. package/dist/mcp/client.js +55 -0
  118. package/dist/mcp/client.js.map +1 -1
  119. package/dist/mcp/config.d.ts +1 -1
  120. package/dist/mcp/config.js +2 -2
  121. package/dist/mcp/config.js.map +1 -1
  122. package/dist/mcp/health.d.ts +120 -0
  123. package/dist/mcp/health.js +267 -0
  124. package/dist/mcp/health.js.map +1 -0
  125. package/dist/mcp/reconnection.d.ts +93 -0
  126. package/dist/mcp/reconnection.js +216 -0
  127. package/dist/mcp/reconnection.js.map +1 -0
  128. package/dist/mcp/registry.d.ts +71 -0
  129. package/dist/mcp/registry.js +257 -0
  130. package/dist/mcp/registry.js.map +1 -0
  131. package/dist/mcp/resources.d.ts +53 -0
  132. package/dist/mcp/resources.js +135 -0
  133. package/dist/mcp/resources.js.map +1 -0
  134. package/dist/mcp/templates.d.ts +52 -0
  135. package/dist/mcp/templates.js +624 -0
  136. package/dist/mcp/templates.js.map +1 -0
  137. package/dist/mcp/validation.d.ts +25 -0
  138. package/dist/mcp/validation.js +209 -0
  139. package/dist/mcp/validation.js.map +1 -0
  140. package/dist/memory/context-generator.js +1 -2
  141. package/dist/memory/context-generator.js.map +1 -1
  142. package/dist/planner/types.d.ts +2 -2
  143. package/dist/schemas/api-schemas.d.ts +2 -1
  144. package/dist/schemas/api-schemas.js +6 -4
  145. package/dist/schemas/api-schemas.js.map +1 -1
  146. package/dist/schemas/index.d.ts +4 -4
  147. package/dist/schemas/tool-schemas.d.ts +2 -2
  148. package/dist/schemas/yaml-schemas.d.ts +15 -0
  149. package/dist/schemas/yaml-schemas.js +3 -0
  150. package/dist/schemas/yaml-schemas.js.map +1 -1
  151. package/dist/sdk/index.d.ts +138 -0
  152. package/dist/sdk/index.js +173 -0
  153. package/dist/sdk/index.js.map +1 -0
  154. package/dist/sdk/types.d.ts +53 -0
  155. package/dist/sdk/types.js +8 -0
  156. package/dist/sdk/types.js.map +1 -0
  157. package/dist/tools/analysis-tools/architecture-tool.d.ts +46 -0
  158. package/dist/tools/analysis-tools/architecture-tool.js +124 -0
  159. package/dist/tools/analysis-tools/architecture-tool.js.map +1 -0
  160. package/dist/tools/analysis-tools/validation-tool.d.ts +51 -0
  161. package/dist/tools/analysis-tools/validation-tool.js +121 -0
  162. package/dist/tools/analysis-tools/validation-tool.js.map +1 -0
  163. package/dist/tools/bash.js +25 -10
  164. package/dist/tools/bash.js.map +1 -1
  165. package/dist/tools/web-search/cache.d.ts +62 -0
  166. package/dist/tools/web-search/cache.js +105 -0
  167. package/dist/tools/web-search/cache.js.map +1 -0
  168. package/dist/tools/web-search/engines/brave.d.ts +16 -0
  169. package/dist/tools/web-search/engines/brave.js +99 -0
  170. package/dist/tools/web-search/engines/brave.js.map +1 -0
  171. package/dist/tools/web-search/engines/crates.d.ts +19 -0
  172. package/dist/tools/web-search/engines/crates.js +87 -0
  173. package/dist/tools/web-search/engines/crates.js.map +1 -0
  174. package/dist/tools/web-search/engines/npm.d.ts +18 -0
  175. package/dist/tools/web-search/engines/npm.js +86 -0
  176. package/dist/tools/web-search/engines/npm.js.map +1 -0
  177. package/dist/tools/web-search/engines/pypi.d.ts +18 -0
  178. package/dist/tools/web-search/engines/pypi.js +75 -0
  179. package/dist/tools/web-search/engines/pypi.js.map +1 -0
  180. package/dist/tools/web-search/engines/tavily.d.ts +17 -0
  181. package/dist/tools/web-search/engines/tavily.js +73 -0
  182. package/dist/tools/web-search/engines/tavily.js.map +1 -0
  183. package/dist/tools/web-search/index.d.ts +13 -0
  184. package/dist/tools/web-search/index.js +13 -0
  185. package/dist/tools/web-search/index.js.map +1 -0
  186. package/dist/tools/web-search/router.d.ts +36 -0
  187. package/dist/tools/web-search/router.js +280 -0
  188. package/dist/tools/web-search/router.js.map +1 -0
  189. package/dist/tools/web-search/types.d.ts +45 -0
  190. package/dist/tools/web-search/types.js +6 -0
  191. package/dist/tools/web-search/types.js.map +1 -0
  192. package/dist/tools/web-search/web-search-tool.d.ts +51 -0
  193. package/dist/tools/web-search/web-search-tool.js +256 -0
  194. package/dist/tools/web-search/web-search-tool.js.map +1 -0
  195. package/dist/types/analysis.d.ts +177 -0
  196. package/dist/types/analysis.js +8 -0
  197. package/dist/types/analysis.js.map +1 -0
  198. package/dist/ui/components/api-key-input.js +2 -2
  199. package/dist/ui/components/api-key-input.js.map +1 -1
  200. package/dist/ui/components/chat-history.js +14 -7
  201. package/dist/ui/components/chat-history.js.map +1 -1
  202. package/dist/ui/components/chat-input.js +12 -7
  203. package/dist/ui/components/chat-input.js.map +1 -1
  204. package/dist/ui/components/chat-interface.js +75 -54
  205. package/dist/ui/components/chat-interface.js.map +1 -1
  206. package/dist/ui/components/keyboard-hints.js +5 -4
  207. package/dist/ui/components/keyboard-hints.js.map +1 -1
  208. package/dist/ui/components/quick-actions.js +1 -0
  209. package/dist/ui/components/quick-actions.js.map +1 -1
  210. package/dist/ui/components/reasoning-display.js +14 -4
  211. package/dist/ui/components/reasoning-display.js.map +1 -1
  212. package/dist/ui/components/status-bar.d.ts +1 -0
  213. package/dist/ui/components/status-bar.js +37 -39
  214. package/dist/ui/components/status-bar.js.map +1 -1
  215. package/dist/ui/components/toast-notification.d.ts +29 -0
  216. package/dist/ui/components/toast-notification.js +17 -3
  217. package/dist/ui/components/toast-notification.js.map +1 -1
  218. package/dist/ui/components/welcome-panel.d.ts +1 -0
  219. package/dist/ui/components/welcome-panel.js +106 -4
  220. package/dist/ui/components/welcome-panel.js.map +1 -1
  221. package/dist/utils/analysis-logger.d.ts +47 -0
  222. package/dist/utils/analysis-logger.js +70 -0
  223. package/dist/utils/analysis-logger.js.map +1 -0
  224. package/dist/utils/automatosx-detector.d.ts +19 -0
  225. package/dist/utils/automatosx-detector.js +52 -0
  226. package/dist/utils/automatosx-detector.js.map +1 -0
  227. package/dist/utils/config-loader.d.ts +4 -0
  228. package/dist/utils/config-loader.js.map +1 -1
  229. package/dist/utils/confirmation-service.js +1 -1
  230. package/dist/utils/confirmation-service.js.map +1 -1
  231. package/dist/utils/init-previewer.js +26 -4
  232. package/dist/utils/init-previewer.js.map +1 -1
  233. package/dist/utils/setup-validator.js +1 -0
  234. package/dist/utils/setup-validator.js.map +1 -1
  235. package/dist/utils/text-utils.d.ts +1 -0
  236. package/dist/utils/text-utils.js +12 -0
  237. package/dist/utils/text-utils.js.map +1 -1
  238. package/package.json +19 -4
  239. package/vitest.config.ts +1 -0
@@ -0,0 +1,18 @@
1
+ /**
2
+ * npm Registry Search Engine
3
+ * Free, unlimited search for npm packages
4
+ * No API key required
5
+ */
6
+ import type { SearchEngine, WebSearchResult, SearchOptions } from "../types.js";
7
+ export declare class NpmSearch implements SearchEngine {
8
+ readonly name = "npm";
9
+ private baseUrl;
10
+ private timeout;
11
+ /**
12
+ * Always available - no API key required
13
+ */
14
+ isAvailable(): boolean;
15
+ search(query: string, options?: SearchOptions): Promise<WebSearchResult[]>;
16
+ private formatResults;
17
+ private createSnippet;
18
+ }
@@ -0,0 +1,86 @@
1
+ /**
2
+ * npm Registry Search Engine
3
+ * Free, unlimited search for npm packages
4
+ * No API key required
5
+ */
6
+ import axios from "axios";
7
+ export class NpmSearch {
8
+ name = "npm";
9
+ baseUrl = "https://registry.npmjs.org/-/v1/search";
10
+ timeout = 10000; // 10 second timeout
11
+ /**
12
+ * Always available - no API key required
13
+ */
14
+ isAvailable() {
15
+ return true;
16
+ }
17
+ async search(query, options) {
18
+ try {
19
+ const params = new URLSearchParams({
20
+ text: query,
21
+ size: Math.min(options?.maxResults || 5, 20).toString(),
22
+ });
23
+ const response = await axios.get(`${this.baseUrl}?${params.toString()}`, {
24
+ timeout: options?.timeout || this.timeout,
25
+ headers: {
26
+ Accept: "application/json",
27
+ },
28
+ });
29
+ return this.formatResults(response.data);
30
+ }
31
+ catch (error) {
32
+ if (axios.isAxiosError(error)) {
33
+ if (error.code === "ECONNABORTED") {
34
+ throw new Error("npm search timeout");
35
+ }
36
+ throw new Error(`npm registry error: ${error.response?.data?.error || error.message}`);
37
+ }
38
+ throw error;
39
+ }
40
+ }
41
+ formatResults(response) {
42
+ return response.objects.map((pkg) => ({
43
+ title: pkg.package.name,
44
+ url: pkg.package.links.npm || `https://www.npmjs.com/package/${pkg.package.name}`,
45
+ snippet: this.createSnippet(pkg),
46
+ source: this.name,
47
+ relevanceScore: pkg.score.final * 100, // Convert 0-1 to 0-100
48
+ publishedDate: pkg.package.date,
49
+ metadata: {
50
+ version: pkg.package.version,
51
+ author: pkg.package.author?.name || pkg.package.publisher.username,
52
+ quality: pkg.score.detail.quality,
53
+ popularity: pkg.score.detail.popularity,
54
+ maintenance: pkg.score.detail.maintenance,
55
+ homepage: pkg.package.links.homepage,
56
+ repository: pkg.package.links.repository,
57
+ },
58
+ }));
59
+ }
60
+ createSnippet(pkg) {
61
+ const parts = [];
62
+ if (pkg.package.description) {
63
+ parts.push(pkg.package.description);
64
+ }
65
+ parts.push(`v${pkg.package.version}`);
66
+ if (pkg.package.author?.name) {
67
+ parts.push(`by ${pkg.package.author.name}`);
68
+ }
69
+ // Add quality indicators
70
+ const quality = pkg.score.detail.quality;
71
+ const popularity = pkg.score.detail.popularity;
72
+ const maintenance = pkg.score.detail.maintenance;
73
+ const indicators = [];
74
+ if (quality > 0.7)
75
+ indicators.push("high quality");
76
+ if (popularity > 0.7)
77
+ indicators.push("popular");
78
+ if (maintenance > 0.7)
79
+ indicators.push("well-maintained");
80
+ if (indicators.length > 0) {
81
+ parts.push(`(${indicators.join(", ")})`);
82
+ }
83
+ return parts.join(" • ");
84
+ }
85
+ }
86
+ //# sourceMappingURL=npm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"npm.js","sourceRoot":"","sources":["../../../../src/tools/web-search/engines/npm.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * PyPI (Python Package Index) Search Engine
3
+ * Free, unlimited search for Python packages
4
+ * No API key required
5
+ */
6
+ import type { SearchEngine, WebSearchResult, SearchOptions } from "../types.js";
7
+ export declare class PyPISearch implements SearchEngine {
8
+ readonly name = "pypi";
9
+ private baseUrl;
10
+ private timeout;
11
+ /**
12
+ * Always available - no API key required
13
+ */
14
+ isAvailable(): boolean;
15
+ search(query: string, options?: SearchOptions): Promise<WebSearchResult[]>;
16
+ private formatResult;
17
+ private createSnippet;
18
+ }
@@ -0,0 +1,75 @@
1
+ /**
2
+ * PyPI (Python Package Index) Search Engine
3
+ * Free, unlimited search for Python packages
4
+ * No API key required
5
+ */
6
+ import axios from "axios";
7
+ // Note: PyPI's search API is being rebuilt, so we use direct package lookup instead
8
+ export class PyPISearch {
9
+ name = "pypi";
10
+ baseUrl = "https://pypi.org/pypi";
11
+ timeout = 10000; // 10 second timeout
12
+ /**
13
+ * Always available - no API key required
14
+ */
15
+ isAvailable() {
16
+ return true;
17
+ }
18
+ async search(query, options) {
19
+ try {
20
+ // PyPI's official search is being rebuilt, so we use direct package lookup
21
+ // Try to fetch package info directly
22
+ const packageResponse = await axios.get(`${this.baseUrl}/${encodeURIComponent(query)}/json`, {
23
+ timeout: options?.timeout || this.timeout,
24
+ validateStatus: (status) => status === 200 || status === 404,
25
+ });
26
+ if (packageResponse.status === 404) {
27
+ // Package not found, return empty results
28
+ return [];
29
+ }
30
+ return this.formatResult(packageResponse.data);
31
+ }
32
+ catch (error) {
33
+ // Return empty results on error rather than failing
34
+ // PyPI search is a best-effort feature
35
+ return [];
36
+ }
37
+ }
38
+ formatResult(data) {
39
+ if (!data.info)
40
+ return [];
41
+ const info = data.info;
42
+ return [
43
+ {
44
+ title: info.name,
45
+ url: `https://pypi.org/project/${info.name}/`,
46
+ snippet: this.createSnippet(info),
47
+ source: this.name,
48
+ relevanceScore: 100, // Exact match
49
+ publishedDate: info.release_date,
50
+ metadata: {
51
+ version: info.version,
52
+ author: info.author,
53
+ license: info.license,
54
+ homepage: info.home_page || info.project_urls?.Homepage,
55
+ requiresPython: info.requires_python,
56
+ },
57
+ },
58
+ ];
59
+ }
60
+ createSnippet(info) {
61
+ const parts = [];
62
+ if (info.summary) {
63
+ parts.push(info.summary);
64
+ }
65
+ parts.push(`v${info.version}`);
66
+ if (info.author) {
67
+ parts.push(`by ${info.author}`);
68
+ }
69
+ if (info.license) {
70
+ parts.push(`License: ${info.license}`);
71
+ }
72
+ return parts.join(" • ");
73
+ }
74
+ }
75
+ //# sourceMappingURL=pypi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pypi.js","sourceRoot":"","sources":["../../../../src/tools/web-search/engines/pypi.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAO1B,oFAAoF;AAEpF,MAAM,OAAO,UAAU;IACL,IAAI,GAAG,MAAM,CAAC;IACtB,OAAO,GAAG,uBAAuB,CAAC;IAClC,OAAO,GAAG,KAAK,CAAC,CAAC,oBAAoB;IAE7C;;OAEG;IACH,WAAW;QACT,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAC,MAAM,CACV,KAAa,EACb,OAAuB;QAEvB,IAAI,CAAC;YACH,2EAA2E;YAC3E,qCAAqC;YACrC,MAAM,eAAe,GAAG,MAAM,KAAK,CAAC,GAAG,CACrC,GAAG,IAAI,CAAC,OAAO,IAAI,kBAAkB,CAAC,KAAK,CAAC,OAAO,EACnD;gBACE,OAAO,EAAE,OAAO,EAAE,OAAO,IAAI,IAAI,CAAC,OAAO;gBACzC,cAAc,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,KAAK,GAAG,IAAI,MAAM,KAAK,GAAG;aAC7D,CACF,CAAC;YAEF,IAAI,eAAe,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBACnC,0CAA0C;gBAC1C,OAAO,EAAE,CAAC;YACZ,CAAC;YAED,OAAO,IAAI,CAAC,YAAY,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;QACjD,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,oDAAoD;YACpD,uCAAuC;YACvC,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;IAEO,YAAY,CAAC,IAAS;QAC5B,IAAI,CAAC,IAAI,CAAC,IAAI;YAAE,OAAO,EAAE,CAAC;QAE1B,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QACvB,OAAO;YACL;gBACE,KAAK,EAAE,IAAI,CAAC,IAAI;gBAChB,GAAG,EAAE,4BAA4B,IAAI,CAAC,IAAI,GAAG;gBAC7C,OAAO,EAAE,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC;gBACjC,MAAM,EAAE,IAAI,CAAC,IAAI;gBACjB,cAAc,EAAE,GAAG,EAAE,cAAc;gBACnC,aAAa,EAAE,IAAI,CAAC,YAAY;gBAChC,QAAQ,EAAE;oBACR,OAAO,EAAE,IAAI,CAAC,OAAO;oBACrB,MAAM,EAAE,IAAI,CAAC,MAAM;oBACnB,OAAO,EAAE,IAAI,CAAC,OAAO;oBACrB,QAAQ,EAAE,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,YAAY,EAAE,QAAQ;oBACvD,cAAc,EAAE,IAAI,CAAC,eAAe;iBACrC;aACF;SACF,CAAC;IACJ,CAAC;IAEO,aAAa,CAAC,IAAS;QAC7B,MAAM,KAAK,GAAa,EAAE,CAAC;QAE3B,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC3B,CAAC;QAED,KAAK,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;QAE/B,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,KAAK,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QAClC,CAAC;QAED,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,KAAK,CAAC,IAAI,CAAC,YAAY,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;QACzC,CAAC;QAED,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC3B,CAAC;CACF"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Tavily AI Search Engine
3
+ * AI-optimized search designed for LLMs
4
+ * https://tavily.com/
5
+ */
6
+ import type { SearchEngine, WebSearchResult, SearchOptions } from "../types.js";
7
+ export declare class TavilySearch implements SearchEngine {
8
+ readonly name = "tavily";
9
+ private apiKey;
10
+ private baseUrl;
11
+ private timeout;
12
+ constructor();
13
+ isAvailable(): boolean;
14
+ search(query: string, options?: SearchOptions): Promise<WebSearchResult[]>;
15
+ private formatResults;
16
+ getAnswer(results: WebSearchResult[]): string | undefined;
17
+ }
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Tavily AI Search Engine
3
+ * AI-optimized search designed for LLMs
4
+ * https://tavily.com/
5
+ */
6
+ import axios from "axios";
7
+ export class TavilySearch {
8
+ name = "tavily";
9
+ apiKey;
10
+ baseUrl = "https://api.tavily.com/search";
11
+ timeout = 10000; // 10 second timeout
12
+ constructor() {
13
+ this.apiKey = process.env.TAVILY_API_KEY;
14
+ }
15
+ isAvailable() {
16
+ return !!this.apiKey;
17
+ }
18
+ async search(query, options) {
19
+ if (!this.isAvailable()) {
20
+ throw new Error("Tavily API key not configured");
21
+ }
22
+ try {
23
+ const response = await axios.post(this.baseUrl, {
24
+ api_key: this.apiKey,
25
+ query: query,
26
+ search_depth: options?.searchDepth || "basic",
27
+ max_results: Math.min(options?.maxResults || 5, 10),
28
+ include_answer: options?.includeAnswer ?? true,
29
+ include_domains: options?.includeDomains || [],
30
+ exclude_domains: options?.excludeDomains || [],
31
+ }, {
32
+ timeout: options?.timeout || this.timeout,
33
+ headers: {
34
+ "Content-Type": "application/json",
35
+ },
36
+ });
37
+ return this.formatResults(response.data);
38
+ }
39
+ catch (error) {
40
+ if (axios.isAxiosError(error)) {
41
+ if (error.code === "ECONNABORTED") {
42
+ throw new Error("Tavily search timeout");
43
+ }
44
+ if (error.response?.status === 401) {
45
+ throw new Error("Invalid Tavily API key");
46
+ }
47
+ if (error.response?.status === 429) {
48
+ throw new Error("Tavily rate limit exceeded");
49
+ }
50
+ throw new Error(`Tavily API error: ${error.response?.data?.message || error.message}`);
51
+ }
52
+ throw error;
53
+ }
54
+ }
55
+ formatResults(response) {
56
+ return response.results.map((result) => ({
57
+ title: result.title,
58
+ url: result.url,
59
+ snippet: result.content,
60
+ source: this.name,
61
+ relevanceScore: result.score * 100, // Convert 0-1 to 0-100
62
+ publishedDate: result.published_date,
63
+ metadata: {
64
+ answer: response.answer,
65
+ responseTime: response.response_time,
66
+ },
67
+ }));
68
+ }
69
+ getAnswer(results) {
70
+ return results[0]?.metadata?.answer;
71
+ }
72
+ }
73
+ //# sourceMappingURL=tavily.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tavily.js","sourceRoot":"","sources":["../../../../src/tools/web-search/engines/tavily.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Web Search Module
3
+ * Exports all web search functionality
4
+ */
5
+ export { WebSearchTool } from "./web-search-tool.js";
6
+ export { WebSearchRouter } from "./router.js";
7
+ export { SearchCache } from "./cache.js";
8
+ export { TavilySearch } from "./engines/tavily.js";
9
+ export { BraveSearch } from "./engines/brave.js";
10
+ export { NpmSearch } from "./engines/npm.js";
11
+ export { PyPISearch } from "./engines/pypi.js";
12
+ export { CratesSearch } from "./engines/crates.js";
13
+ export type { WebSearchResult, SearchOptions, SearchIntent, SearchEngine, SearchEngineResponse, } from "./types.js";
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Web Search Module
3
+ * Exports all web search functionality
4
+ */
5
+ export { WebSearchTool } from "./web-search-tool.js";
6
+ export { WebSearchRouter } from "./router.js";
7
+ export { SearchCache } from "./cache.js";
8
+ export { TavilySearch } from "./engines/tavily.js";
9
+ export { BraveSearch } from "./engines/brave.js";
10
+ export { NpmSearch } from "./engines/npm.js";
11
+ export { PyPISearch } from "./engines/pypi.js";
12
+ export { CratesSearch } from "./engines/crates.js";
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tools/web-search/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Search Router
3
+ * Detects query intent and routes to appropriate search engines
4
+ */
5
+ import type { SearchEngine, SearchIntent } from "./types.js";
6
+ export declare class WebSearchRouter {
7
+ private tavilyEngine;
8
+ private braveEngine;
9
+ private npmEngine;
10
+ private pypiEngine;
11
+ private cratesEngine;
12
+ private readonly technicalKeywords;
13
+ private readonly codeKeywords;
14
+ private readonly packageKeywords;
15
+ private readonly pythonKeywords;
16
+ private readonly rustKeywords;
17
+ private readonly newsKeywords;
18
+ constructor();
19
+ /**
20
+ * Detect the intent of a search query
21
+ */
22
+ detectIntent(query: string): SearchIntent;
23
+ /**
24
+ * Select the best search engines for a given intent
25
+ */
26
+ selectEngines(intent: SearchIntent): SearchEngine[];
27
+ /**
28
+ * Get all available engines
29
+ */
30
+ getAvailableEngines(): SearchEngine[];
31
+ /**
32
+ * Check if any search engine is available
33
+ * Always returns true because package search engines require no API key
34
+ */
35
+ hasAvailableEngines(): boolean;
36
+ }
@@ -0,0 +1,280 @@
1
+ /**
2
+ * Search Router
3
+ * Detects query intent and routes to appropriate search engines
4
+ */
5
+ import { TavilySearch } from "./engines/tavily.js";
6
+ import { BraveSearch } from "./engines/brave.js";
7
+ import { NpmSearch } from "./engines/npm.js";
8
+ import { PyPISearch } from "./engines/pypi.js";
9
+ import { CratesSearch } from "./engines/crates.js";
10
+ export class WebSearchRouter {
11
+ tavilyEngine;
12
+ braveEngine;
13
+ npmEngine;
14
+ pypiEngine;
15
+ cratesEngine;
16
+ // Keywords for intent detection
17
+ technicalKeywords = [
18
+ "error",
19
+ "exception",
20
+ "bug",
21
+ "fix",
22
+ "debug",
23
+ "troubleshoot",
24
+ "code",
25
+ "function",
26
+ "method",
27
+ "class",
28
+ "api",
29
+ "library",
30
+ "framework",
31
+ "npm",
32
+ "package",
33
+ "install",
34
+ "configure",
35
+ "implementation",
36
+ "syntax",
37
+ "typescript",
38
+ "javascript",
39
+ "python",
40
+ "java",
41
+ "rust",
42
+ "go",
43
+ ];
44
+ codeKeywords = [
45
+ "code",
46
+ "example",
47
+ "implementation",
48
+ "snippet",
49
+ "sample",
50
+ "github",
51
+ "repository",
52
+ "source",
53
+ "function",
54
+ "class",
55
+ "how to",
56
+ "tutorial",
57
+ ];
58
+ packageKeywords = [
59
+ "package",
60
+ "npm",
61
+ "library",
62
+ "module",
63
+ "install",
64
+ "dependency",
65
+ "dependencies",
66
+ "node_modules",
67
+ "yarn",
68
+ "pnpm",
69
+ ];
70
+ pythonKeywords = [
71
+ "python",
72
+ "pip",
73
+ "pypi",
74
+ "django",
75
+ "flask",
76
+ "fastapi",
77
+ "pandas",
78
+ "numpy",
79
+ "pytest",
80
+ "virtualenv",
81
+ "conda",
82
+ "poetry",
83
+ ];
84
+ rustKeywords = [
85
+ "rust",
86
+ "cargo",
87
+ "crate",
88
+ "crates.io",
89
+ "rustc",
90
+ "tokio",
91
+ "serde",
92
+ "actix",
93
+ "wasm",
94
+ ];
95
+ newsKeywords = [
96
+ "news",
97
+ "latest",
98
+ "today",
99
+ "yesterday",
100
+ "recent",
101
+ "update",
102
+ "announcement",
103
+ "release",
104
+ "2025",
105
+ "2024",
106
+ "current",
107
+ "breaking",
108
+ "trending",
109
+ ];
110
+ constructor() {
111
+ this.tavilyEngine = new TavilySearch();
112
+ this.braveEngine = new BraveSearch();
113
+ this.npmEngine = new NpmSearch(); // Always available (no API key)
114
+ this.pypiEngine = new PyPISearch(); // Always available (no API key)
115
+ this.cratesEngine = new CratesSearch(); // Always available (no API key)
116
+ }
117
+ /**
118
+ * Detect the intent of a search query
119
+ */
120
+ detectIntent(query) {
121
+ const lowerQuery = query.toLowerCase();
122
+ const words = lowerQuery.split(/\s+/);
123
+ let technicalScore = 0;
124
+ let codeScore = 0;
125
+ let newsScore = 0;
126
+ let packageScore = 0;
127
+ let pythonScore = 0;
128
+ let rustScore = 0;
129
+ // Count keyword matches
130
+ for (const word of words) {
131
+ if (this.technicalKeywords.some((kw) => word.includes(kw))) {
132
+ technicalScore++;
133
+ }
134
+ if (this.codeKeywords.some((kw) => word.includes(kw))) {
135
+ codeScore++;
136
+ }
137
+ if (this.newsKeywords.some((kw) => word.includes(kw))) {
138
+ newsScore++;
139
+ }
140
+ if (this.packageKeywords.some((kw) => word.includes(kw))) {
141
+ packageScore++;
142
+ }
143
+ if (this.pythonKeywords.some((kw) => word.includes(kw))) {
144
+ pythonScore++;
145
+ }
146
+ if (this.rustKeywords.some((kw) => word.includes(kw))) {
147
+ rustScore++;
148
+ }
149
+ }
150
+ // Determine primary intent
151
+ let type = "general";
152
+ let confidence = 0.5; // Default confidence
153
+ let language = undefined;
154
+ // Detect language first
155
+ if (pythonScore > 0 && pythonScore >= rustScore) {
156
+ language = "python";
157
+ }
158
+ else if (rustScore > 0 && rustScore > pythonScore) {
159
+ language = "rust";
160
+ }
161
+ else if (packageScore > 0) {
162
+ language = "javascript"; // npm implies JavaScript
163
+ }
164
+ // Package search takes priority if npm keywords detected
165
+ if (packageScore > 0 || pythonScore > 0 || rustScore > 0) {
166
+ type = "technical"; // Packages are technical
167
+ confidence = Math.min((packageScore + pythonScore + rustScore) / words.length + 0.6, 1.0);
168
+ }
169
+ else if (newsScore > 0) {
170
+ type = "news";
171
+ confidence = Math.min(newsScore / words.length + 0.5, 1.0);
172
+ }
173
+ else if (codeScore > technicalScore) {
174
+ type = "code";
175
+ confidence = Math.min(codeScore / words.length + 0.5, 1.0);
176
+ }
177
+ else if (technicalScore > 0) {
178
+ type = "technical";
179
+ confidence = Math.min(technicalScore / words.length + 0.5, 1.0);
180
+ }
181
+ return {
182
+ type,
183
+ requiresTechnical: technicalScore > 0 || packageScore > 0 || pythonScore > 0 || rustScore > 0,
184
+ requiresCode: codeScore > 0,
185
+ requiresNews: newsScore > 0,
186
+ confidence,
187
+ language,
188
+ };
189
+ }
190
+ /**
191
+ * Select the best search engines for a given intent
192
+ */
193
+ selectEngines(intent) {
194
+ const engines = [];
195
+ // Check if query contains package keywords - prioritize language-specific search
196
+ const hasPackageIntent = intent.requiresTechnical && intent.confidence > 0.6;
197
+ // Select engines based on intent type
198
+ switch (intent.type) {
199
+ case "technical":
200
+ case "code":
201
+ // Route to language-specific package search
202
+ if (hasPackageIntent && intent.language) {
203
+ if (intent.language === "python") {
204
+ engines.push(this.pypiEngine); // Python packages
205
+ }
206
+ else if (intent.language === "rust") {
207
+ engines.push(this.cratesEngine); // Rust crates
208
+ }
209
+ else if (intent.language === "javascript") {
210
+ engines.push(this.npmEngine); // npm packages
211
+ }
212
+ }
213
+ else if (hasPackageIntent) {
214
+ // Default to npm if language not detected
215
+ engines.push(this.npmEngine);
216
+ }
217
+ // Tavily is great for technical queries
218
+ if (this.tavilyEngine.isAvailable()) {
219
+ engines.push(this.tavilyEngine);
220
+ }
221
+ // Brave as fallback
222
+ if (this.braveEngine.isAvailable() && engines.length === 0) {
223
+ engines.push(this.braveEngine);
224
+ }
225
+ break;
226
+ case "news":
227
+ // Brave has better news coverage
228
+ if (this.braveEngine.isAvailable()) {
229
+ engines.push(this.braveEngine);
230
+ }
231
+ // Tavily as fallback
232
+ if (this.tavilyEngine.isAvailable() && engines.length === 0) {
233
+ engines.push(this.tavilyEngine);
234
+ }
235
+ break;
236
+ case "general":
237
+ default:
238
+ // Tavily is optimized for AI/general queries
239
+ if (this.tavilyEngine.isAvailable()) {
240
+ engines.push(this.tavilyEngine);
241
+ }
242
+ // Brave as fallback
243
+ if (this.braveEngine.isAvailable() && engines.length === 0) {
244
+ engines.push(this.braveEngine);
245
+ }
246
+ break;
247
+ }
248
+ // Package search as ultimate fallback (always available, no API key needed)
249
+ // Prefer npm as it's most commonly used
250
+ if (engines.length === 0) {
251
+ engines.push(this.npmEngine);
252
+ }
253
+ return engines;
254
+ }
255
+ /**
256
+ * Get all available engines
257
+ */
258
+ getAvailableEngines() {
259
+ const engines = [];
260
+ if (this.tavilyEngine.isAvailable()) {
261
+ engines.push(this.tavilyEngine);
262
+ }
263
+ if (this.braveEngine.isAvailable()) {
264
+ engines.push(this.braveEngine);
265
+ }
266
+ // Package search engines are always available (no API key required)
267
+ engines.push(this.npmEngine);
268
+ engines.push(this.pypiEngine);
269
+ engines.push(this.cratesEngine);
270
+ return engines;
271
+ }
272
+ /**
273
+ * Check if any search engine is available
274
+ * Always returns true because package search engines require no API key
275
+ */
276
+ hasAvailableEngines() {
277
+ return true; // npm, PyPI, and crates.io search are always available
278
+ }
279
+ }
280
+ //# sourceMappingURL=router.js.map