@claude-flow/memory 3.0.0-alpha.1

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 (214) hide show
  1. package/.agentic-flow/intelligence.json +16 -0
  2. package/README.md +249 -0
  3. package/__tests__/coverage/base.css +224 -0
  4. package/__tests__/coverage/block-navigation.js +87 -0
  5. package/__tests__/coverage/coverage-final.json +19 -0
  6. package/__tests__/coverage/favicon.png +0 -0
  7. package/__tests__/coverage/index.html +206 -0
  8. package/__tests__/coverage/lcov-report/base.css +224 -0
  9. package/__tests__/coverage/lcov-report/block-navigation.js +87 -0
  10. package/__tests__/coverage/lcov-report/favicon.png +0 -0
  11. package/__tests__/coverage/lcov-report/index.html +206 -0
  12. package/__tests__/coverage/lcov-report/prettify.css +1 -0
  13. package/__tests__/coverage/lcov-report/prettify.js +2 -0
  14. package/__tests__/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  15. package/__tests__/coverage/lcov-report/sorter.js +210 -0
  16. package/__tests__/coverage/lcov-report/src/agentdb-adapter.ts.html +2737 -0
  17. package/__tests__/coverage/lcov-report/src/agentdb-backend.ts.html +3130 -0
  18. package/__tests__/coverage/lcov-report/src/application/commands/delete-memory.command.ts.html +601 -0
  19. package/__tests__/coverage/lcov-report/src/application/commands/index.html +131 -0
  20. package/__tests__/coverage/lcov-report/src/application/commands/store-memory.command.ts.html +394 -0
  21. package/__tests__/coverage/lcov-report/src/application/queries/index.html +116 -0
  22. package/__tests__/coverage/lcov-report/src/application/queries/search-memory.query.ts.html +796 -0
  23. package/__tests__/coverage/lcov-report/src/application/services/index.html +116 -0
  24. package/__tests__/coverage/lcov-report/src/application/services/memory-application-service.ts.html +793 -0
  25. package/__tests__/coverage/lcov-report/src/cache-manager.ts.html +1633 -0
  26. package/__tests__/coverage/lcov-report/src/database-provider.ts.html +1618 -0
  27. package/__tests__/coverage/lcov-report/src/domain/entities/index.html +116 -0
  28. package/__tests__/coverage/lcov-report/src/domain/entities/memory-entry.ts.html +952 -0
  29. package/__tests__/coverage/lcov-report/src/domain/services/index.html +116 -0
  30. package/__tests__/coverage/lcov-report/src/domain/services/memory-domain-service.ts.html +1294 -0
  31. package/__tests__/coverage/lcov-report/src/hnsw-index.ts.html +3124 -0
  32. package/__tests__/coverage/lcov-report/src/hybrid-backend.ts.html +2167 -0
  33. package/__tests__/coverage/lcov-report/src/index.html +266 -0
  34. package/__tests__/coverage/lcov-report/src/infrastructure/repositories/hybrid-memory-repository.ts.html +1633 -0
  35. package/__tests__/coverage/lcov-report/src/infrastructure/repositories/index.html +116 -0
  36. package/__tests__/coverage/lcov-report/src/migration.ts.html +2092 -0
  37. package/__tests__/coverage/lcov-report/src/query-builder.ts.html +1711 -0
  38. package/__tests__/coverage/lcov-report/src/sqlite-backend.ts.html +2281 -0
  39. package/__tests__/coverage/lcov-report/src/sqljs-backend.ts.html +2374 -0
  40. package/__tests__/coverage/lcov-report/src/types.ts.html +2266 -0
  41. package/__tests__/coverage/lcov.info +10238 -0
  42. package/__tests__/coverage/prettify.css +1 -0
  43. package/__tests__/coverage/prettify.js +2 -0
  44. package/__tests__/coverage/sort-arrow-sprite.png +0 -0
  45. package/__tests__/coverage/sorter.js +210 -0
  46. package/__tests__/coverage/src/agentdb-adapter.ts.html +2737 -0
  47. package/__tests__/coverage/src/agentdb-backend.ts.html +3130 -0
  48. package/__tests__/coverage/src/application/commands/delete-memory.command.ts.html +601 -0
  49. package/__tests__/coverage/src/application/commands/index.html +131 -0
  50. package/__tests__/coverage/src/application/commands/store-memory.command.ts.html +394 -0
  51. package/__tests__/coverage/src/application/queries/index.html +116 -0
  52. package/__tests__/coverage/src/application/queries/search-memory.query.ts.html +796 -0
  53. package/__tests__/coverage/src/application/services/index.html +116 -0
  54. package/__tests__/coverage/src/application/services/memory-application-service.ts.html +793 -0
  55. package/__tests__/coverage/src/cache-manager.ts.html +1633 -0
  56. package/__tests__/coverage/src/database-provider.ts.html +1618 -0
  57. package/__tests__/coverage/src/domain/entities/index.html +116 -0
  58. package/__tests__/coverage/src/domain/entities/memory-entry.ts.html +952 -0
  59. package/__tests__/coverage/src/domain/services/index.html +116 -0
  60. package/__tests__/coverage/src/domain/services/memory-domain-service.ts.html +1294 -0
  61. package/__tests__/coverage/src/hnsw-index.ts.html +3124 -0
  62. package/__tests__/coverage/src/hybrid-backend.ts.html +2167 -0
  63. package/__tests__/coverage/src/index.html +266 -0
  64. package/__tests__/coverage/src/infrastructure/repositories/hybrid-memory-repository.ts.html +1633 -0
  65. package/__tests__/coverage/src/infrastructure/repositories/index.html +116 -0
  66. package/__tests__/coverage/src/migration.ts.html +2092 -0
  67. package/__tests__/coverage/src/query-builder.ts.html +1711 -0
  68. package/__tests__/coverage/src/sqlite-backend.ts.html +2281 -0
  69. package/__tests__/coverage/src/sqljs-backend.ts.html +2374 -0
  70. package/__tests__/coverage/src/types.ts.html +2266 -0
  71. package/benchmarks/cache-hit-rate.bench.ts +535 -0
  72. package/benchmarks/hnsw-indexing.bench.ts +552 -0
  73. package/benchmarks/memory-write.bench.ts +469 -0
  74. package/benchmarks/vector-search.bench.ts +449 -0
  75. package/dist/agentdb-adapter.d.ts +146 -0
  76. package/dist/agentdb-adapter.d.ts.map +1 -0
  77. package/dist/agentdb-adapter.js +679 -0
  78. package/dist/agentdb-adapter.js.map +1 -0
  79. package/dist/agentdb-backend.d.ts +214 -0
  80. package/dist/agentdb-backend.d.ts.map +1 -0
  81. package/dist/agentdb-backend.js +827 -0
  82. package/dist/agentdb-backend.js.map +1 -0
  83. package/dist/agentdb-backend.test.d.ts +7 -0
  84. package/dist/agentdb-backend.test.d.ts.map +1 -0
  85. package/dist/agentdb-backend.test.js +258 -0
  86. package/dist/agentdb-backend.test.js.map +1 -0
  87. package/dist/application/commands/delete-memory.command.d.ts +65 -0
  88. package/dist/application/commands/delete-memory.command.d.ts.map +1 -0
  89. package/dist/application/commands/delete-memory.command.js +129 -0
  90. package/dist/application/commands/delete-memory.command.js.map +1 -0
  91. package/dist/application/commands/store-memory.command.d.ts +48 -0
  92. package/dist/application/commands/store-memory.command.d.ts.map +1 -0
  93. package/dist/application/commands/store-memory.command.js +72 -0
  94. package/dist/application/commands/store-memory.command.js.map +1 -0
  95. package/dist/application/index.d.ts +12 -0
  96. package/dist/application/index.d.ts.map +1 -0
  97. package/dist/application/index.js +15 -0
  98. package/dist/application/index.js.map +1 -0
  99. package/dist/application/queries/search-memory.query.d.ts +72 -0
  100. package/dist/application/queries/search-memory.query.d.ts.map +1 -0
  101. package/dist/application/queries/search-memory.query.js +143 -0
  102. package/dist/application/queries/search-memory.query.js.map +1 -0
  103. package/dist/application/services/memory-application-service.d.ts +121 -0
  104. package/dist/application/services/memory-application-service.d.ts.map +1 -0
  105. package/dist/application/services/memory-application-service.js +190 -0
  106. package/dist/application/services/memory-application-service.js.map +1 -0
  107. package/dist/cache-manager.d.ts +134 -0
  108. package/dist/cache-manager.d.ts.map +1 -0
  109. package/dist/cache-manager.js +407 -0
  110. package/dist/cache-manager.js.map +1 -0
  111. package/dist/database-provider.d.ts +86 -0
  112. package/dist/database-provider.d.ts.map +1 -0
  113. package/dist/database-provider.js +385 -0
  114. package/dist/database-provider.js.map +1 -0
  115. package/dist/database-provider.test.d.ts +7 -0
  116. package/dist/database-provider.test.d.ts.map +1 -0
  117. package/dist/database-provider.test.js +285 -0
  118. package/dist/database-provider.test.js.map +1 -0
  119. package/dist/domain/entities/memory-entry.d.ts +143 -0
  120. package/dist/domain/entities/memory-entry.d.ts.map +1 -0
  121. package/dist/domain/entities/memory-entry.js +226 -0
  122. package/dist/domain/entities/memory-entry.js.map +1 -0
  123. package/dist/domain/index.d.ts +11 -0
  124. package/dist/domain/index.d.ts.map +1 -0
  125. package/dist/domain/index.js +12 -0
  126. package/dist/domain/index.js.map +1 -0
  127. package/dist/domain/repositories/memory-repository.interface.d.ts +102 -0
  128. package/dist/domain/repositories/memory-repository.interface.d.ts.map +1 -0
  129. package/dist/domain/repositories/memory-repository.interface.js +11 -0
  130. package/dist/domain/repositories/memory-repository.interface.js.map +1 -0
  131. package/dist/domain/services/memory-domain-service.d.ts +105 -0
  132. package/dist/domain/services/memory-domain-service.d.ts.map +1 -0
  133. package/dist/domain/services/memory-domain-service.js +297 -0
  134. package/dist/domain/services/memory-domain-service.js.map +1 -0
  135. package/dist/hnsw-index.d.ts +111 -0
  136. package/dist/hnsw-index.d.ts.map +1 -0
  137. package/dist/hnsw-index.js +781 -0
  138. package/dist/hnsw-index.js.map +1 -0
  139. package/dist/hybrid-backend.d.ts +217 -0
  140. package/dist/hybrid-backend.d.ts.map +1 -0
  141. package/dist/hybrid-backend.js +491 -0
  142. package/dist/hybrid-backend.js.map +1 -0
  143. package/dist/hybrid-backend.test.d.ts +8 -0
  144. package/dist/hybrid-backend.test.d.ts.map +1 -0
  145. package/dist/hybrid-backend.test.js +320 -0
  146. package/dist/hybrid-backend.test.js.map +1 -0
  147. package/dist/index.d.ts +188 -0
  148. package/dist/index.d.ts.map +1 -0
  149. package/dist/index.js +345 -0
  150. package/dist/index.js.map +1 -0
  151. package/dist/infrastructure/index.d.ts +17 -0
  152. package/dist/infrastructure/index.d.ts.map +1 -0
  153. package/dist/infrastructure/index.js +16 -0
  154. package/dist/infrastructure/index.js.map +1 -0
  155. package/dist/infrastructure/repositories/hybrid-memory-repository.d.ts +66 -0
  156. package/dist/infrastructure/repositories/hybrid-memory-repository.d.ts.map +1 -0
  157. package/dist/infrastructure/repositories/hybrid-memory-repository.js +409 -0
  158. package/dist/infrastructure/repositories/hybrid-memory-repository.js.map +1 -0
  159. package/dist/migration.d.ts +68 -0
  160. package/dist/migration.d.ts.map +1 -0
  161. package/dist/migration.js +513 -0
  162. package/dist/migration.js.map +1 -0
  163. package/dist/query-builder.d.ts +211 -0
  164. package/dist/query-builder.d.ts.map +1 -0
  165. package/dist/query-builder.js +438 -0
  166. package/dist/query-builder.js.map +1 -0
  167. package/dist/sqlite-backend.d.ts +121 -0
  168. package/dist/sqlite-backend.d.ts.map +1 -0
  169. package/dist/sqlite-backend.js +564 -0
  170. package/dist/sqlite-backend.js.map +1 -0
  171. package/dist/sqljs-backend.d.ts +128 -0
  172. package/dist/sqljs-backend.d.ts.map +1 -0
  173. package/dist/sqljs-backend.js +598 -0
  174. package/dist/sqljs-backend.js.map +1 -0
  175. package/dist/types.d.ts +481 -0
  176. package/dist/types.d.ts.map +1 -0
  177. package/dist/types.js +58 -0
  178. package/dist/types.js.map +1 -0
  179. package/docs/AGENTDB-INTEGRATION.md +388 -0
  180. package/docs/CROSS_PLATFORM.md +505 -0
  181. package/docs/WINDOWS_SUPPORT.md +422 -0
  182. package/examples/agentdb-example.ts +345 -0
  183. package/examples/cross-platform-usage.ts +326 -0
  184. package/framework/benchmark.ts +112 -0
  185. package/package.json +31 -0
  186. package/src/agentdb-adapter.ts +884 -0
  187. package/src/agentdb-backend.test.ts +339 -0
  188. package/src/agentdb-backend.ts +1016 -0
  189. package/src/application/commands/delete-memory.command.ts +172 -0
  190. package/src/application/commands/store-memory.command.ts +103 -0
  191. package/src/application/index.ts +36 -0
  192. package/src/application/queries/search-memory.query.ts +237 -0
  193. package/src/application/services/memory-application-service.ts +236 -0
  194. package/src/cache-manager.ts +516 -0
  195. package/src/database-provider.test.ts +364 -0
  196. package/src/database-provider.ts +511 -0
  197. package/src/domain/entities/memory-entry.ts +289 -0
  198. package/src/domain/index.ts +35 -0
  199. package/src/domain/repositories/memory-repository.interface.ts +120 -0
  200. package/src/domain/services/memory-domain-service.ts +403 -0
  201. package/src/hnsw-index.ts +1013 -0
  202. package/src/hybrid-backend.test.ts +399 -0
  203. package/src/hybrid-backend.ts +694 -0
  204. package/src/index.ts +515 -0
  205. package/src/infrastructure/index.ts +23 -0
  206. package/src/infrastructure/repositories/hybrid-memory-repository.ts +516 -0
  207. package/src/migration.ts +669 -0
  208. package/src/query-builder.ts +542 -0
  209. package/src/sqlite-backend.ts +732 -0
  210. package/src/sqljs-backend.ts +763 -0
  211. package/src/types.ts +727 -0
  212. package/tsconfig.json +9 -0
  213. package/tsconfig.tsbuildinfo +1 -0
  214. package/verify-cross-platform.ts +170 -0
