@tyvm/knowhow 0.0.90 → 0.0.92

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 (272) hide show
  1. package/.depcheckrc +30 -0
  2. package/bin/knowhow.js +1 -1
  3. package/package.json +8 -34
  4. package/src/agents/configurable/ConfigAgent.ts +2 -2
  5. package/src/agents/tools/executeScript/index.ts +5 -0
  6. package/src/agents/tools/googleSearch.ts +2 -2
  7. package/src/agents/tools/index.ts +0 -3
  8. package/src/agents/tools/list.ts +0 -147
  9. package/src/agents/tools/loadWebpage.ts +3 -113
  10. package/src/auth/browserLogin.ts +10 -13
  11. package/src/chat/modules/AgentModule.ts +0 -1
  12. package/src/chat/types.ts +1 -1
  13. package/src/cli.ts +63 -3
  14. package/src/clients/gemini.ts +96 -25
  15. package/src/clients/http.ts +7 -11
  16. package/src/clients/pricing/google.ts +122 -26
  17. package/src/conversion.ts +24 -54
  18. package/src/index.ts +15 -20
  19. package/src/login.ts +5 -6
  20. package/src/plugins/language.ts +0 -4
  21. package/src/plugins/plugins.ts +0 -14
  22. package/src/plugins/url.ts +31 -12
  23. package/src/services/EmbeddingsService.ts +70 -0
  24. package/src/services/KnowhowClient.ts +34 -34
  25. package/src/{plugins/downloader/downloader.ts → services/MediaProcessorService.ts} +109 -267
  26. package/src/services/S3.ts +19 -87
  27. package/src/services/index.ts +8 -8
  28. package/src/services/modules/index.ts +12 -3
  29. package/src/services/modules/types.ts +8 -2
  30. package/src/services/script-execution/ScriptExecutor.ts +29 -10
  31. package/src/services/script-execution/ScriptPolicy.ts +6 -2
  32. package/src/types.ts +1 -0
  33. package/src/utils/http.ts +127 -0
  34. package/src/workers/auth/PasskeySetup.ts +7 -11
  35. package/tests/clients/AIClient.test.ts +24 -21
  36. package/tests/manual/file-edits/figma.test.ts +3 -70
  37. package/tests/plugins/language/languagePlugin-content-triggers.test.ts +2 -0
  38. package/tests/plugins/language/languagePlugin.test.ts +2 -0
  39. package/tests/processors/ToolResponseCache.test.ts +2 -2
  40. package/tests/test.spec.ts +0 -14
  41. package/tests/unit/modules/moduleLoading.test.ts +12 -4
  42. package/tests/unit/plugins/pluginLoading.test.ts +6 -6
  43. package/ts_build/package.json +8 -34
  44. package/ts_build/src/agents/tools/ast/astAppendNode.d.ts +1 -1
  45. package/ts_build/src/agents/tools/ast/astAppendNode.js +2 -90
  46. package/ts_build/src/agents/tools/ast/astAppendNode.js.map +1 -1
  47. package/ts_build/src/agents/tools/ast/astDeleteNode.d.ts +1 -1
  48. package/ts_build/src/agents/tools/ast/astDeleteNode.js +2 -88
  49. package/ts_build/src/agents/tools/ast/astDeleteNode.js.map +1 -1
  50. package/ts_build/src/agents/tools/ast/astEditNode.d.ts +1 -1
  51. package/ts_build/src/agents/tools/ast/astEditNode.js +2 -90
  52. package/ts_build/src/agents/tools/ast/astEditNode.js.map +1 -1
  53. package/ts_build/src/agents/tools/ast/astGetPathForLine.d.ts +1 -1
  54. package/ts_build/src/agents/tools/ast/astGetPathForLine.js +2 -72
  55. package/ts_build/src/agents/tools/ast/astGetPathForLine.js.map +1 -1
  56. package/ts_build/src/agents/tools/ast/astListPaths.d.ts +1 -1
  57. package/ts_build/src/agents/tools/ast/astListPaths.js +2 -72
  58. package/ts_build/src/agents/tools/ast/astListPaths.js.map +1 -1
  59. package/ts_build/src/agents/tools/executeScript/index.d.ts +3 -2
  60. package/ts_build/src/agents/tools/executeScript/index.js +4 -1
  61. package/ts_build/src/agents/tools/executeScript/index.js.map +1 -1
  62. package/ts_build/src/agents/tools/googleSearch.js +2 -2
  63. package/ts_build/src/agents/tools/googleSearch.js.map +1 -1
  64. package/ts_build/src/agents/tools/index.d.ts +0 -3
  65. package/ts_build/src/agents/tools/index.js +0 -3
  66. package/ts_build/src/agents/tools/index.js.map +1 -1
  67. package/ts_build/src/agents/tools/list.js +0 -138
  68. package/ts_build/src/agents/tools/list.js.map +1 -1
  69. package/ts_build/src/agents/tools/loadWebpage.js +1 -89
  70. package/ts_build/src/agents/tools/loadWebpage.js.map +1 -1
  71. package/ts_build/src/agents/tools/textSearch.d.ts +1 -1
  72. package/ts_build/src/auth/browserLogin.js +7 -7
  73. package/ts_build/src/auth/browserLogin.js.map +1 -1
  74. package/ts_build/src/chat/modules/AgentModule.js.map +1 -1
  75. package/ts_build/src/chat/types.d.ts +1 -1
  76. package/ts_build/src/cli.d.ts +1 -1
  77. package/ts_build/src/cli.js +47 -1
  78. package/ts_build/src/cli.js.map +1 -1
  79. package/ts_build/src/clients/gemini.d.ts +1 -73
  80. package/ts_build/src/clients/gemini.js +57 -19
  81. package/ts_build/src/clients/gemini.js.map +1 -1
  82. package/ts_build/src/clients/http.js +5 -9
  83. package/ts_build/src/clients/http.js.map +1 -1
  84. package/ts_build/src/clients/pricing/google.d.ts +17 -73
  85. package/ts_build/src/clients/pricing/google.js +47 -10
  86. package/ts_build/src/clients/pricing/google.js.map +1 -1
  87. package/ts_build/src/conversion.d.ts +1 -4
  88. package/ts_build/src/conversion.js +12 -27
  89. package/ts_build/src/conversion.js.map +1 -1
  90. package/ts_build/src/index.d.ts +4 -0
  91. package/ts_build/src/index.js +15 -14
  92. package/ts_build/src/index.js.map +1 -1
  93. package/ts_build/src/login.js +5 -4
  94. package/ts_build/src/login.js.map +1 -1
  95. package/ts_build/src/plugins/downloader/downloader.js +3 -3
  96. package/ts_build/src/plugins/downloader/downloader.js.map +1 -1
  97. package/ts_build/src/plugins/language.js.map +1 -1
  98. package/ts_build/src/plugins/plugins.js +0 -14
  99. package/ts_build/src/plugins/plugins.js.map +1 -1
  100. package/ts_build/src/plugins/tree-sitter/editor.d.ts +3 -32
  101. package/ts_build/src/plugins/tree-sitter/editor.js +6 -208
  102. package/ts_build/src/plugins/tree-sitter/editor.js.map +1 -1
  103. package/ts_build/src/plugins/tree-sitter/parser.d.ts +19 -54
  104. package/ts_build/src/plugins/tree-sitter/parser.js +19 -293
  105. package/ts_build/src/plugins/tree-sitter/parser.js.map +1 -1
  106. package/ts_build/src/plugins/tree-sitter/simple-paths.d.ts +2 -15
  107. package/ts_build/src/plugins/tree-sitter/simple-paths.js +2 -324
  108. package/ts_build/src/plugins/tree-sitter/simple-paths.js.map +1 -1
  109. package/ts_build/src/plugins/url.js +27 -8
  110. package/ts_build/src/plugins/url.js.map +1 -1
  111. package/ts_build/src/services/EmbeddingsService.d.ts +14 -0
  112. package/ts_build/src/services/EmbeddingsService.js +33 -0
  113. package/ts_build/src/services/EmbeddingsService.js.map +1 -0
  114. package/ts_build/src/services/GitHub.js +2 -2
  115. package/ts_build/src/services/GitHub.js.map +1 -1
  116. package/ts_build/src/services/KnowhowClient.d.ts +29 -29
  117. package/ts_build/src/services/KnowhowClient.js +33 -33
  118. package/ts_build/src/services/KnowhowClient.js.map +1 -1
  119. package/ts_build/src/services/MediaProcessorService.d.ts +22 -0
  120. package/ts_build/src/services/MediaProcessorService.js +215 -0
  121. package/ts_build/src/services/MediaProcessorService.js.map +1 -0
  122. package/ts_build/src/services/S3.d.ts +0 -4
  123. package/ts_build/src/services/S3.js +14 -60
  124. package/ts_build/src/services/S3.js.map +1 -1
  125. package/ts_build/src/services/index.d.ts +6 -5
  126. package/ts_build/src/services/index.js +6 -6
  127. package/ts_build/src/services/index.js.map +1 -1
  128. package/ts_build/src/services/modules/index.js +12 -3
  129. package/ts_build/src/services/modules/index.js.map +1 -1
  130. package/ts_build/src/services/modules/types.d.ts +8 -2
  131. package/ts_build/src/services/script-execution/ScriptExecutor.js +22 -7
  132. package/ts_build/src/services/script-execution/ScriptExecutor.js.map +1 -1
  133. package/ts_build/src/services/script-execution/ScriptPolicy.d.ts +1 -1
  134. package/ts_build/src/services/script-execution/ScriptPolicy.js +4 -2
  135. package/ts_build/src/services/script-execution/ScriptPolicy.js.map +1 -1
  136. package/ts_build/src/types.d.ts +1 -0
  137. package/ts_build/src/types.js +1 -0
  138. package/ts_build/src/types.js.map +1 -1
  139. package/ts_build/src/utils/http.d.ts +27 -0
  140. package/ts_build/src/utils/http.js +98 -0
  141. package/ts_build/src/utils/http.js.map +1 -0
  142. package/ts_build/src/workers/auth/PasskeySetup.js +6 -7
  143. package/ts_build/src/workers/auth/PasskeySetup.js.map +1 -1
  144. package/ts_build/tests/clients/AIClient.test.js +11 -14
  145. package/ts_build/tests/clients/AIClient.test.js.map +1 -1
  146. package/ts_build/tests/manual/file-edits/figma.test.d.ts +0 -1
  147. package/ts_build/tests/manual/file-edits/figma.test.js +1 -46
  148. package/ts_build/tests/manual/file-edits/figma.test.js.map +1 -1
  149. package/ts_build/tests/plugins/language/languagePlugin-content-triggers.test.js +2 -0
  150. package/ts_build/tests/plugins/language/languagePlugin-content-triggers.test.js.map +1 -1
  151. package/ts_build/tests/plugins/language/languagePlugin.test.js +2 -0
  152. package/ts_build/tests/plugins/language/languagePlugin.test.js.map +1 -1
  153. package/ts_build/tests/processors/ToolResponseCache.test.js +2 -2
  154. package/ts_build/tests/processors/ToolResponseCache.test.js.map +1 -1
  155. package/ts_build/tests/test.spec.js +0 -14
  156. package/ts_build/tests/test.spec.js.map +1 -1
  157. package/ts_build/tests/tree-sitter/tree-sitter.test.d.ts +0 -1
  158. package/ts_build/tests/tree-sitter/tree-sitter.test.js +2 -183
  159. package/ts_build/tests/tree-sitter/tree-sitter.test.js.map +1 -1
  160. package/ts_build/tests/unit/modules/moduleLoading.test.js +11 -4
  161. package/ts_build/tests/unit/modules/moduleLoading.test.js.map +1 -1
  162. package/ts_build/tests/unit/plugins/pluginLoading.test.js +4 -4
  163. package/ts_build/tests/unit/plugins/pluginLoading.test.js.map +1 -1
  164. package/benchmarks/.dockerignore +0 -7
  165. package/benchmarks/README.md +0 -166
  166. package/benchmarks/docker/Dockerfile +0 -68
  167. package/benchmarks/example-config.yml +0 -27
  168. package/benchmarks/jest.config.js +0 -13
  169. package/benchmarks/package-lock.json +0 -4297
  170. package/benchmarks/package.json +0 -39
  171. package/benchmarks/results/27b0a06/2025-09-27/xai/xai-grok-code-fast-1.json +0 -2909
  172. package/benchmarks/results/4057aed/2025-08-14/anthropic/anthropic-claude-sonnet-4-20250514.json +0 -1671
  173. package/benchmarks/results/4542435/2025-08-05/lms/lms-openai-gpt-oss-20b.json +0 -2814
  174. package/benchmarks/results/4542435/2025-08-05/lms/lms-qwen-qwen3-30b-a3b-2507.json +0 -2014
  175. package/benchmarks/results/4fb9125/2025-08-07/anthropic/anthropic-claude-sonnet-4-20250514.json +0 -3121
  176. package/benchmarks/results/5766aee/2025-08-02/lms-qwen/qwen3-coder-30b.json +0 -98
  177. package/benchmarks/results/6d73808/2025-08-07/openai/openai-gpt-5.json +0 -3256
  178. package/benchmarks/results/77bf0a6/2025-08-02/lms-qwen/qwen3-30b-a3b-2507.json +0 -4298
  179. package/benchmarks/results/8c0d445/2025-08-03/anthropic/anthropic-claude-sonnet-4-20250514.json +0 -3031
  180. package/benchmarks/results/8c0d445/2025-08-03/openai/openai-gpt-4.1-2025-04-14.json +0 -2990
  181. package/benchmarks/results/ac6b2ab/2025-08-03/anthropic/anthropic-claude-sonnet-4-20250514.json +0 -3256
  182. package/benchmarks/results/ac6b2ab/2025-08-03/lms/lms-qwen-qwen3-coder-30b.json +0 -3007
  183. package/benchmarks/results/ac6b2ab/2025-08-03/openai/openai-gpt-4.1-2025-04-14.json +0 -3256
  184. package/benchmarks/results/ac6b2ab/2025-08-03/openai/openai-gpt-4.1-mini-2025-04-14.json +0 -3036
  185. package/benchmarks/results/ac6b2ab/2025-08-03/openai/openai-gpt-4.1-nano-2025-04-14.json +0 -3280
  186. package/benchmarks/results/adff675/2025-08-04/lms/lms-qwen-qwen3-30b-a3b-2507.json +0 -1920
  187. package/benchmarks/results/adff675/2025-08-04/lms/lms-qwen-qwen3-coder-30b.json +0 -3281
  188. package/benchmarks/results/b502ed9/2025-08-03/lms-qwen/qwen3-coder-30b.json +0 -2896
  189. package/benchmarks/results/d1a8129/2025-08-03/lms/lms-qwen-qwen3-coder-30b.json +0 -3011
  190. package/benchmarks/results/e60471c/2025-08-03/lms/qwen3-30b-a3b-2507.json +0 -3003
  191. package/benchmarks/scripts/build-and-run.sh +0 -47
  192. package/benchmarks/scripts/clone-exercism.sh +0 -92
  193. package/benchmarks/scripts/validate.sh +0 -48
  194. package/benchmarks/src/__tests__/runner.test.ts +0 -27
  195. package/benchmarks/src/cli.ts +0 -90
  196. package/benchmarks/src/evaluators/EvaluatorRegistry.ts +0 -64
  197. package/benchmarks/src/evaluators/JavaScriptEvaluator.ts +0 -183
  198. package/benchmarks/src/evaluators/index.ts +0 -3
  199. package/benchmarks/src/evaluators/types.ts +0 -22
  200. package/benchmarks/src/index.ts +0 -3
  201. package/benchmarks/src/providers.ts +0 -13
  202. package/benchmarks/src/runner.ts +0 -824
  203. package/benchmarks/src/types.ts +0 -63
  204. package/benchmarks/tsconfig.json +0 -19
  205. package/leaderboard/README.md +0 -148
  206. package/leaderboard/app/api/benchmark-data/route.ts +0 -131
  207. package/leaderboard/app/api/benchmark-detail/route.ts +0 -172
  208. package/leaderboard/app/details/[model]/[provider]/[language]/page.tsx +0 -501
  209. package/leaderboard/app/exercise/[model]/[provider]/[language]/[exercise]/page.tsx +0 -375
  210. package/leaderboard/app/globals.css +0 -27
  211. package/leaderboard/app/layout.tsx +0 -21
  212. package/leaderboard/app/page.tsx +0 -170
  213. package/leaderboard/components/LeaderboardTable.tsx +0 -168
  214. package/leaderboard/components/PerformanceChart.tsx +0 -109
  215. package/leaderboard/next-env.d.ts +0 -5
  216. package/leaderboard/next.config.js +0 -4
  217. package/leaderboard/package-lock.json +0 -6363
  218. package/leaderboard/package.json +0 -28
  219. package/leaderboard/postcss.config.js +0 -6
  220. package/leaderboard/tailwind.config.js +0 -17
  221. package/leaderboard/tsconfig.json +0 -28
  222. package/leaderboard/types/benchmark.ts +0 -67
  223. package/leaderboard/utils/dataProcessor.ts +0 -33
  224. package/src/agents/tools/asana/definitions.ts +0 -199
  225. package/src/agents/tools/asana/index.ts +0 -108
  226. package/src/agents/tools/ast/astAppendNode.ts +0 -90
  227. package/src/agents/tools/ast/astDeleteNode.ts +0 -88
  228. package/src/agents/tools/ast/astEditNode.ts +0 -95
  229. package/src/agents/tools/ast/astGetPathForLine.ts +0 -73
  230. package/src/agents/tools/ast/astListPaths.ts +0 -66
  231. package/src/agents/tools/ast/index.ts +0 -7
  232. package/src/agents/tools/github/definitions.ts +0 -89
  233. package/src/agents/tools/github/index.ts +0 -67
  234. package/src/chat-old.ts +0 -446
  235. package/src/plugins/asana.ts +0 -146
  236. package/src/plugins/downloader/plugin.ts +0 -103
  237. package/src/plugins/downloader/types.ts +0 -92
  238. package/src/plugins/figma.ts +0 -158
  239. package/src/plugins/github.ts +0 -219
  240. package/src/plugins/jira.ts +0 -115
  241. package/src/plugins/linear.ts +0 -230
  242. package/src/plugins/notion.ts +0 -179
  243. package/src/plugins/tree-sitter/editor.ts +0 -369
  244. package/src/plugins/tree-sitter/lang-packs/index.ts +0 -23
  245. package/src/plugins/tree-sitter/lang-packs/java.ts +0 -59
  246. package/src/plugins/tree-sitter/lang-packs/javascript.ts +0 -57
  247. package/src/plugins/tree-sitter/lang-packs/python.ts +0 -45
  248. package/src/plugins/tree-sitter/lang-packs/types.ts +0 -79
  249. package/src/plugins/tree-sitter/lang-packs/typescript.ts +0 -49
  250. package/src/plugins/tree-sitter/parser.ts +0 -470
  251. package/src/plugins/tree-sitter/simple-paths.ts +0 -467
  252. package/src/services/GitHub.ts +0 -59
  253. package/tests/tree-sitter/editor.test.ts +0 -113
  254. package/tests/tree-sitter/invalid.test.ts +0 -299
  255. package/tests/tree-sitter/paths/common-edits.test.ts +0 -564
  256. package/tests/tree-sitter/paths/debug-exact-position.test.ts +0 -44
  257. package/tests/tree-sitter/paths/debug-line-indexing.test.ts +0 -49
  258. package/tests/tree-sitter/paths/debug-paths.test.ts +0 -90
  259. package/tests/tree-sitter/paths/paths.test.ts +0 -170
  260. package/tests/tree-sitter/paths/simple-paths.test.ts +0 -367
  261. package/tests/tree-sitter/sample-after.ts +0 -48
  262. package/tests/tree-sitter/sample-before.ts +0 -25
  263. package/tests/tree-sitter/test-files/completely-broken.ts +0 -7
  264. package/tests/tree-sitter/test-files/duplicate-braces.ts +0 -39
  265. package/tests/tree-sitter/test-files/invalid-nesting.ts +0 -39
  266. package/tests/tree-sitter/test-files/malformed-signature.ts +0 -39
  267. package/tests/tree-sitter/test-files/mismatched-parens.ts +0 -39
  268. package/tests/tree-sitter/test-files/missing-semicolon.ts +0 -39
  269. package/tests/tree-sitter/test-files/partially-broken.ts +0 -20
  270. package/tests/tree-sitter/test-files/specific-errors.ts +0 -14
  271. package/tests/tree-sitter/test-files/unclosed-string.ts +0 -39
  272. package/tests/tree-sitter/tree-sitter.test.ts +0 -251
