bluera-knowledge 0.9.32 → 0.9.36

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 (198) hide show
  1. package/.claude/hooks/post-edit-check.sh +5 -3
  2. package/.claude/skills/atomic-commits/SKILL.md +3 -1
  3. package/.husky/pre-commit +3 -2
  4. package/.prettierrc +9 -0
  5. package/.versionrc.json +1 -1
  6. package/CHANGELOG.md +70 -0
  7. package/CLAUDE.md +6 -0
  8. package/README.md +25 -13
  9. package/bun.lock +277 -33
  10. package/dist/{chunk-L2YVNC63.js → chunk-6FHWC36B.js} +9 -1
  11. package/dist/chunk-6FHWC36B.js.map +1 -0
  12. package/dist/{chunk-RST4XGRL.js → chunk-DC7CGSGT.js} +288 -241
  13. package/dist/chunk-DC7CGSGT.js.map +1 -0
  14. package/dist/{chunk-6PBP5DVD.js → chunk-WFNPNAAP.js} +3212 -3054
  15. package/dist/chunk-WFNPNAAP.js.map +1 -0
  16. package/dist/{chunk-WT2DAEO7.js → chunk-Z2KKVH45.js} +548 -482
  17. package/dist/chunk-Z2KKVH45.js.map +1 -0
  18. package/dist/index.js +871 -758
  19. package/dist/index.js.map +1 -1
  20. package/dist/mcp/server.js +3 -3
  21. package/dist/watch.service-BJV3TI3F.js +7 -0
  22. package/dist/workers/background-worker-cli.js +97 -71
  23. package/dist/workers/background-worker-cli.js.map +1 -1
  24. package/eslint.config.js +43 -1
  25. package/package.json +18 -11
  26. package/plugin.json +8 -0
  27. package/python/requirements.txt +1 -1
  28. package/src/analysis/ast-parser.test.ts +12 -11
  29. package/src/analysis/ast-parser.ts +28 -22
  30. package/src/analysis/code-graph.test.ts +52 -62
  31. package/src/analysis/code-graph.ts +9 -13
  32. package/src/analysis/dependency-usage-analyzer.test.ts +91 -271
  33. package/src/analysis/dependency-usage-analyzer.ts +52 -24
  34. package/src/analysis/go-ast-parser.test.ts +22 -22
  35. package/src/analysis/go-ast-parser.ts +18 -25
  36. package/src/analysis/parser-factory.test.ts +9 -9
  37. package/src/analysis/parser-factory.ts +3 -3
  38. package/src/analysis/python-ast-parser.test.ts +27 -27
  39. package/src/analysis/python-ast-parser.ts +2 -2
  40. package/src/analysis/repo-url-resolver.test.ts +82 -82
  41. package/src/analysis/rust-ast-parser.test.ts +19 -19
  42. package/src/analysis/rust-ast-parser.ts +17 -27
  43. package/src/analysis/tree-sitter-parser.test.ts +3 -3
  44. package/src/analysis/tree-sitter-parser.ts +10 -16
  45. package/src/cli/commands/crawl.test.ts +40 -24
  46. package/src/cli/commands/crawl.ts +186 -166
  47. package/src/cli/commands/index-cmd.test.ts +90 -90
  48. package/src/cli/commands/index-cmd.ts +52 -36
  49. package/src/cli/commands/mcp.test.ts +6 -6
  50. package/src/cli/commands/mcp.ts +2 -2
  51. package/src/cli/commands/plugin-api.test.ts +16 -18
  52. package/src/cli/commands/plugin-api.ts +9 -6
  53. package/src/cli/commands/search.test.ts +16 -7
  54. package/src/cli/commands/search.ts +124 -87
  55. package/src/cli/commands/serve.test.ts +67 -25
  56. package/src/cli/commands/serve.ts +18 -3
  57. package/src/cli/commands/setup.test.ts +176 -101
  58. package/src/cli/commands/setup.ts +140 -117
  59. package/src/cli/commands/store.test.ts +82 -53
  60. package/src/cli/commands/store.ts +56 -37
  61. package/src/cli/program.ts +2 -2
  62. package/src/crawl/article-converter.test.ts +4 -1
  63. package/src/crawl/article-converter.ts +46 -31
  64. package/src/crawl/bridge.test.ts +240 -132
  65. package/src/crawl/bridge.ts +87 -30
  66. package/src/crawl/claude-client.test.ts +124 -56
  67. package/src/crawl/claude-client.ts +7 -15
  68. package/src/crawl/intelligent-crawler.test.ts +65 -22
  69. package/src/crawl/intelligent-crawler.ts +86 -53
  70. package/src/crawl/markdown-utils.ts +1 -4
  71. package/src/db/embeddings.ts +4 -6
  72. package/src/db/lance.test.ts +4 -4
  73. package/src/db/lance.ts +16 -12
  74. package/src/index.ts +26 -17
  75. package/src/logging/index.ts +1 -5
  76. package/src/logging/logger.ts +3 -5
  77. package/src/logging/payload.test.ts +1 -1
  78. package/src/logging/payload.ts +3 -5
  79. package/src/mcp/commands/index.ts +2 -2
  80. package/src/mcp/commands/job.commands.ts +12 -18
  81. package/src/mcp/commands/meta.commands.ts +13 -13
  82. package/src/mcp/commands/registry.ts +5 -8
  83. package/src/mcp/commands/store.commands.ts +19 -19
  84. package/src/mcp/handlers/execute.handler.test.ts +10 -10
  85. package/src/mcp/handlers/execute.handler.ts +4 -5
  86. package/src/mcp/handlers/index.ts +10 -14
  87. package/src/mcp/handlers/job.handler.test.ts +10 -10
  88. package/src/mcp/handlers/job.handler.ts +22 -25
  89. package/src/mcp/handlers/search.handler.test.ts +36 -65
  90. package/src/mcp/handlers/search.handler.ts +135 -104
  91. package/src/mcp/handlers/store.handler.test.ts +41 -52
  92. package/src/mcp/handlers/store.handler.ts +108 -88
  93. package/src/mcp/schemas/index.test.ts +73 -68
  94. package/src/mcp/schemas/index.ts +18 -12
  95. package/src/mcp/server.test.ts +1 -1
  96. package/src/mcp/server.ts +59 -46
  97. package/src/plugin/commands.test.ts +230 -95
  98. package/src/plugin/commands.ts +24 -25
  99. package/src/plugin/dependency-analyzer.test.ts +52 -52
  100. package/src/plugin/dependency-analyzer.ts +85 -22
  101. package/src/plugin/git-clone.test.ts +24 -13
  102. package/src/plugin/git-clone.ts +3 -7
  103. package/src/server/app.test.ts +109 -109
  104. package/src/server/app.ts +32 -23
  105. package/src/server/index.test.ts +64 -66
  106. package/src/services/chunking.service.test.ts +32 -32
  107. package/src/services/chunking.service.ts +16 -9
  108. package/src/services/code-graph.service.test.ts +30 -36
  109. package/src/services/code-graph.service.ts +24 -10
  110. package/src/services/code-unit.service.test.ts +55 -11
  111. package/src/services/code-unit.service.ts +85 -11
  112. package/src/services/config.service.test.ts +37 -18
  113. package/src/services/config.service.ts +30 -7
  114. package/src/services/index.service.test.ts +49 -18
  115. package/src/services/index.service.ts +98 -48
  116. package/src/services/index.ts +6 -9
  117. package/src/services/job.service.test.ts +22 -22
  118. package/src/services/job.service.ts +18 -18
  119. package/src/services/project-root.service.test.ts +1 -3
  120. package/src/services/search.service.test.ts +248 -120
  121. package/src/services/search.service.ts +286 -156
  122. package/src/services/services.test.ts +1 -1
  123. package/src/services/snippet.service.test.ts +14 -6
  124. package/src/services/snippet.service.ts +7 -5
  125. package/src/services/store.service.test.ts +68 -29
  126. package/src/services/store.service.ts +41 -12
  127. package/src/services/watch.service.test.ts +34 -14
  128. package/src/services/watch.service.ts +11 -1
  129. package/src/types/brands.test.ts +3 -1
  130. package/src/types/index.ts +2 -13
  131. package/src/types/search.ts +10 -8
  132. package/src/utils/type-guards.test.ts +20 -15
  133. package/src/utils/type-guards.ts +1 -1
  134. package/src/workers/background-worker-cli.ts +28 -30
  135. package/src/workers/background-worker.test.ts +54 -40
  136. package/src/workers/background-worker.ts +76 -60
  137. package/src/workers/pid-file.test.ts +167 -0
  138. package/src/workers/pid-file.ts +82 -0
  139. package/src/workers/spawn-worker.test.ts +22 -10
  140. package/src/workers/spawn-worker.ts +6 -6
  141. package/tests/analysis/ast-parser.test.ts +3 -3
  142. package/tests/analysis/code-graph.test.ts +5 -5
  143. package/tests/fixtures/code-snippets/api/error-handling.ts +4 -15
  144. package/tests/fixtures/code-snippets/api/rest-controller.ts +3 -9
  145. package/tests/fixtures/code-snippets/auth/jwt-auth.ts +5 -21
  146. package/tests/fixtures/code-snippets/auth/oauth-flow.ts +4 -4
  147. package/tests/fixtures/code-snippets/database/repository-pattern.ts +11 -3
  148. package/tests/fixtures/corpus/oss-repos/hono/src/adapter/aws-lambda/handler.ts +2 -2
  149. package/tests/fixtures/corpus/oss-repos/hono/src/adapter/cloudflare-pages/handler.ts +1 -1
  150. package/tests/fixtures/corpus/oss-repos/hono/src/adapter/cloudflare-workers/serve-static.ts +2 -2
  151. package/tests/fixtures/corpus/oss-repos/hono/src/client/client.ts +2 -2
  152. package/tests/fixtures/corpus/oss-repos/hono/src/client/types.ts +22 -20
  153. package/tests/fixtures/corpus/oss-repos/hono/src/context.ts +13 -10
  154. package/tests/fixtures/corpus/oss-repos/hono/src/helper/accepts/accepts.ts +10 -7
  155. package/tests/fixtures/corpus/oss-repos/hono/src/helper/adapter/index.ts +2 -2
  156. package/tests/fixtures/corpus/oss-repos/hono/src/helper/css/index.ts +1 -1
  157. package/tests/fixtures/corpus/oss-repos/hono/src/helper/factory/index.ts +16 -16
  158. package/tests/fixtures/corpus/oss-repos/hono/src/helper/ssg/ssg.ts +2 -2
  159. package/tests/fixtures/corpus/oss-repos/hono/src/hono-base.ts +3 -3
  160. package/tests/fixtures/corpus/oss-repos/hono/src/hono.ts +1 -1
  161. package/tests/fixtures/corpus/oss-repos/hono/src/jsx/dom/css.ts +2 -2
  162. package/tests/fixtures/corpus/oss-repos/hono/src/jsx/dom/intrinsic-element/components.ts +1 -1
  163. package/tests/fixtures/corpus/oss-repos/hono/src/jsx/dom/render.ts +7 -7
  164. package/tests/fixtures/corpus/oss-repos/hono/src/jsx/hooks/index.ts +3 -3
  165. package/tests/fixtures/corpus/oss-repos/hono/src/jsx/intrinsic-element/components.ts +1 -1
  166. package/tests/fixtures/corpus/oss-repos/hono/src/jsx/utils.ts +6 -6
  167. package/tests/fixtures/corpus/oss-repos/hono/src/middleware/jsx-renderer/index.ts +3 -3
  168. package/tests/fixtures/corpus/oss-repos/hono/src/middleware/serve-static/index.ts +1 -1
  169. package/tests/fixtures/corpus/oss-repos/hono/src/preset/quick.ts +1 -1
  170. package/tests/fixtures/corpus/oss-repos/hono/src/preset/tiny.ts +1 -1
  171. package/tests/fixtures/corpus/oss-repos/hono/src/router/pattern-router/router.ts +2 -2
  172. package/tests/fixtures/corpus/oss-repos/hono/src/router/reg-exp-router/node.ts +4 -4
  173. package/tests/fixtures/corpus/oss-repos/hono/src/router/reg-exp-router/router.ts +1 -1
  174. package/tests/fixtures/corpus/oss-repos/hono/src/router/trie-router/node.ts +1 -1
  175. package/tests/fixtures/corpus/oss-repos/hono/src/types.ts +166 -169
  176. package/tests/fixtures/corpus/oss-repos/hono/src/utils/body.ts +8 -8
  177. package/tests/fixtures/corpus/oss-repos/hono/src/utils/color.ts +3 -3
  178. package/tests/fixtures/corpus/oss-repos/hono/src/utils/cookie.ts +2 -2
  179. package/tests/fixtures/corpus/oss-repos/hono/src/utils/encode.ts +2 -2
  180. package/tests/fixtures/corpus/oss-repos/hono/src/utils/types.ts +30 -33
  181. package/tests/fixtures/corpus/oss-repos/hono/src/validator/validator.ts +2 -2
  182. package/tests/fixtures/test-server.ts +3 -2
  183. package/tests/helpers/performance-metrics.ts +8 -25
  184. package/tests/helpers/search-relevance.ts +14 -69
  185. package/tests/integration/cli-consistency.test.ts +6 -5
  186. package/tests/integration/python-bridge.test.ts +13 -3
  187. package/tests/mcp/server.test.ts +1 -1
  188. package/tests/services/code-unit.service.test.ts +48 -0
  189. package/tests/services/job.service.test.ts +124 -0
  190. package/tests/services/search.progressive-context.test.ts +2 -2
  191. package/.claude-plugin/plugin.json +0 -13
  192. package/dist/chunk-6PBP5DVD.js.map +0 -1
  193. package/dist/chunk-L2YVNC63.js.map +0 -1
  194. package/dist/chunk-RST4XGRL.js.map +0 -1
  195. package/dist/chunk-WT2DAEO7.js.map +0 -1
  196. package/dist/watch.service-YAIKKDCF.js +0 -7
  197. package/skills/atomic-commits/SKILL.md +0 -77
  198. /package/dist/{watch.service-YAIKKDCF.js.map → watch.service-BJV3TI3F.js.map} +0 -0
