bluera-knowledge 0.9.32 → 0.9.34
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/.claude/hooks/post-edit-check.sh +5 -3
- package/.claude/skills/atomic-commits/SKILL.md +3 -1
- package/.husky/pre-commit +3 -2
- package/.prettierrc +9 -0
- package/.versionrc.json +1 -1
- package/CHANGELOG.md +33 -0
- package/CLAUDE.md +6 -0
- package/README.md +25 -13
- package/bun.lock +277 -33
- package/dist/{chunk-L2YVNC63.js → chunk-6FHWC36B.js} +9 -1
- package/dist/chunk-6FHWC36B.js.map +1 -0
- package/dist/{chunk-RST4XGRL.js → chunk-DC7CGSGT.js} +288 -241
- package/dist/chunk-DC7CGSGT.js.map +1 -0
- package/dist/{chunk-6PBP5DVD.js → chunk-WFNPNAAP.js} +3212 -3054
- package/dist/chunk-WFNPNAAP.js.map +1 -0
- package/dist/{chunk-WT2DAEO7.js → chunk-Z2KKVH45.js} +548 -482
- package/dist/chunk-Z2KKVH45.js.map +1 -0
- package/dist/index.js +871 -758
- package/dist/index.js.map +1 -1
- package/dist/mcp/server.js +3 -3
- package/dist/watch.service-BJV3TI3F.js +7 -0
- package/dist/workers/background-worker-cli.js +46 -45
- package/dist/workers/background-worker-cli.js.map +1 -1
- package/eslint.config.js +43 -1
- package/package.json +18 -11
- package/plugin.json +8 -0
- package/python/requirements.txt +1 -1
- package/src/analysis/ast-parser.test.ts +12 -11
- package/src/analysis/ast-parser.ts +28 -22
- package/src/analysis/code-graph.test.ts +52 -62
- package/src/analysis/code-graph.ts +9 -13
- package/src/analysis/dependency-usage-analyzer.test.ts +91 -271
- package/src/analysis/dependency-usage-analyzer.ts +52 -24
- package/src/analysis/go-ast-parser.test.ts +22 -22
- package/src/analysis/go-ast-parser.ts +18 -25
- package/src/analysis/parser-factory.test.ts +9 -9
- package/src/analysis/parser-factory.ts +3 -3
- package/src/analysis/python-ast-parser.test.ts +27 -27
- package/src/analysis/python-ast-parser.ts +2 -2
- package/src/analysis/repo-url-resolver.test.ts +82 -82
- package/src/analysis/rust-ast-parser.test.ts +19 -19
- package/src/analysis/rust-ast-parser.ts +17 -27
- package/src/analysis/tree-sitter-parser.test.ts +3 -3
- package/src/analysis/tree-sitter-parser.ts +10 -16
- package/src/cli/commands/crawl.test.ts +40 -24
- package/src/cli/commands/crawl.ts +186 -166
- package/src/cli/commands/index-cmd.test.ts +90 -90
- package/src/cli/commands/index-cmd.ts +52 -36
- package/src/cli/commands/mcp.test.ts +6 -6
- package/src/cli/commands/mcp.ts +2 -2
- package/src/cli/commands/plugin-api.test.ts +16 -18
- package/src/cli/commands/plugin-api.ts +9 -6
- package/src/cli/commands/search.test.ts +16 -7
- package/src/cli/commands/search.ts +124 -87
- package/src/cli/commands/serve.test.ts +67 -25
- package/src/cli/commands/serve.ts +18 -3
- package/src/cli/commands/setup.test.ts +176 -101
- package/src/cli/commands/setup.ts +140 -117
- package/src/cli/commands/store.test.ts +82 -53
- package/src/cli/commands/store.ts +56 -37
- package/src/cli/program.ts +2 -2
- package/src/crawl/article-converter.test.ts +4 -1
- package/src/crawl/article-converter.ts +46 -31
- package/src/crawl/bridge.test.ts +240 -132
- package/src/crawl/bridge.ts +87 -30
- package/src/crawl/claude-client.test.ts +124 -56
- package/src/crawl/claude-client.ts +7 -15
- package/src/crawl/intelligent-crawler.test.ts +65 -22
- package/src/crawl/intelligent-crawler.ts +86 -53
- package/src/crawl/markdown-utils.ts +1 -4
- package/src/db/embeddings.ts +4 -6
- package/src/db/lance.test.ts +4 -4
- package/src/db/lance.ts +16 -12
- package/src/index.ts +26 -17
- package/src/logging/index.ts +1 -5
- package/src/logging/logger.ts +3 -5
- package/src/logging/payload.test.ts +1 -1
- package/src/logging/payload.ts +3 -5
- package/src/mcp/commands/index.ts +2 -2
- package/src/mcp/commands/job.commands.ts +12 -18
- package/src/mcp/commands/meta.commands.ts +13 -13
- package/src/mcp/commands/registry.ts +5 -8
- package/src/mcp/commands/store.commands.ts +19 -19
- package/src/mcp/handlers/execute.handler.test.ts +10 -10
- package/src/mcp/handlers/execute.handler.ts +4 -5
- package/src/mcp/handlers/index.ts +10 -14
- package/src/mcp/handlers/job.handler.test.ts +10 -10
- package/src/mcp/handlers/job.handler.ts +22 -25
- package/src/mcp/handlers/search.handler.test.ts +36 -65
- package/src/mcp/handlers/search.handler.ts +135 -104
- package/src/mcp/handlers/store.handler.test.ts +41 -52
- package/src/mcp/handlers/store.handler.ts +108 -88
- package/src/mcp/schemas/index.test.ts +73 -68
- package/src/mcp/schemas/index.ts +18 -12
- package/src/mcp/server.test.ts +1 -1
- package/src/mcp/server.ts +59 -46
- package/src/plugin/commands.test.ts +230 -95
- package/src/plugin/commands.ts +24 -25
- package/src/plugin/dependency-analyzer.test.ts +52 -52
- package/src/plugin/dependency-analyzer.ts +85 -22
- package/src/plugin/git-clone.test.ts +24 -13
- package/src/plugin/git-clone.ts +3 -7
- package/src/server/app.test.ts +109 -109
- package/src/server/app.ts +32 -23
- package/src/server/index.test.ts +64 -66
- package/src/services/chunking.service.test.ts +32 -32
- package/src/services/chunking.service.ts +16 -9
- package/src/services/code-graph.service.test.ts +30 -36
- package/src/services/code-graph.service.ts +24 -10
- package/src/services/code-unit.service.test.ts +55 -11
- package/src/services/code-unit.service.ts +85 -11
- package/src/services/config.service.test.ts +37 -18
- package/src/services/config.service.ts +30 -7
- package/src/services/index.service.test.ts +49 -18
- package/src/services/index.service.ts +98 -48
- package/src/services/index.ts +6 -9
- package/src/services/job.service.test.ts +22 -22
- package/src/services/job.service.ts +18 -18
- package/src/services/project-root.service.test.ts +1 -3
- package/src/services/search.service.test.ts +248 -120
- package/src/services/search.service.ts +286 -156
- package/src/services/services.test.ts +1 -1
- package/src/services/snippet.service.test.ts +14 -6
- package/src/services/snippet.service.ts +7 -5
- package/src/services/store.service.test.ts +68 -29
- package/src/services/store.service.ts +41 -12
- package/src/services/watch.service.test.ts +34 -14
- package/src/services/watch.service.ts +11 -1
- package/src/types/brands.test.ts +3 -1
- package/src/types/index.ts +2 -13
- package/src/types/search.ts +10 -8
- package/src/utils/type-guards.test.ts +20 -15
- package/src/utils/type-guards.ts +1 -1
- package/src/workers/background-worker-cli.ts +2 -2
- package/src/workers/background-worker.test.ts +54 -40
- package/src/workers/background-worker.ts +76 -60
- package/src/workers/spawn-worker.test.ts +22 -10
- package/src/workers/spawn-worker.ts +6 -6
- package/tests/analysis/ast-parser.test.ts +3 -3
- package/tests/analysis/code-graph.test.ts +5 -5
- package/tests/fixtures/code-snippets/api/error-handling.ts +4 -15
- package/tests/fixtures/code-snippets/api/rest-controller.ts +3 -9
- package/tests/fixtures/code-snippets/auth/jwt-auth.ts +5 -21
- package/tests/fixtures/code-snippets/auth/oauth-flow.ts +4 -4
- package/tests/fixtures/code-snippets/database/repository-pattern.ts +11 -3
- package/tests/fixtures/corpus/oss-repos/hono/src/adapter/aws-lambda/handler.ts +2 -2
- package/tests/fixtures/corpus/oss-repos/hono/src/adapter/cloudflare-pages/handler.ts +1 -1
- package/tests/fixtures/corpus/oss-repos/hono/src/adapter/cloudflare-workers/serve-static.ts +2 -2
- package/tests/fixtures/corpus/oss-repos/hono/src/client/client.ts +2 -2
- package/tests/fixtures/corpus/oss-repos/hono/src/client/types.ts +22 -20
- package/tests/fixtures/corpus/oss-repos/hono/src/context.ts +13 -10
- package/tests/fixtures/corpus/oss-repos/hono/src/helper/accepts/accepts.ts +10 -7
- package/tests/fixtures/corpus/oss-repos/hono/src/helper/adapter/index.ts +2 -2
- package/tests/fixtures/corpus/oss-repos/hono/src/helper/css/index.ts +1 -1
- package/tests/fixtures/corpus/oss-repos/hono/src/helper/factory/index.ts +16 -16
- package/tests/fixtures/corpus/oss-repos/hono/src/helper/ssg/ssg.ts +2 -2
- package/tests/fixtures/corpus/oss-repos/hono/src/hono-base.ts +3 -3
- package/tests/fixtures/corpus/oss-repos/hono/src/hono.ts +1 -1
- package/tests/fixtures/corpus/oss-repos/hono/src/jsx/dom/css.ts +2 -2
- package/tests/fixtures/corpus/oss-repos/hono/src/jsx/dom/intrinsic-element/components.ts +1 -1
- package/tests/fixtures/corpus/oss-repos/hono/src/jsx/dom/render.ts +7 -7
- package/tests/fixtures/corpus/oss-repos/hono/src/jsx/hooks/index.ts +3 -3
- package/tests/fixtures/corpus/oss-repos/hono/src/jsx/intrinsic-element/components.ts +1 -1
- package/tests/fixtures/corpus/oss-repos/hono/src/jsx/utils.ts +6 -6
- package/tests/fixtures/corpus/oss-repos/hono/src/middleware/jsx-renderer/index.ts +3 -3
- package/tests/fixtures/corpus/oss-repos/hono/src/middleware/serve-static/index.ts +1 -1
- package/tests/fixtures/corpus/oss-repos/hono/src/preset/quick.ts +1 -1
- package/tests/fixtures/corpus/oss-repos/hono/src/preset/tiny.ts +1 -1
- package/tests/fixtures/corpus/oss-repos/hono/src/router/pattern-router/router.ts +2 -2
- package/tests/fixtures/corpus/oss-repos/hono/src/router/reg-exp-router/node.ts +4 -4
- package/tests/fixtures/corpus/oss-repos/hono/src/router/reg-exp-router/router.ts +1 -1
- package/tests/fixtures/corpus/oss-repos/hono/src/router/trie-router/node.ts +1 -1
- package/tests/fixtures/corpus/oss-repos/hono/src/types.ts +166 -169
- package/tests/fixtures/corpus/oss-repos/hono/src/utils/body.ts +8 -8
- package/tests/fixtures/corpus/oss-repos/hono/src/utils/color.ts +3 -3
- package/tests/fixtures/corpus/oss-repos/hono/src/utils/cookie.ts +2 -2
- package/tests/fixtures/corpus/oss-repos/hono/src/utils/encode.ts +2 -2
- package/tests/fixtures/corpus/oss-repos/hono/src/utils/types.ts +30 -33
- package/tests/fixtures/corpus/oss-repos/hono/src/validator/validator.ts +2 -2
- package/tests/fixtures/test-server.ts +3 -2
- package/tests/helpers/performance-metrics.ts +8 -25
- package/tests/helpers/search-relevance.ts +14 -69
- package/tests/integration/cli-consistency.test.ts +5 -4
- package/tests/integration/python-bridge.test.ts +13 -3
- package/tests/mcp/server.test.ts +1 -1
- package/tests/services/code-unit.service.test.ts +48 -0
- package/tests/services/job.service.test.ts +124 -0
- package/tests/services/search.progressive-context.test.ts +2 -2
- package/.claude-plugin/plugin.json +0 -13
- package/dist/chunk-6PBP5DVD.js.map +0 -1
- package/dist/chunk-L2YVNC63.js.map +0 -1
- package/dist/chunk-RST4XGRL.js.map +0 -1
- package/dist/chunk-WT2DAEO7.js.map +0 -1
- package/dist/watch.service-YAIKKDCF.js +0 -7
- package/skills/atomic-commits/SKILL.md +0 -77
- /package/dist/{watch.service-YAIKKDCF.js.map → watch.service-BJV3TI3F.js.map} +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { PythonBridge, ParsePythonResult } from '../crawl/bridge.js';
|
|
2
1
|
import type { CodeNode } from './ast-parser.js';
|
|
2
|
+
import type { PythonBridge, ParsePythonResult } from '../crawl/bridge.js';
|
|
3
3
|
|
|
4
4
|
export class PythonASTParser {
|
|
5
5
|
constructor(private readonly bridge: PythonBridge) {}
|
|
@@ -7,7 +7,7 @@ export class PythonASTParser {
|
|
|
7
7
|
async parse(code: string, filePath: string): Promise<CodeNode[]> {
|
|
8
8
|
const result: ParsePythonResult = await this.bridge.parsePython(code, filePath);
|
|
9
9
|
|
|
10
|
-
return result.nodes.map(node => {
|
|
10
|
+
return result.nodes.map((node) => {
|
|
11
11
|
const codeNode: CodeNode = {
|
|
12
12
|
type: node.type,
|
|
13
13
|
name: node.name,
|
|
@@ -21,9 +21,9 @@ describe('RepoUrlResolver', () => {
|
|
|
21
21
|
json: async () => ({
|
|
22
22
|
repository: {
|
|
23
23
|
type: 'git',
|
|
24
|
-
url: 'git+https://github.com/lodash/lodash.git'
|
|
25
|
-
}
|
|
26
|
-
})
|
|
24
|
+
url: 'git+https://github.com/lodash/lodash.git',
|
|
25
|
+
},
|
|
26
|
+
}),
|
|
27
27
|
} as Response);
|
|
28
28
|
|
|
29
29
|
const result = await resolver.findRepoUrl('lodash', 'javascript');
|
|
@@ -37,8 +37,8 @@ describe('RepoUrlResolver', () => {
|
|
|
37
37
|
vi.mocked(fetch).mockResolvedValueOnce({
|
|
38
38
|
ok: true,
|
|
39
39
|
json: async () => ({
|
|
40
|
-
repository: 'https://github.com/user/repo'
|
|
41
|
-
})
|
|
40
|
+
repository: 'https://github.com/user/repo',
|
|
41
|
+
}),
|
|
42
42
|
} as Response);
|
|
43
43
|
|
|
44
44
|
const result = await resolver.findRepoUrl('package', 'javascript');
|
|
@@ -50,7 +50,7 @@ describe('RepoUrlResolver', () => {
|
|
|
50
50
|
it('handles 404 from npm registry', async () => {
|
|
51
51
|
vi.mocked(fetch).mockResolvedValueOnce({
|
|
52
52
|
ok: false,
|
|
53
|
-
status: 404
|
|
53
|
+
status: 404,
|
|
54
54
|
} as Response);
|
|
55
55
|
|
|
56
56
|
const result = await resolver.findRepoUrl('nonexistent', 'javascript');
|
|
@@ -73,7 +73,7 @@ describe('RepoUrlResolver', () => {
|
|
|
73
73
|
ok: true,
|
|
74
74
|
json: async () => {
|
|
75
75
|
throw new Error('Invalid JSON');
|
|
76
|
-
}
|
|
76
|
+
},
|
|
77
77
|
} as Response);
|
|
78
78
|
|
|
79
79
|
const result = await resolver.findRepoUrl('package', 'javascript');
|
|
@@ -86,8 +86,8 @@ describe('RepoUrlResolver', () => {
|
|
|
86
86
|
ok: true,
|
|
87
87
|
json: async () => ({
|
|
88
88
|
name: 'package',
|
|
89
|
-
version: '1.0.0'
|
|
90
|
-
})
|
|
89
|
+
version: '1.0.0',
|
|
90
|
+
}),
|
|
91
91
|
} as Response);
|
|
92
92
|
|
|
93
93
|
const result = await resolver.findRepoUrl('package', 'javascript');
|
|
@@ -103,10 +103,10 @@ describe('RepoUrlResolver', () => {
|
|
|
103
103
|
json: async () => ({
|
|
104
104
|
info: {
|
|
105
105
|
project_urls: {
|
|
106
|
-
Source: 'https://github.com/psf/requests'
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
})
|
|
106
|
+
Source: 'https://github.com/psf/requests',
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
}),
|
|
110
110
|
} as Response);
|
|
111
111
|
|
|
112
112
|
const result = await resolver.findRepoUrl('requests', 'python');
|
|
@@ -123,10 +123,10 @@ describe('RepoUrlResolver', () => {
|
|
|
123
123
|
info: {
|
|
124
124
|
project_urls: {
|
|
125
125
|
Homepage: 'https://example.com',
|
|
126
|
-
Repository: 'https://github.com/user/repo'
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
})
|
|
126
|
+
Repository: 'https://github.com/user/repo',
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
}),
|
|
130
130
|
} as Response);
|
|
131
131
|
|
|
132
132
|
const result = await resolver.findRepoUrl('package', 'python');
|
|
@@ -141,10 +141,10 @@ describe('RepoUrlResolver', () => {
|
|
|
141
141
|
info: {
|
|
142
142
|
project_urls: {
|
|
143
143
|
Source: 'https://github.com/owner/repo1',
|
|
144
|
-
Code: 'https://github.com/owner/repo2'
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
})
|
|
144
|
+
Code: 'https://github.com/owner/repo2',
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
}),
|
|
148
148
|
} as Response);
|
|
149
149
|
|
|
150
150
|
const result = await resolver.findRepoUrl('package', 'python');
|
|
@@ -158,10 +158,10 @@ describe('RepoUrlResolver', () => {
|
|
|
158
158
|
json: async () => ({
|
|
159
159
|
info: {
|
|
160
160
|
project_urls: {
|
|
161
|
-
Source: 'https://gitlab.com/user/repo'
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
})
|
|
161
|
+
Source: 'https://gitlab.com/user/repo',
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
}),
|
|
165
165
|
} as Response);
|
|
166
166
|
|
|
167
167
|
const result = await resolver.findRepoUrl('package', 'python');
|
|
@@ -172,7 +172,7 @@ describe('RepoUrlResolver', () => {
|
|
|
172
172
|
it('handles 404 from PyPI', async () => {
|
|
173
173
|
vi.mocked(fetch).mockResolvedValueOnce({
|
|
174
174
|
ok: false,
|
|
175
|
-
status: 404
|
|
175
|
+
status: 404,
|
|
176
176
|
} as Response);
|
|
177
177
|
|
|
178
178
|
const result = await resolver.findRepoUrl('nonexistent', 'python');
|
|
@@ -185,9 +185,9 @@ describe('RepoUrlResolver', () => {
|
|
|
185
185
|
ok: true,
|
|
186
186
|
json: async () => ({
|
|
187
187
|
info: {
|
|
188
|
-
name: 'package'
|
|
189
|
-
}
|
|
190
|
-
})
|
|
188
|
+
name: 'package',
|
|
189
|
+
},
|
|
190
|
+
}),
|
|
191
191
|
} as Response);
|
|
192
192
|
|
|
193
193
|
const result = await resolver.findRepoUrl('package', 'python');
|
|
@@ -202,9 +202,9 @@ describe('RepoUrlResolver', () => {
|
|
|
202
202
|
ok: true,
|
|
203
203
|
json: async () => ({
|
|
204
204
|
repository: {
|
|
205
|
-
url: 'git+https://github.com/user/repo.git'
|
|
206
|
-
}
|
|
207
|
-
})
|
|
205
|
+
url: 'git+https://github.com/user/repo.git',
|
|
206
|
+
},
|
|
207
|
+
}),
|
|
208
208
|
} as Response);
|
|
209
209
|
|
|
210
210
|
const result = await resolver.findRepoUrl('package', 'javascript');
|
|
@@ -217,9 +217,9 @@ describe('RepoUrlResolver', () => {
|
|
|
217
217
|
ok: true,
|
|
218
218
|
json: async () => ({
|
|
219
219
|
repository: {
|
|
220
|
-
url: 'https://github.com/user/repo.git'
|
|
221
|
-
}
|
|
222
|
-
})
|
|
220
|
+
url: 'https://github.com/user/repo.git',
|
|
221
|
+
},
|
|
222
|
+
}),
|
|
223
223
|
} as Response);
|
|
224
224
|
|
|
225
225
|
const result = await resolver.findRepoUrl('package', 'javascript');
|
|
@@ -232,9 +232,9 @@ describe('RepoUrlResolver', () => {
|
|
|
232
232
|
ok: true,
|
|
233
233
|
json: async () => ({
|
|
234
234
|
repository: {
|
|
235
|
-
url: 'git://github.com/user/repo.git'
|
|
236
|
-
}
|
|
237
|
-
})
|
|
235
|
+
url: 'git://github.com/user/repo.git',
|
|
236
|
+
},
|
|
237
|
+
}),
|
|
238
238
|
} as Response);
|
|
239
239
|
|
|
240
240
|
const result = await resolver.findRepoUrl('package', 'javascript');
|
|
@@ -247,9 +247,9 @@ describe('RepoUrlResolver', () => {
|
|
|
247
247
|
ok: true,
|
|
248
248
|
json: async () => ({
|
|
249
249
|
repository: {
|
|
250
|
-
url: 'ssh://git@github.com/user/repo.git'
|
|
251
|
-
}
|
|
252
|
-
})
|
|
250
|
+
url: 'ssh://git@github.com/user/repo.git',
|
|
251
|
+
},
|
|
252
|
+
}),
|
|
253
253
|
} as Response);
|
|
254
254
|
|
|
255
255
|
const result = await resolver.findRepoUrl('package', 'javascript');
|
|
@@ -262,9 +262,9 @@ describe('RepoUrlResolver', () => {
|
|
|
262
262
|
ok: true,
|
|
263
263
|
json: async () => ({
|
|
264
264
|
repository: {
|
|
265
|
-
url: 'git@github.com:user/repo.git'
|
|
266
|
-
}
|
|
267
|
-
})
|
|
265
|
+
url: 'git@github.com:user/repo.git',
|
|
266
|
+
},
|
|
267
|
+
}),
|
|
268
268
|
} as Response);
|
|
269
269
|
|
|
270
270
|
const result = await resolver.findRepoUrl('package', 'javascript');
|
|
@@ -277,9 +277,9 @@ describe('RepoUrlResolver', () => {
|
|
|
277
277
|
ok: true,
|
|
278
278
|
json: async () => ({
|
|
279
279
|
repository: {
|
|
280
|
-
url: 'https://bitbucket.org/user/repo'
|
|
281
|
-
}
|
|
282
|
-
})
|
|
280
|
+
url: 'https://bitbucket.org/user/repo',
|
|
281
|
+
},
|
|
282
|
+
}),
|
|
283
283
|
} as Response);
|
|
284
284
|
|
|
285
285
|
const result = await resolver.findRepoUrl('package', 'javascript');
|
|
@@ -292,9 +292,9 @@ describe('RepoUrlResolver', () => {
|
|
|
292
292
|
ok: true,
|
|
293
293
|
json: async () => ({
|
|
294
294
|
repository: {
|
|
295
|
-
url: 'https://github.com/user/repo'
|
|
296
|
-
}
|
|
297
|
-
})
|
|
295
|
+
url: 'https://github.com/user/repo',
|
|
296
|
+
},
|
|
297
|
+
}),
|
|
298
298
|
} as Response);
|
|
299
299
|
|
|
300
300
|
const result = await resolver.findRepoUrl('package', 'javascript');
|
|
@@ -309,9 +309,9 @@ describe('RepoUrlResolver', () => {
|
|
|
309
309
|
ok: true,
|
|
310
310
|
json: async () => ({
|
|
311
311
|
crate: {
|
|
312
|
-
repository: 'https://github.com/serde-rs/serde'
|
|
313
|
-
}
|
|
314
|
-
})
|
|
312
|
+
repository: 'https://github.com/serde-rs/serde',
|
|
313
|
+
},
|
|
314
|
+
}),
|
|
315
315
|
} as Response);
|
|
316
316
|
|
|
317
317
|
const result = await resolver.findRepoUrl('serde', 'rust');
|
|
@@ -326,9 +326,9 @@ describe('RepoUrlResolver', () => {
|
|
|
326
326
|
ok: true,
|
|
327
327
|
json: async () => ({
|
|
328
328
|
crate: {
|
|
329
|
-
repository: 'https://github.com/user/repo'
|
|
330
|
-
}
|
|
331
|
-
})
|
|
329
|
+
repository: 'https://github.com/user/repo',
|
|
330
|
+
},
|
|
331
|
+
}),
|
|
332
332
|
} as Response);
|
|
333
333
|
|
|
334
334
|
await resolver.findRepoUrl('tokio', 'rust');
|
|
@@ -337,8 +337,8 @@ describe('RepoUrlResolver', () => {
|
|
|
337
337
|
'https://crates.io/api/v1/crates/tokio',
|
|
338
338
|
expect.objectContaining({
|
|
339
339
|
headers: expect.objectContaining({
|
|
340
|
-
'User-Agent': expect.stringContaining('bluera-knowledge')
|
|
341
|
-
})
|
|
340
|
+
'User-Agent': expect.stringContaining('bluera-knowledge'),
|
|
341
|
+
}),
|
|
342
342
|
})
|
|
343
343
|
);
|
|
344
344
|
});
|
|
@@ -346,7 +346,7 @@ describe('RepoUrlResolver', () => {
|
|
|
346
346
|
it('handles 404 from crates.io', async () => {
|
|
347
347
|
vi.mocked(fetch).mockResolvedValueOnce({
|
|
348
348
|
ok: false,
|
|
349
|
-
status: 404
|
|
349
|
+
status: 404,
|
|
350
350
|
} as Response);
|
|
351
351
|
|
|
352
352
|
const result = await resolver.findRepoUrl('nonexistent-crate', 'rust');
|
|
@@ -361,9 +361,9 @@ describe('RepoUrlResolver', () => {
|
|
|
361
361
|
json: async () => ({
|
|
362
362
|
crate: {
|
|
363
363
|
name: 'some-crate',
|
|
364
|
-
version: '1.0.0'
|
|
365
|
-
}
|
|
366
|
-
})
|
|
364
|
+
version: '1.0.0',
|
|
365
|
+
},
|
|
366
|
+
}),
|
|
367
367
|
} as Response);
|
|
368
368
|
|
|
369
369
|
const result = await resolver.findRepoUrl('some-crate', 'rust');
|
|
@@ -376,9 +376,9 @@ describe('RepoUrlResolver', () => {
|
|
|
376
376
|
ok: true,
|
|
377
377
|
json: async () => ({
|
|
378
378
|
crate: {
|
|
379
|
-
repository: 'git+https://github.com/user/repo.git'
|
|
380
|
-
}
|
|
381
|
-
})
|
|
379
|
+
repository: 'git+https://github.com/user/repo.git',
|
|
380
|
+
},
|
|
381
|
+
}),
|
|
382
382
|
} as Response);
|
|
383
383
|
|
|
384
384
|
const result = await resolver.findRepoUrl('crate', 'rust');
|
|
@@ -415,7 +415,7 @@ describe('RepoUrlResolver', () => {
|
|
|
415
415
|
it('returns null for non-github modules when proxy fails', async () => {
|
|
416
416
|
vi.mocked(fetch).mockResolvedValueOnce({
|
|
417
417
|
ok: false,
|
|
418
|
-
status: 404
|
|
418
|
+
status: 404,
|
|
419
419
|
} as Response);
|
|
420
420
|
|
|
421
421
|
const result = await resolver.findRepoUrl('golang.org/x/net', 'go');
|
|
@@ -438,9 +438,9 @@ describe('RepoUrlResolver', () => {
|
|
|
438
438
|
ok: true,
|
|
439
439
|
json: async () => ({
|
|
440
440
|
repository: {
|
|
441
|
-
url: 'https://github.com/org/package'
|
|
442
|
-
}
|
|
443
|
-
})
|
|
441
|
+
url: 'https://github.com/org/package',
|
|
442
|
+
},
|
|
443
|
+
}),
|
|
444
444
|
} as Response);
|
|
445
445
|
|
|
446
446
|
const result = await resolver.findRepoUrl('@org/package', 'javascript');
|
|
@@ -454,9 +454,9 @@ describe('RepoUrlResolver', () => {
|
|
|
454
454
|
ok: true,
|
|
455
455
|
json: async () => ({
|
|
456
456
|
repository: {
|
|
457
|
-
url: 'https://github.com/user/my-package'
|
|
458
|
-
}
|
|
459
|
-
})
|
|
457
|
+
url: 'https://github.com/user/my-package',
|
|
458
|
+
},
|
|
459
|
+
}),
|
|
460
460
|
} as Response);
|
|
461
461
|
|
|
462
462
|
const result = await resolver.findRepoUrl('my-package', 'javascript');
|
|
@@ -467,7 +467,7 @@ describe('RepoUrlResolver', () => {
|
|
|
467
467
|
it('handles empty response body', async () => {
|
|
468
468
|
vi.mocked(fetch).mockResolvedValueOnce({
|
|
469
469
|
ok: true,
|
|
470
|
-
json: async () => null
|
|
470
|
+
json: async () => null,
|
|
471
471
|
} as Response);
|
|
472
472
|
|
|
473
473
|
const result = await resolver.findRepoUrl('package', 'javascript');
|
|
@@ -479,8 +479,8 @@ describe('RepoUrlResolver', () => {
|
|
|
479
479
|
vi.mocked(fetch).mockResolvedValueOnce({
|
|
480
480
|
ok: true,
|
|
481
481
|
json: async () => ({
|
|
482
|
-
repository: []
|
|
483
|
-
})
|
|
482
|
+
repository: [],
|
|
483
|
+
}),
|
|
484
484
|
} as Response);
|
|
485
485
|
|
|
486
486
|
const result = await resolver.findRepoUrl('package', 'javascript');
|
|
@@ -493,9 +493,9 @@ describe('RepoUrlResolver', () => {
|
|
|
493
493
|
ok: true,
|
|
494
494
|
json: async () => ({
|
|
495
495
|
repository: {
|
|
496
|
-
url: null
|
|
497
|
-
}
|
|
498
|
-
})
|
|
496
|
+
url: null,
|
|
497
|
+
},
|
|
498
|
+
}),
|
|
499
499
|
} as Response);
|
|
500
500
|
|
|
501
501
|
const result = await resolver.findRepoUrl('package', 'javascript');
|
|
@@ -508,9 +508,9 @@ describe('RepoUrlResolver', () => {
|
|
|
508
508
|
ok: true,
|
|
509
509
|
json: async () => ({
|
|
510
510
|
repository: {
|
|
511
|
-
url: undefined
|
|
512
|
-
}
|
|
513
|
-
})
|
|
511
|
+
url: undefined,
|
|
512
|
+
},
|
|
513
|
+
}),
|
|
514
514
|
} as Response);
|
|
515
515
|
|
|
516
516
|
const result = await resolver.findRepoUrl('package', 'javascript');
|
|
@@ -521,7 +521,7 @@ describe('RepoUrlResolver', () => {
|
|
|
521
521
|
it('uses fallback when all strategies fail', async () => {
|
|
522
522
|
vi.mocked(fetch).mockResolvedValueOnce({
|
|
523
523
|
ok: false,
|
|
524
|
-
status: 500
|
|
524
|
+
status: 500,
|
|
525
525
|
} as Response);
|
|
526
526
|
|
|
527
527
|
const result = await resolver.findRepoUrl('package', 'javascript');
|
|
@@ -14,7 +14,7 @@ describe('RustASTParser', () => {
|
|
|
14
14
|
type: 'function',
|
|
15
15
|
name: 'hello',
|
|
16
16
|
exported: false,
|
|
17
|
-
async: false
|
|
17
|
+
async: false,
|
|
18
18
|
});
|
|
19
19
|
expect(nodes[0]?.signature).toContain('hello');
|
|
20
20
|
});
|
|
@@ -81,9 +81,9 @@ pub fn third() -> i32 { 3 }
|
|
|
81
81
|
`.trim();
|
|
82
82
|
const nodes = parser.parse(code, 'test.rs');
|
|
83
83
|
|
|
84
|
-
const functions = nodes.filter(n => n.type === 'function');
|
|
84
|
+
const functions = nodes.filter((n) => n.type === 'function');
|
|
85
85
|
expect(functions).toHaveLength(3);
|
|
86
|
-
expect(functions.map(f => f.name)).toEqual(['first', 'second', 'third']);
|
|
86
|
+
expect(functions.map((f) => f.name)).toEqual(['first', 'second', 'third']);
|
|
87
87
|
expect(functions[2]?.exported).toBe(true);
|
|
88
88
|
});
|
|
89
89
|
});
|
|
@@ -97,7 +97,7 @@ pub fn third() -> i32 { 3 }
|
|
|
97
97
|
expect(nodes[0]).toMatchObject({
|
|
98
98
|
type: 'class',
|
|
99
99
|
name: 'User',
|
|
100
|
-
exported: false
|
|
100
|
+
exported: false,
|
|
101
101
|
});
|
|
102
102
|
});
|
|
103
103
|
|
|
@@ -157,7 +157,7 @@ struct Data {
|
|
|
157
157
|
expect(nodes[0]).toMatchObject({
|
|
158
158
|
type: 'interface',
|
|
159
159
|
name: 'Drawable',
|
|
160
|
-
exported: false
|
|
160
|
+
exported: false,
|
|
161
161
|
});
|
|
162
162
|
expect(nodes[0]?.methods).toBeDefined();
|
|
163
163
|
});
|
|
@@ -210,7 +210,7 @@ trait Animal {
|
|
|
210
210
|
expect(nodes[0]).toMatchObject({
|
|
211
211
|
type: 'type',
|
|
212
212
|
name: 'Result',
|
|
213
|
-
exported: false
|
|
213
|
+
exported: false,
|
|
214
214
|
});
|
|
215
215
|
expect(nodes[0]?.signature).toContain('Result');
|
|
216
216
|
});
|
|
@@ -240,7 +240,7 @@ trait Animal {
|
|
|
240
240
|
expect(nodes[0]).toMatchObject({
|
|
241
241
|
type: 'const',
|
|
242
242
|
name: 'MAX_SIZE',
|
|
243
|
-
exported: false
|
|
243
|
+
exported: false,
|
|
244
244
|
});
|
|
245
245
|
expect(nodes[0]?.signature).toContain('usize');
|
|
246
246
|
});
|
|
@@ -259,7 +259,7 @@ trait Animal {
|
|
|
259
259
|
|
|
260
260
|
expect(nodes[0]).toMatchObject({
|
|
261
261
|
type: 'const',
|
|
262
|
-
name: 'COUNTER'
|
|
262
|
+
name: 'COUNTER',
|
|
263
263
|
});
|
|
264
264
|
});
|
|
265
265
|
|
|
@@ -289,7 +289,7 @@ impl User {
|
|
|
289
289
|
`.trim();
|
|
290
290
|
const nodes = parser.parse(code, 'test.rs');
|
|
291
291
|
|
|
292
|
-
const userStruct = nodes.find(n => n.name === 'User');
|
|
292
|
+
const userStruct = nodes.find((n) => n.name === 'User');
|
|
293
293
|
expect(userStruct).toBeDefined();
|
|
294
294
|
expect(userStruct?.methods).toHaveLength(2);
|
|
295
295
|
expect(userStruct?.methods?.[0]?.name).toBe('new');
|
|
@@ -308,7 +308,7 @@ impl Service {
|
|
|
308
308
|
`.trim();
|
|
309
309
|
const nodes = parser.parse(code, 'test.rs');
|
|
310
310
|
|
|
311
|
-
const service = nodes.find(n => n.name === 'Service');
|
|
311
|
+
const service = nodes.find((n) => n.name === 'Service');
|
|
312
312
|
expect(service?.methods?.[0]?.async).toBe(true);
|
|
313
313
|
});
|
|
314
314
|
|
|
@@ -326,7 +326,7 @@ impl Drawable for Circle {
|
|
|
326
326
|
const nodes = parser.parse(code, 'test.rs');
|
|
327
327
|
|
|
328
328
|
// Trait impl methods shouldn't attach to struct
|
|
329
|
-
const circle = nodes.find(n => n.name === 'Circle');
|
|
329
|
+
const circle = nodes.find((n) => n.name === 'Circle');
|
|
330
330
|
expect(circle).toBeDefined();
|
|
331
331
|
});
|
|
332
332
|
|
|
@@ -344,7 +344,7 @@ impl Data {
|
|
|
344
344
|
`.trim();
|
|
345
345
|
const nodes = parser.parse(code, 'test.rs');
|
|
346
346
|
|
|
347
|
-
const data = nodes.find(n => n.name === 'Data');
|
|
347
|
+
const data = nodes.find((n) => n.name === 'Data');
|
|
348
348
|
expect(data?.methods).toHaveLength(2);
|
|
349
349
|
});
|
|
350
350
|
});
|
|
@@ -358,7 +358,7 @@ impl Data {
|
|
|
358
358
|
expect(imports[0]).toMatchObject({
|
|
359
359
|
source: 'std::collections',
|
|
360
360
|
specifiers: ['HashMap'],
|
|
361
|
-
isType: false
|
|
361
|
+
isType: false,
|
|
362
362
|
});
|
|
363
363
|
});
|
|
364
364
|
|
|
@@ -490,10 +490,10 @@ trait Handler {
|
|
|
490
490
|
|
|
491
491
|
expect(nodes.length).toBeGreaterThan(0);
|
|
492
492
|
|
|
493
|
-
const structs = nodes.filter(n => n.type === 'class');
|
|
494
|
-
const functions = nodes.filter(n => n.type === 'function');
|
|
495
|
-
const traits = nodes.filter(n => n.type === 'interface');
|
|
496
|
-
const constants = nodes.filter(n => n.type === 'const');
|
|
493
|
+
const structs = nodes.filter((n) => n.type === 'class');
|
|
494
|
+
const functions = nodes.filter((n) => n.type === 'function');
|
|
495
|
+
const traits = nodes.filter((n) => n.type === 'interface');
|
|
496
|
+
const constants = nodes.filter((n) => n.type === 'const');
|
|
497
497
|
|
|
498
498
|
expect(structs).toHaveLength(1);
|
|
499
499
|
expect(functions).toHaveLength(1);
|
|
@@ -539,7 +539,7 @@ impl Test {
|
|
|
539
539
|
`.trim();
|
|
540
540
|
const nodes = parser.parse(code, 'test.rs');
|
|
541
541
|
|
|
542
|
-
const test = nodes.find(n => n.name === 'Test');
|
|
542
|
+
const test = nodes.find((n) => n.name === 'Test');
|
|
543
543
|
const method = test?.methods?.[0];
|
|
544
544
|
|
|
545
545
|
expect(method?.startLine).toBe(4);
|
|
@@ -558,7 +558,7 @@ impl Service {
|
|
|
558
558
|
`.trim();
|
|
559
559
|
const nodes = parser.parse(code, 'test.rs');
|
|
560
560
|
|
|
561
|
-
const service = nodes.find(n => n.name === 'Service');
|
|
561
|
+
const service = nodes.find((n) => n.name === 'Service');
|
|
562
562
|
const method = service?.methods?.[0];
|
|
563
563
|
|
|
564
564
|
expect(method?.signature).toContain('process');
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { CodeNode, ImportInfo } from './ast-parser.js';
|
|
2
1
|
import {
|
|
3
2
|
parseRustCode,
|
|
4
3
|
queryNodesByType,
|
|
@@ -9,8 +8,9 @@ import {
|
|
|
9
8
|
getFunctionSignature,
|
|
10
9
|
extractImportPath,
|
|
11
10
|
type TreeSitterNode,
|
|
12
|
-
type TreeSitterTree
|
|
11
|
+
type TreeSitterTree,
|
|
13
12
|
} from './tree-sitter-parser.js';
|
|
13
|
+
import type { CodeNode, ImportInfo } from './ast-parser.js';
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* Parser for Rust code using tree-sitter
|
|
@@ -90,7 +90,7 @@ export class RustASTParser {
|
|
|
90
90
|
imports.push({
|
|
91
91
|
source,
|
|
92
92
|
specifiers,
|
|
93
|
-
isType: false // Rust doesn't distinguish type-only imports at syntax level
|
|
93
|
+
isType: false, // Rust doesn't distinguish type-only imports at syntax level
|
|
94
94
|
});
|
|
95
95
|
}
|
|
96
96
|
|
|
@@ -132,7 +132,7 @@ export class RustASTParser {
|
|
|
132
132
|
async,
|
|
133
133
|
startLine,
|
|
134
134
|
endLine,
|
|
135
|
-
signature
|
|
135
|
+
signature,
|
|
136
136
|
});
|
|
137
137
|
}
|
|
138
138
|
|
|
@@ -173,9 +173,7 @@ export class RustASTParser {
|
|
|
173
173
|
|
|
174
174
|
// Get type parameters (generics) if present
|
|
175
175
|
const typeParamsNode = getChildByFieldName(structNode, 'type_parameters');
|
|
176
|
-
const signature = typeParamsNode !== null
|
|
177
|
-
? `${name}${typeParamsNode.text}`
|
|
178
|
-
: name;
|
|
176
|
+
const signature = typeParamsNode !== null ? `${name}${typeParamsNode.text}` : name;
|
|
179
177
|
|
|
180
178
|
nodes.push({
|
|
181
179
|
type: 'class',
|
|
@@ -184,7 +182,7 @@ export class RustASTParser {
|
|
|
184
182
|
startLine,
|
|
185
183
|
endLine,
|
|
186
184
|
signature,
|
|
187
|
-
methods: [] // Will be populated by parseImplBlocks
|
|
185
|
+
methods: [], // Will be populated by parseImplBlocks
|
|
188
186
|
});
|
|
189
187
|
}
|
|
190
188
|
|
|
@@ -211,9 +209,7 @@ export class RustASTParser {
|
|
|
211
209
|
|
|
212
210
|
// Get type parameters (generics) if present
|
|
213
211
|
const typeParamsNode = getChildByFieldName(traitNode, 'type_parameters');
|
|
214
|
-
const signature = typeParamsNode !== null
|
|
215
|
-
? `${name}${typeParamsNode.text}`
|
|
216
|
-
: name;
|
|
212
|
+
const signature = typeParamsNode !== null ? `${name}${typeParamsNode.text}` : name;
|
|
217
213
|
|
|
218
214
|
// Extract trait methods
|
|
219
215
|
const methods = this.extractTraitMethods(traitNode);
|
|
@@ -225,7 +221,7 @@ export class RustASTParser {
|
|
|
225
221
|
startLine,
|
|
226
222
|
endLine,
|
|
227
223
|
signature,
|
|
228
|
-
methods
|
|
224
|
+
methods,
|
|
229
225
|
});
|
|
230
226
|
}
|
|
231
227
|
|
|
@@ -252,9 +248,7 @@ export class RustASTParser {
|
|
|
252
248
|
|
|
253
249
|
// Get the full type alias definition
|
|
254
250
|
const valueNode = getChildByFieldName(typeNode, 'type');
|
|
255
|
-
const signature = valueNode !== null
|
|
256
|
-
? `${name} = ${valueNode.text}`
|
|
257
|
-
: name;
|
|
251
|
+
const signature = valueNode !== null ? `${name} = ${valueNode.text}` : name;
|
|
258
252
|
|
|
259
253
|
nodes.push({
|
|
260
254
|
type: 'type',
|
|
@@ -262,7 +256,7 @@ export class RustASTParser {
|
|
|
262
256
|
exported,
|
|
263
257
|
startLine,
|
|
264
258
|
endLine,
|
|
265
|
-
signature
|
|
259
|
+
signature,
|
|
266
260
|
});
|
|
267
261
|
}
|
|
268
262
|
|
|
@@ -289,9 +283,7 @@ export class RustASTParser {
|
|
|
289
283
|
|
|
290
284
|
// Get type annotation
|
|
291
285
|
const typeNode = getChildByFieldName(constNode, 'type');
|
|
292
|
-
const signature = typeNode !== null
|
|
293
|
-
? `${name}: ${typeNode.text}`
|
|
294
|
-
: name;
|
|
286
|
+
const signature = typeNode !== null ? `${name}: ${typeNode.text}` : name;
|
|
295
287
|
|
|
296
288
|
nodes.push({
|
|
297
289
|
type: 'const',
|
|
@@ -299,7 +291,7 @@ export class RustASTParser {
|
|
|
299
291
|
exported,
|
|
300
292
|
startLine,
|
|
301
293
|
endLine,
|
|
302
|
-
signature
|
|
294
|
+
signature,
|
|
303
295
|
});
|
|
304
296
|
}
|
|
305
297
|
|
|
@@ -325,11 +317,9 @@ export class RustASTParser {
|
|
|
325
317
|
const methods = this.extractImplMethods(implNode);
|
|
326
318
|
|
|
327
319
|
// Find the corresponding struct and attach methods
|
|
328
|
-
const structNode = nodes.find(
|
|
329
|
-
node => node.type === 'class' && node.name === typeName
|
|
330
|
-
);
|
|
320
|
+
const structNode = nodes.find((node) => node.type === 'class' && node.name === typeName);
|
|
331
321
|
|
|
332
|
-
if (structNode
|
|
322
|
+
if (structNode?.methods !== undefined) {
|
|
333
323
|
structNode.methods.push(...methods);
|
|
334
324
|
}
|
|
335
325
|
}
|
|
@@ -379,7 +369,7 @@ export class RustASTParser {
|
|
|
379
369
|
async,
|
|
380
370
|
signature,
|
|
381
371
|
startLine,
|
|
382
|
-
endLine
|
|
372
|
+
endLine,
|
|
383
373
|
});
|
|
384
374
|
}
|
|
385
375
|
|
|
@@ -430,7 +420,7 @@ export class RustASTParser {
|
|
|
430
420
|
async,
|
|
431
421
|
signature,
|
|
432
422
|
startLine,
|
|
433
|
-
endLine
|
|
423
|
+
endLine,
|
|
434
424
|
});
|
|
435
425
|
}
|
|
436
426
|
|
|
@@ -459,7 +449,7 @@ export class RustASTParser {
|
|
|
459
449
|
if (scopedMatch !== null) {
|
|
460
450
|
const source = scopedMatch[1] ?? '';
|
|
461
451
|
const specifiersStr = scopedMatch[2] ?? '';
|
|
462
|
-
const specifiers = specifiersStr.split(',').map(s => s.trim());
|
|
452
|
+
const specifiers = specifiersStr.split(',').map((s) => s.trim());
|
|
463
453
|
return { source, specifiers };
|
|
464
454
|
}
|
|
465
455
|
|