ultracode 5.4.0 → 5.6.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 (151) hide show
  1. package/dist/chunks/analysis-tool-handlers-GH5FDEWW.js +817 -0
  2. package/dist/chunks/analysis-tool-handlers-IXP4MWZX.js +817 -0
  3. package/dist/chunks/analysis-tool-handlers-LC2BTQYK.js +13 -0
  4. package/dist/chunks/analysis-tool-handlers-QYFKQPFL.js +817 -0
  5. package/dist/chunks/autodoc-tool-handlers-2HF6ERYN.js +1112 -0
  6. package/dist/chunks/autodoc-tool-handlers-4OGQJ7C3.js +1112 -0
  7. package/dist/chunks/autodoc-tool-handlers-N736CB56.js +138 -0
  8. package/dist/chunks/autodoc-tool-handlers-NQYBY6U4.js +1112 -0
  9. package/dist/chunks/branch-tool-handlers-KW3H4FJK.js +276 -0
  10. package/dist/chunks/branch-tool-handlers-QOUDZKJ2.js +276 -0
  11. package/dist/chunks/branch-tool-handlers-RB2U36KI.js +2 -0
  12. package/dist/chunks/branch-tool-handlers-ZHJM6PDK.js +276 -0
  13. package/dist/chunks/chunk-2Z6OQPYC.js +656 -0
  14. package/dist/chunks/chunk-3MQ7LRPN.js +322 -0
  15. package/dist/chunks/chunk-4W6QYGXZ.js +10 -0
  16. package/dist/chunks/chunk-533NFGUG.js +1 -0
  17. package/dist/chunks/chunk-5NUPOPWM.js +1 -0
  18. package/dist/chunks/chunk-AK4HIPA2.js +322 -0
  19. package/dist/chunks/chunk-B3H5NS3I.js +656 -0
  20. package/dist/chunks/chunk-DPTZHDST.js +4 -0
  21. package/dist/chunks/chunk-E5HQWLU5.js +322 -0
  22. package/dist/chunks/chunk-EOH25B5P.js +572 -0
  23. package/dist/chunks/chunk-ESV6F6E3.js +3179 -0
  24. package/dist/chunks/chunk-FPELPFER.js +924 -0
  25. package/dist/chunks/chunk-G6J42I55.js +161 -0
  26. package/dist/chunks/chunk-GCQE7ZYW.js +1 -0
  27. package/dist/chunks/chunk-GTIF6MOX.js +1 -0
  28. package/dist/chunks/chunk-I6STSSAK.js +2 -0
  29. package/dist/chunks/chunk-J2WBGTK2.js +4697 -0
  30. package/dist/chunks/chunk-KAYOX5EB.js +4697 -0
  31. package/dist/chunks/chunk-KPMTACOT.js +656 -0
  32. package/dist/chunks/chunk-L376GZ44.js +3179 -0
  33. package/dist/chunks/chunk-LCTOTHDA.js +15 -0
  34. package/dist/chunks/chunk-LEDJ7GVQ.js +316 -0
  35. package/dist/chunks/chunk-LH4OUKNZ.js +277 -0
  36. package/dist/chunks/chunk-O6IE2MEZ.js +161 -0
  37. package/dist/chunks/chunk-OEXPCY3F.js +316 -0
  38. package/dist/chunks/chunk-OMXOLFDN.js +924 -0
  39. package/dist/chunks/chunk-PLPBXWOU.js +3179 -0
  40. package/dist/chunks/chunk-PWLE5DN2.js +572 -0
  41. package/dist/chunks/chunk-PY43JPWL.js +447 -0
  42. package/dist/chunks/chunk-Q3B4EB7A.js +15 -0
  43. package/dist/chunks/chunk-Q5LPVLXA.js +337 -0
  44. package/dist/chunks/chunk-QIRZHZK2.js +5 -0
  45. package/dist/chunks/chunk-ROQ27LSL.js +924 -0
  46. package/dist/chunks/chunk-S5Q7BD6J.js +572 -0
  47. package/dist/chunks/chunk-SAMX3HJQ.js +337 -0
  48. package/dist/chunks/chunk-SV3WKUNV.js +1 -0
  49. package/dist/chunks/chunk-TCHCDCDO.js +167 -0
  50. package/dist/chunks/chunk-TR3HS7U6.js +316 -0
  51. package/dist/chunks/chunk-TUWE6FCW.js +167 -0
  52. package/dist/chunks/chunk-TVOTA7EE.js +277 -0
  53. package/dist/chunks/chunk-VS44D772.js +337 -0
  54. package/dist/chunks/chunk-WIE3G5ES.js +167 -0
  55. package/dist/chunks/chunk-XG3ACLWR.js +5 -0
  56. package/dist/chunks/chunk-XJ2Z5QQO.js +1 -0
  57. package/dist/chunks/chunk-XK2NY7RB.js +277 -0
  58. package/dist/chunks/chunk-Y4F7NZFZ.js +4700 -0
  59. package/dist/chunks/chunk-YS75L3ZS.js +161 -0
  60. package/dist/chunks/chunk-ZVG5HHI3.js +15 -0
  61. package/dist/chunks/dev-agent-DDDIVWOF.js +1 -0
  62. package/dist/chunks/dev-agent-E2VCFKXN.js +1624 -0
  63. package/dist/chunks/dev-agent-KJNSU5KQ.js +1624 -0
  64. package/dist/chunks/dev-agent-NDERYIPV.js +1624 -0
  65. package/dist/chunks/faiss-provider-7R4BQDIV.js +12 -0
  66. package/dist/chunks/faiss-provider-7ZFRSDN5.js +12 -0
  67. package/dist/chunks/faiss-provider-SXB7FTLB.js +1 -0
  68. package/dist/chunks/faiss-provider-TKLBEUSH.js +12 -0
  69. package/dist/chunks/file-tool-handlers-5DODQXGF.js +1027 -0
  70. package/dist/chunks/file-tool-handlers-KGHLE4KR.js +1027 -0
  71. package/dist/chunks/file-tool-handlers-KTOQ4NFS.js +12 -0
  72. package/dist/chunks/file-tool-handlers-V4SFUDQB.js +1027 -0
  73. package/dist/chunks/graph-metrics-tool-handlers-3AV4X4ZY.js +65 -0
  74. package/dist/chunks/graph-metrics-tool-handlers-3VMDQHJ6.js +65 -0
  75. package/dist/chunks/graph-metrics-tool-handlers-BZ6E6YHF.js +1 -0
  76. package/dist/chunks/graph-metrics-tool-handlers-IYBGSXL7.js +65 -0
  77. package/dist/chunks/graph-storage-factory-2CQ2RPDV.js +13 -0
  78. package/dist/chunks/graph-storage-factory-C5SMMYL6.js +13 -0
  79. package/dist/chunks/graph-storage-factory-EEO2V3GJ.js +1 -0
  80. package/dist/chunks/graph-storage-factory-WBCTXP34.js +13 -0
  81. package/dist/chunks/history-tool-handlers-AS7OQFZI.js +1 -0
  82. package/dist/chunks/history-tool-handlers-FSNJYXV2.js +208 -0
  83. package/dist/chunks/history-tool-handlers-JZAH4EIQ.js +208 -0
  84. package/dist/chunks/history-tool-handlers-KCSCXZ7T.js +208 -0
  85. package/dist/chunks/incremental-updater-A2EL4QXU.js +14 -0
  86. package/dist/chunks/incremental-updater-EQIKBVY2.js +14 -0
  87. package/dist/chunks/incremental-updater-JFGRPH3B.js +14 -0
  88. package/dist/chunks/incremental-updater-S5BAAGHP.js +1 -0
  89. package/dist/chunks/indexer-agent-ASKY7JPG.js +1 -0
  90. package/dist/chunks/indexer-agent-NKAOF323.js +21 -0
  91. package/dist/chunks/indexer-agent-PJN5IOKQ.js +21 -0
  92. package/dist/chunks/indexer-agent-WRJFWKZX.js +21 -0
  93. package/dist/chunks/indexing-pipeline-D4P2O72Z.js +249 -0
  94. package/dist/chunks/indexing-pipeline-L7C543N4.js +1 -0
  95. package/dist/chunks/indexing-pipeline-NHPRN3AB.js +249 -0
  96. package/dist/chunks/indexing-pipeline-ZAXCZU22.js +249 -0
  97. package/dist/chunks/layered-faiss-provider-62CNW54X.js +1 -0
  98. package/dist/chunks/layered-faiss-provider-O7L77GFX.js +12 -0
  99. package/dist/chunks/layered-faiss-provider-RVHLHLPK.js +12 -0
  100. package/dist/chunks/layered-faiss-provider-YT7EDIJI.js +12 -0
  101. package/dist/chunks/merge-agent-3RF7VFF5.js +2481 -0
  102. package/dist/chunks/merge-agent-JCKTCBCE.js +2481 -0
  103. package/dist/chunks/merge-agent-VCL7OXPN.js +2481 -0
  104. package/dist/chunks/merge-agent-ZGK24WVF.js +11 -0
  105. package/dist/chunks/merge-tool-handlers-GV2LOIKU.js +277 -0
  106. package/dist/chunks/merge-tool-handlers-TYDWU5X2.js +277 -0
  107. package/dist/chunks/merge-tool-handlers-U7X2ZO2M.js +1 -0
  108. package/dist/chunks/merge-tool-handlers-YH62ZLPJ.js +277 -0
  109. package/dist/chunks/pattern-tool-handlers-76NF5JDS.js +13 -0
  110. package/dist/chunks/pattern-tool-handlers-IJAGEIVD.js +1549 -0
  111. package/dist/chunks/pattern-tool-handlers-VA5WYA62.js +1549 -0
  112. package/dist/chunks/pattern-tool-handlers-WQ6UBMJS.js +1549 -0
  113. package/dist/chunks/query-agent-36ADGCFZ.js +1 -0
  114. package/dist/chunks/query-agent-H22CR5N5.js +191 -0
  115. package/dist/chunks/query-agent-K2UGZS4M.js +191 -0
  116. package/dist/chunks/query-agent-YJCEHOXD.js +191 -0
  117. package/dist/chunks/semantic-agent-AC7CBEDE.js +6381 -0
  118. package/dist/chunks/semantic-agent-HK5X6CKU.js +6381 -0
  119. package/dist/chunks/semantic-agent-KONIKEGW.js +6381 -0
  120. package/dist/chunks/semantic-agent-LH6IZ2L7.js +137 -0
  121. package/dist/chunks/semantic-tool-handlers-5LMSH2U7.js +3 -0
  122. package/dist/chunks/semantic-tool-handlers-735UMO7Y.js +817 -0
  123. package/dist/chunks/semantic-tool-handlers-BNUYPP7X.js +817 -0
  124. package/dist/chunks/semantic-tool-handlers-MYZPEUD2.js +817 -0
  125. package/dist/chunks/snapshot-tool-handlers-6SIHZT2F.js +201 -0
  126. package/dist/chunks/snapshot-tool-handlers-DS4P3KOT.js +201 -0
  127. package/dist/chunks/snapshot-tool-handlers-JYHRFPC7.js +201 -0
  128. package/dist/chunks/snapshot-tool-handlers-YEHMAT3L.js +1 -0
  129. package/dist/chunks/storage-paths-A3C7WHHG.js +8 -0
  130. package/dist/chunks/storage-paths-HDYH7WPM.js +1 -0
  131. package/dist/chunks/storage-paths-IMFRHBWF.js +8 -0
  132. package/dist/chunks/storage-paths-P3PUSMUD.js +8 -0
  133. package/dist/chunks/taint-tool-handlers-CWESOOMQ.js +68 -0
  134. package/dist/chunks/taint-tool-handlers-OG3NVVP3.js +1 -0
  135. package/dist/chunks/taint-tool-handlers-ON3G3FA7.js +68 -0
  136. package/dist/chunks/taint-tool-handlers-P4P5J6DB.js +68 -0
  137. package/dist/chunks/tracing-tool-handlers-4BDCXTZZ.js +3935 -0
  138. package/dist/chunks/tracing-tool-handlers-6FPNM7HX.js +3935 -0
  139. package/dist/chunks/tracing-tool-handlers-LQTQ5SKK.js +89 -0
  140. package/dist/chunks/tracing-tool-handlers-XRQX2DTS.js +3935 -0
  141. package/dist/chunks/validation-tool-handlers-DZUG7KYY.js +2 -0
  142. package/dist/chunks/validation-tool-handlers-O6TGFSH5.js +555 -0
  143. package/dist/chunks/validation-tool-handlers-RREUYKIR.js +555 -0
  144. package/dist/chunks/validation-tool-handlers-XPWSMS37.js +555 -0
  145. package/dist/index.js +13 -13
  146. package/dist/roslyn-addon/.build-hash +1 -1
  147. package/dist/roslyn-addon/ILGPU.Algorithms.dll +0 -0
  148. package/dist/roslyn-addon/ILGPU.dll +0 -0
  149. package/dist/roslyn-addon/UltraCode.CSharp.deps.json +35 -0
  150. package/dist/roslyn-addon/UltraCode.CSharp.dll +0 -0
  151. package/package.json +1 -1