@@ -5,13 +5,13 @@ import {
5
5
  handleAddFolder,
6
6
  handleIndex,
7
7
  handleStores,
8
- handleSuggest
8
+ handleSuggest,
9
9
  } from './commands.js';
10
10
  import type { ServiceContainer } from '../services/index.js';
11
11
 
12
12
  // Mock the createServices function
13
13
  vi.mock('../services/index.js', () => ({
14
- createServices: vi.fn()
14
+ createServices: vi.fn(),
15
15
  }));
16
16
 
17
17
  // Mock extractRepoName
@@ -19,7 +19,7 @@ vi.mock('./git-clone.js', () => ({
19
19
  extractRepoName: vi.fn((url: string) => {
20
20
  const match = /\/([^/]+?)(\.git)?$/.exec(url);
21
21
  return match?.[1] ?? 'repository';
22
- })
22
+ }),
23
23
  }));
24
24
 
25
25
  // Mock DependencyUsageAnalyzer
@@ -41,8 +41,8 @@ vi.mock('ora', () => ({
41
41
  default: vi.fn(() => ({
42
42
  start: vi.fn().mockReturnThis(),
43
43
  stop: vi.fn(),
44
- text: ''
45
- }))
44
+ text: '',
45
+ })),
46
46
  }));
47
47
 
