@vfarcic/dot-ai 1.0.3 → 1.2.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 (234) hide show
  1. package/README.md +1 -0
  2. package/dist/core/ai-provider.interface.d.ts +12 -8
  3. package/dist/core/ai-provider.interface.d.ts.map +1 -1
  4. package/dist/core/artifacthub.d.ts +1 -1
  5. package/dist/core/artifacthub.d.ts.map +1 -1
  6. package/dist/core/base-vector-service.d.ts +22 -9
  7. package/dist/core/base-vector-service.d.ts.map +1 -1
  8. package/dist/core/base-vector-service.js +106 -37
  9. package/dist/core/capabilities.d.ts.map +1 -1
  10. package/dist/core/capabilities.js +5 -2
  11. package/dist/core/capability-operations.d.ts +55 -7
  12. package/dist/core/capability-operations.d.ts.map +1 -1
  13. package/dist/core/capability-operations.js +1 -3
  14. package/dist/core/capability-scan-workflow.d.ts +64 -8
  15. package/dist/core/capability-scan-workflow.d.ts.map +1 -1
  16. package/dist/core/capability-scan-workflow.js +14 -13
  17. package/dist/core/capability-tools.d.ts +1 -1
  18. package/dist/core/capability-tools.d.ts.map +1 -1
  19. package/dist/core/capability-tools.js +1 -1
  20. package/dist/core/capability-vector-service.d.ts +3 -4
  21. package/dist/core/capability-vector-service.d.ts.map +1 -1
  22. package/dist/core/capability-vector-service.js +2 -2
  23. package/dist/core/command-executor.d.ts +3 -4
  24. package/dist/core/command-executor.d.ts.map +1 -1
  25. package/dist/core/command-executor.js +8 -4
  26. package/dist/core/crd-availability.d.ts +3 -5
  27. package/dist/core/crd-availability.d.ts.map +1 -1
  28. package/dist/core/crd-availability.js +8 -18
  29. package/dist/core/deploy-operation.d.ts +6 -5
  30. package/dist/core/deploy-operation.d.ts.map +1 -1
  31. package/dist/core/deploy-operation.js +16 -10
  32. package/dist/core/discovery.d.ts +6 -14
  33. package/dist/core/discovery.d.ts.map +1 -1
  34. package/dist/core/discovery.js +35 -51
  35. package/dist/core/embedding-service.d.ts.map +1 -1
  36. package/dist/core/embedding-service.js +1 -1
  37. package/dist/core/error-handling.d.ts +13 -13
  38. package/dist/core/error-handling.d.ts.map +1 -1
  39. package/dist/core/error-handling.js +2 -3
  40. package/dist/core/generic-session-manager.d.ts +2 -2
  41. package/dist/core/generic-session-manager.d.ts.map +1 -1
  42. package/dist/core/helm-types.d.ts +5 -5
  43. package/dist/core/helm-types.d.ts.map +1 -1
  44. package/dist/core/index.d.ts +4 -11
  45. package/dist/core/index.d.ts.map +1 -1
  46. package/dist/core/index.js +8 -14
  47. package/dist/core/knowledge-types.d.ts +114 -0
  48. package/dist/core/knowledge-types.d.ts.map +1 -0
  49. package/dist/core/knowledge-types.js +10 -0
  50. package/dist/core/memory.d.ts +12 -12
  51. package/dist/core/memory.d.ts.map +1 -1
  52. package/dist/core/mermaid-tools.d.ts +24 -1
  53. package/dist/core/mermaid-tools.d.ts.map +1 -1
  54. package/dist/core/mermaid-tools.js +10 -8
  55. package/dist/core/model-config.d.ts +1 -1
  56. package/dist/core/model-config.js +1 -1
  57. package/dist/core/packaging.d.ts +23 -1
  58. package/dist/core/packaging.d.ts.map +1 -1
  59. package/dist/core/pattern-operations.d.ts +32 -9
  60. package/dist/core/pattern-operations.d.ts.map +1 -1
  61. package/dist/core/pattern-operations.js +17 -22
  62. package/dist/core/pattern-vector-service.d.ts +3 -4
  63. package/dist/core/pattern-vector-service.d.ts.map +1 -1
  64. package/dist/core/pattern-vector-service.js +2 -2
  65. package/dist/core/platform-utils.d.ts +2 -2
  66. package/dist/core/platform-utils.d.ts.map +1 -1
  67. package/dist/core/plugin-manager.d.ts +6 -2
  68. package/dist/core/plugin-manager.d.ts.map +1 -1
  69. package/dist/core/plugin-manager.js +9 -16
  70. package/dist/core/plugin-registry.d.ts +59 -0
  71. package/dist/core/plugin-registry.d.ts.map +1 -0
  72. package/dist/core/plugin-registry.js +80 -0
  73. package/dist/core/policy-operations.d.ts +101 -21
  74. package/dist/core/policy-operations.d.ts.map +1 -1
  75. package/dist/core/policy-operations.js +45 -47
  76. package/dist/core/policy-vector-service.d.ts +3 -4
  77. package/dist/core/policy-vector-service.d.ts.map +1 -1
  78. package/dist/core/policy-vector-service.js +2 -2
  79. package/dist/core/providers/host-provider.d.ts +1 -1
  80. package/dist/core/providers/host-provider.d.ts.map +1 -1
  81. package/dist/core/providers/host-provider.js +2 -2
  82. package/dist/core/providers/provider-debug-utils.d.ts +2 -2
  83. package/dist/core/providers/provider-debug-utils.d.ts.map +1 -1
  84. package/dist/core/providers/tool-utils.d.ts +10 -2
  85. package/dist/core/providers/tool-utils.d.ts.map +1 -1
  86. package/dist/core/providers/tool-utils.js +2 -2
  87. package/dist/core/providers/vercel-provider.d.ts.map +1 -1
  88. package/dist/core/providers/vercel-provider.js +29 -23
  89. package/dist/core/resource-tools.d.ts +29 -1
  90. package/dist/core/resource-tools.d.ts.map +1 -1
  91. package/dist/core/resource-vector-service.d.ts +3 -4
  92. package/dist/core/resource-vector-service.d.ts.map +1 -1
  93. package/dist/core/resource-vector-service.js +2 -2
  94. package/dist/core/schema.d.ts +15 -14
  95. package/dist/core/schema.d.ts.map +1 -1
  96. package/dist/core/schema.js +32 -34
  97. package/dist/core/shared-prompt-loader.d.ts +1 -1
  98. package/dist/core/shared-prompt-loader.d.ts.map +1 -1
  99. package/dist/core/solution-cr.js +1 -1
  100. package/dist/core/solution-utils.d.ts +22 -3
  101. package/dist/core/solution-utils.d.ts.map +1 -1
  102. package/dist/core/solution-utils.js +1 -1
  103. package/dist/core/telemetry/client.d.ts +0 -6
  104. package/dist/core/telemetry/client.d.ts.map +1 -1
  105. package/dist/core/telemetry/client.js +6 -17
  106. package/dist/core/telemetry/config.js +1 -1
  107. package/dist/core/telemetry/index.d.ts +1 -1
  108. package/dist/core/telemetry/index.d.ts.map +1 -1
  109. package/dist/core/telemetry/index.js +1 -2
  110. package/dist/core/tracing/tool-tracing.d.ts +1 -1
  111. package/dist/core/tracing/tool-tracing.d.ts.map +1 -1
  112. package/dist/core/unified-creation-session.d.ts +15 -8
  113. package/dist/core/unified-creation-session.d.ts.map +1 -1
  114. package/dist/core/unified-creation-session.js +19 -19
  115. package/dist/core/unified-creation-types.d.ts +2 -2
  116. package/dist/core/unified-creation-types.d.ts.map +1 -1
  117. package/dist/core/visualization.d.ts +1 -1
  118. package/dist/core/visualization.d.ts.map +1 -1
  119. package/dist/core/workflow.d.ts +8 -5
  120. package/dist/core/workflow.d.ts.map +1 -1
  121. package/dist/evaluation/dataset-analyzer.d.ts +13 -7
  122. package/dist/evaluation/dataset-analyzer.d.ts.map +1 -1
  123. package/dist/evaluation/dataset-analyzer.js +1 -1
  124. package/dist/evaluation/datasets/loader.d.ts +2 -2
  125. package/dist/evaluation/datasets/loader.d.ts.map +1 -1
  126. package/dist/evaluation/eval-runner.js +7 -5
  127. package/dist/evaluation/evaluators/base-comparative.d.ts +1 -1
  128. package/dist/evaluation/evaluators/base-comparative.d.ts.map +1 -1
  129. package/dist/evaluation/evaluators/base-comparative.js +4 -3
  130. package/dist/evaluation/evaluators/base.d.ts +5 -5
  131. package/dist/evaluation/evaluators/base.d.ts.map +1 -1
  132. package/dist/evaluation/evaluators/capability-comparative.js +1 -1
  133. package/dist/evaluation/platform-synthesizer.d.ts.map +1 -1
  134. package/dist/interfaces/mcp.d.ts.map +1 -1
  135. package/dist/interfaces/mcp.js +26 -15
  136. package/dist/interfaces/openapi-generator.d.ts +116 -12
  137. package/dist/interfaces/openapi-generator.d.ts.map +1 -1
  138. package/dist/interfaces/openapi-generator.js +500 -207
  139. package/dist/interfaces/rest-api.d.ts +28 -6
  140. package/dist/interfaces/rest-api.d.ts.map +1 -1
  141. package/dist/interfaces/rest-api.js +436 -245
  142. package/dist/interfaces/rest-registry.d.ts +5 -5
  143. package/dist/interfaces/rest-registry.d.ts.map +1 -1
  144. package/dist/interfaces/rest-registry.js +12 -27
  145. package/dist/interfaces/rest-route-registry.d.ts +165 -0
  146. package/dist/interfaces/rest-route-registry.d.ts.map +1 -0
  147. package/dist/interfaces/rest-route-registry.js +230 -0
  148. package/dist/interfaces/routes/index.d.ts +22 -0
  149. package/dist/interfaces/routes/index.d.ts.map +1 -0
  150. package/dist/interfaces/routes/index.js +347 -0
  151. package/dist/interfaces/schemas/common.d.ts +170 -0
  152. package/dist/interfaces/schemas/common.d.ts.map +1 -0
  153. package/dist/interfaces/schemas/common.js +114 -0
  154. package/dist/interfaces/schemas/events.d.ts +127 -0
  155. package/dist/interfaces/schemas/events.d.ts.map +1 -0
  156. package/dist/interfaces/schemas/events.js +66 -0
  157. package/dist/interfaces/schemas/index.d.ts +21 -0
  158. package/dist/interfaces/schemas/index.d.ts.map +1 -0
  159. package/dist/interfaces/schemas/index.js +138 -0
  160. package/dist/interfaces/schemas/knowledge.d.ts +201 -0
  161. package/dist/interfaces/schemas/knowledge.d.ts.map +1 -0
  162. package/dist/interfaces/schemas/knowledge.js +117 -0
  163. package/dist/interfaces/schemas/logs.d.ts +78 -0
  164. package/dist/interfaces/schemas/logs.d.ts.map +1 -0
  165. package/dist/interfaces/schemas/logs.js +46 -0
  166. package/dist/interfaces/schemas/prompts.d.ts +185 -0
  167. package/dist/interfaces/schemas/prompts.d.ts.map +1 -0
  168. package/dist/interfaces/schemas/prompts.js +91 -0
  169. package/dist/interfaces/schemas/resources.d.ts +363 -0
  170. package/dist/interfaces/schemas/resources.d.ts.map +1 -0
  171. package/dist/interfaces/schemas/resources.js +173 -0
  172. package/dist/interfaces/schemas/sessions.d.ts +87 -0
  173. package/dist/interfaces/schemas/sessions.d.ts.map +1 -0
  174. package/dist/interfaces/schemas/sessions.js +56 -0
  175. package/dist/interfaces/schemas/tools.d.ts +188 -0
  176. package/dist/interfaces/schemas/tools.d.ts.map +1 -0
  177. package/dist/interfaces/schemas/tools.js +101 -0
  178. package/dist/interfaces/schemas/visualization.d.ts +369 -0
  179. package/dist/interfaces/schemas/visualization.d.ts.map +1 -0
  180. package/dist/interfaces/schemas/visualization.js +134 -0
  181. package/dist/mcp/server.js +5 -4
  182. package/dist/tools/answer-question.d.ts +1 -1
  183. package/dist/tools/answer-question.d.ts.map +1 -1
  184. package/dist/tools/answer-question.js +9 -8
  185. package/dist/tools/deploy-manifests.d.ts +4 -2
  186. package/dist/tools/deploy-manifests.d.ts.map +1 -1
  187. package/dist/tools/deploy-manifests.js +10 -6
  188. package/dist/tools/generate-manifests.d.ts.map +1 -1
  189. package/dist/tools/generate-manifests.js +28 -20
  190. package/dist/tools/index.d.ts +1 -0
  191. package/dist/tools/index.d.ts.map +1 -1
  192. package/dist/tools/index.js +6 -1
  193. package/dist/tools/manage-knowledge.d.ts +77 -0
  194. package/dist/tools/manage-knowledge.d.ts.map +1 -0
  195. package/dist/tools/manage-knowledge.js +573 -0
  196. package/dist/tools/operate-analysis.d.ts +31 -2
  197. package/dist/tools/operate-analysis.d.ts.map +1 -1
  198. package/dist/tools/operate-execution.d.ts +2 -3
  199. package/dist/tools/operate-execution.d.ts.map +1 -1
  200. package/dist/tools/operate-execution.js +7 -7
  201. package/dist/tools/operate.d.ts +7 -2
  202. package/dist/tools/operate.d.ts.map +1 -1
  203. package/dist/tools/operate.js +2 -2
  204. package/dist/tools/organizational-data.d.ts +30 -4
  205. package/dist/tools/organizational-data.d.ts.map +1 -1
  206. package/dist/tools/organizational-data.js +24 -19
  207. package/dist/tools/project-setup/discovery.d.ts.map +1 -1
  208. package/dist/tools/project-setup/generate-scope.d.ts +1 -1
  209. package/dist/tools/project-setup/generate-scope.d.ts.map +1 -1
  210. package/dist/tools/project-setup/types.d.ts +1 -0
  211. package/dist/tools/project-setup/types.d.ts.map +1 -1
  212. package/dist/tools/prompts.d.ts +29 -3
  213. package/dist/tools/prompts.d.ts.map +1 -1
  214. package/dist/tools/prompts.js +6 -3
  215. package/dist/tools/query.d.ts +17 -3
  216. package/dist/tools/query.d.ts.map +1 -1
  217. package/dist/tools/query.js +1 -7
  218. package/dist/tools/recommend.d.ts +24 -6
  219. package/dist/tools/recommend.d.ts.map +1 -1
  220. package/dist/tools/recommend.js +18 -15
  221. package/dist/tools/remediate.d.ts +12 -3
  222. package/dist/tools/remediate.d.ts.map +1 -1
  223. package/dist/tools/remediate.js +22 -14
  224. package/dist/tools/version.d.ts +19 -5
  225. package/dist/tools/version.d.ts.map +1 -1
  226. package/dist/tools/version.js +106 -54
  227. package/package.json +15 -9
  228. package/prompts/knowledge-ask.md +29 -0
  229. package/scripts/generate-openapi.sh +56 -0
  230. package/scripts/grafana-stack.nu +118 -0
  231. package/shared-prompts/prd-create.md +2 -0
  232. package/dist/core/vector-db-service.d.ts +0 -108
  233. package/dist/core/vector-db-service.d.ts.map +0 -1
  234. package/dist/core/vector-db-service.js +0 -647
