codestrate 0.6.2 → 0.6.3

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 (223) hide show
  1. package/README.md +97 -101
  2. package/dist/constants.d.ts +1 -1
  3. package/dist/constants.d.ts.map +1 -1
  4. package/dist/constants.js +54 -4
  5. package/dist/constants.js.map +1 -1
  6. package/dist/index.d.ts +3 -2
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +198 -119
  9. package/dist/index.js.map +1 -1
  10. package/dist/install.d.ts +0 -0
  11. package/dist/install.d.ts.map +0 -0
  12. package/dist/install.js +2 -2
  13. package/dist/install.js.map +1 -1
  14. package/dist/profiles.d.ts +28 -0
  15. package/dist/profiles.d.ts.map +1 -0
  16. package/dist/profiles.js +89 -0
  17. package/dist/profiles.js.map +1 -0
  18. package/dist/schemas/index.d.ts +1441 -126
  19. package/dist/schemas/index.d.ts.map +1 -1
  20. package/dist/schemas/index.js +221 -10
  21. package/dist/schemas/index.js.map +1 -1
  22. package/dist/security/guard.d.ts +15 -2
  23. package/dist/security/guard.d.ts.map +1 -1
  24. package/dist/security/guard.js +42 -8
  25. package/dist/security/guard.js.map +1 -1
  26. package/dist/services/code-chunker.d.ts +50 -0
  27. package/dist/services/code-chunker.d.ts.map +1 -0
  28. package/dist/services/code-chunker.js +148 -0
  29. package/dist/services/code-chunker.js.map +1 -0
  30. package/dist/services/code-searcher.d.ts +6 -2
  31. package/dist/services/code-searcher.d.ts.map +1 -1
  32. package/dist/services/code-searcher.js +111 -17
  33. package/dist/services/code-searcher.js.map +1 -1
  34. package/dist/services/context-builder.d.ts +0 -11
  35. package/dist/services/context-builder.d.ts.map +1 -1
  36. package/dist/services/context-builder.js +74 -128
  37. package/dist/services/context-builder.js.map +1 -1
  38. package/dist/services/embedding-runtime.d.ts +41 -0
  39. package/dist/services/embedding-runtime.d.ts.map +1 -0
  40. package/dist/services/embedding-runtime.js +636 -0
  41. package/dist/services/embedding-runtime.js.map +1 -0
  42. package/dist/services/embedding.d.ts +79 -0
  43. package/dist/services/embedding.d.ts.map +1 -0
  44. package/dist/services/embedding.js +257 -0
  45. package/dist/services/embedding.js.map +1 -0
  46. package/dist/services/index-state.d.ts +74 -0
  47. package/dist/services/index-state.d.ts.map +1 -0
  48. package/dist/services/index-state.js +151 -0
  49. package/dist/services/index-state.js.map +1 -0
  50. package/dist/services/index-worker.d.ts +60 -0
  51. package/dist/services/index-worker.d.ts.map +1 -0
  52. package/dist/services/index-worker.js +182 -0
  53. package/dist/services/index-worker.js.map +1 -0
  54. package/dist/services/logger.d.ts +48 -0
  55. package/dist/services/logger.d.ts.map +1 -0
  56. package/dist/services/logger.js +106 -0
  57. package/dist/services/logger.js.map +1 -0
  58. package/dist/services/memory-store.d.ts +9 -7
  59. package/dist/services/memory-store.d.ts.map +1 -1
  60. package/dist/services/memory-store.js +93 -7
  61. package/dist/services/memory-store.js.map +1 -1
  62. package/dist/services/repository-parser.d.ts +0 -0
  63. package/dist/services/repository-parser.d.ts.map +0 -0
  64. package/dist/services/repository-parser.js +0 -0
  65. package/dist/services/repository-parser.js.map +0 -0
  66. package/dist/services/symbol-indexer.d.ts +0 -0
  67. package/dist/services/symbol-indexer.d.ts.map +1 -1
  68. package/dist/services/symbol-indexer.js +25 -13
  69. package/dist/services/symbol-indexer.js.map +1 -1
  70. package/dist/services/tree-sitter.d.ts +0 -0
  71. package/dist/services/tree-sitter.d.ts.map +0 -0
  72. package/dist/services/tree-sitter.js +0 -0
  73. package/dist/services/tree-sitter.js.map +0 -0
  74. package/dist/services/validation-runner.d.ts +0 -0
  75. package/dist/services/validation-runner.d.ts.map +1 -1
  76. package/dist/services/validation-runner.js +9 -9
  77. package/dist/services/validation-runner.js.map +1 -1
  78. package/dist/services/vector-indexer.d.ts +53 -0
  79. package/dist/services/vector-indexer.d.ts.map +1 -0
  80. package/dist/services/vector-indexer.js +230 -0
  81. package/dist/services/vector-indexer.js.map +1 -0
  82. package/dist/store/index.d.ts +0 -0
  83. package/dist/store/index.d.ts.map +0 -0
  84. package/dist/store/index.js +0 -0
  85. package/dist/store/index.js.map +0 -0
  86. package/dist/store/interface.d.ts +70 -1
  87. package/dist/store/interface.d.ts.map +1 -1
  88. package/dist/store/interface.js +0 -0
  89. package/dist/store/interface.js.map +0 -0
  90. package/dist/store/memory.d.ts +0 -0
  91. package/dist/store/memory.d.ts.map +0 -0
  92. package/dist/store/memory.js +0 -0
  93. package/dist/store/memory.js.map +0 -0
  94. package/dist/store/service.d.ts +49 -0
  95. package/dist/store/service.d.ts.map +1 -0
  96. package/dist/store/service.js +147 -0
  97. package/dist/store/service.js.map +1 -0
  98. package/dist/store/sqlite.d.ts +68 -3
  99. package/dist/store/sqlite.d.ts.map +1 -1
  100. package/dist/store/sqlite.js +708 -58
  101. package/dist/store/sqlite.js.map +1 -1
  102. package/dist/store/vector-store.d.ts +66 -0
  103. package/dist/store/vector-store.d.ts.map +1 -0
  104. package/dist/store/vector-store.js +330 -0
  105. package/dist/store/vector-store.js.map +1 -0
  106. package/dist/tools/analyze-impact.d.ts +0 -0
  107. package/dist/tools/analyze-impact.d.ts.map +1 -1
  108. package/dist/tools/analyze-impact.js +101 -39
  109. package/dist/tools/analyze-impact.js.map +1 -1
  110. package/dist/tools/deep-explore.d.ts +0 -0
  111. package/dist/tools/deep-explore.d.ts.map +1 -1
  112. package/dist/tools/deep-explore.js +18 -4
  113. package/dist/tools/deep-explore.js.map +1 -1
  114. package/dist/tools/detect-cycles.d.ts +3 -0
  115. package/dist/tools/detect-cycles.d.ts.map +1 -0
  116. package/dist/tools/detect-cycles.js +61 -0
  117. package/dist/tools/detect-cycles.js.map +1 -0
  118. package/dist/tools/detect-dead-code.d.ts +0 -0
  119. package/dist/tools/detect-dead-code.d.ts.map +1 -1
  120. package/dist/tools/detect-dead-code.js +1 -0
  121. package/dist/tools/detect-dead-code.js.map +1 -1
  122. package/dist/tools/explore.d.ts +13 -0
  123. package/dist/tools/explore.d.ts.map +1 -1
  124. package/dist/tools/explore.js +122 -88
  125. package/dist/tools/explore.js.map +1 -1
  126. package/dist/tools/get-context.d.ts +15 -0
  127. package/dist/tools/get-context.d.ts.map +1 -1
  128. package/dist/tools/get-context.js +66 -61
  129. package/dist/tools/get-context.js.map +1 -1
  130. package/dist/tools/graph-explain.d.ts +3 -0
  131. package/dist/tools/graph-explain.d.ts.map +1 -0
  132. package/dist/tools/graph-explain.js +140 -0
  133. package/dist/tools/graph-explain.js.map +1 -0
  134. package/dist/tools/graph-stats.d.ts +3 -0
  135. package/dist/tools/graph-stats.d.ts.map +1 -0
  136. package/dist/tools/graph-stats.js +73 -0
  137. package/dist/tools/graph-stats.js.map +1 -0
  138. package/dist/tools/inspect-symbol.d.ts +10 -0
  139. package/dist/tools/inspect-symbol.d.ts.map +1 -1
  140. package/dist/tools/inspect-symbol.js +112 -101
  141. package/dist/tools/inspect-symbol.js.map +1 -1
  142. package/dist/tools/ping.d.ts +0 -0
  143. package/dist/tools/ping.d.ts.map +1 -1
  144. package/dist/tools/ping.js +2 -3
  145. package/dist/tools/ping.js.map +1 -1
  146. package/dist/tools/profile.d.ts +9 -0
  147. package/dist/tools/profile.d.ts.map +1 -0
  148. package/dist/tools/profile.js +101 -0
  149. package/dist/tools/profile.js.map +1 -0
  150. package/dist/tools/query-graph.d.ts +3 -0
  151. package/dist/tools/query-graph.d.ts.map +1 -0
  152. package/dist/tools/query-graph.js +157 -0
  153. package/dist/tools/query-graph.js.map +1 -0
  154. package/dist/tools/recall-experience.d.ts +0 -0
  155. package/dist/tools/recall-experience.d.ts.map +1 -1
  156. package/dist/tools/recall-experience.js +5 -5
  157. package/dist/tools/recall-experience.js.map +1 -1
  158. package/dist/tools/record-experience.d.ts +0 -0
  159. package/dist/tools/record-experience.d.ts.map +1 -1
  160. package/dist/tools/record-experience.js +2 -5
  161. package/dist/tools/record-experience.js.map +1 -1
  162. package/dist/tools/reflect.d.ts +4 -0
  163. package/dist/tools/reflect.d.ts.map +1 -0
  164. package/dist/tools/reflect.js +99 -0
  165. package/dist/tools/reflect.js.map +1 -0
  166. package/dist/tools/register.d.ts +5 -2
  167. package/dist/tools/register.d.ts.map +1 -1
  168. package/dist/tools/register.js +31 -1
  169. package/dist/tools/register.js.map +1 -1
  170. package/dist/tools/reindex.d.ts +0 -0
  171. package/dist/tools/reindex.d.ts.map +1 -1
  172. package/dist/tools/reindex.js +102 -21
  173. package/dist/tools/reindex.js.map +1 -1
  174. package/dist/tools/repo-overview.d.ts +0 -0
  175. package/dist/tools/repo-overview.d.ts.map +1 -1
  176. package/dist/tools/repo-overview.js +8 -6
  177. package/dist/tools/repo-overview.js.map +1 -1
  178. package/dist/tools/run-validation.d.ts +0 -0
  179. package/dist/tools/run-validation.d.ts.map +1 -1
  180. package/dist/tools/run-validation.js +15 -1
  181. package/dist/tools/run-validation.js.map +1 -1
  182. package/dist/tools/search-code.d.ts +0 -0
  183. package/dist/tools/search-code.d.ts.map +1 -1
  184. package/dist/tools/search-code.js +11 -4
  185. package/dist/tools/search-code.js.map +1 -1
  186. package/dist/tools/search-history.d.ts +0 -0
  187. package/dist/tools/search-history.d.ts.map +0 -0
  188. package/dist/tools/search-history.js +0 -0
  189. package/dist/tools/search-history.js.map +0 -0
  190. package/dist/tools/session-heartbeat.d.ts +0 -0
  191. package/dist/tools/session-heartbeat.d.ts.map +1 -1
  192. package/dist/tools/session-heartbeat.js +1 -0
  193. package/dist/tools/session-heartbeat.js.map +1 -1
  194. package/dist/tools/session-status.d.ts +0 -0
  195. package/dist/tools/session-status.d.ts.map +1 -1
  196. package/dist/tools/session-status.js +1 -0
  197. package/dist/tools/session-status.js.map +1 -1
  198. package/dist/tools/status.d.ts +0 -0
  199. package/dist/tools/status.d.ts.map +1 -1
  200. package/dist/tools/status.js +87 -24
  201. package/dist/tools/status.js.map +1 -1
  202. package/dist/tools/trace-bfs.d.ts +13 -0
  203. package/dist/tools/trace-bfs.d.ts.map +1 -0
  204. package/dist/tools/trace-bfs.js +251 -0
  205. package/dist/tools/trace-bfs.js.map +1 -0
  206. package/dist/tools/trace-flow.d.ts +1 -1
  207. package/dist/tools/trace-flow.d.ts.map +1 -1
  208. package/dist/tools/trace-flow.js +113 -69
  209. package/dist/tools/trace-flow.js.map +1 -1
  210. package/dist/types.d.ts +75 -13
  211. package/dist/types.d.ts.map +1 -1
  212. package/dist/types.js +15 -0
  213. package/dist/types.js.map +1 -1
  214. package/grammars/tree-sitter-c.wasm +0 -0
  215. package/grammars/tree-sitter-cpp.wasm +0 -0
  216. package/grammars/tree-sitter-go.wasm +0 -0
  217. package/grammars/tree-sitter-java.wasm +0 -0
  218. package/grammars/tree-sitter-javascript.wasm +0 -0
  219. package/grammars/tree-sitter-python.wasm +0 -0
  220. package/grammars/tree-sitter-rust.wasm +0 -0
  221. package/grammars/tree-sitter-tsx.wasm +0 -0
  222. package/grammars/tree-sitter-typescript.wasm +0 -0
  223. package/package.json +8 -6
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Embedding client — LFM2.5-Embedding via llama-server HTTP API.
3
+ *
4
+ * Default mode is "auto": embedding-runtime downloads the GGUF model +
5
+ * llama-server binary and spawns a managed process. Document/query prefixes
6
+ * follow Liquid AI docs: "document: " / "query: ".
7
+ *
8
+ * Default endpoint: OpenAI-compatible POST /v1/embeddings on llama-server.
9
+ */
10
+ import type { CIConfig } from "../types.js";
11
+ export declare const DEFAULT_EMBEDDING_DIM = 1024;
12
+ export declare const DEFAULT_EMBEDDING_URL = "http://127.0.0.1:18765";
13
+ export declare const DOCUMENT_PREFIX = "document: ";
14
+ export declare const QUERY_PREFIX = "query: ";
15
+ export type EmbeddingRole = "query" | "document";
16
+ export interface Embedder {
17
+ readonly dim: number;
18
+ readonly available: boolean;
19
+ embed(texts: string[], role: EmbeddingRole): Promise<number[][]>;
20
+ embedOne(text: string, role: EmbeddingRole): Promise<number[]>;
21
+ }
22
+ export declare function setEmbeddingRuntimeOverride(opts: {
23
+ url: string;
24
+ dim: number;
25
+ }): void;
26
+ export declare function clearEmbeddingRuntimeOverride(): void;
27
+ export declare function getEmbeddingRuntimeOverride(): {
28
+ url: string;
29
+ dim: number;
30
+ } | null;
31
+ export declare class EmbedderUnavailableError extends Error {
32
+ constructor(message: string);
33
+ }
34
+ /** Cosine similarity in [0, 1] after normalizing (handles non-unit vectors). */
35
+ export declare function cosineSimilarity(a: number[], b: number[]): number;
36
+ export declare function l2Normalize(v: number[]): number[];
37
+ /**
38
+ * OpenAI-compatible embeddings client for llama-server (`--embeddings`).
39
+ */
40
+ export declare class HttpEmbedder implements Embedder {
41
+ readonly dim: number;
42
+ readonly available = true;
43
+ private readonly url;
44
+ private readonly model;
45
+ private readonly apiKey?;
46
+ private readonly timeoutMs;
47
+ private readonly batchSize;
48
+ constructor(opts?: {
49
+ url?: string;
50
+ model?: string;
51
+ apiKey?: string;
52
+ dim?: number;
53
+ timeoutMs?: number;
54
+ batchSize?: number;
55
+ });
56
+ embedOne(text: string, role: EmbeddingRole): Promise<number[]>;
57
+ embed(texts: string[], role: EmbeddingRole): Promise<number[][]>;
58
+ private embedBatch;
59
+ }
60
+ /** Deterministic mock embedder for tests (hash bag-of-words → fixed dim). */
61
+ export declare class MockEmbedder implements Embedder {
62
+ readonly dim: number;
63
+ readonly available = true;
64
+ constructor(dim?: number);
65
+ embedOne(text: string, role: EmbeddingRole): Promise<number[]>;
66
+ embed(texts: string[], role: EmbeddingRole): Promise<number[][]>;
67
+ private hashEmbed;
68
+ }
69
+ /**
70
+ * Create embedder from CIConfig. Returns null when embedding is disabled.
71
+ * "auto" / "api" / "subprocess" all use HTTP once runtime is up.
72
+ * Call ensureEmbeddingRuntime() first for auto mode.
73
+ */
74
+ export declare function createEmbedder(config: CIConfig): Embedder | null;
75
+ /** True when embeddings should be attempted (not explicitly disabled). */
76
+ export declare function isEmbeddingEnabled(config: CIConfig): boolean;
77
+ /** Probe whether the embedding endpoint responds (best-effort). */
78
+ export declare function probeEmbedder(embedder: Embedder): Promise<boolean>;
79
+ //# sourceMappingURL=embedding.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embedding.d.ts","sourceRoot":"","sources":["../../src/services/embedding.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,257 @@
1
+ /**
2
+ * Embedding client — LFM2.5-Embedding via llama-server HTTP API.
3
+ *
4
+ * Default mode is "auto": embedding-runtime downloads the GGUF model +
5
+ * llama-server binary and spawns a managed process. Document/query prefixes
6
+ * follow Liquid AI docs: "document: " / "query: ".
7
+ *
8
+ * Default endpoint: OpenAI-compatible POST /v1/embeddings on llama-server.
9
+ */
10
+ export const DEFAULT_EMBEDDING_DIM = 1024;
11
+ export const DEFAULT_EMBEDDING_URL = "http://127.0.0.1:18765";
12
+ export const DOCUMENT_PREFIX = "document: ";
13
+ export const QUERY_PREFIX = "query: ";
14
+ /** Set by embedding-runtime after managed/external server is healthy. */
15
+ let runtimeOverride = null;
16
+ export function setEmbeddingRuntimeOverride(opts) {
17
+ runtimeOverride = {
18
+ url: opts.url.replace(/\/$/, ""),
19
+ dim: opts.dim,
20
+ };
21
+ }
22
+ export function clearEmbeddingRuntimeOverride() {
23
+ runtimeOverride = null;
24
+ }
25
+ export function getEmbeddingRuntimeOverride() {
26
+ return runtimeOverride;
27
+ }
28
+ export class EmbedderUnavailableError extends Error {
29
+ constructor(message) {
30
+ super(message);
31
+ this.name = "EmbedderUnavailableError";
32
+ }
33
+ }
34
+ /** Cosine similarity in [0, 1] after normalizing (handles non-unit vectors). */
35
+ export function cosineSimilarity(a, b) {
36
+ if (a.length !== b.length || a.length === 0)
37
+ return 0;
38
+ let dot = 0;
39
+ let na = 0;
40
+ let nb = 0;
41
+ for (let i = 0; i < a.length; i++) {
42
+ dot += a[i] * b[i];
43
+ na += a[i] * a[i];
44
+ nb += b[i] * b[i];
45
+ }
46
+ if (na === 0 || nb === 0)
47
+ return 0;
48
+ return dot / (Math.sqrt(na) * Math.sqrt(nb));
49
+ }
50
+ export function l2Normalize(v) {
51
+ let n = 0;
52
+ for (const x of v)
53
+ n += x * x;
54
+ if (n === 0)
55
+ return v.slice();
56
+ const inv = 1 / Math.sqrt(n);
57
+ return v.map((x) => x * inv);
58
+ }
59
+ function withPrefix(text, role) {
60
+ const trimmed = text.trim();
61
+ if (role === "query") {
62
+ if (trimmed.startsWith(QUERY_PREFIX) || trimmed.startsWith("query:"))
63
+ return trimmed;
64
+ return QUERY_PREFIX + trimmed;
65
+ }
66
+ if (trimmed.startsWith(DOCUMENT_PREFIX) || trimmed.startsWith("document:"))
67
+ return trimmed;
68
+ return DOCUMENT_PREFIX + trimmed;
69
+ }
70
+ /**
71
+ * OpenAI-compatible embeddings client for llama-server (`--embeddings`).
72
+ */
73
+ export class HttpEmbedder {
74
+ dim;
75
+ available = true;
76
+ url;
77
+ model;
78
+ apiKey;
79
+ timeoutMs;
80
+ batchSize;
81
+ constructor(opts = {}) {
82
+ this.url = (opts.url || DEFAULT_EMBEDDING_URL).replace(/\/$/, "");
83
+ this.model = opts.model || "LFM2.5-Embedding-350M";
84
+ this.apiKey = opts.apiKey;
85
+ this.dim = opts.dim ?? DEFAULT_EMBEDDING_DIM;
86
+ this.timeoutMs = opts.timeoutMs ?? 60_000;
87
+ this.batchSize = opts.batchSize ?? 16;
88
+ }
89
+ async embedOne(text, role) {
90
+ const [vec] = await this.embed([text], role);
91
+ if (!vec)
92
+ throw new EmbedderUnavailableError("Empty embedding response");
93
+ return vec;
94
+ }
95
+ async embed(texts, role) {
96
+ if (texts.length === 0)
97
+ return [];
98
+ const out = [];
99
+ for (let i = 0; i < texts.length; i += this.batchSize) {
100
+ const batch = texts.slice(i, i + this.batchSize);
101
+ const vectors = await this.embedBatch(batch, role);
102
+ out.push(...vectors);
103
+ }
104
+ return out;
105
+ }
106
+ async embedBatch(texts, role) {
107
+ const inputs = texts.map((t) => withPrefix(t, role));
108
+ const endpoint = `${this.url}/v1/embeddings`;
109
+ const headers = {
110
+ "Content-Type": "application/json",
111
+ };
112
+ if (this.apiKey)
113
+ headers["Authorization"] = `Bearer ${this.apiKey}`;
114
+ const controller = new AbortController();
115
+ const timer = setTimeout(() => controller.abort(), this.timeoutMs);
116
+ try {
117
+ const res = await fetch(endpoint, {
118
+ method: "POST",
119
+ headers,
120
+ body: JSON.stringify({
121
+ input: inputs.length === 1 ? inputs[0] : inputs,
122
+ model: this.model,
123
+ }),
124
+ signal: controller.signal,
125
+ });
126
+ if (!res.ok) {
127
+ const body = await res.text().catch(() => "");
128
+ throw new EmbedderUnavailableError(`Embedding API ${res.status}: ${body.slice(0, 200) || res.statusText}`);
129
+ }
130
+ const json = (await res.json());
131
+ // OpenAI shape: { data: [{ embedding, index }, ...] }
132
+ if (Array.isArray(json.data)) {
133
+ const sorted = [...json.data].sort((a, b) => (a.index ?? 0) - (b.index ?? 0));
134
+ return sorted.map((row) => {
135
+ const emb = flattenEmbedding(row.embedding);
136
+ if (emb.length === 0) {
137
+ throw new EmbedderUnavailableError("Embedding API returned empty vector");
138
+ }
139
+ return l2Normalize(emb);
140
+ });
141
+ }
142
+ // Some llama.cpp builds return a bare embedding for single input
143
+ if (Array.isArray(json.embedding)) {
144
+ return [l2Normalize(flattenEmbedding(json.embedding))];
145
+ }
146
+ throw new EmbedderUnavailableError("Unrecognized embedding API response shape");
147
+ }
148
+ catch (err) {
149
+ if (err instanceof EmbedderUnavailableError)
150
+ throw err;
151
+ if (err instanceof Error && err.name === "AbortError") {
152
+ throw new EmbedderUnavailableError(`Embedding API timeout after ${this.timeoutMs}ms (${endpoint})`);
153
+ }
154
+ const msg = err instanceof Error ? err.message : String(err);
155
+ throw new EmbedderUnavailableError(`Embedding API request failed: ${msg}`);
156
+ }
157
+ finally {
158
+ clearTimeout(timer);
159
+ }
160
+ }
161
+ }
162
+ /** Deterministic mock embedder for tests (hash bag-of-words → fixed dim). */
163
+ export class MockEmbedder {
164
+ dim;
165
+ available = true;
166
+ constructor(dim = 64) {
167
+ this.dim = dim;
168
+ }
169
+ async embedOne(text, role) {
170
+ const [v] = await this.embed([text], role);
171
+ return v;
172
+ }
173
+ async embed(texts, role) {
174
+ return texts.map((t) => this.hashEmbed(withPrefix(t, role)));
175
+ }
176
+ hashEmbed(text) {
177
+ const v = new Array(this.dim).fill(0);
178
+ const tokens = text.toLowerCase().split(/\W+/).filter(Boolean);
179
+ for (const tok of tokens) {
180
+ let h = 2166136261;
181
+ for (let i = 0; i < tok.length; i++) {
182
+ h ^= tok.charCodeAt(i);
183
+ h = Math.imul(h, 16777619);
184
+ }
185
+ const idx = Math.abs(h) % this.dim;
186
+ v[idx] = (v[idx] ?? 0) + 1;
187
+ // bigram shift
188
+ const idx2 = Math.abs(h >> 8) % this.dim;
189
+ v[idx2] = (v[idx2] ?? 0) + 0.5;
190
+ }
191
+ return l2Normalize(v);
192
+ }
193
+ }
194
+ function flattenEmbedding(emb) {
195
+ if (!emb)
196
+ return [];
197
+ if (Array.isArray(emb[0])) {
198
+ // token-level embeddings → mean pool
199
+ const rows = emb;
200
+ if (rows.length === 0)
201
+ return [];
202
+ const dim = rows[0].length;
203
+ const acc = new Array(dim).fill(0);
204
+ for (const row of rows) {
205
+ for (let i = 0; i < dim; i++)
206
+ acc[i] += row[i] ?? 0;
207
+ }
208
+ return acc.map((x) => x / rows.length);
209
+ }
210
+ return emb;
211
+ }
212
+ /**
213
+ * Create embedder from CIConfig. Returns null when embedding is disabled.
214
+ * "auto" / "api" / "subprocess" all use HTTP once runtime is up.
215
+ * Call ensureEmbeddingRuntime() first for auto mode.
216
+ */
217
+ export function createEmbedder(config) {
218
+ const mode = config.embeddingMode ?? "auto";
219
+ if (mode === "none") {
220
+ return null;
221
+ }
222
+ if (process.env.CI_MCP_MOCK_EMBEDDER === "1") {
223
+ return new MockEmbedder(config.embeddingDim ?? DEFAULT_EMBEDDING_DIM);
224
+ }
225
+ const url = runtimeOverride?.url ??
226
+ config.embeddingApi?.url ??
227
+ DEFAULT_EMBEDDING_URL;
228
+ const dim = runtimeOverride?.dim ?? config.embeddingDim ?? DEFAULT_EMBEDDING_DIM;
229
+ return new HttpEmbedder({
230
+ url,
231
+ model: config.embeddingApi?.model ?? "LFM2.5-Embedding-350M",
232
+ apiKey: config.embeddingApi?.apiKey,
233
+ dim,
234
+ });
235
+ }
236
+ /** True when embeddings should be attempted (not explicitly disabled). */
237
+ export function isEmbeddingEnabled(config) {
238
+ const env = process.env.CI_MCP_EMBEDDING_MODE?.trim().toLowerCase();
239
+ if (env === "none" || env === "0" || env === "off" || env === "false") {
240
+ return false;
241
+ }
242
+ if (process.env.CI_MCP_AUTO_EMBED === "0")
243
+ return false;
244
+ const mode = config.embeddingMode ?? "auto";
245
+ return mode !== "none";
246
+ }
247
+ /** Probe whether the embedding endpoint responds (best-effort). */
248
+ export async function probeEmbedder(embedder) {
249
+ try {
250
+ const v = await embedder.embedOne("probe", "query");
251
+ return v.length > 0;
252
+ }
253
+ catch {
254
+ return false;
255
+ }
256
+ }
257
+ //# sourceMappingURL=embedding.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embedding.js","sourceRoot":"","sources":["../../src/services/embedding.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Index lifecycle state — single source of readiness truth for the MCP server.
3
+ *
4
+ * Tools that need the symbol/graph index must consult this module instead of
5
+ * assuming empty results mean "nothing found". Failed or incomplete indexes
6
+ * surface as typed CiError metadata (partial/stale/retryable).
7
+ */
8
+ import { type CiError } from "../types.js";
9
+ export type IndexLifecycle = "not_started" | "indexing" | "ready" | "failed" | "empty";
10
+ export interface IndexStateSnapshot {
11
+ lifecycle: IndexLifecycle;
12
+ /** True only when lifecycle === "ready" and index has usable data */
13
+ ready: boolean;
14
+ /** True when some data may be present but incomplete (e.g. graph failed) */
15
+ partial: boolean;
16
+ /** True when index is known stale vs HEAD (optional, set by status checks) */
17
+ stale: boolean;
18
+ errorMessage?: string;
19
+ symbolCount: number;
20
+ relationCount: number;
21
+ snapshotId?: string;
22
+ indexedAt?: string;
23
+ }
24
+ export declare function getIndexState(): IndexStateSnapshot;
25
+ /** True once a successful index with symbols is available. */
26
+ export declare function isIndexReady(): boolean;
27
+ export declare function markIndexing(): void;
28
+ export declare function markIndexReady(opts: {
29
+ symbolCount: number;
30
+ relationCount: number;
31
+ snapshotId?: string;
32
+ partial?: boolean;
33
+ }): void;
34
+ export declare function markIndexFailed(message: string, opts?: {
35
+ partial?: boolean;
36
+ symbolCount?: number;
37
+ relationCount?: number;
38
+ snapshotId?: string;
39
+ }): void;
40
+ export declare function markIndexEmpty(snapshotId?: string): void;
41
+ export declare function markIndexStale(stale: boolean): void;
42
+ /**
43
+ * Return a CiError when the index cannot serve reliable results.
44
+ * Returns null when ready (or partial-but-usable with symbols).
45
+ *
46
+ * Policy:
47
+ * - not_started / indexing → INDEX_NOT_READY (retryable)
48
+ * - failed with no symbols → INDEX_FAILED
49
+ * - failed with partial symbols → null + caller should attach partial meta
50
+ * - empty → INDEX_NOT_READY
51
+ */
52
+ export declare function requireIndexReady(): CiError | null;
53
+ /** Metadata to attach on successful tool responses for agent observability. */
54
+ export declare function indexMeta(): {
55
+ indexLifecycle: IndexLifecycle;
56
+ partial: boolean;
57
+ stale: boolean;
58
+ snapshotId?: string;
59
+ symbolCount: number;
60
+ };
61
+ /**
62
+ * Build a standard MCP tool error payload from a CiError.
63
+ */
64
+ export declare function ciErrorToolResult(err: CiError): {
65
+ content: [{
66
+ type: "text";
67
+ text: string;
68
+ }];
69
+ structuredContent: Record<string, unknown>;
70
+ isError: true;
71
+ };
72
+ /** Test helper — reset singleton between unit tests. */
73
+ export declare function _resetIndexStateForTests(): void;
74
+ //# sourceMappingURL=index-state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-state.d.ts","sourceRoot":"","sources":["../../src/services/index-state.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAW,KAAK,OAAO,EAAE,MAAM,aAAa,CAAC;AAEpD,MAAM,MAAM,cAAc,GACtB,aAAa,GACb,UAAU,GACV,OAAO,GACP,QAAQ,GACR,OAAO,CAAC;AAEZ,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,cAAc,CAAC;IAC1B,qEAAqE;IACrE,KAAK,EAAE,OAAO,CAAC;IACf,4EAA4E;IAC5E,OAAO,EAAE,OAAO,CAAC;IACjB,8EAA8E;IAC9E,KAAK,EAAE,OAAO,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAWD,wBAAgB,aAAa,IAAI,kBAAkB,CAElD;AAED,8DAA8D;AAC9D,wBAAgB,YAAY,IAAI,OAAO,CAEtC;AAED,wBAAgB,YAAY,IAAI,IAAI,CAQnC;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE;IACnC,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,GAAG,IAAI,CAcP;AAED,wBAAgB,eAAe,CAC7B,OAAO,EAAE,MAAM,EACf,IAAI,CAAC,EAAE;IACL,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,GACA,IAAI,CAYN;AAED,wBAAgB,cAAc,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAYxD;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAEnD;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,IAAI,OAAO,GAAG,IAAI,CAmClD;AAED,+EAA+E;AAC/E,wBAAgB,SAAS,IAAI;IAC3B,cAAc,EAAE,cAAc,CAAC;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,OAAO,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;CACrB,CAQA;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,GAAG;IAC/C,OAAO,EAAE,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC1C,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC3C,OAAO,EAAE,IAAI,CAAC;CACf,CAkBA;AAED,wDAAwD;AACxD,wBAAgB,wBAAwB,IAAI,IAAI,CAS/C"}
@@ -0,0 +1,151 @@
1
+ /**
2
+ * Index lifecycle state — single source of readiness truth for the MCP server.
3
+ *
4
+ * Tools that need the symbol/graph index must consult this module instead of
5
+ * assuming empty results mean "nothing found". Failed or incomplete indexes
6
+ * surface as typed CiError metadata (partial/stale/retryable).
7
+ */
8
+ import { ciError } from "../types.js";
9
+ let state = {
10
+ lifecycle: "not_started",
11
+ ready: false,
12
+ partial: false,
13
+ stale: false,
14
+ symbolCount: 0,
15
+ relationCount: 0,
16
+ };
17
+ export function getIndexState() {
18
+ return { ...state };
19
+ }
20
+ /** True once a successful index with symbols is available. */
21
+ export function isIndexReady() {
22
+ return state.ready && state.lifecycle === "ready";
23
+ }
24
+ export function markIndexing() {
25
+ state = {
26
+ ...state,
27
+ lifecycle: "indexing",
28
+ ready: false,
29
+ partial: false,
30
+ errorMessage: undefined,
31
+ };
32
+ }
33
+ export function markIndexReady(opts) {
34
+ state = {
35
+ lifecycle: opts.symbolCount === 0 ? "empty" : "ready",
36
+ ready: opts.symbolCount > 0 && !opts.partial,
37
+ partial: opts.partial ?? false,
38
+ stale: false,
39
+ errorMessage: opts.partial
40
+ ? "Index is partial — graph population may be incomplete"
41
+ : undefined,
42
+ symbolCount: opts.symbolCount,
43
+ relationCount: opts.relationCount,
44
+ snapshotId: opts.snapshotId,
45
+ indexedAt: new Date().toISOString(),
46
+ };
47
+ }
48
+ export function markIndexFailed(message, opts) {
49
+ state = {
50
+ lifecycle: "failed",
51
+ ready: false,
52
+ partial: opts?.partial ?? false,
53
+ stale: false,
54
+ errorMessage: message,
55
+ symbolCount: opts?.symbolCount ?? state.symbolCount,
56
+ relationCount: opts?.relationCount ?? state.relationCount,
57
+ snapshotId: opts?.snapshotId ?? state.snapshotId,
58
+ indexedAt: state.indexedAt,
59
+ };
60
+ }
61
+ export function markIndexEmpty(snapshotId) {
62
+ state = {
63
+ lifecycle: "empty",
64
+ ready: false,
65
+ partial: false,
66
+ stale: false,
67
+ errorMessage: "Index is empty — no symbols extracted",
68
+ symbolCount: 0,
69
+ relationCount: 0,
70
+ snapshotId,
71
+ indexedAt: new Date().toISOString(),
72
+ };
73
+ }
74
+ export function markIndexStale(stale) {
75
+ state = { ...state, stale };
76
+ }
77
+ /**
78
+ * Return a CiError when the index cannot serve reliable results.
79
+ * Returns null when ready (or partial-but-usable with symbols).
80
+ *
81
+ * Policy:
82
+ * - not_started / indexing → INDEX_NOT_READY (retryable)
83
+ * - failed with no symbols → INDEX_FAILED
84
+ * - failed with partial symbols → null + caller should attach partial meta
85
+ * - empty → INDEX_NOT_READY
86
+ */
87
+ export function requireIndexReady() {
88
+ switch (state.lifecycle) {
89
+ case "not_started":
90
+ return ciError("INDEX_NOT_READY", "Index has not started. Wait for auto-index or run ci_reindex (full profile).", { retryable: true });
91
+ case "indexing":
92
+ return ciError("INDEX_NOT_READY", "Index is still building. Retry shortly.", { retryable: true });
93
+ case "failed":
94
+ if (state.partial && state.symbolCount > 0) {
95
+ // Partial data available — callers may proceed with partial flag
96
+ return null;
97
+ }
98
+ return ciError("INDEX_FAILED", state.errorMessage ?? "Index build failed", { retryable: true, partial: state.partial, snapshotId: state.snapshotId });
99
+ case "empty":
100
+ return ciError("INDEX_NOT_READY", state.errorMessage ?? "Index is empty. Run ci_reindex (full profile) after indexing sources.", { retryable: true, snapshotId: state.snapshotId });
101
+ case "ready":
102
+ return null;
103
+ default:
104
+ return ciError("INTERNAL_ERROR", `Unknown index lifecycle: ${state.lifecycle}`);
105
+ }
106
+ }
107
+ /** Metadata to attach on successful tool responses for agent observability. */
108
+ export function indexMeta() {
109
+ return {
110
+ indexLifecycle: state.lifecycle,
111
+ partial: state.partial,
112
+ stale: state.stale,
113
+ snapshotId: state.snapshotId,
114
+ symbolCount: state.symbolCount,
115
+ };
116
+ }
117
+ /**
118
+ * Build a standard MCP tool error payload from a CiError.
119
+ */
120
+ export function ciErrorToolResult(err) {
121
+ const lines = [
122
+ `## Error: ${err.code}`,
123
+ err.message,
124
+ "",
125
+ `- retryable: ${err.retryable}`,
126
+ `- partial: ${err.partial}`,
127
+ `- stale: ${err.stale}`,
128
+ ];
129
+ if (err.snapshotId)
130
+ lines.push(`- snapshotId: ${err.snapshotId}`);
131
+ return {
132
+ content: [{ type: "text", text: lines.join("\n") }],
133
+ structuredContent: {
134
+ error: err,
135
+ ...indexMeta(),
136
+ },
137
+ isError: true,
138
+ };
139
+ }
140
+ /** Test helper — reset singleton between unit tests. */
141
+ export function _resetIndexStateForTests() {
142
+ state = {
143
+ lifecycle: "not_started",
144
+ ready: false,
145
+ partial: false,
146
+ stale: false,
147
+ symbolCount: 0,
148
+ relationCount: 0,
149
+ };
150
+ }
151
+ //# sourceMappingURL=index-state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-state.js","sourceRoot":"","sources":["../../src/services/index-state.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,OAAO,EAAgB,MAAM,aAAa,CAAC;AAwBpD,IAAI,KAAK,GAAuB;IAC9B,SAAS,EAAE,aAAa;IACxB,KAAK,EAAE,KAAK;IACZ,OAAO,EAAE,KAAK;IACd,KAAK,EAAE,KAAK;IACZ,WAAW,EAAE,CAAC;IACd,aAAa,EAAE,CAAC;CACjB,CAAC;AAEF,MAAM,UAAU,aAAa;IAC3B,OAAO,EAAE,GAAG,KAAK,EAAE,CAAC;AACtB,CAAC;AAED,8DAA8D;AAC9D,MAAM,UAAU,YAAY;IAC1B,OAAO,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,SAAS,KAAK,OAAO,CAAC;AACpD,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,KAAK,GAAG;QACN,GAAG,KAAK;QACR,SAAS,EAAE,UAAU;QACrB,KAAK,EAAE,KAAK;QACZ,OAAO,EAAE,KAAK;QACd,YAAY,EAAE,SAAS;KACxB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,IAK9B;IACC,KAAK,GAAG;QACN,SAAS,EAAE,IAAI,CAAC,WAAW,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO;QACrD,KAAK,EAAE,IAAI,CAAC,WAAW,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO;QAC5C,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,KAAK;QAC9B,KAAK,EAAE,KAAK;QACZ,YAAY,EAAE,IAAI,CAAC,OAAO;YACxB,CAAC,CAAC,uDAAuD;YACzD,CAAC,CAAC,SAAS;QACb,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,aAAa,EAAE,IAAI,CAAC,aAAa;QACjC,UAAU,EAAE,IAAI,CAAC,UAAU;QAC3B,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACpC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,eAAe,CAC7B,OAAe,EACf,IAKC;IAED,KAAK,GAAG;QACN,SAAS,EAAE,QAAQ;QACnB,KAAK,EAAE,KAAK;QACZ,OAAO,EAAE,IAAI,EAAE,OAAO,IAAI,KAAK;QAC/B,KAAK,EAAE,KAAK;QACZ,YAAY,EAAE,OAAO;QACrB,WAAW,EAAE,IAAI,EAAE,WAAW,IAAI,KAAK,CAAC,WAAW;QACnD,aAAa,EAAE,IAAI,EAAE,aAAa,IAAI,KAAK,CAAC,aAAa;QACzD,UAAU,EAAE,IAAI,EAAE,UAAU,IAAI,KAAK,CAAC,UAAU;QAChD,SAAS,EAAE,KAAK,CAAC,SAAS;KAC3B,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,UAAmB;IAChD,KAAK,GAAG;QACN,SAAS,EAAE,OAAO;QAClB,KAAK,EAAE,KAAK;QACZ,OAAO,EAAE,KAAK;QACd,KAAK,EAAE,KAAK;QACZ,YAAY,EAAE,uCAAuC;QACrD,WAAW,EAAE,CAAC;QACd,aAAa,EAAE,CAAC;QAChB,UAAU;QACV,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACpC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAAc;IAC3C,KAAK,GAAG,EAAE,GAAG,KAAK,EAAE,KAAK,EAAE,CAAC;AAC9B,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,iBAAiB;IAC/B,QAAQ,KAAK,CAAC,SAAS,EAAE,CAAC;QACxB,KAAK,aAAa;YAChB,OAAO,OAAO,CACZ,iBAAiB,EACjB,8EAA8E,EAC9E,EAAE,SAAS,EAAE,IAAI,EAAE,CACpB,CAAC;QACJ,KAAK,UAAU;YACb,OAAO,OAAO,CACZ,iBAAiB,EACjB,yCAAyC,EACzC,EAAE,SAAS,EAAE,IAAI,EAAE,CACpB,CAAC;QACJ,KAAK,QAAQ;YACX,IAAI,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,WAAW,GAAG,CAAC,EAAE,CAAC;gBAC3C,iEAAiE;gBACjE,OAAO,IAAI,CAAC;YACd,CAAC;YACD,OAAO,OAAO,CACZ,cAAc,EACd,KAAK,CAAC,YAAY,IAAI,oBAAoB,EAC1C,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,CAC1E,CAAC;QACJ,KAAK,OAAO;YACV,OAAO,OAAO,CACZ,iBAAiB,EACjB,KAAK,CAAC,YAAY,IAAI,uEAAuE,EAC7F,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,CAClD,CAAC;QACJ,KAAK,OAAO;YACV,OAAO,IAAI,CAAC;QACd;YACE,OAAO,OAAO,CAAC,gBAAgB,EAAE,4BAA4B,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC;IACpF,CAAC;AACH,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,SAAS;IAOvB,OAAO;QACL,cAAc,EAAE,KAAK,CAAC,SAAS;QAC/B,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,WAAW,EAAE,KAAK,CAAC,WAAW;KAC/B,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAY;IAK5C,MAAM,KAAK,GAAG;QACZ,aAAa,GAAG,CAAC,IAAI,EAAE;QACvB,GAAG,CAAC,OAAO;QACX,EAAE;QACF,gBAAgB,GAAG,CAAC,SAAS,EAAE;QAC/B,cAAc,GAAG,CAAC,OAAO,EAAE;QAC3B,YAAY,GAAG,CAAC,KAAK,EAAE;KACxB,CAAC;IACF,IAAI,GAAG,CAAC,UAAU;QAAE,KAAK,CAAC,IAAI,CAAC,iBAAiB,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC;IAClE,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACnD,iBAAiB,EAAE;YACjB,KAAK,EAAE,GAAG;YACV,GAAG,SAAS,EAAE;SACf;QACD,OAAO,EAAE,IAAI;KACd,CAAC;AACJ,CAAC;AAED,wDAAwD;AACxD,MAAM,UAAU,wBAAwB;IACtC,KAAK,GAAG;QACN,SAAS,EAAE,aAAa;QACxB,KAAK,EAAE,KAAK;QACZ,OAAO,EAAE,KAAK;QACd,KAAK,EAAE,KAAK;QACZ,WAAW,EAAE,CAAC;QACd,aAAa,EAAE,CAAC;KACjB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Index Worker — content-hash based incremental indexing with atomic generation swap.
3
+ *
4
+ * Architecture:
5
+ * - Each index run produces an immutable "generation" stored in SQLite.
6
+ * - Files are hashed (SHA-256 of content) to detect changes.
7
+ * - Only changed files are re-parsed; unchanged entries carry forward.
8
+ * - Generation pointer is atomically swapped on success.
9
+ * - Supports cancellation via AbortSignal.
10
+ *
11
+ * This eliminates: full rebuilds on every index, blocking event loop,
12
+ * and mixed-state reads during indexing.
13
+ */
14
+ export interface IndexChange {
15
+ /** Files that were added or modified (need re-indexing) */
16
+ changed: string[];
17
+ /** Files that were deleted */
18
+ removed: string[];
19
+ /** Files that are unchanged (carried forward) */
20
+ unchanged: string[];
21
+ }
22
+ /**
23
+ * Compare current file hashes against stored hashes to determine
24
+ * which files need re-indexing.
25
+ */
26
+ export declare function computeIndexPlan(allFiles: {
27
+ path: string;
28
+ language: string;
29
+ }[]): IndexChange;
30
+ export interface IndexGeneration {
31
+ id: number;
32
+ timestamp: string;
33
+ fileCount: number;
34
+ symbolCount: number;
35
+ relationCount: number;
36
+ contentHashes: Record<string, string>;
37
+ }
38
+ /**
39
+ * Create a new index generation, atomically swapping the active pointer.
40
+ *
41
+ * Process:
42
+ * 1. Start SQLite transaction
43
+ * 2. Parse changed files
44
+ * 3. Remove stale entries
45
+ * 4. Insert new entries + carry-forward hashes
46
+ * 5. Update generation pointer
47
+ * 6. Commit
48
+ */
49
+ export declare function createGeneration(allFiles: {
50
+ path: string;
51
+ language: string;
52
+ }[], plan: IndexChange, repoPath: string, commitSha: string, repoFingerprint: string, signal?: AbortSignal): Promise<IndexGeneration>;
53
+ /**
54
+ * Full re-index (no incremental).
55
+ */
56
+ export declare function fullReindex(allFiles: {
57
+ path: string;
58
+ language: string;
59
+ }[], repoPath: string, commitSha: string, repoFingerprint: string, signal?: AbortSignal): Promise<IndexGeneration>;
60
+ //# sourceMappingURL=index-worker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-worker.d.ts","sourceRoot":"","sources":["../../src/services/index-worker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AA6BH,MAAM,WAAW,WAAW;IAC1B,2DAA2D;IAC3D,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,8BAA8B;IAC9B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,iDAAiD;IACjD,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,EAAE,GAC7C,WAAW,CAgDb;AAID,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACvC;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,EAAE,EAC9C,IAAI,EAAE,WAAW,EACjB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,eAAe,EAAE,MAAM,EACvB,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,eAAe,CAAC,CAuF1B;AAED;;GAEG;AACH,wBAAsB,WAAW,CAC/B,QAAQ,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,EAAE,EAC9C,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,eAAe,EAAE,MAAM,EACvB,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,eAAe,CAAC,CAO1B"}