48
48
  describe('Commands - handleSearch', () => {
@@ -59,17 +59,17 @@ describe('Commands - handleSearch', () => {
59
59
  list: vi.fn(),
60
60
  getByIdOrName: vi.fn(),
61
61
  create: vi.fn(),
62
- delete: vi.fn()
62
+ delete: vi.fn(),
63
63
  },
64
64
  lance: {
65
- initialize: vi.fn()
65
+ initialize: vi.fn(),
66
66
  },
67
67
  search: {
68
- search: vi.fn()
68
+ search: vi.fn(),
69
69
  },
70
70
  index: {
71
- indexStore: vi.fn()
72
- }
71
+ indexStore: vi.fn(),
72
+ },
73
73
  } as unknown as ServiceContainer;
74
74
 
75
75
  vi.mocked(createServices).mockResolvedValue(mockServices);
@@ -86,13 +86,13 @@ describe('Commands - handleSearch', () => {
86
86
  it('searches all stores when no stores specified', async () => {
87
87
  const mockStores = [
88
88
  { id: 'store-1', name: 'test1', type: 'file' as const },
89
- { id: 'store-2', name: 'test2', type: 'repo' as const }
89
+ { id: 'store-2', name: 'test2', type: 'repo' as const },
90
90
  ];
91
91
 
92
92
  vi.mocked(mockServices.store.list).mockResolvedValue(mockStores);
93
93
  vi.mocked(mockServices.search.search).mockResolvedValue({
94
94
  results: [],
95
- totalResults: 0
95
+ totalResults: 0,
96
96
  });
97
97
 
98
98
  await handleSearch({ query: 'test query' });
@@ -102,7 +102,7 @@ describe('Commands - handleSearch', () => {
102
102
  expect(mockServices.search.search).toHaveBeenCalledWith(
103
103
  expect.objectContaining({
104
104
  query: 'test query',
105
- stores: ['store-1', 'store-2']
105
+ stores: ['store-1', 'store-2'],
106
106
  })
107
107
  );
108
108
  });
@@ -111,20 +111,20 @@ describe('Commands - handleSearch', () => {
111
111
  const mockStores = [
112
112
  { id: 'store-1', name: 'test1', type: 'file' as const },
113
113
  { id: 'store-2', name: 'test2', type: 'repo' as const },
114
- { id: 'store-3', name: 'other', type: 'file' as const }
114
+ { id: 'store-3', name: 'other', type: 'file' as const },
115
115
  ];
116
116
 
117
117
  vi.mocked(mockServices.store.list).mockResolvedValue(mockStores);
118
118
  vi.mocked(mockServices.search.search).mockResolvedValue({
119
119
  results: [],
120
- totalResults: 0
120
+ totalResults: 0,
121
121
  });
122
122
 
123
123
  await handleSearch({ query: 'test', stores: 'test1,test2' });
124
124
 
125
125
  expect(mockServices.search.search).toHaveBeenCalledWith(
126
126
  expect.objectContaining({
127
- stores: ['store-1', 'store-2']
127
+ stores: ['store-1', 'store-2'],
128
128
  })
129
129
  );
130
130
  });
@@ -135,14 +135,14 @@ describe('Commands - handleSearch', () => {
135
135
  vi.mocked(mockServices.store.list).mockResolvedValue(mockStores);
136
136
  vi.mocked(mockServices.search.search).mockResolvedValue({
137
137
  results: [],
138
- totalResults: 0
138
+ totalResults: 0,
139
139
  });
140
140
 
141
141
  await handleSearch({ query: 'test', limit: '25' });
142
142
 
143
143
  expect(mockServices.search.search).toHaveBeenCalledWith(
144
144
  expect.objectContaining({
145
- limit: 25
145
+ limit: 25,
146
146
  })
147
147
  );
148
148
  });
@@ -153,14 +153,14 @@ describe('Commands - handleSearch', () => {
153
153
  vi.mocked(mockServices.store.list).mockResolvedValue(mockStores);
154
154
  vi.mocked(mockServices.search.search).mockResolvedValue({
155
155
  results: [],
156
- totalResults: 0
156
+ totalResults: 0,
157
157
  });
158
158
 
159
159
  await handleSearch({ query: 'test' });
160
160
 
161
161
  expect(mockServices.search.search).toHaveBeenCalledWith(
162
162
  expect.objectContaining({
163
- limit: 10
163
+ limit: 10,
164
164
  })
165
165
  );
166
166
  });
@@ -187,11 +187,11 @@ describe('Commands - handleSearch', () => {
187
187
  score: 0.95,
188
188
  summary: {
189
189
  location: 'test.ts:10-20',
190
- purpose: 'Test function'
191
- }
192
- }
190
+ purpose: 'Test function',
191
+ },
192
+ },
193
193
  ],
194
- totalResults: 1
194
+ totalResults: 1,
195
195
  };
196
196
 
197
197
  vi.mocked(mockServices.store.list).mockResolvedValue(mockStores);
@@ -208,7 +208,7 @@ describe('Commands - handleSearch', () => {
208
208
  const mockStores = [{ id: 'store-1', name: 'test', type: 'file' as const }];
209
209
  const mockResults = {
210
210
  results: [{ score: 0.5 }],
211
- totalResults: 1
211
+ totalResults: 1,
212
212
  };
213
213
 
214
214
  vi.mocked(mockServices.store.list).mockResolvedValue(mockStores);
@@ -234,11 +234,11 @@ describe('Commands - handleAddRepo', () => {
234
234
  list: vi.fn(),
235
235
  getByIdOrName: vi.fn(),
236
236
  create: vi.fn(),
237
- delete: vi.fn()
237
+ delete: vi.fn(),
238
238
  },
239
239
  index: {
240
- indexStore: vi.fn()
241
- }
240
+ indexStore: vi.fn(),
241
+ },
242
242
  } as unknown as ServiceContainer;
243
243
 
244
244
  vi.mocked(createServices).mockResolvedValue(mockServices);
@@ -255,11 +255,18 @@ describe('Commands - handleAddRepo', () => {
255
255
  it('creates repo store with extracted name', async () => {
256
256
  vi.mocked(mockServices.store.create).mockResolvedValue({
257
257
  success: true,
258
- data: { id: 'store-1', name: 'test-repo', type: 'repo', path: '/tmp/test-repo', createdAt: new Date(), updatedAt: new Date() }
258
+ data: {
259
+ id: 'store-1',
260
+ name: 'test-repo',
261
+ type: 'repo',
262
+ path: '/tmp/test-repo',
263
+ createdAt: new Date(),
264
+ updatedAt: new Date(),
265
+ },
259
266
  });
260
267
  vi.mocked(mockServices.index.indexStore).mockResolvedValue({
261
268
  success: true,
262
- data: { documentsIndexed: 10, chunksCreated: 50, timeMs: 1000 }
269
+ data: { documentsIndexed: 10, chunksCreated: 50, timeMs: 1000 },
263
270
  });
264
271
 
265
272
  await handleAddRepo({ url: 'https://github.com/user/test-repo.git' });
@@ -267,18 +274,25 @@ describe('Commands - handleAddRepo', () => {
267
274
  expect(mockServices.store.create).toHaveBeenCalledWith({
268
275
  name: 'test-repo',
269
276
  type: 'repo',
270
- url: 'https://github.com/user/test-repo.git'
277
+ url: 'https://github.com/user/test-repo.git',
271
278
  });
272
279
  });
273
280
 
274
281
  it('uses custom name when provided', async () => {
275
282
  vi.mocked(mockServices.store.create).mockResolvedValue({
276
283
  success: true,
277
- data: { id: 'store-1', name: 'my-name', type: 'repo', path: '/tmp/my-name', createdAt: new Date(), updatedAt: new Date() }
284
+ data: {
285
+ id: 'store-1',
286
+ name: 'my-name',
287
+ type: 'repo',
288
+ path: '/tmp/my-name',
289
+ createdAt: new Date(),
290
+ updatedAt: new Date(),
291
+ },
278
292
  });
279
293
  vi.mocked(mockServices.index.indexStore).mockResolvedValue({
280
294
  success: true,
281
- data: { documentsIndexed: 10, chunksCreated: 50, timeMs: 1000 }
295
+ data: { documentsIndexed: 10, chunksCreated: 50, timeMs: 1000 },
282
296
  });
283
297
 
284
298
  await handleAddRepo({ url: 'https://github.com/user/repo.git', name: 'my-name' });
@@ -286,18 +300,26 @@ describe('Commands - handleAddRepo', () => {
286
300
  expect(mockServices.store.create).toHaveBeenCalledWith({
287
301
  name: 'my-name',
288
302
  type: 'repo',
289
- url: 'https://github.com/user/repo.git'
303
+ url: 'https://github.com/user/repo.git',
290
304
  });
291
305
  });
292
306
 
293
307
  it('includes branch when provided', async () => {
294
308
  vi.mocked(mockServices.store.create).mockResolvedValue({
295
309
  success: true,
296
- data: { id: 'store-1', name: 'test-repo', type: 'repo', path: '/tmp/test-repo', branch: 'develop', createdAt: new Date(), updatedAt: new Date() }
310
+ data: {
311
+ id: 'store-1',
312
+ name: 'test-repo',
313
+ type: 'repo',
314
+ path: '/tmp/test-repo',
315
+ branch: 'develop',
316
+ createdAt: new Date(),
317
+ updatedAt: new Date(),
318
+ },
297
319
  });
298
320
  vi.mocked(mockServices.index.indexStore).mockResolvedValue({
299
321
  success: true,
300
- data: { documentsIndexed: 10, chunksCreated: 50, timeMs: 1000 }
322
+ data: { documentsIndexed: 10, chunksCreated: 50, timeMs: 1000 },
301
323
  });
302
324
 
303
325
  await handleAddRepo({ url: 'https://github.com/user/repo.git', branch: 'develop' });
@@ -306,20 +328,27 @@ describe('Commands - handleAddRepo', () => {
306
328
  name: 'repo',
307
329
  type: 'repo',
308
330
  url: 'https://github.com/user/repo.git',
309
- branch: 'develop'
331
+ branch: 'develop',
310
332
  });
311
333
  });
312
334
 
313
335
  it('auto-indexes after creation', async () => {
314
- const mockStore = { id: 'store-1', name: 'test', type: 'repo' as const, path: '/tmp/test', createdAt: new Date(), updatedAt: new Date() };
336
+ const mockStore = {
337
+ id: 'store-1',
338
+ name: 'test',
339
+ type: 'repo' as const,
340
+ path: '/tmp/test',
341
+ createdAt: new Date(),
342
+ updatedAt: new Date(),
343
+ };
315
344
 
316
345
  vi.mocked(mockServices.store.create).mockResolvedValue({
317
346
  success: true,
318
- data: mockStore
347
+ data: mockStore,
319
348
  });
320
349
  vi.mocked(mockServices.index.indexStore).mockResolvedValue({
321
350
  success: true,
322
- data: { documentsIndexed: 10, chunksCreated: 50, timeMs: 1000 }
351
+ data: { documentsIndexed: 10, chunksCreated: 50, timeMs: 1000 },
323
352
  });
324
353
 
325
354
  await handleAddRepo({ url: 'https://github.com/user/test.git' });
@@ -330,7 +359,7 @@ describe('Commands - handleAddRepo', () => {
330
359
  it('exits on store creation failure', async () => {
331
360
  vi.mocked(mockServices.store.create).mockResolvedValue({
332
361
  success: false,
333
- error: new Error('Clone failed')
362
+ error: new Error('Clone failed'),
334
363
  });
335
364
 
336
365
  try {
@@ -346,11 +375,18 @@ describe('Commands - handleAddRepo', () => {
346
375
  it('reports indexing failure without exiting', async () => {
347
376
  vi.mocked(mockServices.store.create).mockResolvedValue({
348
377
  success: true,
349
- data: { id: 'store-1', name: 'test', type: 'repo', path: '/tmp/test', createdAt: new Date(), updatedAt: new Date() }
378
+ data: {
379
+ id: 'store-1',
380
+ name: 'test',
381
+ type: 'repo',
382
+ path: '/tmp/test',
383
+ createdAt: new Date(),
384
+ updatedAt: new Date(),
385
+ },
350
386
  });
351
387
  vi.mocked(mockServices.index.indexStore).mockResolvedValue({
352
388
  success: false,
353
- error: new Error('Indexing failed')
389
+ error: new Error('Indexing failed'),
354
390
  });
355
391
 
356
392
  await handleAddRepo({ url: 'https://github.com/user/repo.git' });
@@ -371,11 +407,11 @@ describe('Commands - handleAddFolder', () => {
371
407
 
372
408
  mockServices = {
373
409
  store: {
374
- create: vi.fn()
410
+ create: vi.fn(),
375
411
  },
376
412
  index: {
377
- indexStore: vi.fn()
378
- }
413
+ indexStore: vi.fn(),
414
+ },
379
415
  } as unknown as ServiceContainer;
380
416
 
381
417
  vi.mocked(createServices).mockResolvedValue(mockServices);
@@ -392,11 +428,18 @@ describe('Commands - handleAddFolder', () => {
392
428
  it('creates file store with basename when no name provided', async () => {
393
429
  vi.mocked(mockServices.store.create).mockResolvedValue({
394
430
  success: true,
395
- data: { id: 'store-1', name: 'my-folder', type: 'file', path: '/path/to/my-folder', createdAt: new Date(), updatedAt: new Date() }
431
+ data: {
432
+ id: 'store-1',
433
+ name: 'my-folder',
434
+ type: 'file',
435
+ path: '/path/to/my-folder',
436
+ createdAt: new Date(),
437
+ updatedAt: new Date(),
438
+ },
396
439
  });
397
440
  vi.mocked(mockServices.index.indexStore).mockResolvedValue({
398
441
  success: true,
399
- data: { documentsIndexed: 5, chunksCreated: 20, timeMs: 500 }
442
+ data: { documentsIndexed: 5, chunksCreated: 20, timeMs: 500 },
400
443
  });
401
444
 
402
445
  await handleAddFolder({ path: '/path/to/my-folder' });
@@ -404,18 +447,25 @@ describe('Commands - handleAddFolder', () => {
404
447
  expect(mockServices.store.create).toHaveBeenCalledWith({
405
448
  name: 'my-folder',
406
449
  type: 'file',
407
- path: '/path/to/my-folder'
450
+ path: '/path/to/my-folder',
408
451
  });
409
452
  });
410
453
 
411
454
  it('uses custom name when provided', async () => {
412
455
  vi.mocked(mockServices.store.create).mockResolvedValue({
413
456
  success: true,
414
- data: { id: 'store-1', name: 'custom', type: 'file', path: '/path/folder', createdAt: new Date(), updatedAt: new Date() }
457
+ data: {
458
+ id: 'store-1',
459
+ name: 'custom',
460
+ type: 'file',
461
+ path: '/path/folder',
462
+ createdAt: new Date(),
463
+ updatedAt: new Date(),
464
+ },
415
465
  });
416
466
  vi.mocked(mockServices.index.indexStore).mockResolvedValue({
417
467
  success: true,
418
- data: { documentsIndexed: 5, chunksCreated: 20, timeMs: 500 }
468
+ data: { documentsIndexed: 5, chunksCreated: 20, timeMs: 500 },
419
469
  });
420
470
 
421
471
  await handleAddFolder({ path: '/path/folder', name: 'custom' });
@@ -423,20 +473,27 @@ describe('Commands - handleAddFolder', () => {
423
473
  expect(mockServices.store.create).toHaveBeenCalledWith({
424
474
  name: 'custom',
425
475
  type: 'file',
426
- path: '/path/folder'
476
+ path: '/path/folder',
427
477
  });
428
478
  });
429
479
 
430
480
  it('auto-indexes after folder store creation', async () => {
431
- const mockStore = { id: 'store-1', name: 'test', type: 'file' as const, path: '/tmp/test', createdAt: new Date(), updatedAt: new Date() };
481
+ const mockStore = {
482
+ id: 'store-1',
483
+ name: 'test',
484
+ type: 'file' as const,
485
+ path: '/tmp/test',
486
+ createdAt: new Date(),
487
+ updatedAt: new Date(),
488
+ };
432
489
 
433
490
  vi.mocked(mockServices.store.create).mockResolvedValue({
434
491
  success: true,
435
- data: mockStore
492
+ data: mockStore,
436
493
  });
437
494
  vi.mocked(mockServices.index.indexStore).mockResolvedValue({
438
495
  success: true,
439
- data: { documentsIndexed: 5, chunksCreated: 20, timeMs: 500 }
496
+ data: { documentsIndexed: 5, chunksCreated: 20, timeMs: 500 },
440
497
  });
441
498
 
442
499
  await handleAddFolder({ path: '/tmp/test' });
@@ -447,7 +504,7 @@ describe('Commands - handleAddFolder', () => {
447
504
  it('exits on folder store creation failure', async () => {
448
505
  vi.mocked(mockServices.store.create).mockResolvedValue({
449
506
  success: false,
450
- error: new Error('Path not found')
507
+ error: new Error('Path not found'),
451
508
  });
452
509
 
453
510
  try {
@@ -472,11 +529,11 @@ describe('Commands - handleIndex', () => {
472
529
 
473
530
  mockServices = {
474
531
  store: {
475
- getByIdOrName: vi.fn()
532
+ getByIdOrName: vi.fn(),
476
533
  },
477
534
  index: {
478
- indexStore: vi.fn()
479
- }
535
+ indexStore: vi.fn(),
536
+ },
480
537
  } as unknown as ServiceContainer;
481
538
 
482
539
  vi.mocked(createServices).mockResolvedValue(mockServices);
@@ -491,12 +548,19 @@ describe('Commands - handleIndex', () => {
491
548
  });
492
549
 
493
550
  it('indexes store by id', async () => {
494
- const mockStore = { id: 'store-1', name: 'test', type: 'file' as const, path: '/tmp/test', createdAt: new Date(), updatedAt: new Date() };
551
+ const mockStore = {
552
+ id: 'store-1',
553
+ name: 'test',
554
+ type: 'file' as const,
555
+ path: '/tmp/test',
556
+ createdAt: new Date(),
557
+ updatedAt: new Date(),
558
+ };
495
559
 
496
560
  vi.mocked(mockServices.store.getByIdOrName).mockResolvedValue(mockStore);
497
561
  vi.mocked(mockServices.index.indexStore).mockResolvedValue({
498
562
  success: true,
499
- data: { documentsIndexed: 10, chunksCreated: 50, timeMs: 1000 }
563
+ data: { documentsIndexed: 10, chunksCreated: 50, timeMs: 1000 },
500
564
  });
501
565
 
502
566
  await handleIndex({ store: 'store-1' });
@@ -506,12 +570,19 @@ describe('Commands - handleIndex', () => {
506
570
  });
507
571
 
508
572
  it('indexes store by name', async () => {
509
- const mockStore = { id: 'store-1', name: 'my-store', type: 'file' as const, path: '/tmp/test', createdAt: new Date(), updatedAt: new Date() };
573
+ const mockStore = {
574
+ id: 'store-1',
575
+ name: 'my-store',
576
+ type: 'file' as const,
577
+ path: '/tmp/test',
578
+ createdAt: new Date(),
579
+ updatedAt: new Date(),
580
+ };
510
581
 
511
582
  vi.mocked(mockServices.store.getByIdOrName).mockResolvedValue(mockStore);
512
583
  vi.mocked(mockServices.index.indexStore).mockResolvedValue({
513
584
  success: true,
514
- data: { documentsIndexed: 10, chunksCreated: 50, timeMs: 1000 }
585
+ data: { documentsIndexed: 10, chunksCreated: 50, timeMs: 1000 },
515
586
  });
516
587
 
517
588
  await handleIndex({ store: 'my-store' });
@@ -520,12 +591,19 @@ describe('Commands - handleIndex', () => {
520
591
  });
521
592
 
522
593
  it('displays indexing statistics on success', async () => {
523
- const mockStore = { id: 'store-1', name: 'test', type: 'file' as const, path: '/tmp/test', createdAt: new Date(), updatedAt: new Date() };
594
+ const mockStore = {
595
+ id: 'store-1',
596
+ name: 'test',
597
+ type: 'file' as const,
598
+ path: '/tmp/test',
599
+ createdAt: new Date(),
600
+ updatedAt: new Date(),
601
+ };
524
602
 
525
603
  vi.mocked(mockServices.store.getByIdOrName).mockResolvedValue(mockStore);
526
604
  vi.mocked(mockServices.index.indexStore).mockResolvedValue({
527
605
  success: true,
528
- data: { documentsIndexed: 25, chunksCreated: 100, timeMs: 2000 }
606
+ data: { documentsIndexed: 25, chunksCreated: 100, timeMs: 2000 },
529
607
  });
530
608
 
531
609
  await handleIndex({ store: 'test' });
@@ -548,12 +626,19 @@ describe('Commands - handleIndex', () => {
548
626
  });
549
627
 
550
628
  it('exits on indexing failure', async () => {
551
- const mockStore = { id: 'store-1', name: 'test', type: 'file' as const, path: '/tmp/test', createdAt: new Date(), updatedAt: new Date() };
629
+ const mockStore = {
630
+ id: 'store-1',
631
+ name: 'test',
632
+ type: 'file' as const,
633
+ path: '/tmp/test',
634
+ createdAt: new Date(),
635
+ updatedAt: new Date(),
636
+ };
552
637
 
553
638
  vi.mocked(mockServices.store.getByIdOrName).mockResolvedValue(mockStore);
554
639
  vi.mocked(mockServices.index.indexStore).mockResolvedValue({
555
640
  success: false,
556
- error: new Error('Indexing error')
641
+ error: new Error('Indexing error'),
557
642
  });
558
643
 
559
644
  try {
@@ -576,8 +661,8 @@ describe('Commands - handleStores', () => {
576
661
 
577
662
  mockServices = {
578
663
  store: {
579
- list: vi.fn()
580
- }
664
+ list: vi.fn(),
665
+ },
581
666
  } as unknown as ServiceContainer;
582
667
 
583
668
  vi.mocked(createServices).mockResolvedValue(mockServices);
@@ -598,7 +683,7 @@ describe('Commands - handleStores', () => {
598
683
  path: '/tmp/test',
599
684
  description: 'Test store',
600
685
  createdAt: new Date(),
601
- updatedAt: new Date()
686
+ updatedAt: new Date(),
602
687
  },
603
688
  {
604
689
  id: 'store-2',
@@ -607,8 +692,8 @@ describe('Commands - handleStores', () => {
607
692
  path: '/tmp/repo',
608
693
  url: 'https://github.com/user/repo.git',
609
694
  createdAt: new Date(),
610
- updatedAt: new Date()
611
- }
695
+ updatedAt: new Date(),
696
+ },
612
697
  ];
613
698
 
614
699
  vi.mocked(mockServices.store.list).mockResolvedValue(mockStores);
@@ -647,8 +732,8 @@ describe('Commands - handleSuggest', () => {
647
732
 
648
733
  mockServices = {
649
734
  store: {
650
- list: vi.fn()
651
- }
735
+ list: vi.fn(),
736
+ },
652
737
  } as unknown as ServiceContainer;
653
738
 
654
739
  vi.mocked(createServices).mockResolvedValue(mockServices);
@@ -667,7 +752,7 @@ describe('Commands - handleSuggest', () => {
667
752
 
668
753
  DependencyUsageAnalyzer.prototype.analyze = vi.fn().mockResolvedValue({
669
754
  success: false,
670
- error: new Error('Analysis failed')
755
+ error: new Error('Analysis failed'),
671
756
  });
672
757
 
673
758
  try {
@@ -689,13 +774,15 @@ describe('Commands - handleSuggest', () => {
689
774
  usages: [],
690
775
  totalFilesScanned: 10,
691
776
  skippedFiles: 0,
692
- analysisTimeMs: 100
693
- }
777
+ analysisTimeMs: 100,
778
+ },
694
779
  });
695
780
 
696
781
  await handleSuggest();
697
782
 
698
- expect(consoleLogSpy).toHaveBeenCalledWith(expect.stringContaining('No external dependencies found'));
783
+ expect(consoleLogSpy).toHaveBeenCalledWith(
784
+ expect.stringContaining('No external dependencies found')
785
+ );
699
786
  });
700
787
 
701
788
  it('filters out packages already in stores', async () => {
@@ -706,23 +793,42 @@ describe('Commands - handleSuggest', () => {
706
793
  success: true,
707
794
  data: {
708
795
  usages: [
709
- { packageName: 'react', importCount: 50, fileCount: 10, files: [], isDevDependency: false },
710
- { packageName: 'lodash', importCount: 30, fileCount: 5, files: [], isDevDependency: false }
796
+ {
797
+ packageName: 'react',
798
+ importCount: 50,
799
+ fileCount: 10,
800
+ files: [],
801
+ isDevDependency: false,
802
+ },
803
+ {
804
+ packageName: 'lodash',
805
+ importCount: 30,
806
+ fileCount: 5,
807
+ files: [],
808
+ isDevDependency: false,
809
+ },
711
810
  ],
712
811
  totalFilesScanned: 20,
713
812
  skippedFiles: 0,
714
- analysisTimeMs: 200
715
- }
813
+ analysisTimeMs: 200,
814
+ },
716
815
  });
717
816
 
718
817
  RepoUrlResolver.prototype.findRepoUrl = vi.fn().mockResolvedValue({
719
818
  url: 'https://github.com/lodash/lodash',
720
819
  confidence: 'high',
721
- source: 'registry'
820
+ source: 'registry',
722
821
  });
723
822
 
724
823
  vi.mocked(mockServices.store.list).mockResolvedValue([
725
- { id: 'store-1', name: 'react', type: 'repo', path: '/tmp/react', createdAt: new Date(), updatedAt: new Date() }
824
+ {
825
+ id: 'store-1',
826
+ name: 'react',
827
+ type: 'repo',
828
+ path: '/tmp/react',
829
+ createdAt: new Date(),
830
+ updatedAt: new Date(),
831
+ },
726
832
  ]);
727
833
 
728
834
  await handleSuggest();
@@ -738,21 +844,36 @@ describe('Commands - handleSuggest', () => {
738
844
  success: true,
739
845
  data: {
740
846
  usages: [
741
- { packageName: 'react', importCount: 50, fileCount: 10, files: [], isDevDependency: false }
847
+ {
848
+ packageName: 'react',
849
+ importCount: 50,
850
+ fileCount: 10,
851
+ files: [],
852
+ isDevDependency: false,
853
+ },
742
854
  ],
743
855
  totalFilesScanned: 20,
744
856
  skippedFiles: 0,
745
- analysisTimeMs: 200
746
- }
857
+ analysisTimeMs: 200,
858
+ },
747
859
  });
748
860
 
749
861
  vi.mocked(mockServices.store.list).mockResolvedValue([
750
- { id: 'store-1', name: 'react', type: 'repo', path: '/tmp/react', createdAt: new Date(), updatedAt: new Date() }
862
+ {
863
+ id: 'store-1',
864
+ name: 'react',
865
+ type: 'repo',
866
+ path: '/tmp/react',
867
+ createdAt: new Date(),
868
+ updatedAt: new Date(),
869
+ },
751
870
  ]);
752
871
 
753
872
  await handleSuggest();
754
873
 
755
- expect(consoleLogSpy).toHaveBeenCalledWith(expect.stringContaining('All dependencies are already in knowledge stores'));
874
+ expect(consoleLogSpy).toHaveBeenCalledWith(
875
+ expect.stringContaining('All dependencies are already in knowledge stores')
876
+ );
756
877
  });
757
878
 
758
879
  it('displays top 5 suggestions with repo URLs', async () => {
@@ -763,19 +884,31 @@ describe('Commands - handleSuggest', () => {
763
884
  success: true,
764
885
  data: {
765
886
  usages: [
766
- { packageName: 'react', importCount: 100, fileCount: 20, files: [], isDevDependency: false },
767
- { packageName: 'lodash', importCount: 80, fileCount: 15, files: [], isDevDependency: false }
887
+ {
888
+ packageName: 'react',
889
+ importCount: 100,
890
+ fileCount: 20,
891
+ files: [],
892
+ isDevDependency: false,
893
+ },
894
+ {
895
+ packageName: 'lodash',
896
+ importCount: 80,
897
+ fileCount: 15,
898
+ files: [],
899
+ isDevDependency: false,
900
+ },
768
901
  ],
769
902
  totalFilesScanned: 30,
770
903
  skippedFiles: 0,
771
- analysisTimeMs: 300
772
- }
904
+ analysisTimeMs: 300,
905
+ },
773
906
  });
774
907
 
775
908
  RepoUrlResolver.prototype.findRepoUrl = vi.fn().mockResolvedValue({
776
909
  url: 'https://github.com/facebook/react',
777
910
  confidence: 'high',
778
- source: 'registry'
911
+ source: 'registry',
779
912
  });
780
913
 
781
914
  vi.mocked(mockServices.store.list).mockResolvedValue([]);
@@ -784,6 +917,8 @@ describe('Commands - handleSuggest', () => {
784
917
 
785
918
  expect(consoleLogSpy).toHaveBeenCalledWith(expect.stringContaining('react'));
786
919
  expect(consoleLogSpy).toHaveBeenCalledWith(expect.stringContaining('100 imports'));
787
- expect(consoleLogSpy).toHaveBeenCalledWith(expect.stringContaining('https://github.com/facebook/react'));
920
+ expect(consoleLogSpy).toHaveBeenCalledWith(
921
+ expect.stringContaining('https://github.com/facebook/react')
922
+ );
788
923
  });
789
924
  });