@@ -1,647 +0,0 @@
1
- "use strict";
2
- /**
3
- * Vector DB Service
4
- *
5
- * Handles Qdrant Vector Database integration for semantic search and storage
6
- */
7
- Object.defineProperty(exports, "__esModule", { value: true });
8
- exports.VectorDBService = void 0;
9
- const js_client_rest_1 = require("@qdrant/js-client-rest");
10
- const qdrant_tracing_1 = require("./tracing/qdrant-tracing");
11
- /**
12
- * Escape special regex characters to prevent ReDoS attacks
13
- */
14
- function escapeRegExp(str) {
15
- return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
16
- }
17
- /**
18
- * Simple semaphore to limit concurrent Qdrant operations
19
- * Prevents overwhelming Qdrant with too many parallel requests
20
- */
21
- class QdrantSemaphore {
22
- maxConcurrent;
23
- currentCount = 0;
24
- waitQueue = [];
25
- constructor(maxConcurrent = 20) {
26
- this.maxConcurrent = maxConcurrent;
27
- }
28
- async acquire() {
29
- if (this.currentCount < this.maxConcurrent) {
30
- this.currentCount++;
31
- return;
32
- }
33
- return new Promise((resolve) => {
34
- this.waitQueue.push(resolve);
35
- });
36
- }
37
- release() {
38
- if (this.waitQueue.length > 0) {
39
- const next = this.waitQueue.shift();
40
- next();
41
- }
42
- else {
43
- this.currentCount--;
44
- }
45
- }
46
- }
47
- // Limit concurrent Qdrant bulk operations (scroll, getAllDocuments)
48
- const qdrantSemaphore = new QdrantSemaphore(100);
49
- class VectorDBService {
50
- client = null;
51
- config;
52
- collectionName;
53
- constructor(config = {}) {
54
- if (!config.collectionName) {
55
- throw new Error('Collection name is required for Vector DB service');
56
- }
57
- this.config = {
58
- url: config.url !== undefined ? config.url : (process.env.QDRANT_URL || 'http://localhost:6333'),
59
- apiKey: config.apiKey || process.env.QDRANT_API_KEY,
60
- collectionName: config.collectionName
61
- };
62
- this.collectionName = this.config.collectionName;
63
- this.validateConfig();
64
- if (this.shouldInitializeClient()) {
65
- this.client = new js_client_rest_1.QdrantClient({
66
- url: this.config.url,
67
- apiKey: this.config.apiKey,
68
- maxConnections: 100, // HTTP keep-alive pool for connection reuse
69
- });
70
- }
71
- }
72
- validateConfig() {
73
- // Allow test-friendly initialization
74
- if (this.config.url === 'test-url' || this.config.url === 'mock-url') {
75
- return; // Allow test configurations
76
- }
77
- if (!this.config.url || this.config.url.trim() === '') {
78
- throw new Error('Qdrant URL is required for Vector DB integration');
79
- }
80
- }
81
- shouldInitializeClient() {
82
- // Don't initialize for test configurations
83
- const testUrls = ['test-url', 'mock-url'];
84
- return !testUrls.includes(this.config.url || '');
85
- }
86
- /**
87
- * Check if collection exists without creating it
88
- */
89
- async collectionExists() {
90
- if (!this.client) {
91
- return false;
92
- }
93
- try {
94
- const collections = await this.client.getCollections();
95
- return collections.collections.some(col => col.name === this.collectionName);
96
- }
97
- catch {
98
- return false;
99
- }
100
- }
101
- /**
102
- * Initialize the collection if it doesn't exist
103
- */
104
- async initializeCollection(vectorSize = 384) {
105
- if (!this.client) {
106
- throw new Error('Vector DB client not initialized');
107
- }
108
- return (0, qdrant_tracing_1.withQdrantTracing)({
109
- operation: 'collection.initialize',
110
- collectionName: this.collectionName,
111
- vectorSize,
112
- serverUrl: this.config.url
113
- }, async () => {
114
- try {
115
- // Check if collection exists
116
- const collections = await this.client.getCollections();
117
- const collectionExists = collections.collections.some(col => col.name === this.collectionName);
118
- if (collectionExists) {
119
- // Verify existing collection has correct vector dimensions
120
- try {
121
- const collectionInfo = await this.client.getCollection(this.collectionName);
122
- const existingVectorSize = collectionInfo.config?.params?.vectors?.size;
123
- if (existingVectorSize && existingVectorSize !== vectorSize) {
124
- // Dimension mismatch - recreate collection
125
- console.warn(`Vector dimension mismatch: existing collection has ${existingVectorSize} dimensions, but ${vectorSize} expected. Recreating collection.`);
126
- await this.client.deleteCollection(this.collectionName);
127
- await this.createCollection(vectorSize);
128
- }
129
- else {
130
- // Ensure text index exists for existing collections (transparent upgrade)
131
- await this.ensureTextIndex();
132
- }
133
- }
134
- catch (error) {
135
- // If we can't get collection info, assume it's corrupted and recreate
136
- console.warn(`Failed to get collection info, recreating collection: ${error}`);
137
- await this.client.deleteCollection(this.collectionName);
138
- await this.createCollection(vectorSize);
139
- }
140
- }
141
- else {
142
- // Create new collection
143
- await this.createCollection(vectorSize);
144
- }
145
- }
146
- catch (error) {
147
- throw new Error(`Failed to initialize collection: ${error}`);
148
- }
149
- });
150
- }
151
- /**
152
- * Create collection with specified vector size
153
- * Handles conflict errors gracefully (collection already exists from race condition or restart)
154
- */
155
- async createCollection(vectorSize) {
156
- if (!this.client) {
157
- throw new Error('Vector DB client not initialized');
158
- }
159
- try {
160
- await this.client.createCollection(this.collectionName, {
161
- vectors: {
162
- size: vectorSize,
163
- distance: 'Cosine',
164
- on_disk: true // Enable on-disk storage for better performance with large collections
165
- },
166
- optimizers_config: {
167
- default_segment_number: 2
168
- }
169
- });
170
- // Create text index on searchText field for efficient keyword search
171
- await this.ensureTextIndex();
172
- }
173
- catch (error) {
174
- // Handle race condition where collection was created between check and create
175
- const errorMessage = error instanceof Error ? error.message : String(error);
176
- if (errorMessage.toLowerCase().includes('conflict') ||
177
- errorMessage.toLowerCase().includes('already exists')) {
178
- // Collection exists - this is fine (race condition or restart)
179
- if (process.env.DEBUG_DOT_AI) {
180
- console.debug(`Collection ${this.collectionName} already exists, skipping creation`);
181
- }
182
- await this.ensureTextIndex();
183
- return;
184
- }
185
- throw error;
186
- }
187
- }
188
- /**
189
- * Ensure text index exists on searchText field for efficient keyword search
190
- * This is idempotent - safe to call multiple times
191
- */
192
- async ensureTextIndex() {
193
- if (!this.client) {
194
- return;
195
- }
196
- try {
197
- // Check if index already exists
198
- const collectionInfo = await this.client.getCollection(this.collectionName);
199
- const payloadSchema = collectionInfo.payload_schema || {};
200
- // Check if searchText already has a text index
201
- const searchTextIndex = payloadSchema['searchText'];
202
- if (searchTextIndex && searchTextIndex.data_type === 'text') {
203
- return; // Index already exists
204
- }
205
- // Create text index on searchText field
206
- await this.client.createPayloadIndex(this.collectionName, {
207
- field_name: 'searchText',
208
- field_schema: 'text',
209
- });
210
- if (process.env.DEBUG_DOT_AI) {
211
- console.debug(`Created text index on searchText field for collection ${this.collectionName}`);
212
- }
213
- }
214
- catch (error) {
215
- const errorMessage = error instanceof Error ? error.message : String(error);
216
- const isAlreadyExists = errorMessage.toLowerCase().includes('already exists') ||
217
- errorMessage.toLowerCase().includes('conflict');
218
- if (isAlreadyExists) {
219
- if (process.env.DEBUG_DOT_AI) {
220
- console.debug(`Text index already exists for collection ${this.collectionName}`);
221
- }
222
- }
223
- else {
224
- // Unexpected error - log at warn level for visibility
225
- console.warn(`Failed to create text index on ${this.collectionName}: ${errorMessage}`);
226
- }
227
- }
228
- }
229
- /**
230
- * Store a document with optional vector
231
- */
232
- async upsertDocument(document) {
233
- if (!this.client) {
234
- throw new Error('Vector DB client not initialized');
235
- }
236
- return (0, qdrant_tracing_1.withQdrantTracing)({
237
- operation: 'vector.upsert',
238
- collectionName: this.collectionName,
239
- documentId: document.id,
240
- vectorSize: document.vector?.length,
241
- serverUrl: this.config.url
242
- }, async () => {
243
- try {
244
- const point = {
245
- id: document.id,
246
- payload: document.payload,
247
- vector: document.vector
248
- };
249
- // Validate vector is provided
250
- if (!document.vector || document.vector.length === 0) {
251
- throw new Error('Vector is required for vector database storage');
252
- }
253
- await this.client.upsert(this.collectionName, {
254
- wait: true,
255
- points: [point]
256
- });
257
- }
258
- catch (error) {
259
- throw new Error(`Failed to upsert document: ${error}`);
260
- }
261
- });
262
- }
263
- /**
264
- * Search for similar documents using vector similarity
265
- */
266
- async searchSimilar(vector, options = {}) {
267
- if (!this.client) {
268
- throw new Error('Vector DB client not initialized');
269
- }
270
- const limit = options.limit || 10;
271
- const scoreThreshold = options.scoreThreshold || 0.5;
272
- return (0, qdrant_tracing_1.withQdrantTracing)({
273
- operation: 'vector.search',
274
- collectionName: this.collectionName,
275
- vectorSize: vector.length,
276
- limit,
277
- scoreThreshold,
278
- serverUrl: this.config.url
279
- }, async () => {
280
- try {
281
- const searchResult = await this.client.search(this.collectionName, {
282
- vector,
283
- limit,
284
- score_threshold: scoreThreshold,
285
- with_payload: true,
286
- ...(options.filter && { filter: options.filter })
287
- });
288
- return searchResult.map(result => ({
289
- id: result.id.toString(),
290
- score: result.score,
291
- payload: result.payload || {}
292
- }));
293
- }
294
- catch (error) {
295
- throw new Error(`Failed to search documents: ${error}`);
296
- }
297
- });
298
- }
299
- /**
300
- * Search for documents using payload filtering (keyword search)
301
- * Uses Qdrant's native text index for efficient server-side filtering
302
- */
303
- async searchByKeywords(keywords, options = {}) {
304
- if (!this.client) {
305
- throw new Error('Vector DB client not initialized');
306
- }
307
- const limit = options.limit || 10;
308
- if (keywords.length === 0) {
309
- return [];
310
- }
311
- return (0, qdrant_tracing_1.withQdrantTracing)({
312
- operation: 'vector.search_keywords',
313
- collectionName: this.collectionName,
314
- keywordCount: keywords.length,
315
- limit,
316
- serverUrl: this.config.url
317
- }, async () => {
318
- try {
319
- // Build Qdrant filter for text search
320
- // Use "should" (OR) to match any keyword in searchText or triggers
321
- const keywordConditions = [];
322
- for (const keyword of keywords) {
323
- // Text match on searchText field (uses text index)
324
- keywordConditions.push({
325
- key: 'searchText',
326
- match: { text: keyword }
327
- });
328
- // Match on triggers array (for patterns/policies)
329
- keywordConditions.push({
330
- key: 'triggers',
331
- match: { any: [keyword, keyword.toLowerCase()] }
332
- });
333
- }
334
- // Combine keyword conditions with any user-provided filter
335
- const filter = {
336
- should: keywordConditions
337
- };
338
- // If user provided additional filters, merge them properly
339
- if (options.filter) {
340
- // Merge must conditions
341
- if (options.filter.must) {
342
- filter.must = Array.isArray(options.filter.must)
343
- ? options.filter.must
344
- : [options.filter.must];
345
- }
346
- // Preserve must_not conditions
347
- if (options.filter.must_not) {
348
- filter.must_not = options.filter.must_not;
349
- }
350
- // If user filter has should conditions, wrap in must to AND with keyword should
351
- if (options.filter.should) {
352
- filter.must = [...(filter.must || []), { should: options.filter.should }];
353
- }
354
- }
355
- // Use scroll with native Qdrant filtering - much faster than client-side
356
- const scrollResult = await this.client.scroll(this.collectionName, {
357
- limit: limit * 10, // Get more candidates for scoring, but not 1000
358
- with_payload: true,
359
- with_vector: false,
360
- filter
361
- });
362
- // Score the filtered results (small set now)
363
- const scoredPoints = scrollResult.points
364
- .map(point => {
365
- if (!point.payload)
366
- return null;
367
- const searchText = (point.payload.searchText || '').toLowerCase();
368
- const triggers = Array.isArray(point.payload.triggers)
369
- ? point.payload.triggers.map(t => t.toLowerCase())
370
- : [];
371
- // Count keyword matches for scoring
372
- let matchCount = 0;
373
- let exactMatch = false;
374
- for (const keyword of keywords) {
375
- const kw = keyword.toLowerCase();
376
- // Check searchText
377
- if (searchText.includes(kw)) {
378
- matchCount++;
379
- const wordPattern = new RegExp(`\\b${escapeRegExp(kw)}\\b`, 'i');
380
- if (wordPattern.test(searchText)) {
381
- exactMatch = true;
382
- }
383
- }
384
- // Check triggers
385
- if (triggers.some(t => t.includes(kw) || kw.includes(t))) {
386
- matchCount++;
387
- }
388
- }
389
- if (matchCount === 0)
390
- return null;
391
- const baseScore = matchCount / keywords.length;
392
- const score = exactMatch ? Math.min(1.0, baseScore + 0.3) : baseScore;
393
- return { point, score };
394
- })
395
- .filter((item) => item !== null)
396
- .sort((a, b) => b.score - a.score);
397
- const limitedResults = scoredPoints.slice(0, limit);
398
- return limitedResults.map(({ point, score }) => ({
399
- id: point.id.toString(),
400
- score,
401
- payload: point.payload || {}
402
- }));
403
- }
404
- catch (error) {
405
- throw new Error(`Failed to search by keywords: ${error}`);
406
- }
407
- });
408
- }
409
- /**
410
- * Get a document by ID
411
- */
412
- async getDocument(id) {
413
- if (!this.client) {
414
- throw new Error('Vector DB client not initialized');
415
- }
416
- return (0, qdrant_tracing_1.withQdrantTracing)({
417
- operation: 'vector.retrieve',
418
- collectionName: this.collectionName,
419
- documentId: id,
420
- serverUrl: this.config.url
421
- }, async () => {
422
- try {
423
- const result = await this.client.retrieve(this.collectionName, {
424
- ids: [id],
425
- with_payload: true,
426
- with_vector: true
427
- });
428
- if (result.length === 0) {
429
- return null;
430
- }
431
- const point = result[0];
432
- return {
433
- id: point.id.toString(),
434
- payload: point.payload || {},
435
- vector: point.vector || undefined
436
- };
437
- }
438
- catch (error) {
439
- throw new Error(`Failed to get document: ${error}`);
440
- }
441
- });
442
- }
443
- /**
444
- * Delete a document by ID
445
- */
446
- async deleteDocument(id) {
447
- if (!this.client) {
448
- throw new Error('Vector DB client not initialized');
449
- }
450
- return (0, qdrant_tracing_1.withQdrantTracing)({
451
- operation: 'vector.delete',
452
- collectionName: this.collectionName,
453
- documentId: id,
454
- serverUrl: this.config.url
455
- }, async () => {
456
- try {
457
- await this.client.delete(this.collectionName, {
458
- wait: true,
459
- points: [id]
460
- });
461
- // Qdrant's wait:true ensures the write operation completes, but there can be
462
- // a brief window where subsequent reads may still return stale data due to
463
- // internal segment synchronization. This delay ensures consistency for
464
- // immediate read-after-delete operations in integration tests and workflows.
465
- await new Promise(resolve => setTimeout(resolve, 100));
466
- }
467
- catch (error) {
468
- throw new Error(`Failed to delete document: ${error}`);
469
- }
470
- });
471
- }
472
- /**
473
- * Delete all documents by clearing all points from the collection
474
- * More efficient than retrieving and deleting individual records
475
- * Collection structure is preserved, avoiding Qdrant storage cleanup issues
476
- */
477
- async deleteAllDocuments() {
478
- if (!this.client) {
479
- throw new Error('Vector DB client not initialized');
480
- }
481
- return (0, qdrant_tracing_1.withQdrantTracing)({
482
- operation: 'vector.delete_all',
483
- collectionName: this.collectionName,
484
- serverUrl: this.config.url
485
- }, async () => {
486
- try {
487
- // Check if collection exists first
488
- const collections = await this.client.getCollections();
489
- const collectionExists = collections.collections.some(col => col.name === this.collectionName);
490
- if (!collectionExists) {
491
- // Collection doesn't exist, nothing to delete
492
- return;
493
- }
494
- // Delete all points from collection instead of deleting entire collection
495
- // This avoids Qdrant's known storage directory cleanup bug
496
- await this.client.delete(this.collectionName, {
497
- filter: {
498
- must: [] // Empty must array matches all points
499
- },
500
- wait: true // Wait for operation to complete synchronously
501
- });
502
- console.warn(`All points deleted from collection ${this.collectionName} (collection structure preserved)`);
503
- }
504
- catch (error) {
505
- throw new Error(`Failed to delete all documents: ${error}`);
506
- }
507
- });
508
- }
509
- /**
510
- * Scroll documents with Qdrant filter
511
- * @param filter - Qdrant filter object (must/should/must_not conditions)
512
- * @param limit - Maximum documents to retrieve
513
- * Uses semaphore to limit concurrent Qdrant operations
514
- */
515
- async scrollWithFilter(filter, limit = 100) {
516
- if (!this.client) {
517
- throw new Error('Vector DB client not initialized');
518
- }
519
- // Acquire semaphore slot before executing
520
- await qdrantSemaphore.acquire();
521
- try {
522
- return await (0, qdrant_tracing_1.withQdrantTracing)({
523
- operation: 'vector.scroll_filtered',
524
- collectionName: this.collectionName,
525
- limit,
526
- serverUrl: this.config.url
527
- }, async () => {
528
- try {
529
- const scrollResult = await this.client.scroll(this.collectionName, {
530
- filter,
531
- limit,
532
- with_payload: true,
533
- with_vector: false
534
- });
535
- return scrollResult.points.map(point => ({
536
- id: point.id.toString(),
537
- payload: point.payload || {}
538
- }));
539
- }
540
- catch (error) {
541
- throw new Error(`Failed to scroll with filter: ${error}`);
542
- }
543
- });
544
- }
545
- finally {
546
- qdrantSemaphore.release();
547
- }
548
- }
549
- /**
550
- * Get all documents (for listing)
551
- * @param limit - Maximum number of documents to retrieve. Defaults to unlimited (10000).
552
- * Uses semaphore to limit concurrent Qdrant operations
553
- */
554
- async getAllDocuments(limit = 10000) {
555
- if (!this.client) {
556
- throw new Error('Vector DB client not initialized');
557
- }
558
- // Acquire semaphore slot before executing
559
- await qdrantSemaphore.acquire();
560
- try {
561
- return await (0, qdrant_tracing_1.withQdrantTracing)({
562
- operation: 'vector.list',
563
- collectionName: this.collectionName,
564
- limit,
565
- serverUrl: this.config.url
566
- }, async () => {
567
- try {
568
- // Check if collection exists first
569
- const collections = await this.client.getCollections();
570
- const collectionExists = collections.collections.some(col => col.name === this.collectionName);
571
- if (!collectionExists) {
572
- throw new Error(`Collection '${this.collectionName}' does not exist. No data has been stored yet.`);
573
- }
574
- const scrollResult = await this.client.scroll(this.collectionName, {
575
- limit,
576
- with_payload: true,
577
- with_vector: false
578
- });
579
- return scrollResult.points.map(point => ({
580
- id: point.id.toString(),
581
- payload: point.payload || {}
582
- }));
583
- }
584
- catch (error) {
585
- throw new Error(`Failed to get all documents: ${error}`);
586
- }
587
- });
588
- }
589
- finally {
590
- qdrantSemaphore.release();
591
- }
592
- }
593
- /**
594
- * Get collection info and statistics
595
- */
596
- async getCollectionInfo() {
597
- if (!this.client) {
598
- throw new Error('Vector DB client not initialized');
599
- }
600
- return (0, qdrant_tracing_1.withQdrantTracing)({
601
- operation: 'collection.get',
602
- collectionName: this.collectionName,
603
- serverUrl: this.config.url
604
- }, async () => {
605
- try {
606
- return await this.client.getCollection(this.collectionName);
607
- }
608
- catch (error) {
609
- throw new Error(`Failed to get collection info: ${error}`);
610
- }
611
- });
612
- }
613
- /**
614
- * Check if Vector DB is available and responsive
615
- */
616
- async healthCheck() {
617
- if (!this.client) {
618
- return false;
619
- }
620
- return (0, qdrant_tracing_1.withQdrantTracing)({
621
- operation: 'health_check',
622
- collectionName: this.collectionName,
623
- serverUrl: this.config.url
624
- }, async () => {
625
- try {
626
- await this.client.getCollections();
627
- return true;
628
- }
629
- catch (error) {
630
- return false;
631
- }
632
- });
633
- }
634
- /**
635
- * Check if client is initialized
636
- */
637
- isInitialized() {
638
- return this.client !== null;
639
- }
640
- /**
641
- * Get configuration (for debugging)
642
- */
643
- getConfig() {
644
- return { ...this.config };
645
- }
646
- }
647
- exports.VectorDBService = VectorDBService;