sweet-search 0.0.1 → 2.3.0

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 (161) hide show
  1. package/LICENSE +190 -0
  2. package/NOTICE +23 -0
  3. package/core/cli.js +51 -0
  4. package/core/config.js +27 -0
  5. package/core/embedding/embedding-cache.js +467 -0
  6. package/core/embedding/embedding-local-model.js +845 -0
  7. package/core/embedding/embedding-remote.js +492 -0
  8. package/core/embedding/embedding-service.js +712 -0
  9. package/core/embedding/embedding-telemetry.js +219 -0
  10. package/core/embedding/index.js +40 -0
  11. package/core/graph/community-detector.js +294 -0
  12. package/core/graph/graph-expansion.js +839 -0
  13. package/core/graph/graph-extractor.js +2304 -0
  14. package/core/graph/graph-search.js +2148 -0
  15. package/core/graph/hcgs-generator.js +666 -0
  16. package/core/graph/index.js +16 -0
  17. package/core/graph/leiden-algorithm.js +547 -0
  18. package/core/graph/relationship-resolver.js +366 -0
  19. package/core/graph/repo-map.js +408 -0
  20. package/core/graph/summary-manager.js +549 -0
  21. package/core/indexing/artifact-builder.js +1054 -0
  22. package/core/indexing/ast-chunker.js +709 -0
  23. package/core/indexing/chunking/chunk-builder.js +170 -0
  24. package/core/indexing/chunking/markdown-chunker.js +503 -0
  25. package/core/indexing/chunking/plaintext-chunker.js +104 -0
  26. package/core/indexing/dedup/dedup-phase.js +159 -0
  27. package/core/indexing/dedup/exemplar-selector.js +65 -0
  28. package/core/indexing/document-chunker.js +56 -0
  29. package/core/indexing/incremental-parser.js +390 -0
  30. package/core/indexing/incremental-tracker.js +761 -0
  31. package/core/indexing/index-codebase-v21.js +472 -0
  32. package/core/indexing/index-maintainer.mjs +1674 -0
  33. package/core/indexing/index.js +90 -0
  34. package/core/indexing/indexer-ann.js +1077 -0
  35. package/core/indexing/indexer-build.js +742 -0
  36. package/core/indexing/indexer-phases.js +800 -0
  37. package/core/indexing/indexer-pool.js +764 -0
  38. package/core/indexing/indexer-sparse-gram.js +98 -0
  39. package/core/indexing/indexer-utils.js +536 -0
  40. package/core/indexing/indexer-worker.js +148 -0
  41. package/core/indexing/li-skip-policy.js +225 -0
  42. package/core/indexing/merkle-tracker.js +244 -0
  43. package/core/indexing/model-pool.js +166 -0
  44. package/core/infrastructure/code-graph-repository.js +120 -0
  45. package/core/infrastructure/codebase-repository.js +131 -0
  46. package/core/infrastructure/config/dedup.js +54 -0
  47. package/core/infrastructure/config/embedding.js +298 -0
  48. package/core/infrastructure/config/graph.js +80 -0
  49. package/core/infrastructure/config/index.js +82 -0
  50. package/core/infrastructure/config/indexing.js +8 -0
  51. package/core/infrastructure/config/platform.js +254 -0
  52. package/core/infrastructure/config/ranking.js +221 -0
  53. package/core/infrastructure/config/search.js +396 -0
  54. package/core/infrastructure/config/translation.js +89 -0
  55. package/core/infrastructure/config/vector-store.js +114 -0
  56. package/core/infrastructure/constants.js +86 -0
  57. package/core/infrastructure/coreml-cascade.js +909 -0
  58. package/core/infrastructure/coreml-cascade.json +46 -0
  59. package/core/infrastructure/coreml-provider.js +81 -0
  60. package/core/infrastructure/db-utils.js +69 -0
  61. package/core/infrastructure/dedup-hashing.js +83 -0
  62. package/core/infrastructure/hardware-capability.js +332 -0
  63. package/core/infrastructure/index.js +104 -0
  64. package/core/infrastructure/language-patterns/maps.js +121 -0
  65. package/core/infrastructure/language-patterns/registry-core.js +323 -0
  66. package/core/infrastructure/language-patterns/registry-data-query.js +155 -0
  67. package/core/infrastructure/language-patterns/registry-object-oriented.js +285 -0
  68. package/core/infrastructure/language-patterns/registry-tooling.js +240 -0
  69. package/core/infrastructure/language-patterns/registry-web-style.js +143 -0
  70. package/core/infrastructure/language-patterns/registry.js +19 -0
  71. package/core/infrastructure/language-patterns.js +141 -0
  72. package/core/infrastructure/llm-provider.js +733 -0
  73. package/core/infrastructure/manifest.json +46 -0
  74. package/core/infrastructure/maxsim.wasm +0 -0
  75. package/core/infrastructure/model-fetcher.js +423 -0
  76. package/core/infrastructure/model-registry.js +214 -0
  77. package/core/infrastructure/native-inference.js +587 -0
  78. package/core/infrastructure/native-resolver.js +187 -0
  79. package/core/infrastructure/native-sparse-gram.js +257 -0
  80. package/core/infrastructure/native-tokenizer.js +160 -0
  81. package/core/infrastructure/onnx-mutex.js +45 -0
  82. package/core/infrastructure/onnx-session-utils.js +261 -0
  83. package/core/infrastructure/ort-pipeline.js +111 -0
  84. package/core/infrastructure/project-detector.js +102 -0
  85. package/core/infrastructure/quantization.js +410 -0
  86. package/core/infrastructure/simd-distance.js +502 -0
  87. package/core/infrastructure/simd-distance.wasm +0 -0
  88. package/core/infrastructure/tree-sitter-provider.js +665 -0
  89. package/core/infrastructure/webgpu-maxsim.js +222 -0
  90. package/core/query/index.js +35 -0
  91. package/core/query/intent-detector.js +201 -0
  92. package/core/query/intent-router.js +156 -0
  93. package/core/query/query-router-catboost.js +222 -0
  94. package/core/query/query-router-ml.js +266 -0
  95. package/core/query/query-router.js +213 -0
  96. package/core/ranking/cascaded-scorer.js +379 -0
  97. package/core/ranking/flashrank.js +810 -0
  98. package/core/ranking/index.js +49 -0
  99. package/core/ranking/late-interaction-index.js +2383 -0
  100. package/core/ranking/late-interaction-model.js +812 -0
  101. package/core/ranking/local-reranker.js +374 -0
  102. package/core/ranking/mmr.js +379 -0
  103. package/core/ranking/quality-scorer.js +363 -0
  104. package/core/search/context-expander.js +1167 -0
  105. package/core/search/dedup/sibling-expander.js +327 -0
  106. package/core/search/index.js +16 -0
  107. package/core/search/search-boost.js +259 -0
  108. package/core/search/search-cli.js +544 -0
  109. package/core/search/search-format.js +282 -0
  110. package/core/search/search-fusion.js +327 -0
  111. package/core/search/search-hybrid.js +204 -0
  112. package/core/search/search-pattern-chunks.js +337 -0
  113. package/core/search/search-pattern-planner.js +439 -0
  114. package/core/search/search-pattern-prefilter.js +412 -0
  115. package/core/search/search-pattern-ripgrep.js +663 -0
  116. package/core/search/search-pattern.js +463 -0
  117. package/core/search/search-postprocess.js +452 -0
  118. package/core/search/search-semantic.js +706 -0
  119. package/core/search/search-server.js +554 -0
  120. package/core/search/session-daemon-prewarm.mjs +164 -0
  121. package/core/search/session-warmup.js +595 -0
  122. package/core/search/sweet-search.js +632 -0
  123. package/core/search/warmup-metrics.js +532 -0
  124. package/core/start-server.js +6 -0
  125. package/core/training/query-router/features/extractor.js +762 -0
  126. package/core/training/query-router/features/multilingual-patterns.js +431 -0
  127. package/core/training/query-router/features/text-segmenter.js +303 -0
  128. package/core/training/query-router/features/unicode-utils.js +383 -0
  129. package/core/training/query-router/output/v45_router_d4.js +11521 -0
  130. package/core/training/query-router/output/v46_router_d4.js +11498 -0
  131. package/core/vector-store/binary-heap.js +227 -0
  132. package/core/vector-store/binary-hnsw-index.js +1004 -0
  133. package/core/vector-store/float-vector-store.js +234 -0
  134. package/core/vector-store/hnsw-index.js +580 -0
  135. package/core/vector-store/index.js +39 -0
  136. package/core/vector-store/seismic-index.js +498 -0
  137. package/core/vocabulary/index.js +84 -0
  138. package/core/vocabulary/vocab-constants.js +20 -0
  139. package/core/vocabulary/vocab-miner-extractors.js +375 -0
  140. package/core/vocabulary/vocab-miner-nl.js +404 -0
  141. package/core/vocabulary/vocab-miner-utils.js +146 -0
  142. package/core/vocabulary/vocab-miner.js +574 -0
  143. package/core/vocabulary/vocab-prewarm-cli.js +110 -0
  144. package/core/vocabulary/vocab-ranker.js +492 -0
  145. package/core/vocabulary/vocab-warmer.js +523 -0
  146. package/core/vocabulary/vocab-warmup-orchestrator.js +425 -0
  147. package/core/vocabulary/vocabulary-utils.js +704 -0
  148. package/crates/wasm-router/pkg/package.json +13 -0
  149. package/crates/wasm-router/pkg/query_router_wasm.d.ts +36 -0
  150. package/crates/wasm-router/pkg/query_router_wasm.js +271 -0
  151. package/crates/wasm-router/pkg/query_router_wasm_bg.wasm +0 -0
  152. package/crates/wasm-router/pkg/query_router_wasm_bg.wasm.d.ts +19 -0
  153. package/mcp/config-gen.js +121 -0
  154. package/mcp/server.js +335 -0
  155. package/mcp/tool-handlers.js +476 -0
  156. package/package.json +131 -9
  157. package/scripts/benchmark-harness.js +794 -0
  158. package/scripts/init.js +1058 -0
  159. package/scripts/smoke-test.js +435 -0
  160. package/scripts/uninstall.js +478 -0
  161. package/scripts/verify-runtime.js +176 -0
