@tyvm/knowhow 0.0.90 → 0.0.91
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.
- package/.depcheckrc +31 -0
- package/bin/knowhow.js +1 -1
- package/package.json +4 -32
- package/src/agents/tools/executeScript/index.ts +5 -0
- package/src/agents/tools/googleSearch.ts +2 -2
- package/src/agents/tools/index.ts +0 -3
- package/src/agents/tools/list.ts +0 -147
- package/src/agents/tools/loadWebpage.ts +3 -113
- package/src/auth/browserLogin.ts +10 -13
- package/src/cli.ts +63 -3
- package/src/clients/gemini.ts +96 -25
- package/src/clients/http.ts +7 -11
- package/src/clients/pricing/google.ts +122 -26
- package/src/conversion.ts +24 -54
- package/src/index.ts +8 -1
- package/src/login.ts +5 -6
- package/src/plugins/language.ts +0 -4
- package/src/plugins/plugins.ts +0 -14
- package/src/plugins/url.ts +31 -12
- package/src/services/GitHub.ts +2 -2
- package/src/services/KnowhowClient.ts +34 -34
- package/src/{plugins/downloader/downloader.ts → services/MediaProcessorService.ts} +109 -267
- package/src/services/S3.ts +16 -16
- package/src/services/index.ts +4 -4
- package/src/services/modules/index.ts +10 -2
- package/src/services/modules/types.ts +5 -2
- package/src/services/script-execution/ScriptExecutor.ts +29 -10
- package/src/services/script-execution/ScriptPolicy.ts +6 -2
- package/src/types.ts +1 -0
- package/src/utils/http.ts +127 -0
- package/src/workers/auth/PasskeySetup.ts +7 -11
- package/tests/clients/AIClient.test.ts +24 -21
- package/tests/manual/file-edits/figma.test.ts +3 -70
- package/tests/plugins/language/languagePlugin-content-triggers.test.ts +2 -0
- package/tests/plugins/language/languagePlugin.test.ts +2 -0
- package/tests/processors/ToolResponseCache.test.ts +2 -2
- package/tests/test.spec.ts +0 -14
- package/tests/unit/modules/moduleLoading.test.ts +7 -4
- package/tests/unit/plugins/pluginLoading.test.ts +6 -6
- package/ts_build/package.json +4 -32
- package/ts_build/src/agents/tools/ast/astAppendNode.d.ts +1 -1
- package/ts_build/src/agents/tools/ast/astAppendNode.js +2 -90
- package/ts_build/src/agents/tools/ast/astAppendNode.js.map +1 -1
- package/ts_build/src/agents/tools/ast/astDeleteNode.d.ts +1 -1
- package/ts_build/src/agents/tools/ast/astDeleteNode.js +2 -88
- package/ts_build/src/agents/tools/ast/astDeleteNode.js.map +1 -1
- package/ts_build/src/agents/tools/ast/astEditNode.d.ts +1 -1
- package/ts_build/src/agents/tools/ast/astEditNode.js +2 -90
- package/ts_build/src/agents/tools/ast/astEditNode.js.map +1 -1
- package/ts_build/src/agents/tools/ast/astGetPathForLine.d.ts +1 -1
- package/ts_build/src/agents/tools/ast/astGetPathForLine.js +2 -72
- package/ts_build/src/agents/tools/ast/astGetPathForLine.js.map +1 -1
- package/ts_build/src/agents/tools/ast/astListPaths.d.ts +1 -1
- package/ts_build/src/agents/tools/ast/astListPaths.js +2 -72
- package/ts_build/src/agents/tools/ast/astListPaths.js.map +1 -1
- package/ts_build/src/agents/tools/executeScript/index.d.ts +3 -2
- package/ts_build/src/agents/tools/executeScript/index.js +4 -1
- package/ts_build/src/agents/tools/executeScript/index.js.map +1 -1
- package/ts_build/src/agents/tools/googleSearch.js +2 -2
- package/ts_build/src/agents/tools/googleSearch.js.map +1 -1
- package/ts_build/src/agents/tools/index.d.ts +0 -3
- package/ts_build/src/agents/tools/index.js +0 -3
- package/ts_build/src/agents/tools/index.js.map +1 -1
- package/ts_build/src/agents/tools/list.js +0 -138
- package/ts_build/src/agents/tools/list.js.map +1 -1
- package/ts_build/src/agents/tools/loadWebpage.js +1 -89
- package/ts_build/src/agents/tools/loadWebpage.js.map +1 -1
- package/ts_build/src/agents/tools/textSearch.d.ts +1 -1
- package/ts_build/src/auth/browserLogin.js +7 -7
- package/ts_build/src/auth/browserLogin.js.map +1 -1
- package/ts_build/src/cli.d.ts +1 -1
- package/ts_build/src/cli.js +47 -1
- package/ts_build/src/cli.js.map +1 -1
- package/ts_build/src/clients/gemini.d.ts +1 -73
- package/ts_build/src/clients/gemini.js +57 -19
- package/ts_build/src/clients/gemini.js.map +1 -1
- package/ts_build/src/clients/http.js +5 -9
- package/ts_build/src/clients/http.js.map +1 -1
- package/ts_build/src/clients/pricing/google.d.ts +17 -73
- package/ts_build/src/clients/pricing/google.js +47 -10
- package/ts_build/src/clients/pricing/google.js.map +1 -1
- package/ts_build/src/conversion.d.ts +1 -4
- package/ts_build/src/conversion.js +12 -27
- package/ts_build/src/conversion.js.map +1 -1
- package/ts_build/src/index.d.ts +4 -0
- package/ts_build/src/index.js +7 -1
- package/ts_build/src/index.js.map +1 -1
- package/ts_build/src/login.js +5 -4
- package/ts_build/src/login.js.map +1 -1
- package/ts_build/src/plugins/downloader/downloader.js +3 -3
- package/ts_build/src/plugins/downloader/downloader.js.map +1 -1
- package/ts_build/src/plugins/language.js.map +1 -1
- package/ts_build/src/plugins/plugins.js +0 -14
- package/ts_build/src/plugins/plugins.js.map +1 -1
- package/ts_build/src/plugins/tree-sitter/editor.d.ts +3 -32
- package/ts_build/src/plugins/tree-sitter/editor.js +6 -208
- package/ts_build/src/plugins/tree-sitter/editor.js.map +1 -1
- package/ts_build/src/plugins/tree-sitter/parser.d.ts +19 -54
- package/ts_build/src/plugins/tree-sitter/parser.js +19 -293
- package/ts_build/src/plugins/tree-sitter/parser.js.map +1 -1
- package/ts_build/src/plugins/tree-sitter/simple-paths.d.ts +2 -15
- package/ts_build/src/plugins/tree-sitter/simple-paths.js +2 -324
- package/ts_build/src/plugins/tree-sitter/simple-paths.js.map +1 -1
- package/ts_build/src/plugins/url.js +27 -8
- package/ts_build/src/plugins/url.js.map +1 -1
- package/ts_build/src/services/GitHub.js +2 -2
- package/ts_build/src/services/GitHub.js.map +1 -1
- package/ts_build/src/services/KnowhowClient.d.ts +29 -29
- package/ts_build/src/services/KnowhowClient.js +33 -33
- package/ts_build/src/services/KnowhowClient.js.map +1 -1
- package/ts_build/src/services/MediaProcessorService.d.ts +22 -0
- package/ts_build/src/services/MediaProcessorService.js +215 -0
- package/ts_build/src/services/MediaProcessorService.js.map +1 -0
- package/ts_build/src/services/S3.js +12 -18
- package/ts_build/src/services/S3.js.map +1 -1
- package/ts_build/src/services/index.d.ts +3 -2
- package/ts_build/src/services/index.js +3 -3
- package/ts_build/src/services/index.js.map +1 -1
- package/ts_build/src/services/modules/index.js +10 -2
- package/ts_build/src/services/modules/index.js.map +1 -1
- package/ts_build/src/services/modules/types.d.ts +5 -2
- package/ts_build/src/services/script-execution/ScriptExecutor.js +22 -7
- package/ts_build/src/services/script-execution/ScriptExecutor.js.map +1 -1
- package/ts_build/src/services/script-execution/ScriptPolicy.d.ts +1 -1
- package/ts_build/src/services/script-execution/ScriptPolicy.js +4 -2
- package/ts_build/src/services/script-execution/ScriptPolicy.js.map +1 -1
- package/ts_build/src/types.d.ts +1 -0
- package/ts_build/src/types.js +1 -0
- package/ts_build/src/types.js.map +1 -1
- package/ts_build/src/utils/http.d.ts +27 -0
- package/ts_build/src/utils/http.js +98 -0
- package/ts_build/src/utils/http.js.map +1 -0
- package/ts_build/src/workers/auth/PasskeySetup.js +6 -7
- package/ts_build/src/workers/auth/PasskeySetup.js.map +1 -1
- package/ts_build/tests/clients/AIClient.test.js +11 -14
- package/ts_build/tests/clients/AIClient.test.js.map +1 -1
- package/ts_build/tests/manual/file-edits/figma.test.d.ts +0 -1
- package/ts_build/tests/manual/file-edits/figma.test.js +1 -46
- package/ts_build/tests/manual/file-edits/figma.test.js.map +1 -1
- package/ts_build/tests/plugins/language/languagePlugin-content-triggers.test.js +2 -0
- package/ts_build/tests/plugins/language/languagePlugin-content-triggers.test.js.map +1 -1
- package/ts_build/tests/plugins/language/languagePlugin.test.js +2 -0
- package/ts_build/tests/plugins/language/languagePlugin.test.js.map +1 -1
- package/ts_build/tests/processors/ToolResponseCache.test.js +2 -2
- package/ts_build/tests/processors/ToolResponseCache.test.js.map +1 -1
- package/ts_build/tests/test.spec.js +0 -14
- package/ts_build/tests/test.spec.js.map +1 -1
- package/ts_build/tests/tree-sitter/tree-sitter.test.d.ts +0 -1
- package/ts_build/tests/tree-sitter/tree-sitter.test.js +2 -183
- package/ts_build/tests/tree-sitter/tree-sitter.test.js.map +1 -1
- package/ts_build/tests/unit/modules/moduleLoading.test.js +6 -4
- package/ts_build/tests/unit/modules/moduleLoading.test.js.map +1 -1
- package/ts_build/tests/unit/plugins/pluginLoading.test.js +4 -4
- package/ts_build/tests/unit/plugins/pluginLoading.test.js.map +1 -1
- package/benchmarks/.dockerignore +0 -7
- package/benchmarks/README.md +0 -166
- package/benchmarks/docker/Dockerfile +0 -68
- package/benchmarks/example-config.yml +0 -27
- package/benchmarks/jest.config.js +0 -13
- package/benchmarks/package-lock.json +0 -4297
- package/benchmarks/package.json +0 -39
- package/benchmarks/results/27b0a06/2025-09-27/xai/xai-grok-code-fast-1.json +0 -2909
- package/benchmarks/results/4057aed/2025-08-14/anthropic/anthropic-claude-sonnet-4-20250514.json +0 -1671
- package/benchmarks/results/4542435/2025-08-05/lms/lms-openai-gpt-oss-20b.json +0 -2814
- package/benchmarks/results/4542435/2025-08-05/lms/lms-qwen-qwen3-30b-a3b-2507.json +0 -2014
- package/benchmarks/results/4fb9125/2025-08-07/anthropic/anthropic-claude-sonnet-4-20250514.json +0 -3121
- package/benchmarks/results/5766aee/2025-08-02/lms-qwen/qwen3-coder-30b.json +0 -98
- package/benchmarks/results/6d73808/2025-08-07/openai/openai-gpt-5.json +0 -3256
- package/benchmarks/results/77bf0a6/2025-08-02/lms-qwen/qwen3-30b-a3b-2507.json +0 -4298
- package/benchmarks/results/8c0d445/2025-08-03/anthropic/anthropic-claude-sonnet-4-20250514.json +0 -3031
- package/benchmarks/results/8c0d445/2025-08-03/openai/openai-gpt-4.1-2025-04-14.json +0 -2990
- package/benchmarks/results/ac6b2ab/2025-08-03/anthropic/anthropic-claude-sonnet-4-20250514.json +0 -3256
- package/benchmarks/results/ac6b2ab/2025-08-03/lms/lms-qwen-qwen3-coder-30b.json +0 -3007
- package/benchmarks/results/ac6b2ab/2025-08-03/openai/openai-gpt-4.1-2025-04-14.json +0 -3256
- package/benchmarks/results/ac6b2ab/2025-08-03/openai/openai-gpt-4.1-mini-2025-04-14.json +0 -3036
- package/benchmarks/results/ac6b2ab/2025-08-03/openai/openai-gpt-4.1-nano-2025-04-14.json +0 -3280
- package/benchmarks/results/adff675/2025-08-04/lms/lms-qwen-qwen3-30b-a3b-2507.json +0 -1920
- package/benchmarks/results/adff675/2025-08-04/lms/lms-qwen-qwen3-coder-30b.json +0 -3281
- package/benchmarks/results/b502ed9/2025-08-03/lms-qwen/qwen3-coder-30b.json +0 -2896
- package/benchmarks/results/d1a8129/2025-08-03/lms/lms-qwen-qwen3-coder-30b.json +0 -3011
- package/benchmarks/results/e60471c/2025-08-03/lms/qwen3-30b-a3b-2507.json +0 -3003
- package/benchmarks/scripts/build-and-run.sh +0 -47
- package/benchmarks/scripts/clone-exercism.sh +0 -92
- package/benchmarks/scripts/validate.sh +0 -48
- package/benchmarks/src/__tests__/runner.test.ts +0 -27
- package/benchmarks/src/cli.ts +0 -90
- package/benchmarks/src/evaluators/EvaluatorRegistry.ts +0 -64
- package/benchmarks/src/evaluators/JavaScriptEvaluator.ts +0 -183
- package/benchmarks/src/evaluators/index.ts +0 -3
- package/benchmarks/src/evaluators/types.ts +0 -22
- package/benchmarks/src/index.ts +0 -3
- package/benchmarks/src/providers.ts +0 -13
- package/benchmarks/src/runner.ts +0 -824
- package/benchmarks/src/types.ts +0 -63
- package/benchmarks/tsconfig.json +0 -19
- package/leaderboard/README.md +0 -148
- package/leaderboard/app/api/benchmark-data/route.ts +0 -131
- package/leaderboard/app/api/benchmark-detail/route.ts +0 -172
- package/leaderboard/app/details/[model]/[provider]/[language]/page.tsx +0 -501
- package/leaderboard/app/exercise/[model]/[provider]/[language]/[exercise]/page.tsx +0 -375
- package/leaderboard/app/globals.css +0 -27
- package/leaderboard/app/layout.tsx +0 -21
- package/leaderboard/app/page.tsx +0 -170
- package/leaderboard/components/LeaderboardTable.tsx +0 -168
- package/leaderboard/components/PerformanceChart.tsx +0 -109
- package/leaderboard/next-env.d.ts +0 -5
- package/leaderboard/next.config.js +0 -4
- package/leaderboard/package-lock.json +0 -6363
- package/leaderboard/package.json +0 -28
- package/leaderboard/postcss.config.js +0 -6
- package/leaderboard/tailwind.config.js +0 -17
- package/leaderboard/tsconfig.json +0 -28
- package/leaderboard/types/benchmark.ts +0 -67
- package/leaderboard/utils/dataProcessor.ts +0 -33
- package/src/agents/tools/asana/definitions.ts +0 -199
- package/src/agents/tools/asana/index.ts +0 -108
- package/src/agents/tools/ast/astAppendNode.ts +0 -90
- package/src/agents/tools/ast/astDeleteNode.ts +0 -88
- package/src/agents/tools/ast/astEditNode.ts +0 -95
- package/src/agents/tools/ast/astGetPathForLine.ts +0 -73
- package/src/agents/tools/ast/astListPaths.ts +0 -66
- package/src/agents/tools/ast/index.ts +0 -7
- package/src/agents/tools/github/definitions.ts +0 -89
- package/src/agents/tools/github/index.ts +0 -67
- package/src/chat-old.ts +0 -446
- package/src/plugins/asana.ts +0 -146
- package/src/plugins/downloader/plugin.ts +0 -103
- package/src/plugins/downloader/types.ts +0 -92
- package/src/plugins/figma.ts +0 -158
- package/src/plugins/github.ts +0 -219
- package/src/plugins/jira.ts +0 -115
- package/src/plugins/linear.ts +0 -230
- package/src/plugins/notion.ts +0 -179
- package/src/plugins/tree-sitter/editor.ts +0 -369
- package/src/plugins/tree-sitter/lang-packs/index.ts +0 -23
- package/src/plugins/tree-sitter/lang-packs/java.ts +0 -59
- package/src/plugins/tree-sitter/lang-packs/javascript.ts +0 -57
- package/src/plugins/tree-sitter/lang-packs/python.ts +0 -45
- package/src/plugins/tree-sitter/lang-packs/types.ts +0 -79
- package/src/plugins/tree-sitter/lang-packs/typescript.ts +0 -49
- package/src/plugins/tree-sitter/parser.ts +0 -470
- package/src/plugins/tree-sitter/simple-paths.ts +0 -467
- package/tests/tree-sitter/editor.test.ts +0 -113
- package/tests/tree-sitter/invalid.test.ts +0 -299
- package/tests/tree-sitter/paths/common-edits.test.ts +0 -564
- package/tests/tree-sitter/paths/debug-exact-position.test.ts +0 -44
- package/tests/tree-sitter/paths/debug-line-indexing.test.ts +0 -49
- package/tests/tree-sitter/paths/debug-paths.test.ts +0 -90
- package/tests/tree-sitter/paths/paths.test.ts +0 -170
- package/tests/tree-sitter/paths/simple-paths.test.ts +0 -367
- package/tests/tree-sitter/sample-after.ts +0 -48
- package/tests/tree-sitter/sample-before.ts +0 -25
- package/tests/tree-sitter/test-files/completely-broken.ts +0 -7
- package/tests/tree-sitter/test-files/duplicate-braces.ts +0 -39
- package/tests/tree-sitter/test-files/invalid-nesting.ts +0 -39
- package/tests/tree-sitter/test-files/malformed-signature.ts +0 -39
- package/tests/tree-sitter/test-files/mismatched-parens.ts +0 -39
- package/tests/tree-sitter/test-files/missing-semicolon.ts +0 -39
- package/tests/tree-sitter/test-files/partially-broken.ts +0 -20
- package/tests/tree-sitter/test-files/specific-errors.ts +0 -14
- package/tests/tree-sitter/test-files/unclosed-string.ts +0 -39
- 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,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
|
-
});
|