@@ -0,0 +1,656 @@
1
+ import { getGpuClient } from './chunk-OMXOLFDN.js';
2
+ import { simdL2Normalize } from './chunk-QN237S7C.js';
3
+ import { detectBaseBranch, loadBaseMetadata, createInitialBaseMetadata, updateBaseMetadata } from './chunk-YS75L3ZS.js';
4
+ import { init_storage_paths, normalizeBranchName, getProjectDir } from './chunk-XK2NY7RB.js';
5
+ import { tryGarbageCollect } from './chunk-IMQ6WSJV.js';
6
+ import { init_logging, log, logMemory } from './chunk-VCCBEJQ5.js';
7
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
8
+ import { dirname, join } from 'path';
9
+
10
+ // src/semantic/faiss/layered-faiss-provider.ts
11
+ init_logging();
12
+ init_storage_paths();
13
+ var DEFAULT_CONFIG = {
14
+ dimensions: 384,
15
+ indexType: "hnsw",
16
+ hnswM: 32,
17
+ hnswEfConstruction: 200,
18
+ hnswEfSearch: 64,
19
+ autoSaveThreshold: 5e4
20
+ // Increased to reduce blocking during indexing
21
+ };
22
+ function getLayeredPaths(projectDir, branchName, baseBranch) {
23
+ const safeBranch = normalizeBranchName(branchName);
24
+ const safeBase = baseBranch ? normalizeBranchName(baseBranch) : safeBranch;
25
+ return {
26
+ // Base layer - uses base branch name (e.g., faiss-dev.bin for base branch "dev")
27
+ baseIndex: join(projectDir, `faiss-${safeBase}.bin`),
28
+ baseIds: join(projectDir, `faiss-${safeBase}.bin.ids.json`),
29
+ baseMeta: join(projectDir, "faiss-base.meta.json"),
30
+ // Delta layer (per feature branch)
31
+ deltaIndex: join(projectDir, `faiss-${safeBranch}.delta.bin`),
32
+ deltaIds: join(projectDir, `faiss-${safeBranch}.delta.ids.json`),
33
+ deltaMeta: join(projectDir, `faiss-${safeBranch}.delta.meta.json`),
34
+ tombstones: join(projectDir, `faiss-${safeBranch}.tombstones.json`)
35
+ };
36
+ }
37
+ var LayeredFaissProvider = class _LayeredFaissProvider {
38
+ config;
39
+ client = null;
40
+ isInitialized = false;
41
+ // Project context
42
+ projectPath = "";
43
+ projectHash = "";
44
+ currentBranch = null;
45
+ baseBranch = null;
46
+ // Layer state
47
+ isOnBaseBranch = false;
48
+ baseIdSet = /* @__PURE__ */ new Set();
49
+ deltaIdSet = /* @__PURE__ */ new Set();
50
+ tombstones = /* @__PURE__ */ new Set();
51
+ // Change tracking
52
+ baseUnsavedCount = 0;
53
+ deltaUnsavedCount = 0;
54
+ /** Maximum delta size before auto-merge to prevent memory leaks */
55
+ static MAX_DELTA_SIZE = 5e3;
56
+ // Initialization mutex
57
+ initializePromise = null;
58
+ constructor(config = {}) {
59
+ this.config = { ...DEFAULT_CONFIG, ...config };
60
+ }
61
+ // ===========================================================================
62
+ // Public API
63
+ // ===========================================================================
64
+ /**
65
+ * Check if the provider is initialized
66
+ */
67
+ get initialized() {
68
+ return this.isInitialized;
69
+ }
70
+ /**
71
+ * Get current configured dimensions
72
+ */
73
+ getDimensions() {
74
+ return this.config.dimensions;
75
+ }
76
+ /**
77
+ * Update dimensions (e.g. when embedding model changes)
78
+ * Only effective before initialize() creates the FAISS index.
79
+ */
80
+ setDimensions(dimensions) {
81
+ if (this.config.dimensions !== dimensions) {
82
+ log.i("LAYERED_FAISS", "dimensions_updated", { from: this.config.dimensions, to: dimensions });
83
+ this.config.dimensions = dimensions;
84
+ }
85
+ }
86
+ // ===========================================================================
87
+ // Lifecycle
88
+ // ===========================================================================
89
+ /**
90
+ * Initialize the provider for a specific project and branch
91
+ * v6: CRITICAL FIX - Check if projectHash changed and reinitialize if needed!
92
+ * Without this, switching projects would continue using the first project's index.
93
+ */
94
+ async initialize(projectPath, projectHash, branchName) {
95
+ if (this.initializePromise && this.projectHash === projectHash) {
96
+ return this.initializePromise;
97
+ }
98
+ if (this.projectHash && this.projectHash !== projectHash) {
99
+ log.i("LAYERED_FAISS", "project_switch", {
100
+ from: this.projectHash,
101
+ to: projectHash
102
+ });
103
+ if (this.isInitialized) {
104
+ log.i("LAYERED_FAISS", "saving_before_switch", {
105
+ project: this.projectHash,
106
+ baseUnsaved: this.baseUnsavedCount,
107
+ deltaUnsaved: this.deltaUnsavedCount
108
+ });
109
+ await this.save();
110
+ }
111
+ this.isInitialized = false;
112
+ this.initializePromise = null;
113
+ }
114
+ this.initializePromise = this.initializeInternal(projectPath, projectHash, branchName);
115
+ return this.initializePromise;
116
+ }
117
+ async initializeInternal(projectPath, projectHash, branchName) {
118
+ try {
119
+ this.projectPath = projectPath;
120
+ this.projectHash = projectHash;
121
+ this.currentBranch = normalizeBranchName(branchName);
122
+ this.baseIdSet.clear();
123
+ this.deltaIdSet.clear();
124
+ this.tombstones.clear();
125
+ this.baseUnsavedCount = 0;
126
+ this.deltaUnsavedCount = 0;
127
+ const projectDir = getProjectDir(projectPath);
128
+ if (!existsSync(projectDir)) {
129
+ mkdirSync(projectDir, { recursive: true });
130
+ }
131
+ this.client = getGpuClient();
132
+ const started = await this.client.start();
133
+ if (!started) {
134
+ log.e("LAYERED_FAISS", "client_start_fail");
135
+ return false;
136
+ }
137
+ this.baseBranch = detectBaseBranch(projectPath);
138
+ this.isOnBaseBranch = this.baseBranch === this.currentBranch;
139
+ log.i("LAYERED_FAISS", "init", {
140
+ project: projectHash,
141
+ current: this.currentBranch,
142
+ base: this.baseBranch,
143
+ isOnBase: this.isOnBaseBranch
144
+ });
145
+ await this.loadLayers();
146
+ this.isInitialized = true;
147
+ return true;
148
+ } catch (error) {
149
+ log.e("LAYERED_FAISS", "init_fail", { err: String(error) });
150
+ this.initializePromise = null;
151
+ return false;
152
+ }
153
+ }
154
+ /**
155
+ * Load the appropriate layers based on current branch
156
+ */
157
+ async loadLayers() {
158
+ const projectDir = getProjectDir(this.projectPath);
159
+ const paths = getLayeredPaths(projectDir, this.currentBranch, this.baseBranch);
160
+ log.d("LAYERED_FAISS", "load_layers", {
161
+ projectDir,
162
+ projectPath: this.projectPath,
163
+ currentBranch: this.currentBranch,
164
+ baseBranch: this.baseBranch,
165
+ baseIndexPath: paths.baseIndex,
166
+ baseIndexExists: existsSync(paths.baseIndex),
167
+ baseIdsPath: paths.baseIds,
168
+ baseIdsExists: existsSync(paths.baseIds)
169
+ });
170
+ await this.loadBaseLayer(paths);
171
+ if (!this.isOnBaseBranch) {
172
+ await this.loadDeltaLayer(paths);
173
+ }
174
+ }
175
+ /**
176
+ * Load base layer index
177
+ */
178
+ async loadBaseLayer(paths) {
179
+ const indexConfig = {
180
+ dimensions: this.config.dimensions,
181
+ indexType: this.config.indexType,
182
+ metric: "l2",
183
+ hnswM: this.config.hnswM,
184
+ hnswEfConstruction: this.config.hnswEfConstruction,
185
+ hnswEfSearch: this.config.hnswEfSearch
186
+ };
187
+ const baseIndexExists = existsSync(paths.baseIndex);
188
+ const loadPath = baseIndexExists ? paths.baseIndex : void 0;
189
+ await this.client.faissInitialize(indexConfig, loadPath);
190
+ if (baseIndexExists && existsSync(paths.baseIds)) {
191
+ try {
192
+ const data = readFileSync(paths.baseIds, "utf-8");
193
+ const ids = JSON.parse(data);
194
+ this.baseIdSet = new Set(ids);
195
+ log.d("LAYERED_FAISS", "base_ids_loaded", { count: this.baseIdSet.size });
196
+ } catch (error) {
197
+ log.w("LAYERED_FAISS", "base_ids_load_fail", { err: String(error) });
198
+ }
199
+ }
200
+ const stats = await this.client.faissGetStats();
201
+ log.i("LAYERED_FAISS", "base_loaded", {
202
+ vectors: stats.totalVectors,
203
+ ids: this.baseIdSet.size,
204
+ fromFile: baseIndexExists
205
+ });
206
+ }
207
+ /**
208
+ * Load delta layer for feature branch
209
+ */
210
+ async loadDeltaLayer(paths) {
211
+ if (existsSync(paths.tombstones)) {
212
+ try {
213
+ const data = readFileSync(paths.tombstones, "utf-8");
214
+ const tombstoneList = JSON.parse(data);
215
+ this.tombstones = new Set(tombstoneList);
216
+ log.d("LAYERED_FAISS", "tombstones_loaded", { count: this.tombstones.size });
217
+ } catch (error) {
218
+ log.w("LAYERED_FAISS", "tombstones_load_fail", { err: String(error) });
219
+ }
220
+ }
221
+ if (existsSync(paths.deltaIds)) {
222
+ try {
223
+ const data = readFileSync(paths.deltaIds, "utf-8");
224
+ const ids = JSON.parse(data);
225
+ this.deltaIdSet = new Set(ids);
226
+ log.d("LAYERED_FAISS", "delta_ids_loaded", { count: this.deltaIdSet.size });
227
+ } catch (error) {
228
+ log.w("LAYERED_FAISS", "delta_ids_load_fail", { err: String(error) });
229
+ }
230
+ }
231
+ }
232
+ // ===========================================================================
233
+ // Branch switching
234
+ // ===========================================================================
235
+ /**
236
+ * Switch to a different branch
237
+ */
238
+ async switchBranch(branchName) {
239
+ const normalizedBranch = normalizeBranchName(branchName);
240
+ if (this.currentBranch === normalizedBranch) {
241
+ return;
242
+ }
243
+ log.i("LAYERED_FAISS", "branch_switch", {
244
+ from: this.currentBranch,
245
+ to: normalizedBranch
246
+ });
247
+ await this.save();
248
+ this.currentBranch = normalizedBranch;
249
+ this.isOnBaseBranch = this.baseBranch === normalizedBranch;
250
+ this.deltaIdSet.clear();
251
+ this.tombstones.clear();
252
+ this.deltaUnsavedCount = 0;
253
+ if (!this.isOnBaseBranch) {
254
+ const projectDir = getProjectDir(this.projectPath);
255
+ const paths = getLayeredPaths(projectDir, normalizedBranch, this.baseBranch);
256
+ await this.loadDeltaLayer(paths);
257
+ }
258
+ log.i("LAYERED_FAISS", "branch_switched", {
259
+ branch: normalizedBranch,
260
+ isOnBase: this.isOnBaseBranch,
261
+ deltaIds: this.deltaIdSet.size,
262
+ tombstones: this.tombstones.size
263
+ });
264
+ }
265
+ // ===========================================================================
266
+ // Search
267
+ // ===========================================================================
268
+ /**
269
+ * Search across all layers
270
+ *
271
+ * Algorithm:
272
+ * 1. Search base index for top K*2 results
273
+ * 2. Filter out tombstones
274
+ * 3. If on feature branch, search delta for top K*2
275
+ * 4. Merge and deduplicate (delta takes precedence)
276
+ * 5. Sort by similarity and return top K
277
+ */
278
+ async search(queryVector, limit) {
279
+ if (!this.isInitialized || !this.client) {
280
+ log.w("LAYERED_FAISS", "search called but not initialized", {
281
+ isInit: this.isInitialized,
282
+ hasClient: !!this.client
283
+ });
284
+ return [];
285
+ }
286
+ const normalizedQuery = simdL2Normalize(queryVector);
287
+ log.d("LAYERED_FAISS", "search", {
288
+ inputLen: queryVector.length,
289
+ normalizedLen: normalizedQuery.length,
290
+ limit,
291
+ normalizedSample: Array.from(normalizedQuery.slice(0, 3))
292
+ });
293
+ const searchLimit = Math.min(limit * 2, 200);
294
+ const results = [];
295
+ const seenIds = /* @__PURE__ */ new Set();
296
+ if (!this.isOnBaseBranch && this.deltaIdSet.size > 0) ;
297
+ log.d("LAYERED_FAISS", "calling faissSearch", {
298
+ vectorLen: normalizedQuery.length,
299
+ vectorType: normalizedQuery.constructor.name,
300
+ searchLimit
301
+ });
302
+ const baseResults = await this.client.faissSearch(normalizedQuery, searchLimit);
303
+ for (const result of baseResults) {
304
+ if (seenIds.has(result.id)) continue;
305
+ if (this.tombstones.has(result.id)) continue;
306
+ if (this.deltaIdSet.has(result.id)) {
307
+ continue;
308
+ }
309
+ results.push({
310
+ id: result.id,
311
+ similarity: 1 - result.distance,
312
+ // Convert L2 distance to similarity
313
+ source: "base"
314
+ });
315
+ seenIds.add(result.id);
316
+ }
317
+ for (const id of this.deltaIdSet) {
318
+ if (!seenIds.has(id) && results.length < limit) {
319
+ const baseResult = baseResults.find((r) => r.id === id);
320
+ if (baseResult) {
321
+ results.push({
322
+ id: baseResult.id,
323
+ similarity: 1 - baseResult.distance,
324
+ source: "delta"
325
+ });
326
+ seenIds.add(id);
327
+ }
328
+ }
329
+ }
330
+ return results.sort((a, b) => b.similarity - a.similarity).slice(0, limit);
331
+ }
332
+ /**
333
+ * Search and return in VectorStore-compatible format
334
+ */
335
+ async searchForVectorStore(queryVector, limit) {
336
+ const results = await this.search(queryVector, limit);
337
+ return results.map((r) => ({
338
+ id: r.id,
339
+ content: "",
340
+ // Content is not stored in FAISS, retrieved separately
341
+ similarity: r.similarity,
342
+ metadata: { source: r.source }
343
+ }));
344
+ }
345
+ // ===========================================================================
346
+ // Add / Remove
347
+ // ===========================================================================
348
+ /**
349
+ * Add a vector embedding
350
+ */
351
+ async add(embedding) {
352
+ if (!this.isInitialized || !this.client) {
353
+ return { success: false, target: "base", error: "Not initialized" };
354
+ }
355
+ const normalizedVector = simdL2Normalize(embedding.vector);
356
+ if (this.isOnBaseBranch) {
357
+ await this.client.faissAdd([embedding.id], normalizedVector);
358
+ this.baseIdSet.add(embedding.id);
359
+ this.baseUnsavedCount++;
360
+ if (this.baseUnsavedCount >= this.config.autoSaveThreshold) {
361
+ await this.saveBase();
362
+ }
363
+ return { success: true, target: "base" };
364
+ } else {
365
+ this.tombstones.delete(embedding.id);
366
+ this.deltaIdSet.add(embedding.id);
367
+ this.deltaUnsavedCount++;
368
+ log.i("LAYERED_FAISS", "add_to_delta", {
369
+ id: embedding.id.slice(0, 50),
370
+ branch: this.currentBranch,
371
+ deltaUnsaved: this.deltaUnsavedCount
372
+ });
373
+ await this.client.faissAdd([embedding.id], normalizedVector);
374
+ if (this.deltaUnsavedCount >= this.config.autoSaveThreshold) {
375
+ await this.saveDelta();
376
+ }
377
+ return { success: true, target: "delta" };
378
+ }
379
+ }
380
+ /**
381
+ * Add multiple embeddings in batch (optimized - single Named Pipe call)
382
+ */
383
+ async addBatch(embeddings) {
384
+ if (embeddings.length === 0) {
385
+ return [];
386
+ }
387
+ if (!this.isInitialized || !this.client) {
388
+ return embeddings.map(() => ({ success: false, target: "base", error: "Not initialized" }));
389
+ }
390
+ log.d("LAYERED_FAISS", "addBatch_called", {
391
+ count: embeddings.length,
392
+ branch: this.currentBranch,
393
+ isOnBase: this.isOnBaseBranch
394
+ });
395
+ const startTime = performance.now();
396
+ const allIds = [];
397
+ const dimensions = this.config.dimensions;
398
+ const allVectors = new Float32Array(embeddings.length * dimensions);
399
+ for (let i = 0; i < embeddings.length; i++) {
400
+ const embedding = embeddings[i];
401
+ const normalized = simdL2Normalize(embedding.vector);
402
+ allIds.push(embedding.id);
403
+ allVectors.set(normalized, i * dimensions);
404
+ if (this.isOnBaseBranch) {
405
+ this.baseIdSet.add(embedding.id);
406
+ } else {
407
+ this.tombstones.delete(embedding.id);
408
+ this.deltaIdSet.add(embedding.id);
409
+ }
410
+ }
411
+ await this.client.faissAdd(allIds, allVectors);
412
+ if (this.isOnBaseBranch) {
413
+ this.baseUnsavedCount += embeddings.length;
414
+ if (this.baseUnsavedCount >= this.config.autoSaveThreshold) {
415
+ await this.saveBase();
416
+ }
417
+ } else {
418
+ this.deltaUnsavedCount += embeddings.length;
419
+ if (this.deltaUnsavedCount >= this.config.autoSaveThreshold) {
420
+ await this.saveDelta();
421
+ }
422
+ }
423
+ const elapsed = performance.now() - startTime;
424
+ log.i("LAYERED_FAISS", "addBatch_complete", {
425
+ count: embeddings.length,
426
+ elapsed: `${elapsed.toFixed(1)}ms`,
427
+ speed: `${Math.round(embeddings.length / (elapsed / 1e3))}/s`,
428
+ target: this.isOnBaseBranch ? "base" : "delta",
429
+ deltaIdSetSize: this.deltaIdSet.size,
430
+ tombstonesSize: this.tombstones.size
431
+ });
432
+ if (!this.isOnBaseBranch && this.deltaIdSet.size > _LayeredFaissProvider.MAX_DELTA_SIZE) {
433
+ log.i("LAYERED_FAISS", "auto_merge_delta", {
434
+ deltaSize: this.deltaIdSet.size,
435
+ tombstones: this.tombstones.size,
436
+ threshold: _LayeredFaissProvider.MAX_DELTA_SIZE
437
+ });
438
+ logMemory("LAYERED_FAISS", { deltaSize: this.deltaIdSet.size, tombstones: this.tombstones.size });
439
+ await this.saveBase();
440
+ if (tryGarbageCollect(true)) {
441
+ log.d("LAYERED_FAISS", "gc_after_merge");
442
+ }
443
+ }
444
+ const target = this.isOnBaseBranch ? "base" : "delta";
445
+ return embeddings.map(() => ({ success: true, target }));
446
+ }
447
+ /**
448
+ * Remove vectors by IDs (IVectorProvider interface)
449
+ */
450
+ async remove(ids) {
451
+ for (const id of ids) {
452
+ await this.removeOne(id);
453
+ }
454
+ }
455
+ /**
456
+ * Remove a single vector by ID
457
+ */
458
+ async removeOne(id) {
459
+ if (!this.isInitialized || !this.client) {
460
+ return { success: false, action: "not_found" };
461
+ }
462
+ if (this.isOnBaseBranch) {
463
+ const existed = this.baseIdSet.has(id);
464
+ if (existed) {
465
+ await this.client.faissRemove([id]);
466
+ this.baseIdSet.delete(id);
467
+ this.baseUnsavedCount++;
468
+ return { success: true, action: "removed_from_base" };
469
+ }
470
+ return { success: false, action: "not_found" };
471
+ } else {
472
+ if (this.deltaIdSet.has(id)) {
473
+ this.deltaIdSet.delete(id);
474
+ this.deltaUnsavedCount++;
475
+ return { success: true, action: "removed_from_delta" };
476
+ } else if (this.baseIdSet.has(id)) {
477
+ this.tombstones.add(id);
478
+ this.deltaUnsavedCount++;
479
+ return { success: true, action: "added_tombstone" };
480
+ }
481
+ return { success: false, action: "not_found" };
482
+ }
483
+ }
484
+ /**
485
+ * Check if ID exists (considering tombstones)
486
+ */
487
+ has(id) {
488
+ if (this.tombstones.has(id)) {
489
+ return false;
490
+ }
491
+ return this.deltaIdSet.has(id) || this.baseIdSet.has(id);
492
+ }
493
+ /**
494
+ * Get existing IDs from a list (considering tombstones)
495
+ * Required by IVectorProvider interface
496
+ */
497
+ getExistingIds(ids) {
498
+ const existing = /* @__PURE__ */ new Set();
499
+ for (const id of ids) {
500
+ if (this.has(id)) {
501
+ existing.add(id);
502
+ }
503
+ }
504
+ return existing;
505
+ }
506
+ // ===========================================================================
507
+ // Persistence
508
+ // ===========================================================================
509
+ /**
510
+ * Save all layers
511
+ */
512
+ async save() {
513
+ log.i("LAYERED_FAISS", "save_called", {
514
+ branch: this.currentBranch,
515
+ isOnBase: this.isOnBaseBranch,
516
+ baseUnsaved: this.baseUnsavedCount,
517
+ deltaUnsaved: this.deltaUnsavedCount
518
+ });
519
+ if (this.baseUnsavedCount > 0) {
520
+ await this.saveBase();
521
+ }
522
+ if (this.deltaUnsavedCount > 0) {
523
+ await this.saveDelta();
524
+ } else if (!this.isOnBaseBranch) {
525
+ log.w("LAYERED_FAISS", "delta_not_saved_zero_unsaved", {
526
+ branch: this.currentBranch,
527
+ deltaIdSetSize: this.deltaIdSet.size
528
+ });
529
+ }
530
+ }
531
+ /**
532
+ * Save base layer
533
+ */
534
+ async saveBase() {
535
+ if (!this.client || !this.isInitialized) return;
536
+ const projectDir = getProjectDir(this.projectPath);
537
+ const paths = getLayeredPaths(projectDir, this.currentBranch, this.baseBranch);
538
+ try {
539
+ const dir = dirname(paths.baseIndex);
540
+ if (!existsSync(dir)) {
541
+ mkdirSync(dir, { recursive: true });
542
+ }
543
+ await this.client.faissSave(paths.baseIndex);
544
+ writeFileSync(paths.baseIds, JSON.stringify([...this.baseIdSet]), "utf-8");
545
+ const existingMeta = loadBaseMetadata(this.projectPath);
546
+ if (!existingMeta) {
547
+ createInitialBaseMetadata(this.projectPath, this.currentBranch, this.config.dimensions, this.baseIdSet.size);
548
+ this.baseBranch = this.currentBranch;
549
+ log.i("LAYERED_FAISS", "base_meta_created", { branch: this.currentBranch });
550
+ } else {
551
+ updateBaseMetadata(this.projectPath, this.baseIdSet.size);
552
+ }
553
+ this.baseUnsavedCount = 0;
554
+ log.i("LAYERED_FAISS", "base_saved", { vectors: this.baseIdSet.size });
555
+ } catch (error) {
556
+ log.e("LAYERED_FAISS", "base_save_fail", { err: String(error) });
557
+ }
558
+ }
559
+ /**
560
+ * Save delta layer
561
+ */
562
+ async saveDelta() {
563
+ if (!this.isInitialized || this.isOnBaseBranch || !this.client) return;
564
+ const projectDir = getProjectDir(this.projectPath);
565
+ const paths = getLayeredPaths(projectDir, this.currentBranch, this.baseBranch);
566
+ try {
567
+ const dir = dirname(paths.deltaIds);
568
+ if (!existsSync(dir)) {
569
+ mkdirSync(dir, { recursive: true });
570
+ }
571
+ await this.client.faissSave(paths.deltaIndex || paths.baseIndex);
572
+ writeFileSync(paths.deltaIds, JSON.stringify([...this.deltaIdSet]), "utf-8");
573
+ writeFileSync(paths.tombstones, JSON.stringify([...this.tombstones]), "utf-8");
574
+ const deltaMeta = {
575
+ branchName: this.currentBranch,
576
+ baseBranch: this.baseBranch,
577
+ deltaVectorCount: this.deltaIdSet.size,
578
+ tombstoneCount: this.tombstones.size,
579
+ createdAt: Date.now(),
580
+ updatedAt: Date.now()
581
+ };
582
+ writeFileSync(paths.deltaMeta, JSON.stringify(deltaMeta, null, 2), "utf-8");
583
+ this.deltaUnsavedCount = 0;
584
+ log.i("LAYERED_FAISS", "delta_saved", {
585
+ branch: this.currentBranch,
586
+ deltaIds: this.deltaIdSet.size,
587
+ tombstones: this.tombstones.size
588
+ });
589
+ } catch (error) {
590
+ log.e("LAYERED_FAISS", "delta_save_fail", { err: String(error) });
591
+ }
592
+ }
593
+ // ===========================================================================
594
+ // Statistics
595
+ // ===========================================================================
596
+ /**
597
+ * Get statistics about the layered index
598
+ */
599
+ async getStats() {
600
+ const baseVectors = this.baseIdSet.size;
601
+ const deltaVectors = this.deltaIdSet.size;
602
+ const tombstoneCount = this.tombstones.size;
603
+ const totalVectors = baseVectors + deltaVectors - tombstoneCount;
604
+ return {
605
+ totalVectors: Math.max(0, totalVectors),
606
+ baseVectors,
607
+ deltaVectors,
608
+ tombstones: tombstoneCount,
609
+ currentBranch: this.currentBranch,
610
+ baseBranch: this.baseBranch,
611
+ isOnBaseBranch: this.isOnBaseBranch
612
+ };
613
+ }
614
+ /**
615
+ * Get count of searchable vectors
616
+ */
617
+ async count() {
618
+ const stats = await this.getStats();
619
+ return stats.totalVectors;
620
+ }
621
+ // ===========================================================================
622
+ // Cleanup
623
+ // ===========================================================================
624
+ /**
625
+ * Close and save all state
626
+ */
627
+ async close() {
628
+ if (!this.isInitialized) return;
629
+ await this.save();
630
+ this.isInitialized = false;
631
+ this.initializePromise = null;
632
+ log.i("LAYERED_FAISS", "closed", {
633
+ project: this.projectHash,
634
+ branch: this.currentBranch
635
+ });
636
+ }
637
+ };
638
+ var layeredProviderInstance = null;
639
+ function getLayeredFaissProvider(config) {
640
+ if (!layeredProviderInstance) {
641
+ layeredProviderInstance = new LayeredFaissProvider(config);
642
+ } else if (config?.dimensions && config.dimensions !== layeredProviderInstance.getDimensions()) {
643
+ layeredProviderInstance.setDimensions(config.dimensions);
644
+ }
645
+ return layeredProviderInstance;
646
+ }
647
+ async function shutdownLayeredFaissProvider() {
648
+ if (layeredProviderInstance) {
649
+ await layeredProviderInstance.close();
650
+ layeredProviderInstance = null;
651
+ }
652
+ }
653
+
654
+ export { LayeredFaissProvider, getLayeredFaissProvider, shutdownLayeredFaissProvider };
655
+ //# sourceMappingURL=chunk-B3H5NS3I.js.map
656
+ //# sourceMappingURL=chunk-B3H5NS3I.js.map
@@ -0,0 +1,4 @@
1
+ import {a as a$2,b as b$1}from'./chunk-IFKMF76K.js';import {I as I$1,a as a$1}from'./chunk-SV3WKUNV.js';import {b as b$2}from'./chunk-AIZJT6AG.js';import {e,d as d$1}from'./chunk-OG62YNVF.js';import {R,I as I$2}from'./chunk-4BI7EBPQ.js';import {a}from'./chunk-DXB73IDG.js';import {existsSync}from'fs';import {dirname,join}from'path';import {fileURLToPath}from'url';import {connect}from'net';R();I$1();e();R();var _={cudaBatchCosine:{dim384:2e3,dim768:1e3,dim1024:500,dim8192:50},cudaNormalize:{dim384:5e3,dim768:2e3,dim1024:1e3,dim8192:100},faissIndexBuild:{bulkInsertThreshold:500,rebuildThreshold:1e3,incrementalDeltaPercent:30},faissSearch:{minIndexSize:100,batchQueryThreshold:10}},l={..._};function A(n,e){return e<=384?n.dim384:e<=768?n.dim768:e<=1024?n.dim1024:n.dim8192}function b(n,e){let s=A(l.cudaBatchCosine,e),t=n>=s;return process.env.ADAPTIVE_DEBUG==="true"&&I$2.d("ADAPTIVE","cudaBatchCosine decision",{count:n,dim:e,threshold:s,useCuda:t}),t}function B(n,e){let s=A(l.cudaNormalize,e);return n>=s}function J(n,e){return n>=l.faissIndexBuild.rebuildThreshold||e!==void 0}function $(n,e=1){return n>=l.faissSearch.minIndexSize||e>=l.faissSearch.batchQueryThreshold}function E(n,e,s,t=1){let r=[],i="libsql-diskann";s&&J(n)?(i="faiss-hnsw",r.push(`Faiss HNSW for rebuild (${n} vectors)`)):n>1e4&&(i="faiss-ivf",r.push(`Faiss IVF for large index (${n} vectors)`));let o="libsql";$(n,t)&&(o=t>1?"faiss":"hybrid",r.push(`Faiss search (index=${n}, queries=${t})`));let c=b(n,e);return c&&r.push(`CUDA reranking (${n} \xD7 ${e}-dim)`),{indexStrategy:i,searchStrategy:o,useCudaForReranking:c,reason:r.join("; ")||"Default CPU strategy"}}var H=process.platform==="win32"?"\\\\.\\pipe\\ultracode-gpu-":"/tmp/ultracode-gpu-",P=class{buffer;length=0;initialSize;constructor(e=65536){this.initialSize=e,this.buffer=Buffer.allocUnsafe(e);}ensureCapacity(e){let s=this.length+e;if(s>this.buffer.length){let t=Math.max(this.buffer.length*2,s),r=Buffer.allocUnsafe(t);this.buffer.copy(r,0,0,this.length),this.buffer=r;}}shrinkIfEmpty(){this.length===0&&this.buffer.length>this.initialSize&&(this.buffer=Buffer.allocUnsafe(this.initialSize));}append(e){this.ensureCapacity(e.length),e.copy(this.buffer,this.length),this.length+=e.length;}get dataLength(){return this.length}readUInt32LE(e){return this.buffer.readUInt32LE(e)}subarray(e,s){return this.buffer.subarray(e,s)}consume(e){e>=this.length?this.length=0:(this.buffer.copy(this.buffer,0,e,this.length),this.length-=e),this.shrinkIfEmpty();}reset(){this.length=0,this.shrinkIfEmpty();}};var y=class{socket=null;options;pipePath;connected=false;pendingRequest=null;responseBuffer=new P(65536);constructor(e){this.options={timeout:3e4,...e},this.pipePath=H+e.pipeId;}get path(){return this.pipePath}get isConnected(){return this.connected}async connect(){if(!this.connected)return new Promise((e,s)=>{this.socket=connect(this.pipePath),this.socket.on("connect",()=>{this.connected=true,this.options.onConnect?.(),e();}),this.socket.on("data",t=>{this.handleData(t);}),this.socket.on("error",t=>{this.connected=false,this.options.onError?.(t),this.pendingRequest&&(this.pendingRequest.reject(t),this.pendingRequest=null),s(t);}),this.socket.on("close",()=>{this.connected=false,this.options.onDisconnect?.(),this.pendingRequest&&(this.pendingRequest.reject(new Error("Connection closed")),this.pendingRequest=null);});})}handleData(e){if(this.responseBuffer.append(e),this.responseBuffer.dataLength>=4){let s=this.responseBuffer.readUInt32LE(0);if(this.responseBuffer.dataLength>=4+s){let t=Buffer.from(this.responseBuffer.subarray(4,4+s));this.responseBuffer.consume(4+s),this.pendingRequest&&(this.pendingRequest.resolve(t),this.pendingRequest=null);}}}async send(e){if(!this.socket||!this.connected)throw new Error("Not connected");if(this.pendingRequest)throw new Error("Another request is pending");let s=new AbortController,t=new Promise((i,o)=>{this.pendingRequest={resolve:u=>{s.abort(),i(u);},reject:u=>{s.abort(),o(u);}};let c=Buffer.allocUnsafe(4+e.length);c.writeUInt32LE(e.length,0),e.copy(c,4),this.socket.write(c);}),r=(async()=>{if(await b$2(this.options.timeout??3e4),s.signal.aborted)return new Promise(()=>{});throw this.pendingRequest=null,new Error("Request timeout")})();return Promise.race([t,r])}disconnect(){this.socket&&(this.socket.destroy(),this.socket=null,this.connected=false);}};function G(n,e){let s=JSON.stringify(n),t=Buffer.from(s);if(!e||e.length===0){let o=Buffer.allocUnsafe(4+t.length);return o.writeUInt32LE(t.length,0),t.copy(o,4),o}let r=Buffer.from(e.buffer,e.byteOffset,e.byteLength),i=Buffer.allocUnsafe(4+t.length+r.length);return i.writeUInt32LE(t.length,0),t.copy(i,4),r.copy(i,4+t.length),i}function x(n){let e=n.readUInt32LE(0),s=n.subarray(4,4+e).toString(),t=JSON.parse(s);if(n.length>4+e){let r=4+e,i=n.length-r,o=n.subarray(r),c=new Float32Array(i/4);for(let u=0;u<c.length;u++)c[u]=o.readFloatLE(u*4);return {header:t,vectors:c}}return {header:t}}function M(n){return n.success===false&&"error"in n}function d(n){return M(n)?n.error:"Unknown GPU error"}function I(n){return n.type==="faiss.add"}function U(n){return n.type==="faiss.search"}function N(n){return n.type==="faiss.batchSearch"}function W(n){return n.type==="faiss.train"}function D(n){return n.type==="cuda.cosine"}function L(n){return n.type==="cuda.batchCosine"}function T(n){if(I(n)){let{vectors:s,...t}=n;return {vectors:s instanceof Float32Array?s:new Float32Array(s),headerData:t}}if(U(n)){let{vector:s,...t}=n;return {vectors:s instanceof Float32Array?s:new Float32Array(s),headerData:t}}if(N(n)){let{vectors:s,...t}=n;return {vectors:s instanceof Float32Array?s:new Float32Array(s),headerData:t}}if(W(n)){let{vectors:s,...t}=n;return {vectors:s instanceof Float32Array?s:new Float32Array(s),headerData:t}}if(D(n)){let{a:s,b:t,...r}=n,i=s instanceof Float32Array?s:new Float32Array(s),o=t instanceof Float32Array?t:new Float32Array(t),c=i.length+o.length,u=new Float32Array(c);u.set(i,0),u.set(o,i.length);let g={...r,dimensions:i.length};return {vectors:u,headerData:g}}if(L(n)){let{query:s,database:t,...r}=n,i=s instanceof Float32Array?s:new Float32Array(s),o=t.map(p=>p instanceof Float32Array?p:new Float32Array(p)),c=i.length+o.reduce((p,O)=>p+O.length,0),u=new Float32Array(c);u.set(i,0);let g=i.length;for(let p of o)u.set(p,g),g+=p.length;let z={...r,dimensions:i.length,queryCount:1,databaseCount:o.length};return {vectors:u,headerData:z}}return {headerData:{...n}}}var Y={nodePath:"node",workerPath:"",timeout:3e4,autoRestart:true,maxRestarts:3,forceSubprocess:false},w=class{config;worker=null;pendingRequests=new Map;requestId=0;restartCount=0;isShuttingDown=false;faissInitConfig=null;responseBuffer="";_cudaAvailable=false;namedPipeClient=null;namedPipePath=null;useNamedPipe=false;startPromise=null;namedPipeRequestQueue=Promise.resolve({});constructor(e={}){this.config={...Y,...e},this.config.workerPath||(this.config.workerPath=this.findWorkerPath()),this.registerCleanupHandlers();}registerCleanupHandlers(){let e=()=>{if(this.worker&&!this.isShuttingDown){this.isShuttingDown=true,I$2.d("GPU","Parent exiting, killing worker..."),this.namedPipeClient&&(this.namedPipeClient.disconnect(),this.namedPipeClient=null),this.worker.kill(),this.worker=null;for(let[,s]of this.pendingRequests)s.abortController.abort(),s.reject(new Error("Client shutting down"));this.pendingRequests.clear();}};process.on("exit",e),process.on("SIGINT",e),process.on("SIGTERM",e);}findWorkerPath(){let e=[],s=dirname(fileURLToPath(import.meta.url)),t=s;s.includes("chunks")?t=dirname(s):s.includes("semantic")&&(t=dirname(dirname(s))),e.push(join(t,"semantic","gpu","gpu-worker.js")),e.push(join(s,"gpu-worker.js"));try{let i=a.resolve("ultracode");e.push(join(dirname(i),"semantic/gpu/gpu-worker.js"));}catch{}e.push(join(process.cwd(),"dist/semantic/gpu/gpu-worker.js"));for(let i of e)if(existsSync(i))return I$2.d("GPU","Found worker at",{path:i}),i;let r=e[0]??join(process.cwd(),"dist/semantic/gpu/gpu-worker.js");return I$2.w("GPU","Worker not found, using fallback",{path:r,candidates:e}),r}async start(){return this.startPromise?this.startPromise:this.worker?true:process.env.ULTRACODE_NO_SUBPROCESS==="1"?(I$2.d("GPU","SKIPPED (ULTRACODE_NO_SUBPROCESS=1)"),false):(this.startPromise=this.startInternal(),this.startPromise)}async startInternal(){try{I$2.i("GPU","Starting worker",{nodePath:this.config.nodePath,workerPath:this.config.workerPath});let e=process.platform==="win32";if(!(typeof Bun<"u")||e){let{spawn:t}=await import('child_process');this.worker=t(this.config.nodePath,["--expose-gc",this.config.workerPath],{stdio:["pipe","pipe","pipe"],windowsHide:!0}),this.worker.unref(),this.worker.stderr&&this.worker.stderr.on("data",r=>{let i=r.toString().trim();i&&I$2.d("GPU",i);});}else {let r=globalThis.Bun?.spawn([this.config.nodePath,"--expose-gc",this.config.workerPath],{stdin:"pipe",stdout:"pipe",stderr:"pipe"}),i={stdin:r.stdin,stdout:r.stdout,stderr:r.stderr,pid:r.pid,kill:()=>r.kill(),on:(o,c)=>{(o==="exit"||o==="close")&&r.exited.then(u=>c(u));}};this.worker=i;}this.setupStdoutReader(),await this.waitForReady();try{let t=await this.cudaInfo();this._cudaAvailable=t.available;}catch{}return I$2.i("GPU","Worker started",{cuda:this._cudaAvailable}),!0}catch(e){return I$2.e("GPU","Failed to start worker",{error:e.message}),false}}setupStdoutReader(){this.worker?.stdout&&(this.worker.stdout.on("data",e=>{this.responseBuffer+=e.toString(),this.processResponseBuffer();}),this.worker.stdout.on("error",e=>{this.isShuttingDown||(I$2.e("GPU","stdout read error",{error:e.message}),this.handleWorkerCrash());}),this.worker.on("exit",e=>{this.isShuttingDown||(I$2.w("GPU","Worker exited",{code:e}),this.handleWorkerCrash());}));}processResponseBuffer(){let e=this.responseBuffer.split(`
2
+ `);this.responseBuffer=e.pop()||"";for(let s of e)if(s.trim())try{let t=JSON.parse(s);if(t.type==="pipe.ready"&&t.path){this.namedPipePath=t.path,I$2.d("GPU","Received pipe.ready",{path:t.path});continue}let r=t;this.handleResponse(r);}catch{}}handleResponse(e){let s=this.pendingRequests.entries().next().value;if(s){let[t,r]=s;r.abortController.abort(),this.pendingRequests.delete(t),r.resolve(e);}}async waitForReady(){let s=Date.now();for(;Date.now()-s<5e3&&!this.namedPipePath;)await d$1(50);if(this.namedPipePath)try{let t=this.namedPipePath.split(/[/\\]/).pop()?.replace("ultracode-gpu-","").replace(".sock","")||"";this.namedPipeClient=new y({pipeId:t,timeout:this.config.timeout,onConnect:()=>{I$2.i("GPU","Connected to Named Pipe",{path:this.namedPipePath});},onDisconnect:()=>{I$2.d("GPU","Named Pipe disconnected"),this.useNamedPipe=!1;},onError:r=>{I$2.w("GPU","Named Pipe error",{error:r.message}),this.useNamedPipe=!1;}}),await this.namedPipeClient.connect(),this.useNamedPipe=!0,I$2.i("GPU","Using Named Pipe for binary IPC");}catch(t){I$2.w("GPU","Failed to connect to Named Pipe, using stdin/stdout",{error:t.message}),this.namedPipeClient=null,this.useNamedPipe=false;}else I$2.d("GPU","Named Pipe not available, using stdin/stdout"),await d$1(100);}async handleWorkerCrash(){if(!this.isShuttingDown){for(let[,e]of this.pendingRequests)e.abortController.abort(),e.reject(new Error("Worker crashed"));this.pendingRequests.clear(),this.worker=null,this.config.autoRestart&&this.restartCount<this.config.maxRestarts&&(this.restartCount++,await this.start()&&this.faissInitConfig&&await this.faissInitialize(this.faissInitConfig));}}async stop(){if(this.isShuttingDown=true,this.namedPipeClient&&(this.namedPipeClient.disconnect(),this.namedPipeClient=null,this.useNamedPipe=false),this.worker){try{this.worker.stdin?.write(`${JSON.stringify({type:"shutdown"})}
3
+ `),await d$1(500);}catch{}if(this.worker){try{this.worker.kill("SIGTERM");}catch{}this.worker=null;}}for(let[,e]of this.pendingRequests)e.abortController.abort(),e.reject(new Error("Client shutting down"));this.pendingRequests.clear();}isRunning(){return this.worker!==null&&!this.isShuttingDown}async sendRequest(e){if(!this.worker?.stdin)throw new Error("Worker not running");if(this.useNamedPipe&&this.namedPipeClient?.isConnected)return I$2.i("GPU","Using Named Pipe",{type:e.type}),this.sendNamedPipeRequest(e);let s=JSON.stringify(e);I$2.i("GPU","Using stdin/stdout JSON",{type:e.type,jsonLen:s.length});let t=++this.requestId,r=new AbortController,i=new Promise((c,u)=>{this.pendingRequests.set(t,{resolve:c,reject:u,abortController:r}),this.worker.stdin.write(`${s}
4
+ `);}),o=(async()=>{if(await d$1(this.config.timeout),r.signal.aborted)return new Promise(()=>{});throw this.pendingRequests.delete(t),new Error(`Request timeout: ${e.type}`)})();return Promise.race([i,o])}async sendNamedPipeRequest(e){let t=this.namedPipeRequestQueue.catch(()=>{}).then(()=>this.sendNamedPipeRequestInternal(e));return this.namedPipeRequestQueue=t,t}async sendNamedPipeRequestInternal(e){if(!this.namedPipeClient?.isConnected)throw new Error("Named Pipe not connected");let{vectors:s,headerData:t}=T(e),r=G(t,s),i=await this.namedPipeClient.send(r),{header:o}=x(i);return o}async faissInitialize(e,s){this.faissInitConfig=e,this.worker||await this.start();let t=await this.sendRequest({type:"faiss.init",config:e,loadPath:s});if(!t.success)throw new Error(d(t));return t}async faissAdd(e,s){let t=s instanceof Float32Array?Array.from(s):s,r=await this.sendRequest({type:"faiss.add",ids:e,vectors:t});if(!r.success)throw new Error(d(r));return r}async faissSearch(e,s){let t=e instanceof Float32Array?Array.from(e):e;I$2.i("GPU","faissSearch input",{vectorLen:t?.length,k:s,isArray:Array.isArray(t)});let r={type:"faiss.search",vector:t,k:s};I$2.i("GPU","faissSearch request",{hasVector:!!r.vector,vectorLen:r.vector?.length,keys:Object.keys(r)});let i=await this.sendRequest(r);if(!i.success)throw new Error(d(i));return i.results}async faissBatchSearch(e,s,t){let r=e instanceof Float32Array?Array.from(e):e,i=await this.sendRequest({type:"faiss.batchSearch",vectors:r,nQueries:s,k:t});if(!i.success)throw new Error(d(i));return i.results}async faissTrain(e,s){let t=e instanceof Float32Array?Array.from(e):e,r=await this.sendRequest({type:"faiss.train",vectors:t,nVectors:s});if(!r.success)throw new Error(d(r));return r}async faissSave(e){let s=e||join(a$1(),"faiss-index.bin"),t=await this.sendRequest({type:"faiss.save",path:s});if(!t.success)throw new Error(d(t));return t}async faissLoad(e){let s=await this.sendRequest({type:"faiss.load",path:e});if(!s.success)throw new Error(d(s));return s}async faissRemove(e){let s=await this.sendRequest({type:"faiss.remove",ids:e});if(!s.success)throw new Error(d(s))}async faissGetStats(){let e=await this.sendRequest({type:"faiss.stats"});if(!e.success)throw new Error(d(e));return e.stats}async cudaInfo(){let e=await this.sendRequest({type:"cuda.info"});if(!e.success)throw new Error(d(e));return e}isCudaAvailable(){return this._cudaAvailable}async cudaCosineSimilarity(e,s){let t=e instanceof Float32Array?Array.from(e):e,r=s instanceof Float32Array?Array.from(s):s,i=await this.sendRequest({type:"cuda.cosine",a:t,b:r});if(!i.success)throw new Error(d(i));return i.similarity}async cudaBatchCosineSimilarity(e,s){let t=e instanceof Float32Array?Array.from(e):e,r=s.map(o=>o instanceof Float32Array?Array.from(o):o),i=await this.sendRequest({type:"cuda.batchCosine",query:t,database:r});if(!i.success)throw new Error(d(i));return new Float32Array(i.similarities)}async cudaEuclideanDistance(e,s){let t=e instanceof Float32Array?Array.from(e):e,r=s instanceof Float32Array?Array.from(s):s,i=await this.sendRequest({type:"cuda.euclidean",a:t,b:r});if(!i.success)throw new Error(d(i));return i.distance}async cudaNormalizeVectors(e){let s=e.map(r=>r instanceof Float32Array?Array.from(r):r),t=await this.sendRequest({type:"cuda.normalize",vectors:s});if(!t.success)throw new Error(d(t));return t.vectors.map(r=>new Float32Array(r))}async adaptiveBatchCosineSimilarity(e,s){let t=s.length,r=e.length;if(this._cudaAvailable&&b(t,r))try{return {similarities:await this.cudaBatchCosineSimilarity(e,s),usedCuda:!0}}catch(o){I$2.w("GPU","CUDA batch cosine failed, falling back to CPU",{error:o.message});}let i=new Float32Array(t);for(let o=0;o<t;o++)i[o]=a$2(e,s[o]);return {similarities:i,usedCuda:false}}async adaptiveNormalizeVectors(e){let s=e.length,t=e[0]?.length??0;if(this._cudaAvailable&&B(s,t))try{return {normalized:await this.cudaNormalizeVectors(e),usedCuda:!0}}catch(i){I$2.w("GPU","CUDA normalize failed, falling back to CPU",{error:i.message});}return {normalized:e.map(i=>{let o=new Float32Array(i);return b$1(o)}),usedCuda:false}}getRecommendedStrategy(e,s,t,r=1){return E(e,s,t,r)}async getStats(){let e=await this.sendRequest({type:"stats"});if(!e.success)throw new Error(d(e));return e}},f=null;function ve(n){return f||(I$2.i("GPU","Using subprocess mode"),f=new w(n)),f}async function qe(){f&&(await f.stop(),f=null);}export{E as a,ve as b,qe as c};