maskweaver 0.9.3 → 0.9.5

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 (246) hide show
  1. package/README.ko.md +279 -325
  2. package/README.md +109 -113
  3. package/assets/commands/meta/commands.json +34 -34
  4. package/assets/commands/weave-agents.md +12 -52
  5. package/assets/commands/weave-approve.md +12 -51
  6. package/assets/commands/weave-archive.md +21 -0
  7. package/assets/commands/weave-build.md +20 -89
  8. package/assets/commands/weave-craft.md +22 -43
  9. package/assets/commands/weave-help.md +37 -106
  10. package/assets/commands/weave-init.md +26 -108
  11. package/assets/commands/weave-interview.md +13 -111
  12. package/assets/commands/weave-map.md +13 -99
  13. package/assets/commands/weave-prepare.md +23 -69
  14. package/assets/commands/weave-refine-plan.md +26 -59
  15. package/assets/commands/weave-repair.md +22 -70
  16. package/assets/commands/weave-status.md +22 -155
  17. package/assets/commands/weave-troubleshoot.md +11 -47
  18. package/assets/commands/weave-verify.md +23 -44
  19. package/assets/commands/weave-worktree.md +27 -69
  20. package/dist/cli/doctor.js +5 -21
  21. package/dist/cli/install.d.ts +0 -8
  22. package/dist/cli/install.js +0 -39
  23. package/dist/context/config.d.ts +0 -22
  24. package/dist/context/config.js +0 -28
  25. package/dist/context/feature.d.ts +0 -39
  26. package/dist/context/feature.js +0 -77
  27. package/dist/context/files.d.ts +0 -13
  28. package/dist/context/files.js +1 -24
  29. package/dist/context/index.d.ts +0 -7
  30. package/dist/context/index.js +0 -12
  31. package/dist/context/project.d.ts +0 -21
  32. package/dist/context/project.js +0 -30
  33. package/dist/context/types.d.ts +0 -48
  34. package/dist/context/types.js +0 -12
  35. package/dist/context/utils.d.ts +0 -18
  36. package/dist/context/utils.js +0 -27
  37. package/dist/core/engine/promptBuilder.d.ts +0 -17
  38. package/dist/core/engine/promptBuilder.js +0 -28
  39. package/dist/core/index.d.ts +0 -6
  40. package/dist/core/index.js +0 -9
  41. package/dist/core/loader/MaskLoader.d.ts +0 -23
  42. package/dist/core/loader/MaskLoader.js +0 -29
  43. package/dist/core/schema/types.d.ts +0 -47
  44. package/dist/core/schema/types.js +0 -6
  45. package/dist/core/schema/validator.d.ts +0 -14
  46. package/dist/core/schema/validator.js +0 -18
  47. package/dist/i18n/index.d.ts +0 -18
  48. package/dist/i18n/index.js +4 -23
  49. package/dist/index.d.ts +0 -8
  50. package/dist/index.js +0 -8
  51. package/dist/lib.d.ts +0 -5
  52. package/dist/lib.js +0 -12
  53. package/dist/memory/chunking.d.ts +0 -22
  54. package/dist/memory/chunking.js +2 -37
  55. package/dist/memory/core.d.ts +0 -29
  56. package/dist/memory/core.js +1 -52
  57. package/dist/memory/index.d.ts +0 -5
  58. package/dist/memory/index.js +0 -10
  59. package/dist/memory/indexer.d.ts +0 -21
  60. package/dist/memory/indexer.js +0 -44
  61. package/dist/memory/providers/examples.d.ts +0 -5
  62. package/dist/memory/providers/examples.js +4 -64
  63. package/dist/memory/providers/factory.d.ts +0 -44
  64. package/dist/memory/providers/factory.js +0 -46
  65. package/dist/memory/providers/index.d.ts +0 -26
  66. package/dist/memory/providers/index.js +0 -28
  67. package/dist/memory/providers/ollama.d.ts +0 -6
  68. package/dist/memory/providers/ollama.js +1 -8
  69. package/dist/memory/providers/openai.d.ts +0 -6
  70. package/dist/memory/providers/openai.js +1 -8
  71. package/dist/memory/providers/openrouter.d.ts +0 -6
  72. package/dist/memory/providers/openrouter.js +0 -8
  73. package/dist/memory/providers/text-only.d.ts +0 -13
  74. package/dist/memory/providers/text-only.js +0 -17
  75. package/dist/memory/providers/types.d.ts +0 -39
  76. package/dist/memory/providers/types.js +0 -7
  77. package/dist/memory/providers/voyage.d.ts +0 -22
  78. package/dist/memory/providers/voyage.js +1 -24
  79. package/dist/memory/search/hybrid.d.ts +0 -12
  80. package/dist/memory/search/hybrid.js +1 -22
  81. package/dist/memory/store/sqlite.d.ts +0 -72
  82. package/dist/memory/store/sqlite.js +4 -127
  83. package/dist/plugin/config/index.d.ts +0 -112
  84. package/dist/plugin/config/index.js +0 -115
  85. package/dist/plugin/index.d.ts +0 -13
  86. package/dist/plugin/index.js +1 -124
  87. package/dist/plugin/tools/command-registry.d.ts +0 -6
  88. package/dist/plugin/tools/command-registry.js +0 -14
  89. package/dist/plugin/tools/context.d.ts +0 -12
  90. package/dist/plugin/tools/context.js +0 -58
  91. package/dist/plugin/tools/maskSave.d.ts +0 -3
  92. package/dist/plugin/tools/maskSave.js +0 -3
  93. package/dist/plugin/tools/memoryGet.d.ts +0 -3
  94. package/dist/plugin/tools/memoryGet.js +0 -3
  95. package/dist/plugin/tools/memoryIndexer.d.ts +0 -3
  96. package/dist/plugin/tools/memoryIndexer.js +0 -10
  97. package/dist/plugin/tools/memorySearch.d.ts +0 -31
  98. package/dist/plugin/tools/memorySearch.js +0 -79
  99. package/dist/plugin/tools/memoryWrite.d.ts +0 -8
  100. package/dist/plugin/tools/memoryWrite.js +0 -32
  101. package/dist/plugin/tools/retrospect.d.ts +0 -3
  102. package/dist/plugin/tools/retrospect.js +0 -3
  103. package/dist/plugin/tools/slashcommand.d.ts +0 -11
  104. package/dist/plugin/tools/slashcommand.js +0 -38
  105. package/dist/plugin/tools/squad.d.ts +0 -12
  106. package/dist/plugin/tools/squad.js +11 -83
  107. package/dist/plugin/tools/weave.d.ts +0 -6
  108. package/dist/plugin/tools/weave.js +0 -78
  109. package/dist/plugin/types.d.ts +0 -20
  110. package/dist/plugin/types.js +0 -7
  111. package/dist/retrospect/index.d.ts +0 -7
  112. package/dist/retrospect/index.js +0 -9
  113. package/dist/retrospect/mask-save.d.ts +0 -12
  114. package/dist/retrospect/mask-save.js +1 -80
  115. package/dist/retrospect/retrospect.d.ts +0 -18
  116. package/dist/retrospect/retrospect.js +0 -63
  117. package/dist/retrospect/strategies/base.d.ts +0 -15
  118. package/dist/retrospect/strategies/base.js +0 -7
  119. package/dist/retrospect/strategies/deep.d.ts +0 -12
  120. package/dist/retrospect/strategies/deep.js +0 -24
  121. package/dist/retrospect/strategies/index.d.ts +0 -12
  122. package/dist/retrospect/strategies/index.js +0 -12
  123. package/dist/retrospect/strategies/quick.d.ts +0 -12
  124. package/dist/retrospect/strategies/quick.js +0 -19
  125. package/dist/retrospect/strategies/standard.d.ts +0 -12
  126. package/dist/retrospect/strategies/standard.js +0 -15
  127. package/dist/retrospect/types.d.ts +0 -7
  128. package/dist/retrospect/types.js +0 -7
  129. package/dist/shared/config.d.ts +0 -105
  130. package/dist/shared/config.js +0 -33
  131. package/dist/shared/errors.d.ts +0 -18
  132. package/dist/shared/errors.js +0 -19
  133. package/dist/shared/generate-agents.d.ts +0 -69
  134. package/dist/shared/generate-agents.js +2 -86
  135. package/dist/shared/image.d.ts +0 -67
  136. package/dist/shared/image.js +6 -104
  137. package/dist/shared/index.d.ts +0 -5
  138. package/dist/shared/index.js +0 -7
  139. package/dist/shared/model-registry.d.ts +0 -72
  140. package/dist/shared/model-registry.js +5 -95
  141. package/dist/shared/types.d.ts +0 -15
  142. package/dist/shared/types.js +0 -3
  143. package/dist/shared-context/dag.d.ts +0 -105
  144. package/dist/shared-context/dag.js +3 -114
  145. package/dist/shared-context/index.d.ts +0 -5
  146. package/dist/shared-context/index.js +0 -15
  147. package/dist/shared-context/logger.d.ts +0 -37
  148. package/dist/shared-context/logger.js +0 -41
  149. package/dist/shared-context/parallel-executor.d.ts +0 -54
  150. package/dist/shared-context/parallel-executor.js +4 -56
  151. package/dist/shared-context/session.d.ts +0 -56
  152. package/dist/shared-context/session.js +0 -47
  153. package/dist/shared-context/squad.d.ts +0 -68
  154. package/dist/shared-context/squad.js +0 -63
  155. package/dist/shared-context/storage.d.ts +0 -132
  156. package/dist/shared-context/storage.js +0 -116
  157. package/dist/shared-context/task.d.ts +0 -120
  158. package/dist/shared-context/task.js +0 -152
  159. package/dist/shared-context/test/dag.test.js +9 -14
  160. package/dist/shared-context/test/logger.test.d.ts +0 -8
  161. package/dist/shared-context/test/logger.test.js +0 -52
  162. package/dist/shared-context/test/session.test.d.ts +0 -7
  163. package/dist/shared-context/test/session.test.js +0 -63
  164. package/dist/shared-context/test/squad.test.d.ts +0 -10
  165. package/dist/shared-context/test/squad.test.js +2 -68
  166. package/dist/shared-context/test/storage.test.d.ts +0 -8
  167. package/dist/shared-context/test/storage.test.js +0 -68
  168. package/dist/shared-context/test/task.test.d.ts +0 -7
  169. package/dist/shared-context/test/task.test.js +0 -54
  170. package/dist/shared-context/test/watchdog.test.d.ts +0 -7
  171. package/dist/shared-context/test/watchdog.test.js +3 -58
  172. package/dist/shared-context/types.d.ts +0 -215
  173. package/dist/shared-context/types.js +0 -125
  174. package/dist/shared-context/watchdog.d.ts +0 -127
  175. package/dist/shared-context/watchdog.js +0 -148
  176. package/dist/shared-context/worktree.d.ts +0 -68
  177. package/dist/shared-context/worktree.js +2 -34
  178. package/dist/verify/budget.d.ts +0 -29
  179. package/dist/verify/budget.js +0 -34
  180. package/dist/verify/critical-files.d.ts +0 -17
  181. package/dist/verify/critical-files.js +0 -37
  182. package/dist/verify/escalation.d.ts +0 -20
  183. package/dist/verify/escalation.js +0 -22
  184. package/dist/verify/index.d.ts +0 -5
  185. package/dist/verify/index.js +0 -11
  186. package/dist/verify/prompts.d.ts +0 -20
  187. package/dist/verify/prompts.js +0 -20
  188. package/dist/verify/types.d.ts +0 -26
  189. package/dist/verify/types.js +1 -12
  190. package/dist/verify/verifier.d.ts +0 -29
  191. package/dist/verify/verifier.js +0 -54
  192. package/dist/version.d.ts +1 -16
  193. package/dist/version.js +1 -16
  194. package/dist/weave/bridge.d.ts +0 -35
  195. package/dist/weave/bridge.js +0 -51
  196. package/dist/weave/environment/detector.d.ts +0 -6
  197. package/dist/weave/environment/detector.js +4 -45
  198. package/dist/weave/environment/index.d.ts +0 -19
  199. package/dist/weave/environment/index.js +1 -39
  200. package/dist/weave/environment/issues.d.ts +0 -35
  201. package/dist/weave/environment/issues.js +0 -59
  202. package/dist/weave/git.d.ts +0 -8
  203. package/dist/weave/git.js +0 -8
  204. package/dist/weave/index.d.ts +0 -13
  205. package/dist/weave/index.js +2 -28
  206. package/dist/weave/knowledge/global.d.ts +0 -39
  207. package/dist/weave/knowledge/global.js +2 -78
  208. package/dist/weave/loop.js +0 -3
  209. package/dist/weave/orchestrator.d.ts +0 -69
  210. package/dist/weave/orchestrator.js +1 -101
  211. package/dist/weave/phase-manager.d.ts +0 -64
  212. package/dist/weave/phase-manager.js +0 -89
  213. package/dist/weave/security/secret-scan.d.ts +0 -14
  214. package/dist/weave/security/secret-scan.js +0 -19
  215. package/dist/weave/stages/build.js +0 -15
  216. package/dist/weave/stages/execute.d.ts +0 -42
  217. package/dist/weave/stages/execute.js +4 -86
  218. package/dist/weave/stages/handoff.d.ts +0 -7
  219. package/dist/weave/stages/handoff.js +0 -43
  220. package/dist/weave/stages/index.d.ts +0 -3
  221. package/dist/weave/stages/index.js +0 -3
  222. package/dist/weave/stages/intake.d.ts +0 -8
  223. package/dist/weave/stages/intake.js +5 -65
  224. package/dist/weave/stages/map.d.ts +0 -1
  225. package/dist/weave/stages/openspec.d.ts +0 -1
  226. package/dist/weave/stages/plan.d.ts +0 -11
  227. package/dist/weave/stages/plan.js +1 -53
  228. package/dist/weave/stages/refine.d.ts +0 -7
  229. package/dist/weave/stages/refine.js +0 -7
  230. package/dist/weave/stages/research.d.ts +0 -6
  231. package/dist/weave/stages/research.js +0 -6
  232. package/dist/weave/stages/spec.d.ts +0 -12
  233. package/dist/weave/stages/spec.js +0 -17
  234. package/dist/weave/types.d.ts +0 -20
  235. package/dist/weave/types.js +0 -5
  236. package/dist/weave/verification/commands.d.ts +0 -12
  237. package/dist/weave/verification/commands.js +0 -19
  238. package/dist/weave/verification/index.d.ts +0 -6
  239. package/dist/weave/verification/index.js +1 -19
  240. package/dist/weave/verification/playwright.d.ts +0 -47
  241. package/dist/weave/verification/playwright.js +1 -90
  242. package/dist/weave/worktree.d.ts +0 -16
  243. package/dist/weave/worktree.js +0 -23
  244. package/dist/weave/yaml-repair.d.ts +0 -39
  245. package/dist/weave/yaml-repair.js +13 -116
  246. package/package.json +1 -1
