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,924 @@
1
+ import { cosineSimilarity, simdL2Normalize } from './chunk-QN237S7C.js';
2
+ import { init_storage_paths, getDataDir } from './chunk-LH4OUKNZ.js';
3
+ import { sleep as sleep$1 } from './chunk-IMQ6WSJV.js';
4
+ import { init_runtime, sleep } from './chunk-BMHPPH2B.js';
5
+ import { init_logging, log } from './chunk-VCCBEJQ5.js';
6
+ import { __require } from './chunk-NAQKA54E.js';
7
+ import { existsSync } from 'fs';
8
+ import { dirname, join } from 'path';
9
+ import { fileURLToPath } from 'url';
10
+ import { connect } from 'net';
11
+
12
+ // src/semantic/gpu/gpu-client.ts
13
+ init_logging();
14
+ init_storage_paths();
15
+ init_runtime();
16
+
17
+ // src/semantic/gpu/adaptive-thresholds.ts
18
+ init_logging();
19
+ var DEFAULT_THRESHOLDS = {
20
+ cudaBatchCosine: {
21
+ dim384: 2e3,
22
+ // Very small vectors - high IPC overhead ratio
23
+ dim768: 1e3,
24
+ // Medium vectors - ~1ms IPC vs ~1ms compute
25
+ dim1024: 500,
26
+ // Larger vectors - compute dominates
27
+ dim8192: 50
28
+ // Large vectors - CUDA always wins for batches
29
+ },
30
+ cudaNormalize: {
31
+ dim384: 5e3,
32
+ // Normalization is simpler - needs more vectors
33
+ dim768: 2e3,
34
+ dim1024: 1e3,
35
+ dim8192: 100
36
+ },
37
+ faissIndexBuild: {
38
+ bulkInsertThreshold: 500,
39
+ // Use Faiss for 500+ vectors bulk insert
40
+ rebuildThreshold: 1e3,
41
+ // Use Faiss if rebuilding index with 1000+ vectors
42
+ incrementalDeltaPercent: 30
43
+ // Use Faiss rebuild if delta > 30% of total
44
+ },
45
+ faissSearch: {
46
+ minIndexSize: 100,
47
+ // Use Faiss HNSW if index has 100+ vectors
48
+ batchQueryThreshold: 10
49
+ // Use Faiss batch search for 10+ queries
50
+ }
51
+ };
52
+ var currentThresholds = { ...DEFAULT_THRESHOLDS };
53
+ function getDimThreshold(thresholds, dimensions) {
54
+ if (dimensions <= 384) return thresholds.dim384;
55
+ if (dimensions <= 768) return thresholds.dim768;
56
+ if (dimensions <= 1024) return thresholds.dim1024;
57
+ return thresholds.dim8192;
58
+ }
59
+ function shouldUseCudaBatchCosine(vectorCount, dimensions) {
60
+ const threshold = getDimThreshold(currentThresholds.cudaBatchCosine, dimensions);
61
+ const shouldUse = vectorCount >= threshold;
62
+ if (process.env["ADAPTIVE_DEBUG"] === "true") {
63
+ log.d("ADAPTIVE", "cudaBatchCosine decision", {
64
+ count: vectorCount,
65
+ dim: dimensions,
66
+ threshold,
67
+ useCuda: shouldUse
68
+ });
69
+ }
70
+ return shouldUse;
71
+ }
72
+ function shouldUseCudaNormalize(vectorCount, dimensions) {
73
+ const threshold = getDimThreshold(currentThresholds.cudaNormalize, dimensions);
74
+ return vectorCount >= threshold;
75
+ }
76
+ function shouldUseFaissRebuild(currentIndexSize, deltaCount) {
77
+ if (currentIndexSize >= currentThresholds.faissIndexBuild.rebuildThreshold) {
78
+ return true;
79
+ }
80
+ return false;
81
+ }
82
+ function shouldUseFaissSearch(indexSize, queryCount = 1) {
83
+ if (indexSize >= currentThresholds.faissSearch.minIndexSize) {
84
+ return true;
85
+ }
86
+ if (queryCount >= currentThresholds.faissSearch.batchQueryThreshold) {
87
+ return true;
88
+ }
89
+ return false;
90
+ }
91
+ function getRecommendedStrategy(vectorCount, dimensions, isRebuild, queryBatchSize = 1) {
92
+ const reasons = [];
93
+ let indexStrategy = "libsql-diskann";
94
+ if (isRebuild && shouldUseFaissRebuild(vectorCount)) {
95
+ indexStrategy = "faiss-hnsw";
96
+ reasons.push(`Faiss HNSW for rebuild (${vectorCount} vectors)`);
97
+ } else if (vectorCount > 1e4) {
98
+ indexStrategy = "faiss-ivf";
99
+ reasons.push(`Faiss IVF for large index (${vectorCount} vectors)`);
100
+ }
101
+ let searchStrategy = "libsql";
102
+ if (shouldUseFaissSearch(vectorCount, queryBatchSize)) {
103
+ searchStrategy = queryBatchSize > 1 ? "faiss" : "hybrid";
104
+ reasons.push(`Faiss search (index=${vectorCount}, queries=${queryBatchSize})`);
105
+ }
106
+ const useCudaForReranking = shouldUseCudaBatchCosine(vectorCount, dimensions);
107
+ if (useCudaForReranking) {
108
+ reasons.push(`CUDA reranking (${vectorCount} \xD7 ${dimensions}-dim)`);
109
+ }
110
+ return {
111
+ indexStrategy,
112
+ searchStrategy,
113
+ useCudaForReranking,
114
+ reason: reasons.join("; ") || "Default CPU strategy"
115
+ };
116
+ }
117
+ var PIPE_PREFIX = process.platform === "win32" ? "\\\\.\\pipe\\ultracode-gpu-" : "/tmp/ultracode-gpu-";
118
+ var GrowableBuffer = class {
119
+ buffer;
120
+ length = 0;
121
+ initialSize;
122
+ constructor(initialSize = 65536) {
123
+ this.initialSize = initialSize;
124
+ this.buffer = Buffer.allocUnsafe(initialSize);
125
+ }
126
+ /** Ensure capacity for additional bytes */
127
+ ensureCapacity(needed) {
128
+ const required = this.length + needed;
129
+ if (required > this.buffer.length) {
130
+ const newSize = Math.max(this.buffer.length * 2, required);
131
+ const newBuffer = Buffer.allocUnsafe(newSize);
132
+ this.buffer.copy(newBuffer, 0, 0, this.length);
133
+ this.buffer = newBuffer;
134
+ }
135
+ }
136
+ /** Shrink buffer back to initial size if empty and oversized */
137
+ shrinkIfEmpty() {
138
+ if (this.length === 0 && this.buffer.length > this.initialSize) {
139
+ this.buffer = Buffer.allocUnsafe(this.initialSize);
140
+ }
141
+ }
142
+ /** Append chunk to buffer */
143
+ append(chunk) {
144
+ this.ensureCapacity(chunk.length);
145
+ chunk.copy(this.buffer, this.length);
146
+ this.length += chunk.length;
147
+ }
148
+ /** Get current data length */
149
+ get dataLength() {
150
+ return this.length;
151
+ }
152
+ /** Read UInt32LE at offset */
153
+ readUInt32LE(offset) {
154
+ return this.buffer.readUInt32LE(offset);
155
+ }
156
+ /** Get subarray view (valid until next append) */
157
+ subarray(start, end) {
158
+ return this.buffer.subarray(start, end);
159
+ }
160
+ /** Consume bytes from front (shift remaining data) */
161
+ consume(bytes) {
162
+ if (bytes >= this.length) {
163
+ this.length = 0;
164
+ } else {
165
+ this.buffer.copy(this.buffer, 0, bytes, this.length);
166
+ this.length -= bytes;
167
+ }
168
+ this.shrinkIfEmpty();
169
+ }
170
+ /** Reset buffer */
171
+ reset() {
172
+ this.length = 0;
173
+ this.shrinkIfEmpty();
174
+ }
175
+ };
176
+ var NamedPipeClient = class {
177
+ socket = null;
178
+ options;
179
+ pipePath;
180
+ connected = false;
181
+ pendingRequest = null;
182
+ responseBuffer = new GrowableBuffer(65536);
183
+ constructor(options) {
184
+ this.options = {
185
+ timeout: 3e4,
186
+ ...options
187
+ };
188
+ this.pipePath = PIPE_PREFIX + options.pipeId;
189
+ }
190
+ get path() {
191
+ return this.pipePath;
192
+ }
193
+ get isConnected() {
194
+ return this.connected;
195
+ }
196
+ async connect() {
197
+ if (this.connected) return;
198
+ return new Promise((resolve, reject) => {
199
+ this.socket = connect(this.pipePath);
200
+ this.socket.on("connect", () => {
201
+ this.connected = true;
202
+ this.options.onConnect?.();
203
+ resolve();
204
+ });
205
+ this.socket.on("data", (chunk) => {
206
+ this.handleData(chunk);
207
+ });
208
+ this.socket.on("error", (err) => {
209
+ this.connected = false;
210
+ this.options.onError?.(err);
211
+ if (this.pendingRequest) {
212
+ this.pendingRequest.reject(err);
213
+ this.pendingRequest = null;
214
+ }
215
+ reject(err);
216
+ });
217
+ this.socket.on("close", () => {
218
+ this.connected = false;
219
+ this.options.onDisconnect?.();
220
+ if (this.pendingRequest) {
221
+ this.pendingRequest.reject(new Error("Connection closed"));
222
+ this.pendingRequest = null;
223
+ }
224
+ });
225
+ });
226
+ }
227
+ handleData(chunk) {
228
+ this.responseBuffer.append(chunk);
229
+ if (this.responseBuffer.dataLength >= 4) {
230
+ const respLen = this.responseBuffer.readUInt32LE(0);
231
+ if (this.responseBuffer.dataLength >= 4 + respLen) {
232
+ const response = Buffer.from(this.responseBuffer.subarray(4, 4 + respLen));
233
+ this.responseBuffer.consume(4 + respLen);
234
+ if (this.pendingRequest) {
235
+ this.pendingRequest.resolve(response);
236
+ this.pendingRequest = null;
237
+ }
238
+ }
239
+ }
240
+ }
241
+ async send(packet) {
242
+ if (!this.socket || !this.connected) {
243
+ throw new Error("Not connected");
244
+ }
245
+ if (this.pendingRequest) {
246
+ throw new Error("Another request is pending");
247
+ }
248
+ const abortController = new AbortController();
249
+ const responsePromise = new Promise((resolve, reject) => {
250
+ this.pendingRequest = {
251
+ resolve: (response) => {
252
+ abortController.abort();
253
+ resolve(response);
254
+ },
255
+ reject: (error) => {
256
+ abortController.abort();
257
+ reject(error);
258
+ }
259
+ };
260
+ const sendBuffer = Buffer.allocUnsafe(4 + packet.length);
261
+ sendBuffer.writeUInt32LE(packet.length, 0);
262
+ packet.copy(sendBuffer, 4);
263
+ this.socket.write(sendBuffer);
264
+ });
265
+ const timeoutPromise = (async () => {
266
+ await sleep$1(this.options.timeout ?? 3e4);
267
+ if (abortController.signal.aborted) {
268
+ return new Promise(() => {
269
+ });
270
+ }
271
+ this.pendingRequest = null;
272
+ throw new Error("Request timeout");
273
+ })();
274
+ return Promise.race([responsePromise, timeoutPromise]);
275
+ }
276
+ disconnect() {
277
+ if (this.socket) {
278
+ this.socket.destroy();
279
+ this.socket = null;
280
+ this.connected = false;
281
+ }
282
+ }
283
+ };
284
+ function createPacket(header, vectors) {
285
+ const headerJson = JSON.stringify(header);
286
+ const headerBuf = Buffer.from(headerJson);
287
+ if (!vectors || vectors.length === 0) {
288
+ const packet2 = Buffer.allocUnsafe(4 + headerBuf.length);
289
+ packet2.writeUInt32LE(headerBuf.length, 0);
290
+ headerBuf.copy(packet2, 4);
291
+ return packet2;
292
+ }
293
+ const vectorsBuf = Buffer.from(vectors.buffer, vectors.byteOffset, vectors.byteLength);
294
+ const packet = Buffer.allocUnsafe(4 + headerBuf.length + vectorsBuf.length);
295
+ packet.writeUInt32LE(headerBuf.length, 0);
296
+ headerBuf.copy(packet, 4);
297
+ vectorsBuf.copy(packet, 4 + headerBuf.length);
298
+ return packet;
299
+ }
300
+ function parsePacket(packet) {
301
+ const headerLen = packet.readUInt32LE(0);
302
+ const headerJson = packet.subarray(4, 4 + headerLen).toString();
303
+ const header = JSON.parse(headerJson);
304
+ if (packet.length > 4 + headerLen) {
305
+ const vectorsOffset = 4 + headerLen;
306
+ const vectorsLen = packet.length - vectorsOffset;
307
+ const vectorsBuf = packet.subarray(vectorsOffset);
308
+ const vectors = new Float32Array(vectorsLen / 4);
309
+ for (let i = 0; i < vectors.length; i++) {
310
+ vectors[i] = vectorsBuf.readFloatLE(i * 4);
311
+ }
312
+ return { header, vectors };
313
+ }
314
+ return { header };
315
+ }
316
+
317
+ // src/semantic/gpu/type-guards.ts
318
+ function isGpuErrorResponse(response) {
319
+ return response.success === false && "error" in response;
320
+ }
321
+ function extractGpuError(response) {
322
+ if (isGpuErrorResponse(response)) {
323
+ return response.error;
324
+ }
325
+ return "Unknown GPU error";
326
+ }
327
+ function isFaissAddRequest(req) {
328
+ return req.type === "faiss.add";
329
+ }
330
+ function isFaissSearchRequest(req) {
331
+ return req.type === "faiss.search";
332
+ }
333
+ function isFaissBatchSearchRequest(req) {
334
+ return req.type === "faiss.batchSearch";
335
+ }
336
+ function isFaissTrainRequest(req) {
337
+ return req.type === "faiss.train";
338
+ }
339
+ function isCudaCosineRequest(req) {
340
+ return req.type === "cuda.cosine";
341
+ }
342
+ function isCudaBatchCosineRequest(req) {
343
+ return req.type === "cuda.batchCosine";
344
+ }
345
+
346
+ // src/semantic/gpu/request-helpers.ts
347
+ function extractVectorsFromRequest(request) {
348
+ if (isFaissAddRequest(request)) {
349
+ const { vectors: v, ...rest } = request;
350
+ const vectors = v instanceof Float32Array ? v : new Float32Array(v);
351
+ return { vectors, headerData: rest };
352
+ }
353
+ if (isFaissSearchRequest(request)) {
354
+ const { vector: v, ...rest } = request;
355
+ const vectors = v instanceof Float32Array ? v : new Float32Array(v);
356
+ return { vectors, headerData: rest };
357
+ }
358
+ if (isFaissBatchSearchRequest(request)) {
359
+ const { vectors: v, ...rest } = request;
360
+ const vectors = v instanceof Float32Array ? v : new Float32Array(v);
361
+ return { vectors, headerData: rest };
362
+ }
363
+ if (isFaissTrainRequest(request)) {
364
+ const { vectors: v, ...rest } = request;
365
+ const vectors = v instanceof Float32Array ? v : new Float32Array(v);
366
+ return { vectors, headerData: rest };
367
+ }
368
+ if (isCudaCosineRequest(request)) {
369
+ const { a, b, ...rest } = request;
370
+ const aArr = a instanceof Float32Array ? a : new Float32Array(a);
371
+ const bArr = b instanceof Float32Array ? b : new Float32Array(b);
372
+ const totalLen = aArr.length + bArr.length;
373
+ const vectors = new Float32Array(totalLen);
374
+ vectors.set(aArr, 0);
375
+ vectors.set(bArr, aArr.length);
376
+ const headerData2 = {
377
+ ...rest,
378
+ dimensions: aArr.length
379
+ };
380
+ return { vectors, headerData: headerData2 };
381
+ }
382
+ if (isCudaBatchCosineRequest(request)) {
383
+ const { query, database, ...rest } = request;
384
+ const queryArr = query instanceof Float32Array ? query : new Float32Array(query);
385
+ const dbArrs = database.map((d) => d instanceof Float32Array ? d : new Float32Array(d));
386
+ const totalLen = queryArr.length + dbArrs.reduce((sum, arr) => sum + arr.length, 0);
387
+ const vectors = new Float32Array(totalLen);
388
+ vectors.set(queryArr, 0);
389
+ let offset = queryArr.length;
390
+ for (const arr of dbArrs) {
391
+ vectors.set(arr, offset);
392
+ offset += arr.length;
393
+ }
394
+ const headerData2 = {
395
+ ...rest,
396
+ dimensions: queryArr.length,
397
+ queryCount: 1,
398
+ databaseCount: dbArrs.length
399
+ };
400
+ return { vectors, headerData: headerData2 };
401
+ }
402
+ const headerData = { ...request };
403
+ return { headerData };
404
+ }
405
+
406
+ // src/semantic/gpu/gpu-client.ts
407
+ var DEFAULT_CONFIG = {
408
+ nodePath: "node",
409
+ workerPath: "",
410
+ timeout: 3e4,
411
+ autoRestart: true,
412
+ maxRestarts: 3,
413
+ forceSubprocess: false
414
+ };
415
+ var GpuSubprocessClient = class {
416
+ config;
417
+ worker = null;
418
+ pendingRequests = /* @__PURE__ */ new Map();
419
+ requestId = 0;
420
+ restartCount = 0;
421
+ isShuttingDown = false;
422
+ faissInitConfig = null;
423
+ responseBuffer = "";
424
+ _cudaAvailable = false;
425
+ // Named Pipe client for binary IPC
426
+ namedPipeClient = null;
427
+ namedPipePath = null;
428
+ useNamedPipe = false;
429
+ // Mutex for start() to prevent race condition with concurrent calls
430
+ startPromise = null;
431
+ // Request queue for Named Pipe (only supports one pending request at a time)
432
+ namedPipeRequestQueue = Promise.resolve({});
433
+ constructor(config = {}) {
434
+ this.config = { ...DEFAULT_CONFIG, ...config };
435
+ if (!this.config.workerPath) {
436
+ this.config.workerPath = this.findWorkerPath();
437
+ }
438
+ this.registerCleanupHandlers();
439
+ }
440
+ registerCleanupHandlers() {
441
+ const cleanup = () => {
442
+ if (this.worker && !this.isShuttingDown) {
443
+ this.isShuttingDown = true;
444
+ log.d("GPU", "Parent exiting, killing worker...");
445
+ if (this.namedPipeClient) {
446
+ this.namedPipeClient.disconnect();
447
+ this.namedPipeClient = null;
448
+ }
449
+ this.worker.kill();
450
+ this.worker = null;
451
+ for (const [, pending] of this.pendingRequests) {
452
+ pending.abortController.abort();
453
+ pending.reject(new Error("Client shutting down"));
454
+ }
455
+ this.pendingRequests.clear();
456
+ }
457
+ };
458
+ process.on("exit", cleanup);
459
+ process.on("SIGINT", cleanup);
460
+ process.on("SIGTERM", cleanup);
461
+ }
462
+ findWorkerPath() {
463
+ const candidates = [];
464
+ const currentDir = dirname(fileURLToPath(import.meta.url));
465
+ let distRoot = currentDir;
466
+ if (currentDir.includes("chunks")) {
467
+ distRoot = dirname(currentDir);
468
+ } else if (currentDir.includes("semantic")) {
469
+ distRoot = dirname(dirname(currentDir));
470
+ }
471
+ candidates.push(join(distRoot, "semantic", "gpu", "gpu-worker.js"));
472
+ candidates.push(join(currentDir, "gpu-worker.js"));
473
+ try {
474
+ const pkgPath = __require.resolve("ultracode");
475
+ candidates.push(join(dirname(pkgPath), "semantic/gpu/gpu-worker.js"));
476
+ } catch {
477
+ }
478
+ candidates.push(join(process.cwd(), "dist/semantic/gpu/gpu-worker.js"));
479
+ for (const path of candidates) {
480
+ if (existsSync(path)) {
481
+ log.d("GPU", "Found worker at", { path });
482
+ return path;
483
+ }
484
+ }
485
+ const fallback = candidates[0] ?? join(process.cwd(), "dist/semantic/gpu/gpu-worker.js");
486
+ log.w("GPU", "Worker not found, using fallback", { path: fallback, candidates });
487
+ return fallback;
488
+ }
489
+ async start() {
490
+ if (this.startPromise) {
491
+ return this.startPromise;
492
+ }
493
+ if (this.worker) return true;
494
+ if (process.env["ULTRACODE_NO_SUBPROCESS"] === "1") {
495
+ log.d("GPU", "SKIPPED (ULTRACODE_NO_SUBPROCESS=1)");
496
+ return false;
497
+ }
498
+ this.startPromise = this.startInternal();
499
+ return this.startPromise;
500
+ }
501
+ async startInternal() {
502
+ try {
503
+ log.i("GPU", "Starting worker", {
504
+ nodePath: this.config.nodePath,
505
+ workerPath: this.config.workerPath
506
+ });
507
+ const isWindows = process.platform === "win32";
508
+ const isBun = typeof Bun !== "undefined";
509
+ if (!isBun || isWindows) {
510
+ const { spawn } = await import('child_process');
511
+ this.worker = spawn(this.config.nodePath, ["--expose-gc", this.config.workerPath], {
512
+ stdio: ["pipe", "pipe", "pipe"],
513
+ // Capture stderr for logging
514
+ windowsHide: true
515
+ });
516
+ this.worker.unref();
517
+ if (this.worker.stderr) {
518
+ this.worker.stderr.on("data", (data) => {
519
+ const msg = data.toString().trim();
520
+ if (msg) {
521
+ log.d("GPU", msg);
522
+ }
523
+ });
524
+ }
525
+ } else {
526
+ const global = globalThis;
527
+ const proc = global.Bun?.["spawn"]([this.config.nodePath, "--expose-gc", this.config.workerPath], {
528
+ stdin: "pipe",
529
+ stdout: "pipe",
530
+ stderr: "pipe"
531
+ // Capture stderr for logging
532
+ });
533
+ const wrapper = {
534
+ stdin: proc.stdin,
535
+ stdout: proc.stdout,
536
+ stderr: proc.stderr,
537
+ pid: proc.pid,
538
+ kill: () => proc.kill(),
539
+ on: (event, handler) => {
540
+ if (event === "exit" || event === "close") {
541
+ proc.exited.then((code) => handler(code));
542
+ }
543
+ }
544
+ };
545
+ this.worker = wrapper;
546
+ }
547
+ this.setupStdoutReader();
548
+ await this.waitForReady();
549
+ try {
550
+ const info = await this.cudaInfo();
551
+ this._cudaAvailable = info.available;
552
+ } catch {
553
+ }
554
+ log.i("GPU", "Worker started", { cuda: this._cudaAvailable });
555
+ return true;
556
+ } catch (error) {
557
+ log.e("GPU", "Failed to start worker", { error: error.message });
558
+ return false;
559
+ }
560
+ }
561
+ setupStdoutReader() {
562
+ if (!this.worker?.stdout) return;
563
+ this.worker.stdout.on("data", (data) => {
564
+ this.responseBuffer += data.toString();
565
+ this.processResponseBuffer();
566
+ });
567
+ this.worker.stdout.on("error", (error) => {
568
+ if (!this.isShuttingDown) {
569
+ log.e("GPU", "stdout read error", { error: error.message });
570
+ this.handleWorkerCrash();
571
+ }
572
+ });
573
+ this.worker.on("exit", (code) => {
574
+ if (!this.isShuttingDown) {
575
+ log.w("GPU", "Worker exited", { code });
576
+ this.handleWorkerCrash();
577
+ }
578
+ });
579
+ }
580
+ processResponseBuffer() {
581
+ const lines = this.responseBuffer.split("\n");
582
+ this.responseBuffer = lines.pop() || "";
583
+ for (const line of lines) {
584
+ if (!line.trim()) continue;
585
+ try {
586
+ const parsed = JSON.parse(line);
587
+ if (parsed.type === "pipe.ready" && parsed.path) {
588
+ this.namedPipePath = parsed.path;
589
+ log.d("GPU", "Received pipe.ready", { path: parsed.path });
590
+ continue;
591
+ }
592
+ const response = parsed;
593
+ this.handleResponse(response);
594
+ } catch {
595
+ }
596
+ }
597
+ }
598
+ handleResponse(response) {
599
+ const entry = this.pendingRequests.entries().next().value;
600
+ if (entry) {
601
+ const [requestId, pending] = entry;
602
+ pending.abortController.abort();
603
+ this.pendingRequests.delete(requestId);
604
+ pending.resolve(response);
605
+ }
606
+ }
607
+ async waitForReady() {
608
+ const timeout = 5e3;
609
+ const startTime = Date.now();
610
+ while (Date.now() - startTime < timeout) {
611
+ if (this.namedPipePath) break;
612
+ await sleep(50);
613
+ }
614
+ if (this.namedPipePath) {
615
+ try {
616
+ const pipeId = this.namedPipePath.split(/[/\\]/).pop()?.replace("ultracode-gpu-", "").replace(".sock", "") || "";
617
+ this.namedPipeClient = new NamedPipeClient({
618
+ pipeId,
619
+ timeout: this.config.timeout,
620
+ onConnect: () => {
621
+ log.i("GPU", "Connected to Named Pipe", { path: this.namedPipePath });
622
+ },
623
+ onDisconnect: () => {
624
+ log.d("GPU", "Named Pipe disconnected");
625
+ this.useNamedPipe = false;
626
+ },
627
+ onError: (err) => {
628
+ log.w("GPU", "Named Pipe error", { error: err.message });
629
+ this.useNamedPipe = false;
630
+ }
631
+ });
632
+ await this.namedPipeClient.connect();
633
+ this.useNamedPipe = true;
634
+ log.i("GPU", "Using Named Pipe for binary IPC");
635
+ } catch (error) {
636
+ log.w("GPU", "Failed to connect to Named Pipe, using stdin/stdout", {
637
+ error: error.message
638
+ });
639
+ this.namedPipeClient = null;
640
+ this.useNamedPipe = false;
641
+ }
642
+ } else {
643
+ log.d("GPU", "Named Pipe not available, using stdin/stdout");
644
+ await sleep(100);
645
+ }
646
+ }
647
+ async handleWorkerCrash() {
648
+ if (this.isShuttingDown) return;
649
+ for (const [, pending] of this.pendingRequests) {
650
+ pending.abortController.abort();
651
+ pending.reject(new Error("Worker crashed"));
652
+ }
653
+ this.pendingRequests.clear();
654
+ this.worker = null;
655
+ if (this.config.autoRestart && this.restartCount < this.config.maxRestarts) {
656
+ this.restartCount++;
657
+ const started = await this.start();
658
+ if (started && this.faissInitConfig) {
659
+ await this.faissInitialize(this.faissInitConfig);
660
+ }
661
+ }
662
+ }
663
+ async stop() {
664
+ this.isShuttingDown = true;
665
+ if (this.namedPipeClient) {
666
+ this.namedPipeClient.disconnect();
667
+ this.namedPipeClient = null;
668
+ this.useNamedPipe = false;
669
+ }
670
+ if (this.worker) {
671
+ try {
672
+ this.worker.stdin?.write(`${JSON.stringify({ type: "shutdown" })}
673
+ `);
674
+ await sleep(500);
675
+ } catch {
676
+ }
677
+ if (this.worker) {
678
+ try {
679
+ this.worker.kill("SIGTERM");
680
+ } catch {
681
+ }
682
+ this.worker = null;
683
+ }
684
+ }
685
+ for (const [, pending] of this.pendingRequests) {
686
+ pending.abortController.abort();
687
+ pending.reject(new Error("Client shutting down"));
688
+ }
689
+ this.pendingRequests.clear();
690
+ }
691
+ isRunning() {
692
+ return this.worker !== null && !this.isShuttingDown;
693
+ }
694
+ async sendRequest(request) {
695
+ if (!this.worker?.stdin) {
696
+ throw new Error("Worker not running");
697
+ }
698
+ if (this.useNamedPipe && this.namedPipeClient?.isConnected) {
699
+ log.i("GPU", "Using Named Pipe", { type: request.type });
700
+ return this.sendNamedPipeRequest(request);
701
+ }
702
+ const jsonStr = JSON.stringify(request);
703
+ log.i("GPU", "Using stdin/stdout JSON", {
704
+ type: request.type,
705
+ jsonLen: jsonStr.length
706
+ });
707
+ const requestId = ++this.requestId;
708
+ const abortController = new AbortController();
709
+ const responsePromise = new Promise((resolve, reject) => {
710
+ this.pendingRequests.set(requestId, { resolve, reject, abortController });
711
+ this.worker.stdin.write(`${jsonStr}
712
+ `);
713
+ });
714
+ const timeoutPromise = (async () => {
715
+ await sleep(this.config.timeout);
716
+ if (abortController.signal.aborted) {
717
+ return new Promise(() => {
718
+ });
719
+ }
720
+ this.pendingRequests.delete(requestId);
721
+ throw new Error(`Request timeout: ${request.type}`);
722
+ })();
723
+ return Promise.race([responsePromise, timeoutPromise]);
724
+ }
725
+ /**
726
+ * Send request via Named Pipe (binary protocol)
727
+ * Uses queue to ensure only one request is pending at a time
728
+ */
729
+ async sendNamedPipeRequest(request) {
730
+ const previousRequest = this.namedPipeRequestQueue;
731
+ const currentRequest = previousRequest.catch(() => {
732
+ }).then(() => this.sendNamedPipeRequestInternal(request));
733
+ this.namedPipeRequestQueue = currentRequest;
734
+ return currentRequest;
735
+ }
736
+ /**
737
+ * Internal Named Pipe request handler (called sequentially via queue)
738
+ */
739
+ async sendNamedPipeRequestInternal(request) {
740
+ if (!this.namedPipeClient?.isConnected) {
741
+ throw new Error("Named Pipe not connected");
742
+ }
743
+ const { vectors, headerData } = extractVectorsFromRequest(request);
744
+ const packet = createPacket(headerData, vectors);
745
+ const responseBuffer = await this.namedPipeClient.send(packet);
746
+ const { header } = parsePacket(responseBuffer);
747
+ return header;
748
+ }
749
+ // =========================================================================
750
+ // Faiss Operations
751
+ // =========================================================================
752
+ async faissInitialize(config, loadPath) {
753
+ this.faissInitConfig = config;
754
+ if (!this.worker) {
755
+ await this.start();
756
+ }
757
+ const response = await this.sendRequest({ type: "faiss.init", config, loadPath });
758
+ if (!response.success) throw new Error(extractGpuError(response));
759
+ return response;
760
+ }
761
+ async faissAdd(ids, vectors) {
762
+ const vectorArray = vectors instanceof Float32Array ? Array.from(vectors) : vectors;
763
+ const response = await this.sendRequest({ type: "faiss.add", ids, vectors: vectorArray });
764
+ if (!response.success) throw new Error(extractGpuError(response));
765
+ return response;
766
+ }
767
+ async faissSearch(vector, k) {
768
+ const vectorArray = vector instanceof Float32Array ? Array.from(vector) : vector;
769
+ log.i("GPU", "faissSearch input", {
770
+ vectorLen: vectorArray?.length,
771
+ k,
772
+ isArray: Array.isArray(vectorArray)
773
+ });
774
+ const request = { type: "faiss.search", vector: vectorArray, k };
775
+ log.i("GPU", "faissSearch request", {
776
+ hasVector: !!request.vector,
777
+ vectorLen: request.vector?.length,
778
+ keys: Object.keys(request)
779
+ });
780
+ const response = await this.sendRequest(request);
781
+ if (!response.success) throw new Error(extractGpuError(response));
782
+ return response.results;
783
+ }
784
+ async faissBatchSearch(vectors, nQueries, k) {
785
+ const vectorArray = vectors instanceof Float32Array ? Array.from(vectors) : vectors;
786
+ const response = await this.sendRequest({ type: "faiss.batchSearch", vectors: vectorArray, nQueries, k });
787
+ if (!response.success) throw new Error(extractGpuError(response));
788
+ return response.results;
789
+ }
790
+ async faissTrain(vectors, nVectors) {
791
+ const vectorArray = vectors instanceof Float32Array ? Array.from(vectors) : vectors;
792
+ const response = await this.sendRequest({ type: "faiss.train", vectors: vectorArray, nVectors });
793
+ if (!response.success) throw new Error(extractGpuError(response));
794
+ return response;
795
+ }
796
+ async faissSave(path) {
797
+ const savePath = path || join(getDataDir(), "faiss-index.bin");
798
+ const response = await this.sendRequest({ type: "faiss.save", path: savePath });
799
+ if (!response.success) throw new Error(extractGpuError(response));
800
+ return response;
801
+ }
802
+ async faissLoad(path) {
803
+ const response = await this.sendRequest({ type: "faiss.load", path });
804
+ if (!response.success) throw new Error(extractGpuError(response));
805
+ return response;
806
+ }
807
+ async faissRemove(ids) {
808
+ const response = await this.sendRequest({ type: "faiss.remove", ids });
809
+ if (!response.success) throw new Error(extractGpuError(response));
810
+ }
811
+ async faissGetStats() {
812
+ const response = await this.sendRequest({ type: "faiss.stats" });
813
+ if (!response.success) throw new Error(extractGpuError(response));
814
+ return response.stats;
815
+ }
816
+ // =========================================================================
817
+ // CUDA Operations
818
+ // =========================================================================
819
+ async cudaInfo() {
820
+ const response = await this.sendRequest({ type: "cuda.info" });
821
+ if (!response.success) throw new Error(extractGpuError(response));
822
+ return response;
823
+ }
824
+ isCudaAvailable() {
825
+ return this._cudaAvailable;
826
+ }
827
+ async cudaCosineSimilarity(a, b) {
828
+ const vecA = a instanceof Float32Array ? Array.from(a) : a;
829
+ const vecB = b instanceof Float32Array ? Array.from(b) : b;
830
+ const response = await this.sendRequest({ type: "cuda.cosine", a: vecA, b: vecB });
831
+ if (!response.success) throw new Error(extractGpuError(response));
832
+ return response.similarity;
833
+ }
834
+ async cudaBatchCosineSimilarity(query, database) {
835
+ const queryArr = query instanceof Float32Array ? Array.from(query) : query;
836
+ const dbArr = database.map((v) => v instanceof Float32Array ? Array.from(v) : v);
837
+ const response = await this.sendRequest({ type: "cuda.batchCosine", query: queryArr, database: dbArr });
838
+ if (!response.success) throw new Error(extractGpuError(response));
839
+ return new Float32Array(response.similarities);
840
+ }
841
+ async cudaEuclideanDistance(a, b) {
842
+ const vecA = a instanceof Float32Array ? Array.from(a) : a;
843
+ const vecB = b instanceof Float32Array ? Array.from(b) : b;
844
+ const response = await this.sendRequest({ type: "cuda.euclidean", a: vecA, b: vecB });
845
+ if (!response.success) throw new Error(extractGpuError(response));
846
+ return response.distance;
847
+ }
848
+ async cudaNormalizeVectors(vectors) {
849
+ const input = vectors.map((v) => v instanceof Float32Array ? Array.from(v) : v);
850
+ const response = await this.sendRequest({ type: "cuda.normalize", vectors: input });
851
+ if (!response.success) throw new Error(extractGpuError(response));
852
+ return response.vectors.map((v) => new Float32Array(v));
853
+ }
854
+ // =========================================================================
855
+ // Adaptive Operations (auto-select CUDA vs CPU)
856
+ // =========================================================================
857
+ async adaptiveBatchCosineSimilarity(query, database) {
858
+ const vectorCount = database.length;
859
+ const dimensions = query.length;
860
+ if (this._cudaAvailable && shouldUseCudaBatchCosine(vectorCount, dimensions)) {
861
+ try {
862
+ const similarities2 = await this.cudaBatchCosineSimilarity(query, database);
863
+ return { similarities: similarities2, usedCuda: true };
864
+ } catch (error) {
865
+ log.w("GPU", "CUDA batch cosine failed, falling back to CPU", {
866
+ error: error.message
867
+ });
868
+ }
869
+ }
870
+ const similarities = new Float32Array(vectorCount);
871
+ for (let i = 0; i < vectorCount; i++) {
872
+ similarities[i] = cosineSimilarity(query, database[i]);
873
+ }
874
+ return { similarities, usedCuda: false };
875
+ }
876
+ async adaptiveNormalizeVectors(vectors) {
877
+ const vectorCount = vectors.length;
878
+ const dimensions = vectors[0]?.length ?? 0;
879
+ if (this._cudaAvailable && shouldUseCudaNormalize(vectorCount, dimensions)) {
880
+ try {
881
+ const normalized2 = await this.cudaNormalizeVectors(vectors);
882
+ return { normalized: normalized2, usedCuda: true };
883
+ } catch (error) {
884
+ log.w("GPU", "CUDA normalize failed, falling back to CPU", {
885
+ error: error.message
886
+ });
887
+ }
888
+ }
889
+ const normalized = vectors.map((v) => {
890
+ const copy = new Float32Array(v);
891
+ return simdL2Normalize(copy);
892
+ });
893
+ return { normalized, usedCuda: false };
894
+ }
895
+ getRecommendedStrategy(vectorCount, dimensions, isRebuild, queryBatchSize = 1) {
896
+ return getRecommendedStrategy(vectorCount, dimensions, isRebuild, queryBatchSize);
897
+ }
898
+ // =========================================================================
899
+ // Combined Stats
900
+ // =========================================================================
901
+ async getStats() {
902
+ const response = await this.sendRequest({ type: "stats" });
903
+ if (!response.success) throw new Error(extractGpuError(response));
904
+ return response;
905
+ }
906
+ };
907
+ var gpuClient = null;
908
+ function getGpuClient(config) {
909
+ if (!gpuClient) {
910
+ log.i("GPU", "Using subprocess mode");
911
+ gpuClient = new GpuSubprocessClient(config);
912
+ }
913
+ return gpuClient;
914
+ }
915
+ async function shutdownGpuClient() {
916
+ if (gpuClient) {
917
+ await gpuClient.stop();
918
+ gpuClient = null;
919
+ }
920
+ }
921
+
922
+ export { getGpuClient, getRecommendedStrategy, shutdownGpuClient };
923
+ //# sourceMappingURL=chunk-ROQ27LSL.js.map
924
+ //# sourceMappingURL=chunk-ROQ27LSL.js.map