@@ -0,0 +1,396 @@
1
+ /**
2
+ * Search Configuration — file patterns, routing, performance targets.
3
+ * Split from core/config.js during DDD migration.
4
+ */
5
+
6
+ import { existsSync, readFileSync } from 'fs';
7
+ import path from 'path';
8
+
9
+ // =============================================================================
10
+ // QUERY ROUTING CONFIGURATION
11
+ // =============================================================================
12
+
13
+ export const ROUTING_CONFIG = {
14
+ lexicalPatterns: [
15
+ /^[A-Z][a-zA-Z0-9]*$/, // CamelCase (starts with capital)
16
+ /^[a-z]+[A-Z][a-zA-Z0-9]*$/, // camelCase (has capital in middle) - Fix #3
17
+ /^[a-z][a-z0-9_]*_[a-z0-9_]+$/, // snake_case (must have underscore) - Fix #3
18
+ /^[A-Z_][A-Z0-9_]*$/, // SCREAMING_SNAKE
19
+ /\.(java|js|jsx|ts|tsx|proto)$/, // File extensions
20
+ /\/|\\/, // Paths
21
+ /"[^"]*"/, // Quoted strings
22
+ /\bclass\s+\w+/,
23
+ /\bfunction\s+\w+/,
24
+ /\binterface\s+\w+/,
25
+ // Fix #5: Code Structural Keywords
26
+ /\b(method|constructor|field|property|annotation|decorator|enum|abstract|static|final|private|public|protected)\b/i,
27
+ /^@\w+/, // Annotations: @Override, @Test
28
+ /\b(extends|implements)\s+\w+/i,
29
+ ],
30
+ semanticPatterns: [
31
+ /how\s+(does|do|to|can)/i,
32
+ /what\s+(is|are|does)/i,
33
+ /why\s+(does|is|are)/i,
34
+ /where\s+(is|are|does)/i,
35
+ /find\s+.*\s+(that|which)/i,
36
+ /\s+(related|similar)\s+to/i,
37
+ /implement/i,
38
+ /handle|handling/i,
39
+ /work(s|ing)?/i,
40
+ // Fix #4: Imperative Command Detection
41
+ /^(list|show|find|get|fetch|retrieve|search|locate)\s+(all|any)/i,
42
+ /^(list|show|display)\s+/i,
43
+ ],
44
+ defaultMode: 'hybrid',
45
+ };
46
+
47
+ // =============================================================================
48
+ // FILE PATTERNS
49
+ // =============================================================================
50
+
51
+ export const FILE_PATTERNS = {
52
+ include: [
53
+ // Source code (all major languages)
54
+ '**/*.{js,jsx,ts,tsx,mjs,cjs}', // JavaScript/TypeScript
55
+ '**/*.{java,kt,kts,scala,groovy}', // JVM
56
+ '**/*.{py,pyi}', // Python
57
+ '**/*.go', // Go
58
+ '**/*.rs', // Rust
59
+ '**/*.{c,cpp,cc,cxx,h,hpp,hxx}', // C/C++
60
+ '**/*.{cs,fs,vb}', // .NET
61
+ '**/*.{rb,erb}', // Ruby
62
+ '**/*.php', // PHP
63
+ '**/*.{swift,m,mm}', // Apple
64
+ '**/*.{lua,zig,nim,ex,exs}', // Other
65
+ '**/*.{sh,bash,zsh,fish,ps1}', // Shell
66
+ '**/*.sql', // SQL
67
+ '**/*.proto', // Protobuf
68
+ '**/*.{graphql,gql}', // GraphQL
69
+ // Config & docs
70
+ '**/*.{json,jsonc,json5}', // JSON
71
+ '**/*.{yaml,yml}', // YAML
72
+ '**/*.toml', // TOML
73
+ '**/*.{xml,xsl,xsd,wsdl,pom,csproj}', // XML
74
+ '**/*.{md,mdx,mdc,rst,txt}', // Documentation + Cursor rules
75
+ '**/*.{html,htm,xhtml,vue,svelte}', // Web markup/SFC
76
+ '**/*.{css,scss,sass,less}', // Stylesheets
77
+ '**/*.svg', // SVG
78
+ // Build & deploy
79
+ '**/Dockerfile', // Dockerfile
80
+ '**/Dockerfile.*', // Dockerfile variants
81
+ '**/*.dockerfile', // Dockerfile alt extension
82
+ '**/Makefile', // Makefile
83
+ '**/*.mk', // Makefile includes
84
+ // Project markers
85
+ '**/CLAUDE.md',
86
+ '**/AGENTS.md',
87
+ '**/README.md',
88
+ '**/.cursorrules',
89
+ '**/.clinerules',
90
+ '**/.roorules',
91
+ '**/.roorules-*',
92
+ '**/.windsurfrules',
93
+ '**/.aider.conf.yml',
94
+ ],
95
+ exclude: [
96
+ // ── Package manager dependencies ──────────────────────────────────────
97
+ '**/node_modules/**',
98
+ '**/bower_components/**',
99
+ '**/jspm_packages/**',
100
+ '**/.yarn/**',
101
+ '**/.pnp.*',
102
+ '**/vendor/**',
103
+ '**/vendors/**',
104
+ '**/third_party/**',
105
+ '**/thirdparty/**',
106
+ '**/.cargo/**',
107
+ '**/Godeps/**',
108
+ '**/Pods/**',
109
+ '**/Carthage/**',
110
+ '**/.gradle/**',
111
+ '**/.mvn/**',
112
+ '**/venv/**',
113
+ '**/.venv/**',
114
+ '**/site-packages/**',
115
+ '**/_esy/**',
116
+
117
+ // ── Build outputs & generated code ────────────────────────────────────
118
+ '**/target/**',
119
+ '**/build/**',
120
+ '**/dist/**',
121
+ '**/out/**',
122
+ '**/.next/**',
123
+ '**/.nuxt/**',
124
+ '**/.output/**',
125
+ '**/.svelte-kit/**',
126
+ '**/.turbo/**',
127
+ '**/.angular/**',
128
+ '**/.parcel-cache/**',
129
+ '**/storybook-static/**',
130
+ '**/__generated__/**',
131
+ '**/generated/**',
132
+ '**/.vercel/**',
133
+ '**/.netlify/**',
134
+ '**/.serverless/**',
135
+ '**/.aws-sam/**',
136
+ '**/.terraform/**',
137
+
138
+ // ── VCS & IDE ─────────────────────────────────────────────────────────
139
+ '**/.git/**',
140
+ '**/.idea/**',
141
+ '**/.vscode/**',
142
+ '**/.vs/**',
143
+ '**/.eclipse/**',
144
+ '**/.settings/**',
145
+
146
+ // ── Caches & temp ─────────────────────────────────────────────────────
147
+ '**/.vite/**',
148
+ '**/coverage/**',
149
+ '**/.coverage/**',
150
+ '**/__pycache__/**',
151
+ '**/.mypy_cache/**',
152
+ '**/.pytest_cache/**',
153
+ '**/.ruff_cache/**',
154
+ '**/.tox/**',
155
+ '**/.eggs/**',
156
+ '**/*.egg-info/**',
157
+ '**/.pytype/**',
158
+ '**/htmlcov/**',
159
+ '**/.cache/**',
160
+ '**/.nx/**',
161
+ '**/.eslintcache',
162
+ '**/.stylelintcache',
163
+ '**/tmp/**',
164
+ '**/.tmp/**',
165
+ '**/.temp/**',
166
+
167
+ // ── Lock files (all ecosystems) ───────────────────────────────────────
168
+ '**/package-lock.json',
169
+ '**/bun.lock',
170
+ '**/bun.lockb',
171
+ '**/yarn.lock',
172
+ '**/pnpm-lock.yaml',
173
+ '**/composer.lock',
174
+ '**/Cargo.lock',
175
+ '**/Gemfile.lock',
176
+ '**/poetry.lock',
177
+ '**/pdm.lock',
178
+ '**/uv.lock',
179
+ '**/Pipfile.lock',
180
+ '**/npm-shrinkwrap.json',
181
+ '**/deno.lock',
182
+ '**/pixi.lock',
183
+ '**/flake.lock',
184
+ '**/gradle.lockfile',
185
+ '**/.terraform.lock.hcl',
186
+ '**/go.sum',
187
+ '**/Package.resolved',
188
+
189
+ // ── Minified / bundled / sourcemaps ───────────────────────────────────
190
+ '**/*.min.js',
191
+ '**/*.min.mjs',
192
+ '**/*.min.cjs',
193
+ '**/*.min.css',
194
+ '**/*.bundle.js',
195
+ '**/*.bundle.css',
196
+ '**/*.umd.js',
197
+ '**/*.iife.js',
198
+ '**/*.chunk.js',
199
+ '**/*.map',
200
+
201
+ // ── Test snapshots ────────────────────────────────────────────────────
202
+ '**/*.snap',
203
+
204
+ // ── Binary & compiled artifacts ───────────────────────────────────────
205
+ '**/*.class',
206
+ '**/*.pyc',
207
+ '**/*.pyo',
208
+ '**/*.o',
209
+ '**/*.so',
210
+ '**/*.dylib',
211
+ '**/*.dll',
212
+ '**/*.exe',
213
+ '**/*.wasm',
214
+
215
+ // ── OS metadata & misc ────────────────────────────────────────────────
216
+ '**/*.log',
217
+ '**/.DS_Store',
218
+ '**/Thumbs.db',
219
+ '**/*.swp',
220
+ '**/*.swo',
221
+
222
+ // ── Secrets & environment files (all stacks) ────────────────────────
223
+ '**/.env',
224
+ '**/.env.*',
225
+
226
+ // ── .NET secrets & env-specific config ────────────────────────────────
227
+ '**/appsettings.Development.json',
228
+ '**/appsettings.Local.json',
229
+ '**/appsettings.Staging.json',
230
+ '**/appsettings.Production.json',
231
+ '**/secrets.json',
232
+ '**/*.user',
233
+
234
+ // ── Python (Django, FastAPI, Flask) secrets ───────────────────────────
235
+ '**/local_settings.py',
236
+ '**/settings/local.py',
237
+ '**/settings/dev.py',
238
+ '**/secrets.py',
239
+ '**/config/local.py',
240
+
241
+ // ── Java/Kotlin (Spring) env-specific config ─────────────────────────
242
+ '**/application-dev.properties',
243
+ '**/application-local.properties',
244
+ '**/application-test.properties',
245
+ '**/application-*-local.yml',
246
+ '**/application-*-local.yaml',
247
+
248
+ // ── Node/JS/TS secrets ────────────────────────────────────────────────
249
+ '**/config/secrets.js',
250
+ '**/config/secrets.ts',
251
+ '**/config/local.js',
252
+ '**/config/local.ts',
253
+ '**/config.local.js',
254
+ '**/config.local.ts',
255
+ '**/.firebaserc',
256
+
257
+ // ── Ruby (Rails) ──────────────────────────────────────────────────────
258
+ '**/config/credentials.yml.enc',
259
+
260
+ // ── PHP (Laravel) ─────────────────────────────────────────────────────
261
+ '**/config/local.php',
262
+
263
+ // ── Go / Rust / generic local config ──────────────────────────────────
264
+ '**/config.local.*',
265
+ '**/config/local.*',
266
+
267
+ // ── Mobile: iOS ───────────────────────────────────────────────────────
268
+ '**/Secrets.plist',
269
+ '**/GoogleService-Info.plist',
270
+ '**/*-Credentials.plist',
271
+ '**/Config/Secrets.swift',
272
+
273
+ // ── Mobile: Android ───────────────────────────────────────────────────
274
+ '**/local.properties',
275
+ '**/google-services.json',
276
+ '**/keystore.properties',
277
+ '**/secrets.properties',
278
+
279
+ // ── Embedded (Arduino, ESP-IDF, PlatformIO) ──────────────────────────
280
+ '**/credentials.h',
281
+ '**/secrets.h',
282
+ '**/config_private.h',
283
+ '**/sdkconfig.local',
284
+ '**/platformio.ini.local',
285
+ '**/*_credentials.*',
286
+
287
+ // ── Sweet Search data ─────────────────────────────────────────────────
288
+ '**/.sweet-search/**',
289
+ ],
290
+
291
+ // Default max file size for indexing (1 MB). Files larger than this are
292
+ // almost always generated data, minified bundles, or binary blobs that
293
+ // add noise without meaningful search value. Override per-project via
294
+ // "maxFileSize" in .sweet-search.config.json (value in bytes).
295
+ maxFileSize: 1 * 1024 * 1024,
296
+
297
+ // Align indexing with .gitignore by default. Agentic paths are allowlisted
298
+ // in AGENTIC_GITIGNORE_ALLOWLIST so local AI setup remains searchable.
299
+ respectGitignore: true,
300
+ };
301
+
302
+ // Agentic tooling paths that should stay indexable even when listed in
303
+ // .gitignore. This supports local AI workflow files without requiring users
304
+ // to maintain extra include rules.
305
+ export const AGENTIC_GITIGNORE_ALLOWLIST = {
306
+ directories: [
307
+ '.claude/',
308
+ '.agents/',
309
+ '.cursor/',
310
+ '.codex/',
311
+ '.cline/',
312
+ '.clinerules/',
313
+ '.roo/',
314
+ '.continue/',
315
+ '.windsurf/',
316
+ ],
317
+ files: [
318
+ '.cursorrules',
319
+ '.clinerules',
320
+ '.roorules',
321
+ '.windsurfrules',
322
+ '.aider.conf.yml',
323
+ '.aider.conf.yaml',
324
+ ],
325
+ filePrefixes: [
326
+ '.roorules-',
327
+ '.aider.',
328
+ ],
329
+ };
330
+
331
+ /**
332
+ * Load per-project configuration from .sweet-search.config.json
333
+ * Precedence: config file > defaults. Environment variables > config file.
334
+ *
335
+ * @param {string} [projectRoot] - Project root to search for config file
336
+ * @returns {{ include: string[], exclude: string[], maxFileSize: number, respectGitignore: boolean, projectRoot?: string }}
337
+ */
338
+ export function loadProjectConfig(projectRoot = process.cwd()) {
339
+ const configPath = path.join(projectRoot, '.sweet-search.config.json');
340
+
341
+ if (!existsSync(configPath)) {
342
+ return {
343
+ include: FILE_PATTERNS.include,
344
+ exclude: FILE_PATTERNS.exclude,
345
+ maxFileSize: FILE_PATTERNS.maxFileSize,
346
+ respectGitignore: FILE_PATTERNS.respectGitignore,
347
+ };
348
+ }
349
+
350
+ try {
351
+ const raw = readFileSync(configPath, 'utf-8');
352
+ const config = JSON.parse(raw);
353
+
354
+ // Validate known keys, warn on unknown
355
+ const knownKeys = new Set(['include', 'exclude', 'projectRoot', 'indexDocs', 'maxFileSize', 'respectGitignore', 'lateInteractionModel', 'cascade']);
356
+ for (const key of Object.keys(config)) {
357
+ if (!knownKeys.has(key)) {
358
+ console.error(`[sweet-search] Warning: unknown key "${key}" in .sweet-search.config.json`);
359
+ }
360
+ }
361
+
362
+ return {
363
+ include: Array.isArray(config.include) ? config.include : FILE_PATTERNS.include,
364
+ exclude: Array.isArray(config.exclude) ? [...FILE_PATTERNS.exclude, ...config.exclude] : FILE_PATTERNS.exclude,
365
+ maxFileSize: typeof config.maxFileSize === 'number' ? config.maxFileSize : FILE_PATTERNS.maxFileSize,
366
+ respectGitignore: typeof config.respectGitignore === 'boolean' ? config.respectGitignore : FILE_PATTERNS.respectGitignore,
367
+ ...(config.projectRoot ? { projectRoot: config.projectRoot } : {}),
368
+ ...(config.lateInteractionModel !== undefined ? { lateInteractionModel: config.lateInteractionModel } : {}),
369
+ ...(config.cascade ? { cascade: config.cascade } : {}),
370
+ };
371
+ } catch (err) {
372
+ console.error(`[sweet-search] Error loading .sweet-search.config.json: ${err.message}`);
373
+ return {
374
+ include: FILE_PATTERNS.include,
375
+ exclude: FILE_PATTERNS.exclude,
376
+ maxFileSize: FILE_PATTERNS.maxFileSize,
377
+ respectGitignore: FILE_PATTERNS.respectGitignore,
378
+ };
379
+ }
380
+ }
381
+
382
+ // =============================================================================
383
+ // PERFORMANCE TARGETS
384
+ // =============================================================================
385
+
386
+ export const PERFORMANCE_TARGETS = {
387
+ latency: {
388
+ lexicalP50: 10,
389
+ hnswLookupP50: 1,
390
+ semanticP50: 150,
391
+ rerankP50: 100,
392
+ },
393
+ accuracy: {
394
+ topKRecall: 0.85,
395
+ },
396
+ };
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Cerebras LLM Configuration — fast inference for HCGS and graph summary generation.
3
+ * Split from core/config.js during DDD migration.
4
+ */
5
+
6
+ const CEREBRAS_API_KEY = process.env.CEREBRAS_API_KEY || '';
7
+ const GROQ_API_KEY = process.env.GROQ_API_KEY || '';
8
+ const OPENROUTER_API_KEY = process.env.OPENROUTER_API_KEY || '';
9
+
10
+ // =============================================================================
11
+ // CEREBRAS GLM CONFIGURATION (Fast Standalone LLM)
12
+ // Reference: https://inference-docs.cerebras.ai/models/zai-glm-46
13
+ // =============================================================================
14
+
15
+ export const CEREBRAS_CONFIG = {
16
+ enabled: CEREBRAS_API_KEY.length > 0,
17
+ apiKey: CEREBRAS_API_KEY,
18
+ baseUrl: 'https://api.cerebras.ai/v1',
19
+
20
+ // Available models (December 2025)
21
+ // Run: node -e "fetch('https://api.cerebras.ai/v1/models', {headers:{'Authorization':'Bearer '+process.env.CEREBRAS_API_KEY}}).then(r=>r.json()).then(d=>d.data.forEach(m=>console.log(m.id)))"
22
+ models: {
23
+ // GLM-4.6: Best general purpose reasoning (~1000 tok/s)
24
+ 'glm-4.6': {
25
+ id: 'zai-glm-4.6',
26
+ contextLength: 131072, // 131K
27
+ features: ['reasoning', 'tool_use', 'json_mode'],
28
+ speed: '1000+ tok/s',
29
+ strengths: ['general', 'fast', 'reasoning'],
30
+ },
31
+ // Qwen 3 235B: Large MoE model for complex tasks
32
+ 'qwen3-235b': {
33
+ id: 'qwen-3-235b-a22b-instruct-2507',
34
+ contextLength: 32768,
35
+ features: ['instruct'],
36
+ speed: '500+ tok/s',
37
+ strengths: ['complex', 'multilingual'],
38
+ },
39
+ // Llama 3.3 70B: Strong all-rounder
40
+ 'llama-70b': {
41
+ id: 'llama-3.3-70b',
42
+ contextLength: 128000,
43
+ features: ['instruct', 'tool_use'],
44
+ speed: '800+ tok/s',
45
+ strengths: ['coding', 'general'],
46
+ },
47
+ // Llama 3.1 8B: Fast small model
48
+ 'llama-8b': {
49
+ id: 'llama3.1-8b',
50
+ contextLength: 128000,
51
+ features: ['instruct'],
52
+ speed: '2000+ tok/s',
53
+ strengths: ['fast', 'simple'],
54
+ },
55
+ // Qwen 3 32B: Good balance of speed and quality
56
+ 'qwen3-32b': {
57
+ id: 'qwen-3-32b',
58
+ contextLength: 32768,
59
+ features: ['instruct'],
60
+ speed: '1000+ tok/s',
61
+ strengths: ['balanced', 'multilingual'],
62
+ },
63
+ },
64
+
65
+ // Default model for different use cases
66
+ defaults: {
67
+ fast: 'zai-glm-4.6', // Speed + quality balance
68
+ coding: 'llama-3.3-70b', // Best for code
69
+ simple: 'llama3.1-8b', // Quick simple tasks
70
+ hcgs: 'llama3.1-8b', // Summary generation (fast, cheap — GLM-4.6 is overkill)
71
+ complex: 'qwen-3-235b-a22b-instruct-2507', // Complex reasoning
72
+ },
73
+
74
+ // Reasoning mode (disable for faster direct responses)
75
+ reasoning: {
76
+ // disable_reasoning: true skips chain-of-thought
77
+ fastMode: true, // Default: no CoT for speed
78
+ },
79
+ };
80
+
81
+ export function isCerebrasAvailable() {
82
+ return CEREBRAS_CONFIG.enabled;
83
+ }
84
+
85
+ export function getCerebrasModel(useCase = 'fast') {
86
+ return CEREBRAS_CONFIG.defaults[useCase] || CEREBRAS_CONFIG.defaults.fast;
87
+ }
88
+
89
+ // HCGS_CONFIG lives in ./graph.js (graph-related, not Cerebras)
@@ -0,0 +1,114 @@
1
+ /**
2
+ * Vector Store Configuration — HNSW, Binary HNSW, SEISMIC indices.
3
+ * Split from core/config.js during DDD migration.
4
+ */
5
+
6
+ import { EMBEDDING_CONFIG } from './embedding.js';
7
+
8
+ // =============================================================================
9
+ // HNSW INDEX CONFIGURATION
10
+ // =============================================================================
11
+
12
+ export const HNSW_CONFIG = {
13
+ // Dimension matches active provider's HNSW dimension
14
+ get dimension() {
15
+ return EMBEDDING_CONFIG.hnswDimension;
16
+ },
17
+
18
+ // Index construction
19
+ M: 16, // Bi-directional links
20
+ efConstruction: 200, // Construction-time candidate list
21
+
22
+ // Search parameters
23
+ efSearch: 100, // Query-time candidate list
24
+
25
+ // Distance metric
26
+ metric: 'cosine',
27
+
28
+ // Memory settings
29
+ maxElements: 100000,
30
+ };
31
+
32
+ // =============================================================================
33
+ // BINARY HNSW INDEX CONFIGURATION (32x memory reduction, 10x faster search)
34
+ // Reference: https://huggingface.co/blog/embedding-quantization
35
+ // =============================================================================
36
+
37
+ export const BINARY_HNSW_CONFIG = {
38
+ // Binary dimension = float dimension / 8 (bits to bytes)
39
+ // 512d float → 64 bytes binary
40
+ get dimension() {
41
+ return Math.ceil(EMBEDDING_CONFIG.hnswDimension / 8);
42
+ },
43
+
44
+ // Float dimension for rescore stage
45
+ get floatDimension() {
46
+ return EMBEDDING_CONFIG.hnswDimension;
47
+ },
48
+
49
+ // Index construction (can be more aggressive since search is cheap)
50
+ M: 64, // Dense graph for fast convergence + recall
51
+ efConstruction: 800, // High ef for quality graph construction
52
+
53
+ // Search parameters
54
+ efSearch: 400, // Higher budget — adaptive ef reduces for easy queries
55
+
56
+ // Distance metric
57
+ metric: 'hamming',
58
+
59
+ // Memory settings (can hold more since binary is 32x smaller)
60
+ maxElements: 500000,
61
+
62
+ // 3-stage retrieval configuration
63
+ retrieval: {
64
+ stage1Candidates: 1000, // Binary HNSW retrieves top 1000
65
+ stage2Candidates: 200, // Int8 rescores top 200 (legacy fixed, used as maxStage2 fallback)
66
+ stage2_5Candidates: 200, // Float rescore pool size (legacy fixed, used as maxStage2_5 fallback)
67
+ stage3Candidates: 20, // Reranker sees top 20
68
+
69
+ // Phase 1 flag: batched normalized-dot Stage 2 scoring.
70
+ // When false, falls back to per-candidate int8CosineSimilarity.
71
+ useBatchedDot: true,
72
+
73
+ // Phase 3: Adaptive oversampling (replaces fixed 200/200 pools)
74
+ // Pool sizes derived from k × oversample, adjusted by score spread.
75
+ adaptive: {
76
+ minStage2: 40, // Hard minimum for Stage 2 pool
77
+ maxStage2: 400, // Hard maximum for Stage 2 pool
78
+ oversample1: 10, // Stage 2 base = k × oversample1
79
+ minStage2_5: 20, // Hard minimum for Stage 2.5 pool
80
+ maxStage2_5: 200, // Hard maximum for Stage 2.5 pool
81
+ oversample2: 5, // Stage 2.5 base = k × oversample2
82
+ },
83
+ },
84
+
85
+ // Insertion order for graph quality ('sequential' | 'shuffle' | 'diversity')
86
+ insertionOrder: 'shuffle',
87
+
88
+ // Adaptive early termination thresholds (Fix 4).
89
+ // Tune via parameter sweep; values below are starting heuristics.
90
+ earlyTermination: {
91
+ windowSize: 16, // Sliding window for discovery rate
92
+ // [progressThreshold, discoveryRateThreshold]
93
+ // "If progress > X and discoveryRate < Y, stop."
94
+ thresholds: [
95
+ [0.3, 0.05], // Mature search with near-zero discovery
96
+ [0.6, 0.10], // Well-explored with diminishing returns
97
+ ],
98
+ },
99
+ };
100
+
101
+ // =============================================================================
102
+ // SEISMIC SPARSE VECTOR INDEX CONFIGURATION
103
+ // =============================================================================
104
+ // SEISMIC: block-based inverted index with summary pruning for learned sparse
105
+ // embeddings (SPLADE, etc.). Third retrieval pathway alongside FTS5 + HNSW.
106
+ // Currently DISABLED: requires a code-specific sparse encoder (SPLADE or similar)
107
+ // that is not yet available. See docs/AST_OPTIMIZATIONS.md #12 for full plan.
108
+
109
+ export const SEISMIC_CONFIG = {
110
+ enabled: false, // Disabled by default until sparse encoder is available
111
+ blockSize: 64, // Postings per block in inverted lists
112
+ alpha: 0.8, // Importance fraction (reserved for future scoring tuning)
113
+ weight: 0.2, // Weight in reciprocal rank fusion (when enabled)
114
+ };
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Shared constants for sweet-search
3
+ * Extracted to prevent drift between graph-search.js and sweet-search.js
4
+ */
5
+
6
+ export const SYMBOL_KIND_WEIGHTS = {
7
+ class: 1.0,
8
+ interface: 0.95,
9
+ struct: 0.95,
10
+ enum: 0.9,
11
+ function: 0.85,
12
+ method: 0.80,
13
+ constructor: 0.75,
14
+ constant: 0.7,
15
+ property: 0.65,
16
+ field: 0.6,
17
+ variable: 0.4,
18
+ parameter: 0.3,
19
+ reference: 0.2,
20
+ call: 0.15,
21
+ import: 0.1,
22
+ };
23
+
24
+ export const DEFINITION_TYPES = new Set([
25
+ 'class', 'interface', 'struct', 'enum', 'function', 'method', 'constructor'
26
+ ]);
27
+
28
+ /**
29
+ * Canonical set of code file extensions recognized by sweet-search.
30
+ * Used by both the indexer (sparse gram builder) and the search pipeline
31
+ * (ripgrep type filter + code file detection). Single source of truth.
32
+ */
33
+ export const CODE_FILE_EXTENSIONS = new Set([
34
+ 'js', 'ts', 'jsx', 'tsx', 'py', 'rs', 'go', 'java', 'c', 'cpp', 'h', 'hpp',
35
+ 'cs', 'rb', 'php', 'swift', 'kt', 'scala', 'lua', 'sh', 'zig', 'hs', 'ml',
36
+ 'ex', 'exs', 'clj', 'erl', 'r', 'jl', 'dart', 'v', 'nim', 'cr', 'd', 'f90',
37
+ 'ada', 'pas', 'cob', 'pl', 'pm', 'sql', 'graphql', 'proto', 'yaml', 'yml',
38
+ 'json', 'toml', 'xml', 'html', 'css', 'scss', 'sass', 'less', 'svelte',
39
+ 'vue', 'astro', 'mdx',
40
+ ]);
41
+
42
+ /**
43
+ * Ripgrep type definition glob matching CODE_FILE_EXTENSIONS.
44
+ * Used with --type-add to define a custom 'code' type for ripgrep.
45
+ */
46
+ export const RIPGREP_CODE_TYPE_GLOB =
47
+ 'code:*.{js,ts,jsx,tsx,py,rs,go,java,c,cpp,h,hpp,cs,rb,php,swift,kt,scala,lua,sh,zig,hs,ml,ex,exs,clj,erl,r,jl,dart,v,nim,cr,d,f90,ada,pas,cob,pl,pm,sql,graphql,proto,yaml,yml,json,toml,xml,html,css,scss,sass,less,svelte,vue,astro,mdx}';
48
+
49
+ /**
50
+ * Sparse gram symbol type bitmasks.
51
+ * These bit positions must match the Rust native addon's expectations.
52
+ * Used by both the indexer (to tag files) and the search pipeline (to filter).
53
+ */
54
+ export const SPARSE_SYMBOL_MASKS = {
55
+ function: 1 << 0,
56
+ class: 1 << 1,
57
+ method: 1 << 2,
58
+ import: 1 << 3,
59
+ type: 1 << 4,
60
+ other: 1 << 5,
61
+ };
62
+
63
+ /**
64
+ * Resolve a symbol type string to its sparse gram bitmask value.
65
+ * @param {string} symbolType
66
+ * @returns {number} bitmask (0 if unrecognized)
67
+ */
68
+ export function resolveSparseSymbolMask(symbolType) {
69
+ if (typeof symbolType !== 'string') return 0;
70
+
71
+ const normalized = symbolType.trim().toLowerCase();
72
+ if (!normalized) return 0;
73
+ if (normalized.includes('function')) return SPARSE_SYMBOL_MASKS.function;
74
+ if (normalized.includes('method')) return SPARSE_SYMBOL_MASKS.method;
75
+ if (normalized.includes('class')) return SPARSE_SYMBOL_MASKS.class;
76
+ if (normalized.includes('import')) return SPARSE_SYMBOL_MASKS.import;
77
+ if (
78
+ normalized.includes('type') ||
79
+ normalized.includes('interface') ||
80
+ normalized.includes('enum') ||
81
+ normalized.includes('typedef')
82
+ ) {
83
+ return SPARSE_SYMBOL_MASKS.type;
84
+ }
85
+ return SPARSE_SYMBOL_MASKS.other;
86
+ }