@@ -0,0 +1,172 @@
1
+ /**
2
+ * Delete Memory Command - Application Layer (CQRS)
3
+ *
4
+ * Command for deleting memory entries.
5
+ * Supports soft delete and hard delete.
6
+ *
7
+ * @module v3/memory/application/commands
8
+ */
9
+
10
+ import { IMemoryRepository } from '../../domain/repositories/memory-repository.interface.js';
11
+
12
+ /**
13
+ * Delete Memory Command Input
14
+ */
15
+ export interface DeleteMemoryInput {
16
+ id?: string;
17
+ namespace?: string;
18
+ key?: string;
19
+ hardDelete?: boolean;
20
+ }
21
+
22
+ /**
23
+ * Delete Memory Command Result
24
+ */
25
+ export interface DeleteMemoryResult {
26
+ success: boolean;
27
+ deleted: boolean;
28
+ entryId?: string;
29
+ wasHardDelete: boolean;
30
+ }
31
+
32
+ /**
33
+ * Delete Memory Command Handler
34
+ */
35
+ export class DeleteMemoryCommandHandler {
36
+ constructor(private readonly repository: IMemoryRepository) {}
37
+
38
+ async execute(input: DeleteMemoryInput): Promise<DeleteMemoryResult> {
39
+ let entryId: string | undefined;
40
+
41
+ // Find entry by ID or by namespace:key
42
+ if (input.id) {
43
+ entryId = input.id;
44
+ } else if (input.namespace && input.key) {
45
+ const entry = await this.repository.findByKey(input.namespace, input.key);
46
+ entryId = entry?.id;
47
+ }
48
+
49
+ if (!entryId) {
50
+ return {
51
+ success: false,
52
+ deleted: false,
53
+ wasHardDelete: false,
54
+ };
55
+ }
56
+
57
+ if (input.hardDelete) {
58
+ // Hard delete - remove from database
59
+ const deleted = await this.repository.delete(entryId);
60
+ return {
61
+ success: true,
62
+ deleted,
63
+ entryId,
64
+ wasHardDelete: true,
65
+ };
66
+ } else {
67
+ // Soft delete - mark as deleted
68
+ const entry = await this.repository.findById(entryId);
69
+ if (entry) {
70
+ entry.delete();
71
+ await this.repository.save(entry);
72
+ return {
73
+ success: true,
74
+ deleted: true,
75
+ entryId,
76
+ wasHardDelete: false,
77
+ };
78
+ }
79
+ }
80
+
81
+ return {
82
+ success: false,
83
+ deleted: false,
84
+ entryId,
85
+ wasHardDelete: false,
86
+ };
87
+ }
88
+ }
89
+
90
+ /**
91
+ * Bulk Delete Command Input
92
+ */
93
+ export interface BulkDeleteMemoryInput {
94
+ ids?: string[];
95
+ namespace?: string;
96
+ olderThan?: Date;
97
+ hardDelete?: boolean;
98
+ }
99
+
100
+ /**
101
+ * Bulk Delete Command Result
102
+ */
103
+ export interface BulkDeleteMemoryResult {
104
+ success: boolean;
105
+ deletedCount: number;
106
+ failedCount: number;
107
+ errors: Array<{ id: string; error: string }>;
108
+ }
109
+
110
+ /**
111
+ * Bulk Delete Memory Command Handler
112
+ */
113
+ export class BulkDeleteMemoryCommandHandler {
114
+ constructor(private readonly repository: IMemoryRepository) {}
115
+
116
+ async execute(input: BulkDeleteMemoryInput): Promise<BulkDeleteMemoryResult> {
117
+ let idsToDelete: string[] = [];
118
+
119
+ if (input.ids) {
120
+ idsToDelete = input.ids;
121
+ } else if (input.namespace) {
122
+ const entries = await this.repository.findByNamespace(input.namespace);
123
+ idsToDelete = entries
124
+ .filter((e) => !input.olderThan || e.createdAt < input.olderThan)
125
+ .map((e) => e.id);
126
+ }
127
+
128
+ if (idsToDelete.length === 0) {
129
+ return {
130
+ success: true,
131
+ deletedCount: 0,
132
+ failedCount: 0,
133
+ errors: [],
134
+ };
135
+ }
136
+
137
+ if (input.hardDelete) {
138
+ const result = await this.repository.deleteMany(idsToDelete);
139
+ return {
140
+ success: result.failed === 0,
141
+ deletedCount: result.success,
142
+ failedCount: result.failed,
143
+ errors: result.errors,
144
+ };
145
+ } else {
146
+ // Soft delete
147
+ const entries = await this.repository.findByIds(idsToDelete);
148
+ let deletedCount = 0;
149
+ const errors: Array<{ id: string; error: string }> = [];
150
+
151
+ for (const entry of entries) {
152
+ try {
153
+ entry.delete();
154
+ await this.repository.save(entry);
155
+ deletedCount++;
156
+ } catch (error) {
157
+ errors.push({
158
+ id: entry.id,
159
+ error: error instanceof Error ? error.message : 'Unknown error',
160
+ });
161
+ }
162
+ }
163
+
164
+ return {
165
+ success: errors.length === 0,
166
+ deletedCount,
167
+ failedCount: errors.length,
168
+ errors,
169
+ };
170
+ }
171
+ }
172
+ }
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Store Memory Command - Application Layer (CQRS)
3
+ *
4
+ * Command for storing a new memory entry.
5
+ * Implements CQRS pattern per ADR-002.
6
+ *
7
+ * @module v3/memory/application/commands
8
+ */
9
+
10
+ import { MemoryEntry, MemoryType } from '../../domain/entities/memory-entry.js';
11
+ import { IMemoryRepository } from '../../domain/repositories/memory-repository.interface.js';
12
+ import { MemoryDomainService } from '../../domain/services/memory-domain-service.js';
13
+
14
+ /**
15
+ * Store Memory Command Input
16
+ */
17
+ export interface StoreMemoryInput {
18
+ namespace: string;
19
+ key: string;
20
+ value: unknown;
21
+ type?: MemoryType;
22
+ vector?: Float32Array;
23
+ metadata?: Record<string, unknown>;
24
+ ttl?: number;
25
+ }
26
+
27
+ /**
28
+ * Store Memory Command Result
29
+ */
30
+ export interface StoreMemoryResult {
31
+ success: boolean;
32
+ entryId: string;
33
+ entry: MemoryEntry;
34
+ isUpdate: boolean;
35
+ }
36
+
37
+ /**
38
+ * Store Memory Command Handler
39
+ *
40
+ * Handles the command to store a memory entry.
41
+ * Coordinates between domain services and repository.
42
+ */
43
+ export class StoreMemoryCommandHandler {
44
+ constructor(
45
+ private readonly repository: IMemoryRepository,
46
+ private readonly domainService: MemoryDomainService
47
+ ) {}
48
+
49
+ /**
50
+ * Execute the store memory command
51
+ */
52
+ async execute(input: StoreMemoryInput): Promise<StoreMemoryResult> {
53
+ // Check if entry already exists
54
+ const existing = await this.repository.findByKey(input.namespace, input.key);
55
+ const isUpdate = existing !== null;
56
+
57
+ let entry: MemoryEntry;
58
+
59
+ if (existing) {
60
+ // Update existing entry
61
+ existing.updateValue(input.value);
62
+ if (input.vector) {
63
+ existing.updateVector(input.vector);
64
+ }
65
+ if (input.metadata) {
66
+ for (const [key, value] of Object.entries(input.metadata)) {
67
+ existing.setMetadata(key, value);
68
+ }
69
+ }
70
+ await this.repository.save(existing);
71
+ entry = existing;
72
+ } else {
73
+ // Create new entry
74
+ if (input.type) {
75
+ entry = MemoryEntry.create({
76
+ namespace: input.namespace,
77
+ key: input.key,
78
+ value: input.value,
79
+ type: input.type,
80
+ vector: input.vector,
81
+ metadata: input.metadata,
82
+ ttl: input.ttl,
83
+ });
84
+ await this.repository.save(entry);
85
+ } else {
86
+ // Use domain service for type detection
87
+ entry = await this.domainService.storeWithTypeDetection(
88
+ input.namespace,
89
+ input.key,
90
+ input.value,
91
+ input.vector
92
+ );
93
+ }
94
+ }
95
+
96
+ return {
97
+ success: true,
98
+ entryId: entry.id,
99
+ entry,
100
+ isUpdate,
101
+ };
102
+ }
103
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Memory Application Layer - Public Exports
3
+ *
4
+ * Exports all application services, commands, and queries.
5
+ *
6
+ * @module v3/memory/application
7
+ */
8
+
9
+ // Commands
10
+ export {
11
+ StoreMemoryCommandHandler,
12
+ type StoreMemoryInput,
13
+ type StoreMemoryResult,
14
+ } from './commands/store-memory.command.js';
15
+
16
+ export {
17
+ DeleteMemoryCommandHandler,
18
+ BulkDeleteMemoryCommandHandler,
19
+ type DeleteMemoryInput,
20
+ type DeleteMemoryResult,
21
+ type BulkDeleteMemoryInput,
22
+ type BulkDeleteMemoryResult,
23
+ } from './commands/delete-memory.command.js';
24
+
25
+ // Queries
26
+ export {
27
+ SearchMemoryQueryHandler,
28
+ GetMemoryByKeyQueryHandler,
29
+ type SearchMemoryInput,
30
+ type SearchMemoryResult,
31
+ type GetMemoryByKeyInput,
32
+ type GetMemoryByKeyResult,
33
+ } from './queries/search-memory.query.js';
34
+
35
+ // Application Service
36
+ export { MemoryApplicationService } from './services/memory-application-service.js';
@@ -0,0 +1,237 @@
1
+ /**
2
+ * Search Memory Query - Application Layer (CQRS)
3
+ *
4
+ * Query for searching memory entries.
5
+ * Supports text search, vector search, and filtering.
6
+ *
7
+ * @module v3/memory/application/queries
8
+ */
9
+
10
+ import { MemoryEntry, MemoryType, MemoryStatus } from '../../domain/entities/memory-entry.js';
11
+ import {
12
+ IMemoryRepository,
13
+ VectorSearchResult,
14
+ MemoryQueryOptions,
15
+ } from '../../domain/repositories/memory-repository.interface.js';
16
+
17
+ /**
18
+ * Search Memory Query Input
19
+ */
20
+ export interface SearchMemoryInput {
21
+ // Vector search
22
+ vector?: Float32Array;
23
+ similarityThreshold?: number;
24
+
25
+ // Filter options
26
+ namespace?: string;
27
+ type?: MemoryType;
28
+ status?: MemoryStatus;
29
+
30
+ // Pagination
31
+ limit?: number;
32
+ offset?: number;
33
+
34
+ // Sorting
35
+ orderBy?: 'createdAt' | 'updatedAt' | 'accessCount' | 'lastAccessedAt';
36
+ orderDirection?: 'asc' | 'desc';
37
+
38
+ // Text search (searches in value and metadata)
39
+ textQuery?: string;
40
+
41
+ // Access tracking
42
+ trackAccess?: boolean;
43
+ }
44
+
45
+ /**
46
+ * Search Memory Query Result
47
+ */
48
+ export interface SearchMemoryResult {
49
+ entries: MemoryEntry[];
50
+ total: number;
51
+ hasMore: boolean;
52
+ searchType: 'vector' | 'filter' | 'text';
53
+ similarities?: number[];
54
+ }
55
+
56
+ /**
57
+ * Search Memory Query Handler
58
+ */
59
+ export class SearchMemoryQueryHandler {
60
+ constructor(private readonly repository: IMemoryRepository) {}
61
+
62
+ async execute(input: SearchMemoryInput): Promise<SearchMemoryResult> {
63
+ const limit = input.limit ?? 10;
64
+ const offset = input.offset ?? 0;
65
+
66
+ // Vector search takes precedence
67
+ if (input.vector) {
68
+ return this.executeVectorSearch(input, limit, offset);
69
+ }
70
+
71
+ // Text search
72
+ if (input.textQuery) {
73
+ return this.executeTextSearch(input, limit, offset);
74
+ }
75
+
76
+ // Filter-based search
77
+ return this.executeFilterSearch(input, limit, offset);
78
+ }
79
+
80
+ private async executeVectorSearch(
81
+ input: SearchMemoryInput,
82
+ limit: number,
83
+ offset: number
84
+ ): Promise<SearchMemoryResult> {
85
+ const results = await this.repository.searchByVector({
86
+ vector: input.vector!,
87
+ namespace: input.namespace,
88
+ limit: limit + offset, // Get extra for pagination
89
+ threshold: input.similarityThreshold ?? 0.5,
90
+ type: input.type,
91
+ });
92
+
93
+ // Apply offset
94
+ const paginatedResults = results.slice(offset, offset + limit);
95
+
96
+ // Track access if requested
97
+ if (input.trackAccess) {
98
+ await this.trackEntryAccess(paginatedResults.map((r) => r.entry));
99
+ }
100
+
101
+ return {
102
+ entries: paginatedResults.map((r) => r.entry),
103
+ total: results.length,
104
+ hasMore: results.length > offset + limit,
105
+ searchType: 'vector',
106
+ similarities: paginatedResults.map((r) => r.similarity),
107
+ };
108
+ }
109
+
110
+ private async executeTextSearch(
111
+ input: SearchMemoryInput,
112
+ limit: number,
113
+ offset: number
114
+ ): Promise<SearchMemoryResult> {
115
+ // Get all entries matching filters
116
+ const options: MemoryQueryOptions = {
117
+ namespace: input.namespace,
118
+ type: input.type,
119
+ status: input.status ?? 'active',
120
+ orderBy: input.orderBy ?? 'createdAt',
121
+ orderDirection: input.orderDirection ?? 'desc',
122
+ };
123
+
124
+ const allEntries = await this.repository.findAll(options);
125
+
126
+ // Filter by text query
127
+ const query = input.textQuery!.toLowerCase();
128
+ const matchingEntries = allEntries.filter((entry) => {
129
+ const valueStr = JSON.stringify(entry.value).toLowerCase();
130
+ const metadataStr = JSON.stringify(entry.metadata).toLowerCase();
131
+ return valueStr.includes(query) || metadataStr.includes(query);
132
+ });
133
+
134
+ // Paginate
135
+ const paginatedEntries = matchingEntries.slice(offset, offset + limit);
136
+
137
+ // Track access if requested
138
+ if (input.trackAccess) {
139
+ await this.trackEntryAccess(paginatedEntries);
140
+ }
141
+
142
+ return {
143
+ entries: paginatedEntries,
144
+ total: matchingEntries.length,
145
+ hasMore: matchingEntries.length > offset + limit,
146
+ searchType: 'text',
147
+ };
148
+ }
149
+
150
+ private async executeFilterSearch(
151
+ input: SearchMemoryInput,
152
+ limit: number,
153
+ offset: number
154
+ ): Promise<SearchMemoryResult> {
155
+ const options: MemoryQueryOptions = {
156
+ namespace: input.namespace,
157
+ type: input.type,
158
+ status: input.status ?? 'active',
159
+ limit,
160
+ offset,
161
+ orderBy: input.orderBy ?? 'createdAt',
162
+ orderDirection: input.orderDirection ?? 'desc',
163
+ };
164
+
165
+ const entries = await this.repository.findAll(options);
166
+ const total = await this.repository.count({
167
+ namespace: input.namespace,
168
+ type: input.type,
169
+ status: input.status ?? 'active',
170
+ });
171
+
172
+ // Track access if requested
173
+ if (input.trackAccess) {
174
+ await this.trackEntryAccess(entries);
175
+ }
176
+
177
+ return {
178
+ entries,
179
+ total,
180
+ hasMore: total > offset + limit,
181
+ searchType: 'filter',
182
+ };
183
+ }
184
+
185
+ private async trackEntryAccess(entries: MemoryEntry[]): Promise<void> {
186
+ for (const entry of entries) {
187
+ entry.recordAccess();
188
+ await this.repository.save(entry);
189
+ }
190
+ }
191
+ }
192
+
193
+ /**
194
+ * Get Memory By Key Query Input
195
+ */
196
+ export interface GetMemoryByKeyInput {
197
+ namespace: string;
198
+ key: string;
199
+ trackAccess?: boolean;
200
+ }
201
+
202
+ /**
203
+ * Get Memory By Key Query Result
204
+ */
205
+ export interface GetMemoryByKeyResult {
206
+ found: boolean;
207
+ entry?: MemoryEntry;
208
+ }
209
+
210
+ /**
211
+ * Get Memory By Key Query Handler
212
+ */
213
+ export class GetMemoryByKeyQueryHandler {
214
+ constructor(private readonly repository: IMemoryRepository) {}
215
+
216
+ async execute(input: GetMemoryByKeyInput): Promise<GetMemoryByKeyResult> {
217
+ const entry = await this.repository.findByKey(input.namespace, input.key);
218
+
219
+ if (!entry) {
220
+ return { found: false };
221
+ }
222
+
223
+ if (!entry.isAccessible()) {
224
+ return { found: false };
225
+ }
226
+
227
+ if (input.trackAccess) {
228
+ entry.recordAccess();
229
+ await this.repository.save(entry);
230
+ }
231
+
232
+ return {
233
+ found: true,
234
+ entry,
235
+ };
236
+ }
237
+ }