@oisheek_c/codeforge 1.0.1

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 (141) hide show
  1. package/LICENSE +0 -0
  2. package/README.md +7 -0
  3. package/apps/cli/bin/codeforge.cmd +2 -0
  4. package/apps/cli/src/bootstrap.js +115 -0
  5. package/apps/cli/src/cli.js +189 -0
  6. package/apps/cli/src/dev/git.js +17 -0
  7. package/apps/cli/src/dev/index.js +68 -0
  8. package/apps/cli/src/dev/provider.js +48 -0
  9. package/apps/cli/src/dev/scanner.js +14 -0
  10. package/apps/cli/src/index.js +31 -0
  11. package/bin/codeforge.js +2 -0
  12. package/package.json +63 -0
  13. package/packages/agent/contextBuilder.js +234 -0
  14. package/packages/agent/executor.js +1729 -0
  15. package/packages/agent/fallback.js +129 -0
  16. package/packages/agent/index.js +26 -0
  17. package/packages/agent/intent.js +73 -0
  18. package/packages/agent/modelSelector.js +469 -0
  19. package/packages/agent/planner.js +379 -0
  20. package/packages/agent/rag.js +412 -0
  21. package/packages/agent/ragSelector.js +570 -0
  22. package/packages/agent/router.js +121 -0
  23. package/packages/agent/thinking.js +54 -0
  24. package/packages/agent/toolCalls.js +258 -0
  25. package/packages/config/config.js +391 -0
  26. package/packages/config/defaults.js +72 -0
  27. package/packages/config/index.js +2 -0
  28. package/packages/core/approvalPolicy.js +140 -0
  29. package/packages/core/context.js +0 -0
  30. package/packages/core/message.js +0 -0
  31. package/packages/core/plan.js +0 -0
  32. package/packages/core/reasoning.js +0 -0
  33. package/packages/core/result.js +0 -0
  34. package/packages/core/retrieval.js +0 -0
  35. package/packages/core/tool.js +536 -0
  36. package/packages/git/branch.js +7 -0
  37. package/packages/git/commit.js +16 -0
  38. package/packages/git/diff.js +15 -0
  39. package/packages/git/git.js +35 -0
  40. package/packages/git/index.js +6 -0
  41. package/packages/git/remote.js +9 -0
  42. package/packages/git/status.js +11 -0
  43. package/packages/memory/index.js +0 -0
  44. package/packages/memory/project.js +0 -0
  45. package/packages/memory/session.js +0 -0
  46. package/packages/prompts/builder.js +43 -0
  47. package/packages/prompts/coder.js +38 -0
  48. package/packages/prompts/index.js +5 -0
  49. package/packages/prompts/planner.js +49 -0
  50. package/packages/prompts/reviewer.js +38 -0
  51. package/packages/prompts/system.js +94 -0
  52. package/packages/providers/index.js +31 -0
  53. package/packages/providers/openrouter.js +380 -0
  54. package/packages/reasoning/budget.js +0 -0
  55. package/packages/reasoning/chain.js +0 -0
  56. package/packages/reasoning/coder.js +0 -0
  57. package/packages/reasoning/evaluator.js +0 -0
  58. package/packages/reasoning/index.js +8 -0
  59. package/packages/reasoning/planner.js +0 -0
  60. package/packages/reasoning/reflector.js +0 -0
  61. package/packages/reasoning/reviewer.js +0 -0
  62. package/packages/reasoning/router.js +0 -0
  63. package/packages/retrieval/budget.js +92 -0
  64. package/packages/retrieval/cache.js +84 -0
  65. package/packages/retrieval/embeddings.js +147 -0
  66. package/packages/retrieval/graph.js +151 -0
  67. package/packages/retrieval/imports.js +74 -0
  68. package/packages/retrieval/index.js +9 -0
  69. package/packages/retrieval/parser/extractors/calls.js +43 -0
  70. package/packages/retrieval/parser/extractors/comments.js +49 -0
  71. package/packages/retrieval/parser/extractors/diagnostics.js +21 -0
  72. package/packages/retrieval/parser/extractors/exports.js +71 -0
  73. package/packages/retrieval/parser/extractors/imports.js +40 -0
  74. package/packages/retrieval/parser/extractors/index.js +12 -0
  75. package/packages/retrieval/parser/extractors/metrics.js +78 -0
  76. package/packages/retrieval/parser/extractors/symbols.js +51 -0
  77. package/packages/retrieval/parser/extractors/todos.js +53 -0
  78. package/packages/retrieval/parser/helpers.js +138 -0
  79. package/packages/retrieval/parser/index.js +10 -0
  80. package/packages/retrieval/parser/languages/c.js +14 -0
  81. package/packages/retrieval/parser/languages/cpp.js +21 -0
  82. package/packages/retrieval/parser/languages/csharp.js +14 -0
  83. package/packages/retrieval/parser/languages/go.js +14 -0
  84. package/packages/retrieval/parser/languages/index.js +12 -0
  85. package/packages/retrieval/parser/languages/java.js +14 -0
  86. package/packages/retrieval/parser/languages/javascript.js +14 -0
  87. package/packages/retrieval/parser/languages/php.js +14 -0
  88. package/packages/retrieval/parser/languages/python.js +14 -0
  89. package/packages/retrieval/parser/languages/ruby.js +14 -0
  90. package/packages/retrieval/parser/languages/rust.js +14 -0
  91. package/packages/retrieval/parser/languages/swift.js +14 -0
  92. package/packages/retrieval/parser/languages/typescript.js +14 -0
  93. package/packages/retrieval/parser/languages.js +218 -0
  94. package/packages/retrieval/parser/parseFile.js +79 -0
  95. package/packages/retrieval/parser/parseRepository.js +78 -0
  96. package/packages/retrieval/parser/queries/c.js +148 -0
  97. package/packages/retrieval/parser/queries/cpp.js +198 -0
  98. package/packages/retrieval/parser/queries/csharp.js +151 -0
  99. package/packages/retrieval/parser/queries/go.js +124 -0
  100. package/packages/retrieval/parser/queries/index.js +35 -0
  101. package/packages/retrieval/parser/queries/java.js +128 -0
  102. package/packages/retrieval/parser/queries/javascript.js +181 -0
  103. package/packages/retrieval/parser/queries/php.js +140 -0
  104. package/packages/retrieval/parser/queries/python.js +110 -0
  105. package/packages/retrieval/parser/queries/ruby.js +105 -0
  106. package/packages/retrieval/parser/queries/rust.js +175 -0
  107. package/packages/retrieval/parser/queries/swift.js +134 -0
  108. package/packages/retrieval/parser/queries/typescript.js +202 -0
  109. package/packages/retrieval/parser/registry.js +107 -0
  110. package/packages/retrieval/parser/traverse.js +82 -0
  111. package/packages/retrieval/parser/types.js +239 -0
  112. package/packages/retrieval/parser.js +78 -0
  113. package/packages/retrieval/ranker.js +73 -0
  114. package/packages/retrieval/retriever.js +910 -0
  115. package/packages/retrieval/symbols.js +145 -0
  116. package/packages/scanner/detect.js +69 -0
  117. package/packages/scanner/ignore.js +12 -0
  118. package/packages/scanner/index.js +2 -0
  119. package/packages/scanner/root.js +21 -0
  120. package/packages/scanner/scanner.js +35 -0
  121. package/packages/scanner/tree.js +45 -0
  122. package/packages/terminal/activity.js +514 -0
  123. package/packages/terminal/banner.js +34 -0
  124. package/packages/terminal/colors.js +16 -0
  125. package/packages/terminal/dashboard.js +94 -0
  126. package/packages/terminal/index.js +19 -0
  127. package/packages/terminal/logger.js +43 -0
  128. package/packages/terminal/prompt.js +11 -0
  129. package/packages/terminal/renderer.js +1209 -0
  130. package/packages/terminal/spinner.js +9 -0
  131. package/packages/tools/editFile.js +261 -0
  132. package/packages/tools/filesystem.js +82 -0
  133. package/packages/tools/index.js +24 -0
  134. package/packages/tools/readFile.js +101 -0
  135. package/packages/tools/registry.js +227 -0
  136. package/packages/tools/searchFiles.js +322 -0
  137. package/packages/tools/shell.js +352 -0
  138. package/packages/tools/writeFile.js +212 -0
  139. package/packages/utils/constants.js +0 -0
  140. package/packages/utils/helpers.js +0 -0
  141. package/packages/utils/logger.js +0 -0
