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
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
handleGetStoreInfo,
|
|
5
5
|
handleCreateStore,
|
|
6
6
|
handleIndexStore,
|
|
7
|
-
handleDeleteStore
|
|
7
|
+
handleDeleteStore,
|
|
8
8
|
} from './store.handler.js';
|
|
9
9
|
import type { HandlerContext } from '../types.js';
|
|
10
10
|
import type {
|
|
@@ -12,7 +12,7 @@ import type {
|
|
|
12
12
|
GetStoreInfoArgs,
|
|
13
13
|
CreateStoreArgs,
|
|
14
14
|
IndexStoreArgs,
|
|
15
|
-
DeleteStoreArgs
|
|
15
|
+
DeleteStoreArgs,
|
|
16
16
|
} from '../schemas/index.js';
|
|
17
17
|
import { StoreService } from '../../services/store.service.js';
|
|
18
18
|
import { mkdtempSync, rmSync, writeFileSync } from 'fs';
|
|
@@ -21,7 +21,7 @@ import { tmpdir } from 'os';
|
|
|
21
21
|
|
|
22
22
|
// Mock the worker spawn function
|
|
23
23
|
vi.mock('../../workers/spawn-worker.js', () => ({
|
|
24
|
-
spawnBackgroundWorker: vi.fn()
|
|
24
|
+
spawnBackgroundWorker: vi.fn(),
|
|
25
25
|
}));
|
|
26
26
|
|
|
27
27
|
import { spawnBackgroundWorker } from '../../workers/spawn-worker.js';
|
|
@@ -40,10 +40,10 @@ describe('store.handler', () => {
|
|
|
40
40
|
services: {
|
|
41
41
|
store: storeService,
|
|
42
42
|
lance: {
|
|
43
|
-
deleteStore: vi.fn().mockResolvedValue(undefined)
|
|
44
|
-
}
|
|
43
|
+
deleteStore: vi.fn().mockResolvedValue(undefined),
|
|
44
|
+
},
|
|
45
45
|
} as any,
|
|
46
|
-
options: { dataDir: tempDir }
|
|
46
|
+
options: { dataDir: tempDir },
|
|
47
47
|
};
|
|
48
48
|
|
|
49
49
|
mockSpawnBackgroundWorker.mockClear();
|
|
@@ -63,13 +63,13 @@ describe('store.handler', () => {
|
|
|
63
63
|
name: 'store1',
|
|
64
64
|
type: 'file',
|
|
65
65
|
path: path1,
|
|
66
|
-
description: 'Test store 1'
|
|
66
|
+
description: 'Test store 1',
|
|
67
67
|
});
|
|
68
68
|
await storeService.create({
|
|
69
69
|
name: 'store2',
|
|
70
70
|
type: 'file',
|
|
71
71
|
path: path2,
|
|
72
|
-
description: 'Test store 2'
|
|
72
|
+
description: 'Test store 2',
|
|
73
73
|
});
|
|
74
74
|
|
|
75
75
|
const args: ListStoresArgs = {};
|
|
@@ -88,13 +88,13 @@ describe('store.handler', () => {
|
|
|
88
88
|
name: 'file-store',
|
|
89
89
|
type: 'file',
|
|
90
90
|
path: tempDir,
|
|
91
|
-
description: 'File store'
|
|
91
|
+
description: 'File store',
|
|
92
92
|
});
|
|
93
93
|
await storeService.create({
|
|
94
94
|
name: 'repo-store',
|
|
95
95
|
type: 'repo',
|
|
96
96
|
url: 'https://github.com/test/repo',
|
|
97
|
-
description: 'Repo store'
|
|
97
|
+
description: 'Repo store',
|
|
98
98
|
});
|
|
99
99
|
|
|
100
100
|
const args: ListStoresArgs = { type: 'file' };
|
|
@@ -110,7 +110,7 @@ describe('store.handler', () => {
|
|
|
110
110
|
name: 'test-store',
|
|
111
111
|
type: 'file',
|
|
112
112
|
path: tempDir,
|
|
113
|
-
description: 'Test description'
|
|
113
|
+
description: 'Test description',
|
|
114
114
|
});
|
|
115
115
|
|
|
116
116
|
const args: ListStoresArgs = {};
|
|
@@ -132,7 +132,7 @@ describe('store.handler', () => {
|
|
|
132
132
|
name: 'test-store',
|
|
133
133
|
type: 'file',
|
|
134
134
|
path: tempDir,
|
|
135
|
-
description: 'Test store'
|
|
135
|
+
description: 'Test store',
|
|
136
136
|
});
|
|
137
137
|
|
|
138
138
|
const args: GetStoreInfoArgs = { store: createResult.data.id };
|
|
@@ -148,7 +148,7 @@ describe('store.handler', () => {
|
|
|
148
148
|
name: 'test-store',
|
|
149
149
|
type: 'file',
|
|
150
150
|
path: tempDir,
|
|
151
|
-
description: 'Test store'
|
|
151
|
+
description: 'Test store',
|
|
152
152
|
});
|
|
153
153
|
|
|
154
154
|
const args: GetStoreInfoArgs = { store: 'test-store' };
|
|
@@ -163,7 +163,7 @@ describe('store.handler', () => {
|
|
|
163
163
|
name: 'file-store',
|
|
164
164
|
type: 'file',
|
|
165
165
|
path: tempDir,
|
|
166
|
-
description: 'Test description'
|
|
166
|
+
description: 'Test description',
|
|
167
167
|
});
|
|
168
168
|
|
|
169
169
|
const args: GetStoreInfoArgs = { store: 'file-store' };
|
|
@@ -183,9 +183,9 @@ describe('store.handler', () => {
|
|
|
183
183
|
it('should throw if store not found', async () => {
|
|
184
184
|
const args: GetStoreInfoArgs = { store: 'nonexistent' };
|
|
185
185
|
|
|
186
|
-
await expect(
|
|
187
|
-
|
|
188
|
-
)
|
|
186
|
+
await expect(handleGetStoreInfo(args, mockContext)).rejects.toThrow(
|
|
187
|
+
'Store not found: nonexistent'
|
|
188
|
+
);
|
|
189
189
|
});
|
|
190
190
|
});
|
|
191
191
|
|
|
@@ -198,7 +198,7 @@ describe('store.handler', () => {
|
|
|
198
198
|
name: 'new-store',
|
|
199
199
|
type: 'file',
|
|
200
200
|
source: sourcePath,
|
|
201
|
-
description: 'New test store'
|
|
201
|
+
description: 'New test store',
|
|
202
202
|
};
|
|
203
203
|
|
|
204
204
|
const result = await handleCreateStore(args, mockContext);
|
|
@@ -219,16 +219,13 @@ describe('store.handler', () => {
|
|
|
219
219
|
const args: CreateStoreArgs = {
|
|
220
220
|
name: 'worker-test',
|
|
221
221
|
type: 'file',
|
|
222
|
-
source: sourcePath
|
|
222
|
+
source: sourcePath,
|
|
223
223
|
};
|
|
224
224
|
|
|
225
225
|
const result = await handleCreateStore(args, mockContext);
|
|
226
226
|
const data = JSON.parse(result.content[0].text);
|
|
227
227
|
|
|
228
|
-
expect(mockSpawnBackgroundWorker).toHaveBeenCalledWith(
|
|
229
|
-
data.job.id,
|
|
230
|
-
tempDir
|
|
231
|
-
);
|
|
228
|
+
expect(mockSpawnBackgroundWorker).toHaveBeenCalledWith(data.job.id, tempDir);
|
|
232
229
|
|
|
233
230
|
rmSync(sourcePath, { recursive: true, force: true });
|
|
234
231
|
});
|
|
@@ -239,17 +236,15 @@ describe('store.handler', () => {
|
|
|
239
236
|
type: 'repo',
|
|
240
237
|
source: 'https://github.com/test/repo.git',
|
|
241
238
|
branch: 'main',
|
|
242
|
-
description: 'Git repo store'
|
|
239
|
+
description: 'Git repo store',
|
|
243
240
|
};
|
|
244
241
|
|
|
245
242
|
// This will fail to clone, but should still create the store record
|
|
246
|
-
await expect(
|
|
247
|
-
handleCreateStore(args, mockContext)
|
|
248
|
-
).rejects.toThrow(/Git clone failed/);
|
|
243
|
+
await expect(handleCreateStore(args, mockContext)).rejects.toThrow(/Git clone failed/);
|
|
249
244
|
|
|
250
245
|
// Verify store was NOT created since clone failed
|
|
251
246
|
const stores = await storeService.list();
|
|
252
|
-
const found = stores.find(s => s.name === 'repo-store');
|
|
247
|
+
const found = stores.find((s) => s.name === 'repo-store');
|
|
253
248
|
expect(found).toBeUndefined();
|
|
254
249
|
});
|
|
255
250
|
|
|
@@ -257,13 +252,11 @@ describe('store.handler', () => {
|
|
|
257
252
|
const httpArgs: CreateStoreArgs = {
|
|
258
253
|
name: 'http-store',
|
|
259
254
|
type: 'repo',
|
|
260
|
-
source: 'http://github.com/test/repo'
|
|
255
|
+
source: 'http://github.com/test/repo',
|
|
261
256
|
};
|
|
262
257
|
|
|
263
258
|
// Will fail to clone, which is expected
|
|
264
|
-
await expect(
|
|
265
|
-
handleCreateStore(httpArgs, mockContext)
|
|
266
|
-
).rejects.toThrow(/Git clone failed/);
|
|
259
|
+
await expect(handleCreateStore(httpArgs, mockContext)).rejects.toThrow(/Git clone failed/);
|
|
267
260
|
});
|
|
268
261
|
|
|
269
262
|
it('should reject store with nonexistent path', async () => {
|
|
@@ -271,7 +264,7 @@ describe('store.handler', () => {
|
|
|
271
264
|
const args: CreateStoreArgs = {
|
|
272
265
|
name: 'bad-store',
|
|
273
266
|
type: 'file',
|
|
274
|
-
source: '/nonexistent/path/that/does/not/exist'
|
|
267
|
+
source: '/nonexistent/path/that/does/not/exist',
|
|
275
268
|
};
|
|
276
269
|
|
|
277
270
|
await expect(handleCreateStore(args, mockContext)).rejects.toThrow(
|
|
@@ -286,7 +279,7 @@ describe('store.handler', () => {
|
|
|
286
279
|
name: 'index-test',
|
|
287
280
|
type: 'file',
|
|
288
281
|
path: tempDir,
|
|
289
|
-
description: 'Test indexing'
|
|
282
|
+
description: 'Test indexing',
|
|
290
283
|
});
|
|
291
284
|
|
|
292
285
|
const args: IndexStoreArgs = { store: createResult.data.id };
|
|
@@ -304,17 +297,14 @@ describe('store.handler', () => {
|
|
|
304
297
|
const createResult = await storeService.create({
|
|
305
298
|
name: 'index-worker-test',
|
|
306
299
|
type: 'file',
|
|
307
|
-
path: tempDir
|
|
300
|
+
path: tempDir,
|
|
308
301
|
});
|
|
309
302
|
|
|
310
303
|
const args: IndexStoreArgs = { store: createResult.data.id };
|
|
311
304
|
const result = await handleIndexStore(args, mockContext);
|
|
312
305
|
const data = JSON.parse(result.content[0].text);
|
|
313
306
|
|
|
314
|
-
expect(mockSpawnBackgroundWorker).toHaveBeenCalledWith(
|
|
315
|
-
data.job.id,
|
|
316
|
-
tempDir
|
|
317
|
-
);
|
|
307
|
+
expect(mockSpawnBackgroundWorker).toHaveBeenCalledWith(data.job.id, tempDir);
|
|
318
308
|
});
|
|
319
309
|
|
|
320
310
|
it('should work with store name', async () => {
|
|
@@ -322,7 +312,7 @@ describe('store.handler', () => {
|
|
|
322
312
|
name: 'named-store',
|
|
323
313
|
type: 'file',
|
|
324
314
|
path: tempDir,
|
|
325
|
-
description: 'Test'
|
|
315
|
+
description: 'Test',
|
|
326
316
|
});
|
|
327
317
|
|
|
328
318
|
const args: IndexStoreArgs = { store: 'named-store' };
|
|
@@ -335,9 +325,9 @@ describe('store.handler', () => {
|
|
|
335
325
|
it('should throw if store not found', async () => {
|
|
336
326
|
const args: IndexStoreArgs = { store: 'nonexistent' };
|
|
337
327
|
|
|
338
|
-
await expect(
|
|
339
|
-
|
|
340
|
-
)
|
|
328
|
+
await expect(handleIndexStore(args, mockContext)).rejects.toThrow(
|
|
329
|
+
'Store not found: nonexistent'
|
|
330
|
+
);
|
|
341
331
|
});
|
|
342
332
|
});
|
|
343
333
|
|
|
@@ -346,7 +336,7 @@ describe('store.handler', () => {
|
|
|
346
336
|
await storeService.create({
|
|
347
337
|
name: 'delete-test',
|
|
348
338
|
type: 'file',
|
|
349
|
-
path: tempDir
|
|
339
|
+
path: tempDir,
|
|
350
340
|
});
|
|
351
341
|
|
|
352
342
|
const args: DeleteStoreArgs = { store: 'delete-test' };
|
|
@@ -359,14 +349,14 @@ describe('store.handler', () => {
|
|
|
359
349
|
|
|
360
350
|
// Verify store is actually deleted
|
|
361
351
|
const stores = await storeService.list();
|
|
362
|
-
expect(stores.find(s => s.name === 'delete-test')).toBeUndefined();
|
|
352
|
+
expect(stores.find((s) => s.name === 'delete-test')).toBeUndefined();
|
|
363
353
|
});
|
|
364
354
|
|
|
365
355
|
it('should delete store by ID', async () => {
|
|
366
356
|
const createResult = await storeService.create({
|
|
367
357
|
name: 'delete-by-id',
|
|
368
358
|
type: 'file',
|
|
369
|
-
path: tempDir
|
|
359
|
+
path: tempDir,
|
|
370
360
|
});
|
|
371
361
|
|
|
372
362
|
const args: DeleteStoreArgs = { store: createResult.data.id };
|
|
@@ -381,7 +371,7 @@ describe('store.handler', () => {
|
|
|
381
371
|
const createResult = await storeService.create({
|
|
382
372
|
name: 'lance-delete-test',
|
|
383
373
|
type: 'file',
|
|
384
|
-
path: tempDir
|
|
374
|
+
path: tempDir,
|
|
385
375
|
});
|
|
386
376
|
|
|
387
377
|
const args: DeleteStoreArgs = { store: 'lance-delete-test' };
|
|
@@ -393,16 +383,16 @@ describe('store.handler', () => {
|
|
|
393
383
|
it('should throw if store not found', async () => {
|
|
394
384
|
const args: DeleteStoreArgs = { store: 'nonexistent' };
|
|
395
385
|
|
|
396
|
-
await expect(
|
|
397
|
-
|
|
398
|
-
)
|
|
386
|
+
await expect(handleDeleteStore(args, mockContext)).rejects.toThrow(
|
|
387
|
+
'Store not found: nonexistent'
|
|
388
|
+
);
|
|
399
389
|
});
|
|
400
390
|
|
|
401
391
|
it('should include store type in response', async () => {
|
|
402
392
|
await storeService.create({
|
|
403
393
|
name: 'type-test',
|
|
404
394
|
type: 'file',
|
|
405
|
-
path: tempDir
|
|
395
|
+
path: tempDir,
|
|
406
396
|
});
|
|
407
397
|
|
|
408
398
|
const args: DeleteStoreArgs = { store: 'type-test' };
|
|
@@ -411,6 +401,5 @@ describe('store.handler', () => {
|
|
|
411
401
|
const data = JSON.parse(result.content[0].text);
|
|
412
402
|
expect(data.store.type).toBe('file');
|
|
413
403
|
});
|
|
414
|
-
|
|
415
404
|
});
|
|
416
405
|
});
|
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
import { rm } from 'node:fs/promises';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
|
|
6
|
-
GetStoreInfoArgs,
|
|
7
|
-
CreateStoreArgs,
|
|
8
|
-
IndexStoreArgs,
|
|
9
|
-
DeleteStoreArgs
|
|
10
|
-
} from '../schemas/index.js';
|
|
3
|
+
import { JobService } from '../../services/job.service.js';
|
|
4
|
+
import { createStoreId } from '../../types/brands.js';
|
|
5
|
+
import { spawnBackgroundWorker } from '../../workers/spawn-worker.js';
|
|
11
6
|
import {
|
|
12
7
|
ListStoresArgsSchema,
|
|
13
8
|
GetStoreInfoArgsSchema,
|
|
14
9
|
CreateStoreArgsSchema,
|
|
15
10
|
IndexStoreArgsSchema,
|
|
16
|
-
DeleteStoreArgsSchema
|
|
11
|
+
DeleteStoreArgsSchema,
|
|
17
12
|
} from '../schemas/index.js';
|
|
18
|
-
import {
|
|
19
|
-
|
|
20
|
-
|
|
13
|
+
import type {
|
|
14
|
+
ListStoresArgs,
|
|
15
|
+
GetStoreInfoArgs,
|
|
16
|
+
CreateStoreArgs,
|
|
17
|
+
IndexStoreArgs,
|
|
18
|
+
DeleteStoreArgs,
|
|
19
|
+
} from '../schemas/index.js';
|
|
20
|
+
import type { ToolHandler, ToolResponse } from '../types.js';
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
23
|
* Handle list_stores requests
|
|
@@ -34,27 +34,30 @@ export const handleListStores: ToolHandler<ListStoresArgs> = async (
|
|
|
34
34
|
const { services } = context;
|
|
35
35
|
|
|
36
36
|
const stores = await services.store.list();
|
|
37
|
-
const filtered =
|
|
38
|
-
? stores.filter(s => s.type === validated.type)
|
|
39
|
-
: stores;
|
|
37
|
+
const filtered =
|
|
38
|
+
validated.type !== undefined ? stores.filter((s) => s.type === validated.type) : stores;
|
|
40
39
|
|
|
41
40
|
return {
|
|
42
41
|
content: [
|
|
43
42
|
{
|
|
44
43
|
type: 'text',
|
|
45
|
-
text: JSON.stringify(
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
44
|
+
text: JSON.stringify(
|
|
45
|
+
{
|
|
46
|
+
stores: filtered.map((s) => ({
|
|
47
|
+
id: s.id,
|
|
48
|
+
name: s.name,
|
|
49
|
+
type: s.type,
|
|
50
|
+
path: 'path' in s ? s.path : undefined,
|
|
51
|
+
url: 'url' in s && s.url !== undefined ? s.url : undefined,
|
|
52
|
+
description: s.description,
|
|
53
|
+
createdAt: s.createdAt.toISOString(),
|
|
54
|
+
})),
|
|
55
|
+
},
|
|
56
|
+
null,
|
|
57
|
+
2
|
|
58
|
+
),
|
|
59
|
+
},
|
|
60
|
+
],
|
|
58
61
|
};
|
|
59
62
|
};
|
|
60
63
|
|
|
@@ -82,20 +85,24 @@ export const handleGetStoreInfo: ToolHandler<GetStoreInfoArgs> = async (
|
|
|
82
85
|
content: [
|
|
83
86
|
{
|
|
84
87
|
type: 'text',
|
|
85
|
-
text: JSON.stringify(
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
88
|
+
text: JSON.stringify(
|
|
89
|
+
{
|
|
90
|
+
id: store.id,
|
|
91
|
+
name: store.name,
|
|
92
|
+
type: store.type,
|
|
93
|
+
path: 'path' in store ? store.path : undefined,
|
|
94
|
+
url: 'url' in store && store.url !== undefined ? store.url : undefined,
|
|
95
|
+
branch: 'branch' in store ? store.branch : undefined,
|
|
96
|
+
description: store.description,
|
|
97
|
+
status: store.status,
|
|
98
|
+
createdAt: store.createdAt.toISOString(),
|
|
99
|
+
updatedAt: store.updatedAt.toISOString(),
|
|
100
|
+
},
|
|
101
|
+
null,
|
|
102
|
+
2
|
|
103
|
+
),
|
|
104
|
+
},
|
|
105
|
+
],
|
|
99
106
|
};
|
|
100
107
|
};
|
|
101
108
|
|
|
@@ -115,16 +122,17 @@ export const handleCreateStore: ToolHandler<CreateStoreArgs> = async (
|
|
|
115
122
|
const { services, options } = context;
|
|
116
123
|
|
|
117
124
|
// Determine if source is a URL or path
|
|
118
|
-
const isUrl =
|
|
119
|
-
|
|
120
|
-
|
|
125
|
+
const isUrl =
|
|
126
|
+
validated.source.startsWith('http://') ||
|
|
127
|
+
validated.source.startsWith('https://') ||
|
|
128
|
+
validated.source.startsWith('git@');
|
|
121
129
|
|
|
122
130
|
const result = await services.store.create({
|
|
123
131
|
name: validated.name,
|
|
124
132
|
type: validated.type,
|
|
125
133
|
...(isUrl ? { url: validated.source } : { path: validated.source }),
|
|
126
134
|
...(validated.branch !== undefined ? { branch: validated.branch } : {}),
|
|
127
|
-
...(validated.description !== undefined ? { description: validated.description } : {})
|
|
135
|
+
...(validated.description !== undefined ? { description: validated.description } : {}),
|
|
128
136
|
});
|
|
129
137
|
|
|
130
138
|
if (!result.success) {
|
|
@@ -135,7 +143,7 @@ export const handleCreateStore: ToolHandler<CreateStoreArgs> = async (
|
|
|
135
143
|
const jobService = new JobService(options.dataDir);
|
|
136
144
|
const jobDetails: Record<string, unknown> = {
|
|
137
145
|
storeName: result.data.name,
|
|
138
|
-
storeId: result.data.id
|
|
146
|
+
storeId: result.data.id,
|
|
139
147
|
};
|
|
140
148
|
if (isUrl) {
|
|
141
149
|
jobDetails['url'] = validated.source;
|
|
@@ -146,7 +154,7 @@ export const handleCreateStore: ToolHandler<CreateStoreArgs> = async (
|
|
|
146
154
|
const job = jobService.createJob({
|
|
147
155
|
type: validated.type === 'repo' && isUrl ? 'clone' : 'index',
|
|
148
156
|
details: jobDetails,
|
|
149
|
-
message: `Indexing ${result.data.name}
|
|
157
|
+
message: `Indexing ${result.data.name}...`,
|
|
150
158
|
});
|
|
151
159
|
|
|
152
160
|
// Spawn background worker (dataDir defaults to project-local .bluera if undefined)
|
|
@@ -156,22 +164,26 @@ export const handleCreateStore: ToolHandler<CreateStoreArgs> = async (
|
|
|
156
164
|
content: [
|
|
157
165
|
{
|
|
158
166
|
type: 'text',
|
|
159
|
-
text: JSON.stringify(
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
167
|
+
text: JSON.stringify(
|
|
168
|
+
{
|
|
169
|
+
store: {
|
|
170
|
+
id: result.data.id,
|
|
171
|
+
name: result.data.name,
|
|
172
|
+
type: result.data.type,
|
|
173
|
+
path: 'path' in result.data ? result.data.path : undefined,
|
|
174
|
+
},
|
|
175
|
+
job: {
|
|
176
|
+
id: job.id,
|
|
177
|
+
status: job.status,
|
|
178
|
+
message: job.message,
|
|
179
|
+
},
|
|
180
|
+
message: `Store created. Indexing started in background (Job ID: ${job.id})`,
|
|
165
181
|
},
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
message: `Store created. Indexing started in background (Job ID: ${job.id})`
|
|
172
|
-
}, null, 2)
|
|
173
|
-
}
|
|
174
|
-
]
|
|
182
|
+
null,
|
|
183
|
+
2
|
|
184
|
+
),
|
|
185
|
+
},
|
|
186
|
+
],
|
|
175
187
|
};
|
|
176
188
|
};
|
|
177
189
|
|
|
@@ -200,7 +212,7 @@ export const handleIndexStore: ToolHandler<IndexStoreArgs> = async (
|
|
|
200
212
|
const jobService = new JobService(options.dataDir);
|
|
201
213
|
const jobDetails: Record<string, unknown> = {
|
|
202
214
|
storeName: store.name,
|
|
203
|
-
storeId: store.id
|
|
215
|
+
storeId: store.id,
|
|
204
216
|
};
|
|
205
217
|
if ('path' in store && store.path) {
|
|
206
218
|
jobDetails['path'] = store.path;
|
|
@@ -208,7 +220,7 @@ export const handleIndexStore: ToolHandler<IndexStoreArgs> = async (
|
|
|
208
220
|
const job = jobService.createJob({
|
|
209
221
|
type: 'index',
|
|
210
222
|
details: jobDetails,
|
|
211
|
-
message: `Re-indexing ${store.name}
|
|
223
|
+
message: `Re-indexing ${store.name}...`,
|
|
212
224
|
});
|
|
213
225
|
|
|
214
226
|
// Spawn background worker (dataDir defaults to project-local .bluera if undefined)
|
|
@@ -218,20 +230,24 @@ export const handleIndexStore: ToolHandler<IndexStoreArgs> = async (
|
|
|
218
230
|
content: [
|
|
219
231
|
{
|
|
220
232
|
type: 'text',
|
|
221
|
-
text: JSON.stringify(
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
233
|
+
text: JSON.stringify(
|
|
234
|
+
{
|
|
235
|
+
store: {
|
|
236
|
+
id: store.id,
|
|
237
|
+
name: store.name,
|
|
238
|
+
},
|
|
239
|
+
job: {
|
|
240
|
+
id: job.id,
|
|
241
|
+
status: job.status,
|
|
242
|
+
message: job.message,
|
|
243
|
+
},
|
|
244
|
+
message: `Indexing started in background (Job ID: ${job.id})`,
|
|
225
245
|
},
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
message: `Indexing started in background (Job ID: ${job.id})`
|
|
232
|
-
}, null, 2)
|
|
233
|
-
}
|
|
234
|
-
]
|
|
246
|
+
null,
|
|
247
|
+
2
|
|
248
|
+
),
|
|
249
|
+
},
|
|
250
|
+
],
|
|
235
251
|
};
|
|
236
252
|
};
|
|
237
253
|
|
|
@@ -280,16 +296,20 @@ export const handleDeleteStore: ToolHandler<DeleteStoreArgs> = async (
|
|
|
280
296
|
content: [
|
|
281
297
|
{
|
|
282
298
|
type: 'text',
|
|
283
|
-
text: JSON.stringify(
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
299
|
+
text: JSON.stringify(
|
|
300
|
+
{
|
|
301
|
+
deleted: true,
|
|
302
|
+
store: {
|
|
303
|
+
id: store.id,
|
|
304
|
+
name: store.name,
|
|
305
|
+
type: store.type,
|
|
306
|
+
},
|
|
307
|
+
message: `Successfully deleted store: ${store.name}`,
|
|
289
308
|
},
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
309
|
+
null,
|
|
310
|
+
2
|
|
311
|
+
),
|
|
312
|
+
},
|
|
313
|
+
],
|
|
294
314
|
};
|
|
295
315
|
};
|