@@ -1,467 +0,0 @@
1
- import { LanguageAgnosticParser, SyntaxNode, Tree } from "./parser";
2
- import { getLanguagePack, LanguagePackConfig } from "./lang-packs";
3
- import { Query } from "tree-sitter";
4
-
5
- export interface SimplePathMatch {
6
- node: SyntaxNode;
7
- path: string;
8
- simplePath: string;
9
- description: string;
10
- }
11
-
12
- export class SimplePathResolver {
13
- private parser: LanguageAgnosticParser;
14
- private languagePack: LanguagePackConfig;
15
-
16
- constructor(parser: LanguageAgnosticParser) {
17
- this.parser = parser;
18
- this.languagePack = parser.getLanguagePack();
19
- }
20
-
21
- /**
22
- * Execute a tree-sitter query and return matches with capture names
23
- */
24
- private executeQuery(
25
- tree: Tree,
26
- queryString: string
27
- ): { node: SyntaxNode; captures: Record<string, SyntaxNode> }[] {
28
- try {
29
- const language = this.parser.parser.getLanguage(); // Access internal parser
30
- if (!language) return [];
31
-
32
- const query = new Query(language, queryString);
33
- const matches = query.matches(tree.rootNode);
34
-
35
- return matches.map((match) => {
36
- const captures: Record<string, SyntaxNode> = {};
37
- for (const capture of match.captures) {
38
- captures[capture.name] = capture.node;
39
- }
40
- return {
41
- node: match.captures[0]?.node, // Main node
42
- captures,
43
- };
44
- });
45
- } catch (error) {
46
- console.warn("Failed to execute tree-sitter query:", error);
47
- console.warn("Query that failed:", JSON.stringify(queryString));
48
- return [];
49
- }
50
- }
51
- /**
52
- * Find all nodes of a specific type using the language pack
53
- */
54
- private findNodesByQuery(
55
- tree: Tree,
56
- queryType: keyof LanguagePackConfig["queries"]
57
- ): { node: SyntaxNode; captures: Record<string, SyntaxNode> }[] {
58
- if (!this.languagePack || !this.languagePack.queries[queryType]) {
59
- return [];
60
- }
61
- return this.executeQuery(tree, this.languagePack.queries[queryType]);
62
- }
63
-
64
- /**
65
- * Parse a path to detect block syntax like describe("name") vs regular paths
66
- */
67
- private parseSimplePath(simplePath: string): {
68
- type: "block" | "regular";
69
- functionName?: string;
70
- argument?: string;
71
- parts: string[];
72
- } {
73
- // Check for function call syntax like describe("name") or test("should work")
74
- const blockPattern = /^(\w+)\s*\(\s*["'`]([^"'`]*)["'`]\s*\)$/;
75
- const blockMatch = simplePath.match(blockPattern);
76
-
77
- if (blockMatch) {
78
- return {
79
- type: "block",
80
- functionName: blockMatch[1],
81
- argument: blockMatch[2],
82
- parts: [blockMatch[1]],
83
- };
84
- }
85
-
86
- // Check for parameterless function calls like beforeEach()
87
- const parameterlessBlockPattern = /^(\w+)\s*\(\s*\)$/;
88
- const parameterlessMatch = simplePath.match(parameterlessBlockPattern);
89
-
90
- if (parameterlessMatch) {
91
- return {
92
- type: "block",
93
- functionName: parameterlessMatch[1],
94
- parts: [parameterlessMatch[1]],
95
- };
96
- }
97
-
98
- // Regular path like "ClassName.methodName" or just "name"
99
- return {
100
- type: "regular",
101
- parts: simplePath.split("."),
102
- };
103
- }
104
- /**
105
- * Find block matches for syntax like describe("name") or beforeEach()
106
- */
107
- private findBlockMatches(
108
- tree: Tree,
109
- functionName: string,
110
- argument: string | undefined,
111
- simplePath: string
112
- ): SimplePathMatch[] {
113
- const matches: SimplePathMatch[] = [];
114
- const blockMatches = this.findNodesByQuery(tree, "blocks");
115
-
116
- for (const match of blockMatches) {
117
- const calleeNode = match.captures.callee;
118
- const nameNode = match.captures.name;
119
-
120
- if (!calleeNode || calleeNode.text !== functionName) {
121
- continue;
122
- }
123
-
124
- // For parameterless blocks like beforeEach(), just match the function name
125
- if (!argument) {
126
- matches.push({
127
- node: match.node,
128
- path: this.getNodePath(tree.rootNode, match.node),
129
- simplePath,
130
- description: `${functionName} block`,
131
- });
132
- continue;
133
- }
134
-
135
- // For blocks with arguments, match the argument text
136
- if (nameNode) {
137
- // Extract string content from quotes
138
- let nameText = nameNode.text;
139
- if (
140
- (nameText.startsWith('"') && nameText.endsWith('"')) ||
141
- (nameText.startsWith("'") && nameText.endsWith("'")) ||
142
- (nameText.startsWith("`") && nameText.endsWith("`"))
143
- ) {
144
- nameText = nameText.slice(1, -1);
145
- }
146
-
147
- if (nameText === argument) {
148
- matches.push({
149
- node: match.node,
150
- path: this.getNodePath(tree.rootNode, match.node),
151
- simplePath,
152
- description: `${functionName} block: ${argument}`,
153
- });
154
- }
155
- }
156
- }
157
-
158
- return matches;
159
- }
160
- /**
161
- * Find nodes using human-readable paths like:
162
- * - "ClassName.methodName" - finds a method in a class
163
- * - "ClassName" - finds a class declaration
164
- * - "methodName" - finds any method with that name
165
- * - "ClassName.propertyName" - finds a property in a class
166
- * - "describe(\"test name\")" - finds a describe block
167
- */
168
- findBySimplePath(tree: Tree, simplePath: string): SimplePathMatch[] {
169
- if (!tree.rootNode) {
170
- return [];
171
- }
172
-
173
- const matches: SimplePathMatch[] = [];
174
- const pathInfo = this.parseSimplePath(simplePath);
175
- const parts = pathInfo.parts;
176
-
177
- // Handle block syntax like describe("Authentication") or beforeEach()
178
- if (pathInfo.type === "block") {
179
- return this.findBlockMatches(
180
- tree,
181
- pathInfo.functionName!,
182
- pathInfo.argument,
183
- simplePath
184
- );
185
- }
186
-
187
- if (parts.length === 1) {
188
- // Single part - could be class, method, or property
189
- const singleName = parts[0];
190
-
191
- // Check for classes
192
- const classMatches = this.findNodesByQuery(tree, "classes");
193
- for (const match of classMatches) {
194
- const nameNode = match.captures.name;
195
- if (nameNode && nameNode.text === singleName) {
196
- matches.push({
197
- node: match.node,
198
- path: this.getNodePath(tree.rootNode, match.node),
199
- simplePath,
200
- description: `Class declaration: ${singleName}`,
201
- });
202
- }
203
- }
204
- // Check for methods
205
- const methodMatches = this.findNodesByQuery(tree, "methods");
206
- for (const match of methodMatches) {
207
- const nameNode = match.captures.name;
208
- if (nameNode && nameNode.text === singleName) {
209
- const className = this.findContainingClassName(tree, match.node);
210
- const description = className
211
- ? `${singleName} method in class ${className}`
212
- : `Method declaration: ${singleName}`;
213
- matches.push({
214
- node: match.node,
215
- path: this.getNodePath(tree.rootNode, match.node),
216
- simplePath,
217
- description,
218
- });
219
- }
220
- }
221
-
222
- // Check for properties
223
- const propertyMatches = this.findNodesByQuery(tree, "properties");
224
- for (const match of propertyMatches) {
225
- const nameNode = match.captures.name;
226
- if (nameNode && nameNode.text === singleName) {
227
- matches.push({
228
- node: match.node,
229
- path: this.getNodePath(tree.rootNode, match.node),
230
- simplePath,
231
- description: `Property declaration: ${singleName}`,
232
- });
233
- }
234
- }
235
-
236
- // Check for generic blocks like describe(), test(), it(), etc.
237
- const blockMatches = this.findNodesByQuery(tree, "blocks");
238
- for (const match of blockMatches) {
239
- const calleeNode = match.captures.callee;
240
- const nameNode = match.captures.name;
241
-
242
- // Check if this is a parameterless call matching the search term
243
- if (calleeNode && calleeNode.text === singleName) {
244
- matches.push({
245
- node: match.node,
246
- path: this.getNodePath(tree.rootNode, match.node),
247
- simplePath,
248
- description: `${singleName} block`,
249
- });
250
- continue;
251
- }
252
-
253
- if (nameNode && nameNode.text === singleName && calleeNode) {
254
- matches.push({
255
- node: match.node,
256
- path: this.getNodePath(tree.rootNode, match.node),
257
- simplePath,
258
- description: `${calleeNode.text} block: ${singleName}`,
259
- });
260
- }
261
- }
262
- } else if (parts.length === 2) {
263
- const [className, memberName] = parts;
264
- // Find classes with the given name
265
- const classMatches = this.findNodesByQuery(tree, "classes");
266
- for (const classMatch of classMatches) {
267
- const classNameNode = classMatch.captures.name;
268
- if (classNameNode && classNameNode.text === className) {
269
- // Look for methods in this class
270
- const methodMatches = this.findNodesByQuery(tree, "methods");
271
- for (const methodMatch of methodMatches) {
272
- const methodNameNode = methodMatch.captures.name;
273
- if (methodNameNode && methodNameNode.text === memberName) {
274
- // Check if this method is within the target class
275
- if (this.isNodeWithinNode(methodMatch.node, classMatch.node)) {
276
- matches.push({
277
- node: methodMatch.node,
278
- path: this.getNodePath(tree.rootNode, methodMatch.node),
279
- simplePath,
280
- description: `${memberName} method in class ${className}`,
281
- });
282
- }
283
- }
284
- }
285
-
286
- // Look for properties in this class
287
- const propertyMatches = this.findNodesByQuery(tree, "properties");
288
- for (const propertyMatch of propertyMatches) {
289
- const propertyNameNode = propertyMatch.captures.name;
290
- if (propertyNameNode && propertyNameNode.text === memberName) {
291
- // Check if this property is within the target class
292
- if (this.isNodeWithinNode(propertyMatch.node, classMatch.node)) {
293
- matches.push({
294
- node: propertyMatch.node,
295
- path: this.getNodePath(tree.rootNode, propertyMatch.node),
296
- simplePath,
297
- description: `Property ${memberName} in class ${className}`,
298
- });
299
- }
300
- }
301
- }
302
- }
303
- }
304
- }
305
-
306
- return matches;
307
- }
308
- /**
309
- * Find the containing class name for a method node
310
- */
311
- private findContainingClassName(
312
- tree: Tree,
313
- methodNode: SyntaxNode
314
- ): string | null {
315
- if (!this.languagePack) return null;
316
-
317
- // Find all classes and check if this method is within any of them
318
- const classMatches = this.findNodesByQuery(tree, "classes");
319
-
320
- for (const classMatch of classMatches) {
321
- if (this.isNodeWithinNode(methodNode, classMatch.node)) {
322
- const nameNode = classMatch.captures.name;
323
- return nameNode ? nameNode.text : null;
324
- }
325
- }
326
- return null;
327
- }
328
-
329
- /**
330
- * Get the parser instance (for testing or advanced usage)
331
- */
332
- getParser(): LanguageAgnosticParser {
333
- return this.parser;
334
- }
335
-
336
- private getNodePath(rootNode: SyntaxNode, targetNode: SyntaxNode): string {
337
- const path: string[] = [];
338
- let current: SyntaxNode | null = targetNode;
339
-
340
- while (current && current !== rootNode) {
341
- if (current.parent) {
342
- const siblings = current.parent.children;
343
- const index = siblings.indexOf(current);
344
- path.unshift(`${current.type}[${index}]`);
345
- current = current.parent;
346
- } else {
347
- break;
348
- }
349
- }
350
-
351
- return path.join("/");
352
- }
353
- /**
354
- * Get all possible human-readable paths for a tree
355
- */
356
- getAllSimplePaths(tree: Tree): string[] {
357
- const paths: string[] = [];
358
-
359
- if (!this.languagePack || !tree.rootNode) {
360
- return paths;
361
- }
362
-
363
- // Add class names
364
- const classMatches = this.findNodesByQuery(tree, "classes");
365
- for (const classMatch of classMatches) {
366
- const classNameNode = classMatch.captures.name;
367
- if (classNameNode && classNameNode.text) {
368
- const className = classNameNode.text;
369
- paths.push(className);
370
-
371
- // Add methods within this class
372
- const methodMatches = this.findNodesByQuery(tree, "methods");
373
- for (const methodMatch of methodMatches) {
374
- const methodNameNode = methodMatch.captures.name;
375
- if (
376
- methodNameNode &&
377
- methodNameNode.text &&
378
- this.isNodeWithinNode(methodMatch.node, classMatch.node)
379
- ) {
380
- const methodName = methodNameNode.text;
381
- paths.push(`${className}.${methodName}`);
382
- }
383
- }
384
-
385
- // Add properties within this class
386
- const propertyMatches = this.findNodesByQuery(tree, "properties");
387
- for (const propertyMatch of propertyMatches) {
388
- const propertyNameNode = propertyMatch.captures.name;
389
- if (
390
- propertyNameNode &&
391
- propertyNameNode.text &&
392
- this.isNodeWithinNode(propertyMatch.node, classMatch.node)
393
- ) {
394
- const propertyName = propertyNameNode.text;
395
- paths.push(`${className}.${propertyName}`);
396
- }
397
- }
398
- }
399
- }
400
- // Add standalone methods (not within classes)
401
- const standaloneMethods = this.findNodesByQuery(tree, "methods");
402
- for (const methodMatch of standaloneMethods) {
403
- const methodNameNode = methodMatch.captures.name;
404
- if (methodNameNode && methodNameNode.text) {
405
- const methodName = methodNameNode.text;
406
-
407
- // Check if this method is NOT within a class
408
- let isWithinClass = false;
409
- for (const classMatch of classMatches) {
410
- if (this.isNodeWithinNode(methodMatch.node, classMatch.node)) {
411
- isWithinClass = true;
412
- break;
413
- }
414
- }
415
-
416
- if (!isWithinClass) {
417
- paths.push(methodName);
418
- }
419
- }
420
- }
421
-
422
- // Add blocks
423
- const blockMatches = this.findNodesByQuery(tree, "blocks");
424
- for (const blockMatch of blockMatches) {
425
- const calleeNode = blockMatch.captures.callee;
426
- const nameNode = blockMatch.captures.name;
427
-
428
- if (calleeNode && calleeNode.text) {
429
- const callee = calleeNode.text;
430
-
431
- if (nameNode && nameNode.text) {
432
- // Extract the name from quotes if needed
433
- let name = nameNode.text;
434
- if (
435
- (name.startsWith('"') && name.endsWith('"')) ||
436
- (name.startsWith("'") && name.endsWith("'"))
437
- ) {
438
- name = name.slice(1, -1);
439
- }
440
- paths.push(`${callee}("${name}")`);
441
- } else {
442
- // Block without name parameter
443
- paths.push(`${callee}()`);
444
- }
445
- }
446
- }
447
-
448
- return paths;
449
- }
450
-
451
- /**
452
- * Helper method to check if one node is contained within another
453
- */
454
- private isNodeWithinNode(
455
- childNode: SyntaxNode,
456
- parentNode: SyntaxNode
457
- ): boolean {
458
- let current = childNode.parent;
459
- while (current) {
460
- if (current === parentNode) {
461
- return true;
462
- }
463
- current = current.parent;
464
- }
465
- return false;
466
- }
467
- }
@@ -1,59 +0,0 @@
1
- import { Octokit } from "@octokit/rest";
2
- import axios from "axios";
3
-
4
- export class GitHubService {
5
- octokit: Octokit;
6
-
7
- constructor() {
8
- this.octokit = new Octokit({
9
- auth: process.env.GITHUB_TOKEN,
10
- });
11
- }
12
-
13
- private isLfsFile(content: string): boolean {
14
- return content.startsWith("version https://git-lfs.github.com/spec/v1");
15
- }
16
-
17
- private getLfsPointerContent(content: string) {
18
- const oid = content.split("\n").find((line) => line.startsWith("oid"));
19
- const second = oid?.split(" ")[1];
20
- const sha = second.split(":")[1];
21
- return sha;
22
- }
23
-
24
- private async getLfsContent(downloadUrl: string): Promise<string> {
25
- const response = await axios.get(downloadUrl);
26
- return JSON.stringify(response.data);
27
- }
28
-
29
- private async getFileContent(
30
- owner: string,
31
- repo: string,
32
- path: string
33
- ): Promise<string> {
34
- const { data } = await this.octokit.repos.getContent({
35
- owner,
36
- repo,
37
- path,
38
- });
39
- if (!("content" in data)) {
40
- throw new Error("File content not found in GitHub API response");
41
- }
42
- const content = Buffer.from(data.content, "base64").toString("utf-8");
43
- return this.isLfsFile(content)
44
- ? await this.getLfsContent(data.download_url)
45
- : content;
46
- }
47
-
48
- async downloadFile(
49
- orgProject: string,
50
- fileName: string,
51
- destinationPath: string
52
- ): Promise<void> {
53
- const [owner, repo] = orgProject.split("/");
54
- const content = await this.getFileContent(owner, repo, fileName);
55
- const fs = require("fs");
56
- fs.writeFileSync(destinationPath, content);
57
- }
58
- }
59
-
@@ -1,113 +0,0 @@
1
- import { join } from "path";
2
- import { TreeEditor } from "../../src/plugins/tree-sitter/editor";
3
- import { LanguageAgnosticParser } from "../../src/plugins/tree-sitter/parser";
4
-
5
- describe("TreeEditor", () => {
6
- let parser: LanguageAgnosticParser;
7
- const sampleCode = `class Calculator {
8
- add(a, b) {
9
- return a + b;
10
- }
11
-
12
- multiply(a, b) {
13
- return a * b;
14
- }
15
- }`;
16
-
17
- beforeEach(() => {
18
- parser = LanguageAgnosticParser.createJavaScriptParser();
19
- });
20
-
21
- test("should create TreeEditor from string", () => {
22
- const editor = new TreeEditor(parser, sampleCode);
23
- expect(editor).toBeDefined();
24
- expect(editor.getCurrentText()).toBe(sampleCode);
25
- });
26
-
27
- test("should create TreeEditor from file", () => {
28
- const beforeFilePath = join(__dirname, "sample-before.ts");
29
- const editor = TreeEditor.fromFile(parser, beforeFilePath);
30
- expect(editor).toBeDefined();
31
- expect(editor.getCurrentText().length).toBeGreaterThan(0);
32
- });
33
-
34
- test("should add lines to code", () => {
35
- const editor = new TreeEditor(parser, sampleCode);
36
- const newEditor = editor.addLines(
37
- "",
38
- " subtract(a, b) {\n return a - b;\n }",
39
- 5
40
- );
41
-
42
- const newText = newEditor.getCurrentText();
43
- expect(newText).toContain("subtract");
44
- expect(newText.split("\n").length).toBeGreaterThan(
45
- sampleCode.split("\n").length
46
- );
47
-
48
- console.log("After adding lines:\n", newText);
49
- });
50
-
51
- test("should remove lines from code", () => {
52
- const editor = new TreeEditor(parser, sampleCode);
53
- const newEditor = editor.removeLines(1, 3); // Remove add method
54
-
55
- const newText = newEditor.getCurrentText();
56
- expect(newText).not.toContain("add(a, b)");
57
- expect(newText.split("\n").length).toBeLessThan(
58
- sampleCode.split("\n").length
59
- );
60
-
61
- console.log("After removing lines:\n", newText);
62
- });
63
-
64
- test("should update a specific line", () => {
65
- const editor = new TreeEditor(parser, sampleCode);
66
- const newEditor = editor.updateLine(0, "class AdvancedCalculator {");
67
-
68
- const newText = newEditor.getCurrentText();
69
- expect(newText).toContain("AdvancedCalculator");
70
- expect(newText).not.toContain("class Calculator {");
71
-
72
- console.log("After updating line:\n", newText);
73
- });
74
-
75
- test("should generate diff between original and modified", () => {
76
- const editor = new TreeEditor(parser, sampleCode);
77
- const newEditor = editor
78
- .updateLine(0, "class AdvancedCalculator {")
79
- .addLines("", " subtract(a, b) {\n return a - b;\n }", 5);
80
-
81
- const diff = newEditor.generateDiff();
82
-
83
- expect(diff).toContain("---");
84
- expect(diff).toContain("+++");
85
- expect(diff).toContain("-class Calculator {");
86
- expect(diff).toContain("+class AdvancedCalculator {");
87
- expect(diff).toContain("+ subtract(a, b) {");
88
- expect(diff).toContain("+ return a - b;");
89
-
90
- console.log("Generated diff:\n", diff);
91
- });
92
-
93
- test("should handle complex editing workflow", () => {
94
- const beforeFilePath = join(__dirname, "sample-before.ts");
95
- const editor = TreeEditor.fromFile(parser, beforeFilePath);
96
-
97
- // Make multiple edits
98
- const modifiedEditor = editor
99
- .addLines("", " private operationCount: number = 0;", 2)
100
- .updateLine(5, " // Enhanced add method")
101
- .addLines("", " this.operationCount++;", 9);
102
-
103
- const diff = modifiedEditor.generateDiff();
104
- const newText = modifiedEditor.getCurrentText();
105
-
106
- expect(newText).toContain("operationCount");
107
- expect(newText).toContain("Enhanced add method");
108
- expect(diff).toContain("operationCount");
109
-
110
- console.log("Complex edit result:\n", newText);
111
- console.log("Complex edit diff:\n", diff);
112
- });
113
- });