@@ -0,0 +1,92 @@
1
+ /**
2
+ * packages/retrieval/budget.js
3
+ *
4
+ * Context budget manager.
5
+ */
6
+
7
+ export class ContextBudget {
8
+ constructor(limit = 16000) {
9
+ this.limit = limit;
10
+ }
11
+
12
+ /**
13
+ * Estimate token count.
14
+ *
15
+ * Default heuristic:
16
+ * 1 token ≈ 4 characters.
17
+ */
18
+ estimate(text = "") {
19
+ return Math.ceil(text.length / 4);
20
+ }
21
+
22
+ /**
23
+ * Select as many items as fit within the budget.
24
+ */
25
+ select(items) {
26
+ let used = 0;
27
+
28
+ const selected = [];
29
+
30
+ for (const item of items) {
31
+ const text =
32
+ item.text ??
33
+ item.metadata?.text ??
34
+ "";
35
+
36
+ const cost = this.estimate(text);
37
+
38
+ if (used + cost > this.limit) {
39
+ continue;
40
+ }
41
+
42
+ used += cost;
43
+ selected.push(item);
44
+ }
45
+
46
+ return {
47
+ items: selected,
48
+ used,
49
+ remaining: this.limit - used,
50
+ limit: this.limit,
51
+ utilization:
52
+ this.limit === 0
53
+ ? 0
54
+ : used / this.limit,
55
+ };
56
+ }
57
+
58
+ /**
59
+ * Check whether a single item fits.
60
+ */
61
+ fits(item) {
62
+ const text =
63
+ item.text ??
64
+ item.metadata?.text ??
65
+ "";
66
+
67
+ return this.estimate(text) <= this.limit;
68
+ }
69
+
70
+ /**
71
+ * Remaining budget after using some tokens.
72
+ */
73
+ remaining(used) {
74
+ return Math.max(0, this.limit - used);
75
+ }
76
+
77
+ /**
78
+ * Budget statistics.
79
+ */
80
+ stats() {
81
+ return {
82
+ limit: this.limit,
83
+ };
84
+ }
85
+ }
86
+
87
+ /**
88
+ * Factory.
89
+ */
90
+ export function createContextBudget(limit) {
91
+ return new ContextBudget(limit);
92
+ }
@@ -0,0 +1,84 @@
1
+ /**
2
+ * packages/retrieval/cache.js
3
+ *
4
+ * Simple in-memory cache for retrieval artifacts.
5
+ */
6
+
7
+ export class RetrievalCache {
8
+ constructor() {
9
+ this.clear();
10
+ }
11
+
12
+ clear() {
13
+ this.cache = new Map();
14
+ }
15
+
16
+ /**
17
+ * Check if a key exists.
18
+ */
19
+ has(key) {
20
+ return this.cache.has(key);
21
+ }
22
+
23
+ /**
24
+ * Retrieve a cached value.
25
+ */
26
+ get(key) {
27
+ const entry = this.cache.get(key);
28
+
29
+ if (!entry) {
30
+ return null;
31
+ }
32
+
33
+ return entry.value;
34
+ }
35
+
36
+ /**
37
+ * Store a value.
38
+ */
39
+ set(key, value) {
40
+ this.cache.set(key, {
41
+ value,
42
+ createdAt: Date.now(),
43
+ });
44
+
45
+ return value;
46
+ }
47
+
48
+ /**
49
+ * Remove one cache entry.
50
+ */
51
+ delete(key) {
52
+ return this.cache.delete(key);
53
+ }
54
+
55
+ /**
56
+ * Number of cached entries.
57
+ */
58
+ size() {
59
+ return this.cache.size;
60
+ }
61
+
62
+ /**
63
+ * List all cache keys.
64
+ */
65
+ keys() {
66
+ return [...this.cache.keys()];
67
+ }
68
+
69
+ /**
70
+ * Cache statistics.
71
+ */
72
+ stats() {
73
+ return {
74
+ entries: this.cache.size,
75
+ };
76
+ }
77
+ }
78
+
79
+ /**
80
+ * Factory.
81
+ */
82
+ export function createRetrievalCache() {
83
+ return new RetrievalCache();
84
+ }
@@ -0,0 +1,147 @@
1
+ /**
2
+ * packages/retrieval/embeddings.js
3
+ *
4
+ * Embedding provider abstraction and vector store.
5
+ */
6
+
7
+ /**
8
+ * Base embedding provider.
9
+ */
10
+ export class EmbeddingProvider {
11
+ async embed(_text) {
12
+ throw new Error("embed() not implemented");
13
+ }
14
+
15
+ async embedBatch(texts) {
16
+ return Promise.all(
17
+ texts.map(text => this.embed(text))
18
+ );
19
+ }
20
+ }
21
+
22
+ /**
23
+ * Normalize a vector.
24
+ */
25
+ export function normalizeVector(vector) {
26
+ const magnitude = Math.sqrt(
27
+ vector.reduce((sum, value) => sum + value * value, 0)
28
+ );
29
+
30
+ if (magnitude === 0) {
31
+ return [...vector];
32
+ }
33
+
34
+ return vector.map(value => value / magnitude);
35
+ }
36
+
37
+ /**
38
+ * In-memory embedding store.
39
+ */
40
+ export class EmbeddingStore {
41
+ constructor() {
42
+ this.clear();
43
+ }
44
+
45
+ clear() {
46
+ this.vectors = new Map();
47
+ }
48
+
49
+ set(key, embedding, metadata = {}) {
50
+ this.vectors.set(key, {
51
+ embedding: normalizeVector(embedding),
52
+ metadata,
53
+ createdAt: Date.now(),
54
+ });
55
+ }
56
+
57
+ setMany(entries) {
58
+ for (const entry of entries) {
59
+ this.set(
60
+ entry.key,
61
+ entry.embedding,
62
+ entry.metadata
63
+ );
64
+ }
65
+ }
66
+
67
+ get(key) {
68
+ return this.vectors.get(key) ?? null;
69
+ }
70
+
71
+ has(key) {
72
+ return this.vectors.has(key);
73
+ }
74
+
75
+ delete(key) {
76
+ return this.vectors.delete(key);
77
+ }
78
+
79
+ entries() {
80
+ return [...this.vectors.entries()];
81
+ }
82
+
83
+ size() {
84
+ return this.vectors.size;
85
+ }
86
+
87
+ stats() {
88
+ return {
89
+ vectors: this.vectors.size,
90
+ };
91
+ }
92
+ }
93
+
94
+ /**
95
+ * Cosine similarity.
96
+ */
97
+ export function cosineSimilarity(a, b) {
98
+ if (
99
+ !Array.isArray(a) ||
100
+ !Array.isArray(b) ||
101
+ a.length !== b.length ||
102
+ a.length === 0
103
+ ) {
104
+ return 0;
105
+ }
106
+
107
+ let dot = 0;
108
+
109
+ let magA = 0;
110
+ let magB = 0;
111
+
112
+ for (let i = 0; i < a.length; i++) {
113
+ dot += a[i] * b[i];
114
+ magA += a[i] * a[i];
115
+ magB += b[i] * b[i];
116
+ }
117
+
118
+ if (magA === 0 || magB === 0) {
119
+ return 0;
120
+ }
121
+
122
+ return dot / (Math.sqrt(magA) * Math.sqrt(magB));
123
+ }
124
+
125
+ /**
126
+ * Search embeddings.
127
+ */
128
+ export function searchEmbeddings(queryVector, store) {
129
+ const query = normalizeVector(queryVector);
130
+
131
+ return store
132
+ .entries()
133
+ .map(([key, value]) => ({
134
+ key,
135
+ score: cosineSimilarity(
136
+ query,
137
+ value.embedding
138
+ ),
139
+ metadata: value.metadata,
140
+ }))
141
+ .sort((a, b) => b.score - a.score);
142
+ }
143
+
144
+ /**
145
+ * Default singleton store.
146
+ */
147
+ export const embeddingStore = new EmbeddingStore();
@@ -0,0 +1,151 @@
1
+ /**
2
+ * packages/retrieval/graph.js
3
+ *
4
+ * Repository dependency graph.
5
+ */
6
+
7
+ export class RepositoryGraph {
8
+ constructor() {
9
+ this.clear();
10
+ }
11
+
12
+ clear() {
13
+ this.files = new Map();
14
+
15
+ // Graph edges
16
+ this.dependencies = new Map();
17
+ this.dependents = new Map();
18
+
19
+ // External indexes
20
+ this.symbolIndex = null;
21
+ this.importIndex = null;
22
+ }
23
+
24
+ /**
25
+ * Build graph from repository indexes.
26
+ */
27
+ build(repository, symbolIndex, importIndex) {
28
+ this.clear();
29
+
30
+ this.symbolIndex = symbolIndex;
31
+ this.importIndex = importIndex;
32
+
33
+ const files = repository.files ?? repository;
34
+
35
+ for (const file of files) {
36
+ this.addFile(file);
37
+ }
38
+
39
+ return this;
40
+ }
41
+
42
+ /**
43
+ * Add one parsed file.
44
+ */
45
+ addFile(parsedFile) {
46
+ this.files.set(parsedFile.path, parsedFile);
47
+
48
+ const edges = new Set();
49
+
50
+ const imports = this.importIndex?.file(parsedFile.path) ?? [];
51
+
52
+ for (const imp of imports) {
53
+ edges.add(imp.source);
54
+
55
+ if (!this.dependents.has(imp.source)) {
56
+ this.dependents.set(imp.source, new Set());
57
+ }
58
+
59
+ this.dependents
60
+ .get(imp.source)
61
+ .add(parsedFile.path);
62
+ }
63
+
64
+ this.dependencies.set(parsedFile.path, edges);
65
+ }
66
+
67
+ /**
68
+ * Lookup a parsed file.
69
+ */
70
+ getFile(path) {
71
+ return this.files.get(path) ?? null;
72
+ }
73
+
74
+ /**
75
+ * All parsed files.
76
+ */
77
+ getFiles() {
78
+ return [...this.files.values()];
79
+ }
80
+
81
+ /**
82
+ * File dependencies.
83
+ */
84
+ getDependencies(path) {
85
+ return [...(this.dependencies.get(path) ?? [])];
86
+ }
87
+
88
+ /**
89
+ * Reverse dependencies.
90
+ */
91
+ getDependents(module) {
92
+ return [...(this.dependents.get(module) ?? [])];
93
+ }
94
+
95
+ /**
96
+ * Symbol lookup.
97
+ *
98
+ * Delegates to SymbolIndex.
99
+ */
100
+ findSymbol(name) {
101
+ return this.symbolIndex?.find(name) ?? [];
102
+ }
103
+
104
+ /**
105
+ * File exists.
106
+ */
107
+ hasFile(path) {
108
+ return this.files.has(path);
109
+ }
110
+
111
+ /**
112
+ * Repository statistics.
113
+ */
114
+ stats() {
115
+ let edgeCount = 0;
116
+
117
+ for (const deps of this.dependencies.values()) {
118
+ edgeCount += deps.size;
119
+ }
120
+
121
+ return {
122
+ files: this.files.size,
123
+ edges: edgeCount,
124
+ symbols: this.symbolIndex?.stats().total ?? 0,
125
+ modules: this.importIndex?.stats().modules ?? 0,
126
+ };
127
+ }
128
+
129
+ fileCount() {
130
+ return this.files.size;
131
+ }
132
+
133
+ symbolCount() {
134
+ return this.symbolIndex?.stats().total ?? 0;
135
+ }
136
+ }
137
+
138
+ /**
139
+ * Convenience builder.
140
+ */
141
+ export function buildRepositoryGraph(
142
+ repository,
143
+ symbolIndex,
144
+ importIndex
145
+ ) {
146
+ return new RepositoryGraph().build(
147
+ repository,
148
+ symbolIndex,
149
+ importIndex
150
+ );
151
+ }
@@ -0,0 +1,74 @@
1
+ /**
2
+ * packages/retrieval/imports.js
3
+ *
4
+ * Repository-wide import index.
5
+ */
6
+
7
+ export class ImportIndex {
8
+ constructor() {
9
+ this.clear();
10
+ }
11
+
12
+ clear() {
13
+ this.byFile = new Map();
14
+ this.bySource = new Map();
15
+ }
16
+
17
+ add(file, imp) {
18
+ if (!this.byFile.has(file)) {
19
+ this.byFile.set(file, []);
20
+ }
21
+
22
+ this.byFile.get(file).push(imp);
23
+
24
+ if (!this.bySource.has(imp.source)) {
25
+ this.bySource.set(imp.source, []);
26
+ }
27
+
28
+ this.bySource.get(imp.source).push({
29
+ file,
30
+ import: imp,
31
+ });
32
+ }
33
+
34
+ addFile(parsedFile) {
35
+ if (!parsedFile?.imports) {
36
+ return;
37
+ }
38
+
39
+ for (const imp of parsedFile.imports) {
40
+ this.add(parsedFile.path, imp);
41
+ }
42
+ }
43
+
44
+ build(repository) {
45
+ this.clear();
46
+
47
+ const files = repository.files ?? repository;
48
+
49
+ for (const file of files) {
50
+ this.addFile(file);
51
+ }
52
+
53
+ return this;
54
+ }
55
+
56
+ file(path) {
57
+ return this.byFile.get(path) ?? [];
58
+ }
59
+
60
+ source(module) {
61
+ return this.bySource.get(module) ?? [];
62
+ }
63
+
64
+ stats() {
65
+ return {
66
+ files: this.byFile.size,
67
+ modules: this.bySource.size,
68
+ };
69
+ }
70
+ }
71
+
72
+ export function buildImportIndex(repository) {
73
+ return new ImportIndex().build(repository);
74
+ }
@@ -0,0 +1,9 @@
1
+ export * from "./budget.js";
2
+ export * from "./cache.js";
3
+ export * from "./embeddings.js";
4
+ export * from "./graph.js";
5
+ export * from "./imports.js";
6
+ export * from "./parser.js";
7
+ export * from "./ranker.js";
8
+ export * from "./retriever.js";
9
+ export * from "./symbols.js";
@@ -0,0 +1,43 @@
1
+ /**
2
+ * packages/retrieval/parser/extractors/calls.js
3
+ */
4
+
5
+ import {
6
+ iterateCaptures,
7
+ getNodeLocation,
8
+ getNodeText,
9
+ } from "../helpers.js";
10
+
11
+ import { createCall } from "../types.js";
12
+
13
+ export default function extractCalls({
14
+ query,
15
+ tree,
16
+ source,
17
+ }) {
18
+ const calls = [];
19
+
20
+ if (!query) {
21
+ return calls;
22
+ }
23
+
24
+ for (const { node, name } of iterateCaptures(query, tree)) {
25
+ calls.push(
26
+ createCall({
27
+ // Query should capture the called identifier/member.
28
+ name: node.text,
29
+
30
+ // e.g. call.function, call.method, call.constructor
31
+ kind: name.replace(/^call\./, ""),
32
+
33
+ location: getNodeLocation(node),
34
+
35
+ metadata: {
36
+ text: getNodeText(node, source),
37
+ },
38
+ })
39
+ );
40
+ }
41
+
42
+ return calls;
43
+ }
@@ -0,0 +1,49 @@
1
+ /**
2
+ * packages/retrieval/parser/extractors/comments.js
3
+ */
4
+
5
+ import {
6
+ iterateCaptures,
7
+ getNodeLocation,
8
+ getNodeText,
9
+ } from "../helpers.js";
10
+
11
+ import { createComment } from "../types.js";
12
+
13
+ export default function extractComments({
14
+ query,
15
+ tree,
16
+ source,
17
+ }) {
18
+ const comments = [];
19
+
20
+ if (!query) {
21
+ return comments;
22
+ }
23
+
24
+ for (const { node } of iterateCaptures(query, tree)) {
25
+ const text = getNodeText(node, source);
26
+
27
+ comments.push(
28
+ createComment({
29
+ text,
30
+
31
+ block: text.startsWith("/*"),
32
+
33
+ documentation:
34
+ text.startsWith("/**") ||
35
+ text.startsWith("///"),
36
+
37
+ line: node.startPosition.row + 1,
38
+
39
+ metadata: {
40
+ raw: text,
41
+ },
42
+
43
+ location: getNodeLocation(node),
44
+ })
45
+ );
46
+ }
47
+
48
+ return comments;
49
+ }
@@ -0,0 +1,21 @@
1
+ /**
2
+ * packages/retrieval/parser/extractors/diagnostics.js
3
+ */
4
+
5
+ import { createDiagnostic } from "../types.js";
6
+
7
+ export default function extractDiagnostics({
8
+ tree,
9
+ }) {
10
+ if (!tree.rootNode.hasError) {
11
+ return [];
12
+ }
13
+
14
+ return [
15
+ createDiagnostic({
16
+ severity: "error",
17
+ type: "syntax",
18
+ message: "Tree-sitter detected syntax errors.",
19
+ }),
20
+ ];
21
+ }