@@ -1,11 +1,3 @@
1
- /**
2
- * Voyage AI Embedding Provider
3
- *
4
- * Specialized embeddings with code-specific models (voyage-code-3).
5
- * Supports asymmetric search with input_type distinction.
6
- *
7
- * Key feature: embedCode() method for superior code understanding.
8
- */
9
1
  import type { Embedding, HealthCheckResult, IEmbeddingProvider, ProviderConfig } from "./types.js";
10
2
  export declare class VoyageProvider implements IEmbeddingProvider {
11
3
  readonly name = "Voyage AI";
@@ -17,22 +9,8 @@ export declare class VoyageProvider implements IEmbeddingProvider {
17
9
  constructor(config: ProviderConfig);
18
10
  private validateDimensions;
19
11
  healthCheck(): Promise<HealthCheckResult>;
20
- /**
21
- * General-purpose embedding (documents)
22
- */
23
12
  embed(texts: string[]): Promise<Embedding[]>;
24
- /**
25
- * Code-optimized embedding
26
- * Use voyage-code-3 model for best results
27
- */
28
13
  embedCode(texts: string[]): Promise<Embedding[]>;
29
- /**
30
- * Query-optimized embedding
31
- * For asymmetric search (query vs document)
32
- */
33
14
  embedQuery(text: string): Promise<Embedding>;
34
- /**
35
- * Core embedding method with input_type specification
36
- */
37
15
  private embedWithType;
38
16
  }
@@ -1,11 +1,3 @@
1
- /**
2
- * Voyage AI Embedding Provider
3
- *
4
- * Specialized embeddings with code-specific models (voyage-code-3).
5
- * Supports asymmetric search with input_type distinction.
6
- *
7
- * Key feature: embedCode() method for superior code understanding.
8
- */
9
1
  const VALID_DIMENSIONS = [256, 512, 1024, 2048];
10
2
  const CODE_MODELS = ["voyage-code-3"];
11
3
  const GENERAL_MODELS = ["voyage-4-lite", "voyage-4-large"];
@@ -28,7 +20,7 @@ export class VoyageProvider {
28
20
  }
29
21
  validateDimensions(dim) {
30
22
  if (!dim)
31
- return 1024; // Default for voyage-4-lite
23
+ return 1024;
32
24
  if (!VALID_DIMENSIONS.includes(dim)) {
33
25
  throw new Error(`Invalid dimensions ${dim}. Must be one of: ${VALID_DIMENSIONS.join(", ")}`);
34
26
  }
@@ -36,7 +28,6 @@ export class VoyageProvider {
36
28
  }
37
29
  async healthCheck() {
38
30
  try {
39
- // Test with a minimal embedding request
40
31
  const response = await fetch(`${this.baseUrl}/embeddings`, {
41
32
  method: "POST",
42
33
  headers: {
@@ -74,16 +65,9 @@ export class VoyageProvider {
74
65
  };
75
66
  }
76
67
  }
77
- /**
78
- * General-purpose embedding (documents)
79
- */
80
68
  async embed(texts) {
81
69
  return this.embedWithType(texts, "document");
82
70
  }
83
- /**
84
- * Code-optimized embedding
85
- * Use voyage-code-3 model for best results
86
- */
87
71
  async embedCode(texts) {
88
72
  const isCodeModel = CODE_MODELS.includes(this.model);
89
73
  if (!isCodeModel) {
@@ -91,17 +75,10 @@ export class VoyageProvider {
91
75
  }
92
76
  return this.embedWithType(texts, "document");
93
77
  }
94
- /**
95
- * Query-optimized embedding
96
- * For asymmetric search (query vs document)
97
- */
98
78
  async embedQuery(text) {
99
79
  const [embedding] = await this.embedWithType([text], "query");
100
80
  return embedding;
101
81
  }
102
- /**
103
- * Core embedding method with input_type specification
104
- */
105
82
  async embedWithType(texts, inputType) {
106
83
  const response = await fetch(`${this.baseUrl}/embeddings`, {
107
84
  method: "POST",
@@ -1,15 +1,3 @@
1
- /**
2
- * Hybrid Search - Combine vector and text search
3
- *
4
- * Simple weighted combination of vector similarity and FTS scores.
5
- * Gracefully degrades to text-only when no embedding is available.
6
- */
7
1
  import type { SearchResult } from '../core.js';
8
2
  import type { SearchOptions } from '../store/sqlite.js';
9
- /**
10
- * Hybrid search combining vector and text search.
11
- *
12
- * If queryEmbedding is empty/missing, automatically falls back
13
- * to text-only search with adjusted scoring.
14
- */
15
3
  export declare function hybridSearch(query: string, queryEmbedding: number[], options?: SearchOptions): SearchResult[];
@@ -1,42 +1,23 @@
1
- /**
2
- * Hybrid Search - Combine vector and text search
3
- *
4
- * Simple weighted combination of vector similarity and FTS scores.
5
- * Gracefully degrades to text-only when no embedding is available.
6
- */
7
1
  import { getDatabase } from '../store/sqlite.js';
8
2
  const DEFAULT_VECTOR_WEIGHT = 0.7;
9
3
  const DEFAULT_TEXT_WEIGHT = 0.3;
10
4
  const DEFAULT_MIN_SCORE = 0.35;
11
5
  const DEFAULT_MAX_RESULTS = 6;
12
- /**
13
- * Hybrid search combining vector and text search.
14
- *
15
- * If queryEmbedding is empty/missing, automatically falls back
16
- * to text-only search with adjusted scoring.
17
- */
18
6
  export function hybridSearch(query, queryEmbedding, options = {}) {
19
7
  const { limit = DEFAULT_MAX_RESULTS, minScore = DEFAULT_MIN_SCORE, vectorWeight = DEFAULT_VECTOR_WEIGHT, textWeight = DEFAULT_TEXT_WEIGHT, sourceFilter, } = options;
20
8
  const db = getDatabase();
21
- // SQLite not available - return empty results (graceful degradation)
22
9
  if (!db) {
23
10
  return [];
24
11
  }
25
- // Get more candidates for reranking
26
12
  const candidateLimit = limit * 3;
27
- // Determine if we can do vector search
28
13
  const hasEmbedding = queryEmbedding && queryEmbedding.length > 0;
29
- // Run vector search only if we have a real embedding
30
14
  const vectorResults = hasEmbedding
31
15
  ? db.searchByVector(queryEmbedding, candidateLimit, sourceFilter)
32
16
  : [];
33
- // Always try text search
34
17
  const textResults = db.searchByText(query, candidateLimit);
35
- // If both are empty, nothing to merge
36
18
  if (vectorResults.length === 0 && textResults.length === 0) {
37
19
  return [];
38
20
  }
39
- // Merge results
40
21
  const scoreMap = new Map();
41
22
  for (const result of vectorResults) {
42
23
  scoreMap.set(result.chunk.id, {
@@ -58,14 +39,12 @@ export function hybridSearch(query, queryEmbedding, options = {}) {
58
39
  });
59
40
  }
60
41
  }
61
- // Calculate combined scores
62
- // When in text-only mode, use text score directly (don't penalize via vectorWeight)
63
42
  const effectiveMinScore = hasEmbedding ? minScore : minScore * textWeight;
64
43
  const results = Array.from(scoreMap.values())
65
44
  .map(({ chunk, vectorScore, textScore }) => {
66
45
  const combinedScore = hasEmbedding
67
46
  ? vectorScore * vectorWeight + textScore * textWeight
68
- : textScore; // Pure text mode — use raw text score
47
+ : textScore;
69
48
  return {
70
49
  chunk,
71
50
  score: combinedScore,
@@ -1,21 +1,5 @@
1
- /**
2
- * SQLite Storage - Persistent chunk and embedding storage
3
- *
4
- * Uses better-sqlite3 for Node.js compatibility.
5
- * WAL mode for concurrent access.
6
- *
7
- * NOTE: better-sqlite3 is an optional dependency.
8
- * This module uses dynamic import to avoid errors when not installed.
9
- */
10
1
  import { type Chunk, type SearchResult } from '../core.js';
11
- /**
12
- * Check if SQLite is available without throwing.
13
- * Returns true if SQLite can be loaded, false otherwise.
14
- */
15
2
  export declare function isSqliteAvailable(): boolean;
16
- /**
17
- * Get the reason SQLite is unavailable.
18
- */
19
3
  export declare function getSqliteUnavailableReason(): string;
20
4
  export interface SearchOptions {
21
5
  limit?: number;
@@ -29,62 +13,19 @@ export declare class MemoryDatabase {
29
13
  private statements;
30
14
  private ftsAvailable;
31
15
  private constructor();
32
- /**
33
- * Create a new MemoryDatabase instance.
34
- * Uses async factory pattern because better-sqlite3 is dynamically imported.
35
- * Returns null if SQLite is not available (graceful degradation).
36
- */
37
16
  static create(dbPath: string): Promise<MemoryDatabase | null>;
38
- /**
39
- * Initialize database schema.
40
- */
41
17
  private initSchema;
42
- /**
43
- * Prepare SQL statements for reuse.
44
- */
45
18
  private prepareStatements;
46
- /**
47
- * Insert or update chunk.
48
- *
49
- * If embedding is empty (e.g., text-only mode), the chunk is stored
50
- * but the embedding row is skipped. This allows text search to work
51
- * while vector search gracefully returns no results for these chunks.
52
- */
53
19
  upsertChunk(chunk: Chunk, embedding: number[]): number;
54
- /**
55
- * Bulk insert chunks in transaction.
56
- */
57
20
  upsertChunks(chunks: Array<{
58
21
  chunk: Chunk;
59
22
  embedding: number[];
60
23
  }>): number[];
61
- /**
62
- * Delete chunks by path.
63
- */
64
24
  deleteChunksByPath(path: string): number;
65
- /**
66
- * Check if chunk changed.
67
- */
68
25
  isChunkChanged(path: string, hash: string): boolean;
69
- /**
70
- * Get chunks by path.
71
- */
72
26
  getChunksByPath(path: string): Chunk[];
73
- /**
74
- * Vector similarity search.
75
- *
76
- * Returns empty results if queryEmbedding is empty (e.g., text-only mode).
77
- * Skips stored embeddings with dimension mismatches instead of crashing.
78
- */
79
27
  searchByVector(queryEmbedding: number[], limit?: number, sourceFilter?: Chunk['source'][]): SearchResult[];
80
- /**
81
- * Full-text search using FTS5.
82
- * Returns empty results if FTS is not available.
83
- */
84
28
  searchByText(query: string, limit?: number): SearchResult[];
85
- /**
86
- * Normalize FTS query.
87
- */
88
29
  private normalizeFtsQuery;
89
30
  recordMaskUsage(maskName: string, taskDescription?: string, effectivenessScore?: number): void;
90
31
  getMaskStats(): Array<{
@@ -103,21 +44,8 @@ export declare class MemoryDatabase {
103
44
  optimize(): void;
104
45
  close(): void;
105
46
  }
106
- /**
107
- * Initialize the database.
108
- * Returns null if SQLite is not available (graceful degradation).
109
- */
110
47
  export declare function initDatabase(dbPath: string): Promise<MemoryDatabase | null>;
111
- /**
112
- * Get the database instance.
113
- * Returns null if SQLite is not available or not initialized.
114
- * Use this for optional memory features.
115
- */
116
48
  export declare function getDatabase(): MemoryDatabase | null;
117
- /**
118
- * Try to get the database instance, returning null if not initialized.
119
- * Use this when database access is optional (e.g., in intake stage).
120
- */
121
49
  export declare function tryGetDatabase(): MemoryDatabase | null;
122
50
  export declare function upsertChunk(chunk: Chunk, embedding: number[]): number;
123
51
  export declare function searchByVector(embedding: number[], limit?: number): SearchResult[];
@@ -1,47 +1,24 @@
1
- /**
2
- * SQLite Storage - Persistent chunk and embedding storage
3
- *
4
- * Uses better-sqlite3 for Node.js compatibility.
5
- * WAL mode for concurrent access.
6
- *
7
- * NOTE: better-sqlite3 is an optional dependency.
8
- * This module uses dynamic import to avoid errors when not installed.
9
- */
10
1
  import { existsSync, mkdirSync } from 'fs';
11
2
  import { dirname } from 'path';
12
3
  import { cosineSimilarityFloat32, embeddingToBlob, blobToEmbedding, toFloat32Array, } from '../core.js';
13
- // Dynamic import for better-sqlite3 or bun:sqlite
14
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
15
4
  let DatabaseConstructor = null;
16
5
  let isBun = false;
17
6
  let sqliteUnavailable = false;
18
7
  let sqliteUnavailableReason = '';
19
- // Check if running in Bun at module level
20
- // @ts-ignore
21
8
  const IS_BUN = typeof Bun !== 'undefined';
22
- /**
23
- * Check if SQLite is available without throwing.
24
- * Returns true if SQLite can be loaded, false otherwise.
25
- */
26
9
  export function isSqliteAvailable() {
27
10
  return !sqliteUnavailable;
28
11
  }
29
- /**
30
- * Get the reason SQLite is unavailable.
31
- */
32
12
  export function getSqliteUnavailableReason() {
33
13
  return sqliteUnavailableReason;
34
14
  }
35
15
  async function loadDatabase() {
36
16
  if (DatabaseConstructor)
37
17
  return DatabaseConstructor;
38
- // If we already know SQLite is unavailable, return null immediately
39
18
  if (sqliteUnavailable)
40
19
  return null;
41
- // In Bun environment, use bun:sqlite exclusively
42
20
  if (IS_BUN) {
43
21
  try {
44
- // @ts-ignore
45
22
  const { Database } = await import('bun:sqlite');
46
23
  DatabaseConstructor = Database;
47
24
  isBun = true;
@@ -54,8 +31,6 @@ async function loadDatabase() {
54
31
  return null;
55
32
  }
56
33
  }
57
- // In Node.js environment, use better-sqlite3
58
- // Use Function constructor to avoid Bun's static analysis of import()
59
34
  try {
60
35
  const dynamicImport = new Function('specifier', 'return import(specifier)');
61
36
  const module = await dynamicImport('better-sqlite3');
@@ -72,35 +47,23 @@ async function loadDatabase() {
72
47
  return null;
73
48
  }
74
49
  }
75
- // ============================================================================
76
- // Database Class
77
- // ============================================================================
78
50
  export class MemoryDatabase {
79
- db; // Database.Database type
51
+ db;
80
52
  statements = new Map();
81
53
  ftsAvailable = false;
82
54
  constructor(db) {
83
55
  this.db = db;
84
56
  }
85
- /**
86
- * Create a new MemoryDatabase instance.
87
- * Uses async factory pattern because better-sqlite3 is dynamically imported.
88
- * Returns null if SQLite is not available (graceful degradation).
89
- */
90
57
  static async create(dbPath) {
91
58
  const DatabaseClass = await loadDatabase();
92
- // SQLite not available - graceful degradation
93
59
  if (!DatabaseClass) {
94
60
  return null;
95
61
  }
96
- // Ensure directory exists
97
62
  const dir = dirname(dbPath);
98
63
  if (!existsSync(dir)) {
99
64
  mkdirSync(dir, { recursive: true });
100
65
  }
101
- // Open database
102
66
  const db = new DatabaseClass(dbPath);
103
- // Enable WAL mode for concurrency
104
67
  if (isBun) {
105
68
  db.exec('PRAGMA journal_mode = WAL');
106
69
  db.exec('PRAGMA synchronous = NORMAL');
@@ -108,19 +71,14 @@ export class MemoryDatabase {
108
71
  else {
109
72
  db.pragma('journal_mode = WAL');
110
73
  db.pragma('synchronous = NORMAL');
111
- db.pragma('cache_size = -64000'); // 64MB
74
+ db.pragma('cache_size = -64000');
112
75
  db.pragma('temp_store = MEMORY');
113
76
  }
114
77
  const instance = new MemoryDatabase(db);
115
- // Initialize schema
116
78
  instance.initSchema();
117
- // Prepare statements
118
79
  instance.prepareStatements();
119
80
  return instance;
120
81
  }
121
- /**
122
- * Initialize database schema.
123
- */
124
82
  initSchema() {
125
83
  this.db.exec(`
126
84
  -- Chunks table
@@ -158,7 +116,6 @@ export class MemoryDatabase {
158
116
  CREATE INDEX IF NOT EXISTS idx_chunks_hash ON chunks(hash);
159
117
  CREATE INDEX IF NOT EXISTS idx_mask_usage_name ON mask_usage(mask_name);
160
118
  `);
161
- // FTS5 virtual table
162
119
  this.ftsAvailable = false;
163
120
  try {
164
121
  this.db.exec(`
@@ -172,10 +129,8 @@ export class MemoryDatabase {
172
129
  this.ftsAvailable = true;
173
130
  }
174
131
  catch (error) {
175
- // FTS5 not supported by this SQLite build
176
132
  console.warn('[Memory DB] FTS5 not available. Text search will be disabled:', error);
177
133
  }
178
- // FTS triggers — only if FTS table was created successfully
179
134
  if (this.ftsAvailable) {
180
135
  try {
181
136
  this.db.exec(`
@@ -202,9 +157,6 @@ export class MemoryDatabase {
202
157
  }
203
158
  }
204
159
  }
205
- /**
206
- * Prepare SQL statements for reuse.
207
- */
208
160
  prepareStatements() {
209
161
  this.statements.set('upsertChunk', this.db.prepare(`
210
162
  INSERT INTO chunks (path, start_line, end_line, text, hash, source)
@@ -236,7 +188,6 @@ export class MemoryDatabase {
236
188
  FROM chunks c
237
189
  JOIN embeddings e ON c.id = e.chunk_id
238
190
  `));
239
- // FTS statement — only prepare if FTS table exists
240
191
  if (this.ftsAvailable) {
241
192
  this.statements.set('searchFts', this.db.prepare(`
242
193
  SELECT rowid, text, rank
@@ -264,23 +215,12 @@ export class MemoryDatabase {
264
215
  ORDER BY usage_count DESC
265
216
  `));
266
217
  }
267
- // ==========================================================================
268
- // CRUD Operations
269
- // ==========================================================================
270
- /**
271
- * Insert or update chunk.
272
- *
273
- * If embedding is empty (e.g., text-only mode), the chunk is stored
274
- * but the embedding row is skipped. This allows text search to work
275
- * while vector search gracefully returns no results for these chunks.
276
- */
277
218
  upsertChunk(chunk, embedding) {
278
219
  const stmt = this.statements.get('upsertChunk');
279
220
  const result = stmt.get(chunk.path, chunk.startLine, chunk.endLine, chunk.text, chunk.hash, chunk.source);
280
221
  if (!result?.id) {
281
222
  throw new Error('[Memory DB] Failed to upsert chunk');
282
223
  }
283
- // Only save embedding if it has actual content
284
224
  if (embedding && embedding.length > 0) {
285
225
  const embStmt = this.statements.get('upsertEmbedding');
286
226
  const embeddingBlob = embeddingToBlob(embedding);
@@ -288,9 +228,6 @@ export class MemoryDatabase {
288
228
  }
289
229
  return result.id;
290
230
  }
291
- /**
292
- * Bulk insert chunks in transaction.
293
- */
294
231
  upsertChunks(chunks) {
295
232
  const ids = [];
296
233
  const transaction = this.db.transaction(() => {
@@ -302,25 +239,16 @@ export class MemoryDatabase {
302
239
  transaction();
303
240
  return ids;
304
241
  }
305
- /**
306
- * Delete chunks by path.
307
- */
308
242
  deleteChunksByPath(path) {
309
243
  const stmt = this.statements.get('deleteChunksByPath');
310
244
  const result = stmt.run(path);
311
245
  return result.changes;
312
246
  }
313
- /**
314
- * Check if chunk changed.
315
- */
316
247
  isChunkChanged(path, hash) {
317
248
  const stmt = this.statements.get('checkChunkByHash');
318
249
  const result = stmt.get(path, hash);
319
250
  return result === undefined;
320
251
  }
321
- /**
322
- * Get chunks by path.
323
- */
324
252
  getChunksByPath(path) {
325
253
  const stmt = this.statements.get('getChunksByPath');
326
254
  const rows = stmt.all(path);
@@ -335,34 +263,19 @@ export class MemoryDatabase {
335
263
  createdAt: row.created_at,
336
264
  }));
337
265
  }
338
- // ==========================================================================
339
- // Search Operations
340
- // ==========================================================================
341
- /**
342
- * Vector similarity search.
343
- *
344
- * Returns empty results if queryEmbedding is empty (e.g., text-only mode).
345
- * Skips stored embeddings with dimension mismatches instead of crashing.
346
- */
347
266
  searchByVector(queryEmbedding, limit = 6, sourceFilter) {
348
- // Empty embedding = text-only mode. Skip vector search entirely.
349
267
  if (!queryEmbedding || queryEmbedding.length === 0) {
350
268
  return [];
351
269
  }
352
270
  const queryVec = toFloat32Array(queryEmbedding);
353
- // Get all embeddings
354
271
  const stmt = this.statements.get('getAllEmbeddings');
355
272
  let rows = stmt.all();
356
- // Filter by source if specified
357
273
  if (sourceFilter && sourceFilter.length > 0) {
358
274
  rows = rows.filter(row => sourceFilter.includes(row.source));
359
275
  }
360
- // Calculate similarities and sort
361
- // cosineSimilarityFloat32 returns 0 on dimension mismatch (no throw)
362
276
  const scored = [];
363
277
  for (const row of rows) {
364
278
  const embeddingVec = blobToEmbedding(row.embedding);
365
- // Skip rows with empty or invalid embeddings
366
279
  if (embeddingVec.length === 0) {
367
280
  continue;
368
281
  }
@@ -386,10 +299,6 @@ export class MemoryDatabase {
386
299
  .sort((a, b) => b.score - a.score)
387
300
  .slice(0, limit);
388
301
  }
389
- /**
390
- * Full-text search using FTS5.
391
- * Returns empty results if FTS is not available.
392
- */
393
302
  searchByText(query, limit = 6) {
394
303
  if (!this.ftsAvailable) {
395
304
  return [];
@@ -408,7 +317,6 @@ export class MemoryDatabase {
408
317
  const chunk = chunkStmt.get(fts.rowid);
409
318
  if (!chunk)
410
319
  continue;
411
- // Normalize BM25 score to 0-1 range
412
320
  const normalizedScore = Math.min(1, Math.max(0, -fts.rank / 10));
413
321
  results.push({
414
322
  chunk: {
@@ -432,9 +340,6 @@ export class MemoryDatabase {
432
340
  return [];
433
341
  }
434
342
  }
435
- /**
436
- * Normalize FTS query.
437
- */
438
343
  normalizeFtsQuery(query) {
439
344
  const tokens = query
440
345
  .replace(/[^\w\s가-힣]/g, ' ')
@@ -444,9 +349,6 @@ export class MemoryDatabase {
444
349
  return '';
445
350
  return tokens.map(t => `${t}*`).join(' OR ');
446
351
  }
447
- // ==========================================================================
448
- // Mask Usage
449
- // ==========================================================================
450
352
  recordMaskUsage(maskName, taskDescription, effectivenessScore) {
451
353
  const stmt = this.statements.get('insertMaskUsage');
452
354
  stmt.run(maskName, taskDescription ?? null, effectivenessScore ?? null);
@@ -455,9 +357,6 @@ export class MemoryDatabase {
455
357
  const stmt = this.statements.get('getMaskStats');
456
358
  return stmt.all();
457
359
  }
458
- // ==========================================================================
459
- // Utilities
460
- // ==========================================================================
461
360
  getStats() {
462
361
  const chunkCount = this.db.prepare('SELECT COUNT(*) as count FROM chunks').get().count;
463
362
  const embeddingCount = this.db.prepare('SELECT COUNT(*) as count FROM embeddings').get().count;
@@ -491,14 +390,7 @@ export class MemoryDatabase {
491
390
  this.db.close();
492
391
  }
493
392
  }
494
- // ============================================================================
495
- // Singleton Instance
496
- // ============================================================================
497
393
  let defaultInstance = null;
498
- /**
499
- * Initialize the database.
500
- * Returns null if SQLite is not available (graceful degradation).
501
- */
502
394
  export async function initDatabase(dbPath) {
503
395
  if (defaultInstance) {
504
396
  defaultInstance.close();
@@ -506,30 +398,15 @@ export async function initDatabase(dbPath) {
506
398
  defaultInstance = await MemoryDatabase.create(dbPath);
507
399
  return defaultInstance;
508
400
  }
509
- /**
510
- * Get the database instance.
511
- * Returns null if SQLite is not available or not initialized.
512
- * Use this for optional memory features.
513
- */
514
401
  export function getDatabase() {
515
402
  if (!defaultInstance && !isSqliteAvailable()) {
516
- // SQLite not available - return null instead of throwing
517
403
  return null;
518
404
  }
519
405
  return defaultInstance;
520
406
  }
521
- /**
522
- * Try to get the database instance, returning null if not initialized.
523
- * Use this when database access is optional (e.g., in intake stage).
524
- */
525
407
  export function tryGetDatabase() {
526
408
  return defaultInstance;
527
409
  }
528
- // ============================================================================
529
- // Convenience Functions
530
- // These throw errors if SQLite is not available. Use getDatabase() directly
531
- // for optional access with null checks.
532
- // ============================================================================
533
410
  export function upsertChunk(chunk, embedding) {
534
411
  const db = getDatabase();
535
412
  if (!db)
@@ -539,13 +416,13 @@ export function upsertChunk(chunk, embedding) {
539
416
  export function searchByVector(embedding, limit) {
540
417
  const db = getDatabase();
541
418
  if (!db)
542
- return []; // Graceful degradation - return empty results
419
+ return [];
543
420
  return db.searchByVector(embedding, limit);
544
421
  }
545
422
  export function searchByText(query, limit) {
546
423
  const db = getDatabase();
547
424
  if (!db)
548
- return []; // Graceful degradation - return empty results
425
+ return [];
549
426
  return db.searchByText(query, limit);
550
427
  }
551
428
  export function deleteChunksByPath(path) {