@prmichaelsen/remember-mcp 3.0.0 → 3.13.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.
- package/AGENT.md +296 -250
- package/CHANGELOG.md +358 -0
- package/README.md +68 -45
- package/agent/commands/acp.clarification-create.md +382 -0
- package/agent/commands/acp.project-info.md +309 -0
- package/agent/commands/acp.project-remove.md +379 -0
- package/agent/commands/acp.project-update.md +296 -0
- package/agent/commands/acp.task-create.md +17 -9
- package/agent/commands/git.commit.md +13 -1
- package/agent/design/comment-memory-type.md +2 -2
- package/agent/design/local.collaborative-memory-sync.md +265 -0
- package/agent/design/local.content-flags.md +210 -0
- package/agent/design/local.ghost-persona-system.md +273 -0
- package/agent/design/local.group-acl-integration.md +338 -0
- package/agent/design/local.memory-acl-schema.md +352 -0
- package/agent/design/local.memory-collection-pattern-v2.md +348 -0
- package/agent/design/local.moderation-and-space-config.md +257 -0
- package/agent/design/local.v2-api-reference.md +621 -0
- package/agent/design/local.v2-migration-guide.md +191 -0
- package/agent/design/local.v2-usage-examples.md +265 -0
- package/agent/design/permissions-storage-architecture.md +11 -3
- package/agent/design/trust-escalation-prevention.md +9 -2
- package/agent/design/trust-system-implementation.md +12 -3
- package/agent/milestones/milestone-14-memory-collection-v2.md +182 -0
- package/agent/milestones/milestone-15-moderation-space-config.md +126 -0
- package/agent/progress.yaml +628 -49
- package/agent/scripts/acp.common.sh +2 -0
- package/agent/scripts/acp.install.sh +11 -1
- package/agent/scripts/acp.package-install-optimized.sh +454 -0
- package/agent/scripts/acp.package-install.sh +247 -300
- package/agent/scripts/acp.project-info.sh +218 -0
- package/agent/scripts/acp.project-remove.sh +302 -0
- package/agent/scripts/acp.project-update.sh +296 -0
- package/agent/scripts/acp.yaml-parser.sh +128 -10
- package/agent/tasks/milestone-14-memory-collection-v2/task-165-core-infrastructure-setup.md +171 -0
- package/agent/tasks/milestone-14-memory-collection-v2/task-166-update-remember-publish.md +191 -0
- package/agent/tasks/milestone-14-memory-collection-v2/task-167-update-remember-retract.md +186 -0
- package/agent/tasks/milestone-14-memory-collection-v2/task-168-implement-remember-revise.md +184 -0
- package/agent/tasks/milestone-14-memory-collection-v2/task-169-update-remember-search-space.md +179 -0
- package/agent/tasks/milestone-14-memory-collection-v2/task-170-update-remember-create-update.md +139 -0
- package/agent/tasks/milestone-14-memory-collection-v2/task-172-performance-testing-optimization.md +161 -0
- package/agent/tasks/milestone-14-memory-collection-v2/task-173-documentation-examples.md +258 -0
- package/agent/tasks/milestone-15-moderation-space-config/task-174-add-moderation-schema-fields.md +57 -0
- package/agent/tasks/milestone-15-moderation-space-config/task-175-create-space-config-service.md +64 -0
- package/agent/tasks/milestone-15-moderation-space-config/task-176-wire-moderation-publish-flow.md +45 -0
- package/agent/tasks/milestone-15-moderation-space-config/task-177-add-moderation-search-filters.md +70 -0
- package/agent/tasks/milestone-15-moderation-space-config/task-178-create-remember-moderate-tool.md +69 -0
- package/agent/tasks/milestone-15-moderation-space-config/task-179-documentation-integration-tests.md +58 -0
- package/agent/tasks/milestone-16-ghost-system/task-187-ghost-config-firestore.md +41 -0
- package/agent/tasks/milestone-16-ghost-system/task-188-trust-filter-integration.md +44 -0
- package/agent/tasks/milestone-16-ghost-system/task-189-ghost-memory-filtering.md +43 -0
- package/agent/tasks/milestone-16-ghost-system/task-190-ghost-config-tools.md +45 -0
- package/agent/tasks/milestone-16-ghost-system/task-191-escalation-firestore.md +38 -0
- package/agent/tasks/milestone-16-ghost-system/task-192-documentation-verification.md +39 -0
- package/agent/tasks/milestone-7-trust-permissions/task-180-access-result-permission-types.md +69 -0
- package/agent/tasks/milestone-7-trust-permissions/task-181-firestore-permissions-access-logs.md +56 -0
- package/agent/tasks/milestone-7-trust-permissions/task-182-trust-enforcement-service.md +68 -0
- package/agent/tasks/milestone-7-trust-permissions/task-183-access-control-service.md +70 -0
- package/agent/tasks/milestone-7-trust-permissions/task-184-permission-tools.md +79 -0
- package/agent/tasks/milestone-7-trust-permissions/task-185-wire-trust-into-search-query.md +55 -0
- package/agent/tasks/milestone-7-trust-permissions/task-186-documentation-verification.md +56 -0
- package/agent/tasks/task-76-fix-indexnullstate-schema-bug.md +197 -0
- package/dist/collections/composite-ids.d.ts +106 -0
- package/dist/collections/core-infrastructure.spec.d.ts +11 -0
- package/dist/collections/dot-notation.d.ts +106 -0
- package/dist/collections/tracking-arrays.d.ts +176 -0
- package/dist/constants/content-types.d.ts +1 -0
- package/dist/schema/v2-collections-comments.spec.d.ts +8 -0
- package/dist/schema/v2-collections.d.ts +210 -0
- package/dist/server-factory.d.ts +15 -0
- package/dist/server-factory.js +2798 -1029
- package/dist/server.js +2526 -1012
- package/dist/services/access-control.d.ts +103 -0
- package/dist/services/access-control.spec.d.ts +2 -0
- package/dist/services/credentials-provider.d.ts +24 -0
- package/dist/services/credentials-provider.spec.d.ts +2 -0
- package/dist/services/escalation.service.d.ts +22 -0
- package/dist/services/escalation.service.spec.d.ts +2 -0
- package/dist/services/ghost-config.service.d.ts +55 -0
- package/dist/services/ghost-config.service.spec.d.ts +2 -0
- package/dist/services/space-config.service.d.ts +23 -0
- package/dist/services/space-config.service.spec.d.ts +2 -0
- package/dist/services/trust-enforcement.d.ts +83 -0
- package/dist/services/trust-enforcement.spec.d.ts +2 -0
- package/dist/services/trust-validator.d.ts +43 -0
- package/dist/services/trust-validator.spec.d.ts +2 -0
- package/dist/tools/confirm-publish-moderation.spec.d.ts +8 -0
- package/dist/tools/confirm.d.ts +8 -1
- package/dist/tools/create-memory.d.ts +2 -1
- package/dist/tools/create-memory.spec.d.ts +10 -0
- package/dist/tools/create-relationship.d.ts +2 -1
- package/dist/tools/delete-memory.d.ts +2 -1
- package/dist/tools/delete-relationship.d.ts +2 -1
- package/dist/tools/deny.d.ts +2 -1
- package/dist/tools/find-similar.d.ts +2 -1
- package/dist/tools/get-preferences.d.ts +2 -1
- package/dist/tools/ghost-config.d.ts +27 -0
- package/dist/tools/ghost-config.spec.d.ts +2 -0
- package/dist/tools/moderate.d.ts +20 -0
- package/dist/tools/moderate.spec.d.ts +5 -0
- package/dist/tools/publish.d.ts +11 -3
- package/dist/tools/query-memory.d.ts +3 -1
- package/dist/tools/query-space.d.ts +4 -1
- package/dist/tools/retract.d.ts +29 -0
- package/dist/tools/revise.d.ts +45 -0
- package/dist/tools/revise.spec.d.ts +8 -0
- package/dist/tools/search-memory.d.ts +2 -1
- package/dist/tools/search-relationship.d.ts +2 -1
- package/dist/tools/search-space.d.ts +25 -5
- package/dist/tools/search-space.spec.d.ts +9 -0
- package/dist/tools/set-preference.d.ts +2 -1
- package/dist/tools/update-memory.d.ts +2 -1
- package/dist/tools/update-relationship.d.ts +2 -1
- package/dist/types/access-result.d.ts +48 -0
- package/dist/types/access-result.spec.d.ts +2 -0
- package/dist/types/auth.d.ts +46 -0
- package/dist/types/ghost-config.d.ts +36 -0
- package/dist/types/memory.d.ts +3 -1
- package/dist/types/preferences.d.ts +1 -1
- package/dist/utils/auth-helpers.d.ts +14 -0
- package/dist/utils/auth-helpers.spec.d.ts +2 -0
- package/dist/utils/test-data-generator.d.ts +124 -0
- package/dist/utils/test-data-generator.spec.d.ts +12 -0
- package/dist/v2-performance.e2e.d.ts +17 -0
- package/dist/v2-smoke.e2e.d.ts +14 -0
- package/dist/weaviate/client.d.ts +5 -8
- package/dist/weaviate/space-schema.d.ts +2 -2
- package/docs/performance/v2-benchmarks.md +80 -0
- package/jest.e2e.config.js +14 -3
- package/package.json +1 -1
- package/scripts/.collection-recreation-state.yaml +16 -0
- package/scripts/.gitkeep +5 -0
- package/scripts/README-collection-recreation.md +224 -0
- package/scripts/README.md +51 -0
- package/scripts/backup-collections.ts +543 -0
- package/scripts/delete-collection.ts +137 -0
- package/scripts/migrate-recreate-collections.ts +578 -0
- package/scripts/migrate-v1-to-v2.ts +1094 -0
- package/scripts/package-lock.json +1113 -0
- package/scripts/package.json +27 -0
- package/src/collections/composite-ids.ts +193 -0
- package/src/collections/core-infrastructure.spec.ts +353 -0
- package/src/collections/dot-notation.ts +212 -0
- package/src/collections/tracking-arrays.ts +298 -0
- package/src/constants/content-types.ts +20 -0
- package/src/schema/v2-collections-comments.spec.ts +141 -0
- package/src/schema/v2-collections.ts +433 -0
- package/src/server-factory.ts +89 -20
- package/src/server.ts +45 -17
- package/src/services/access-control.spec.ts +383 -0
- package/src/services/access-control.ts +291 -0
- package/src/services/credentials-provider.spec.ts +22 -0
- package/src/services/credentials-provider.ts +34 -0
- package/src/services/escalation.service.spec.ts +183 -0
- package/src/services/escalation.service.ts +150 -0
- package/src/services/ghost-config.service.spec.ts +339 -0
- package/src/services/ghost-config.service.ts +219 -0
- package/src/services/space-config.service.spec.ts +102 -0
- package/src/services/space-config.service.ts +79 -0
- package/src/services/trust-enforcement.spec.ts +309 -0
- package/src/services/trust-enforcement.ts +197 -0
- package/src/services/trust-validator.spec.ts +108 -0
- package/src/services/trust-validator.ts +105 -0
- package/src/tools/confirm-publish-moderation.spec.ts +240 -0
- package/src/tools/confirm.ts +869 -135
- package/src/tools/create-memory.spec.ts +126 -0
- package/src/tools/create-memory.ts +20 -27
- package/src/tools/create-relationship.ts +17 -8
- package/src/tools/delete-memory.ts +13 -6
- package/src/tools/delete-relationship.ts +15 -6
- package/src/tools/deny.ts +8 -1
- package/src/tools/find-similar.ts +21 -8
- package/src/tools/get-preferences.ts +10 -1
- package/src/tools/ghost-config.spec.ts +180 -0
- package/src/tools/ghost-config.ts +230 -0
- package/src/tools/moderate.spec.ts +277 -0
- package/src/tools/moderate.ts +219 -0
- package/src/tools/publish.ts +99 -41
- package/src/tools/query-memory.ts +28 -6
- package/src/tools/query-space.ts +39 -4
- package/src/tools/retract.ts +292 -0
- package/src/tools/revise.spec.ts +146 -0
- package/src/tools/revise.ts +283 -0
- package/src/tools/search-memory.ts +30 -7
- package/src/tools/search-relationship.ts +11 -2
- package/src/tools/search-space.spec.ts +341 -0
- package/src/tools/search-space.ts +323 -99
- package/src/tools/set-preference.ts +10 -1
- package/src/tools/update-memory.ts +16 -5
- package/src/tools/update-relationship.ts +10 -1
- package/src/types/access-result.spec.ts +193 -0
- package/src/types/access-result.ts +62 -0
- package/src/types/auth.ts +52 -0
- package/src/types/ghost-config.ts +46 -0
- package/src/types/memory.ts +9 -1
- package/src/types/preferences.ts +2 -2
- package/src/utils/auth-helpers.spec.ts +75 -0
- package/src/utils/auth-helpers.ts +25 -0
- package/src/utils/test-data-generator.spec.ts +317 -0
- package/src/utils/test-data-generator.ts +292 -0
- package/src/utils/weaviate-filters.ts +4 -4
- package/src/v2-performance.e2e.ts +173 -0
- package/src/v2-smoke.e2e.ts +401 -0
- package/src/weaviate/client.spec.ts +5 -5
- package/src/weaviate/client.ts +51 -36
- package/src/weaviate/schema.ts +11 -256
- package/src/weaviate/space-schema.spec.ts +24 -24
- package/src/weaviate/space-schema.ts +18 -6
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "remember-mcp-scripts",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Migration and utility scripts for remember-mcp",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"private": true,
|
|
7
|
+
"scripts": {
|
|
8
|
+
"backup": "tsx backup-collections.ts",
|
|
9
|
+
"backup:dry-run": "tsx backup-collections.ts --dry-run",
|
|
10
|
+
"delete": "tsx delete-collection.ts",
|
|
11
|
+
"migrate:recreate": "tsx migrate-recreate-collections.ts",
|
|
12
|
+
"migrate:recreate:dry-run": "tsx migrate-recreate-collections.ts --dry-run",
|
|
13
|
+
"migrate:v1-to-v2": "tsx migrate-v1-to-v2.ts",
|
|
14
|
+
"migrate:v1-to-v2:dry-run": "tsx migrate-v1-to-v2.ts --dry-run",
|
|
15
|
+
"migrate:v1-to-v2:verify": "tsx migrate-v1-to-v2.ts --verify-only"
|
|
16
|
+
},
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"dotenv": "^16.4.5",
|
|
19
|
+
"weaviate-client": "^3.2.0",
|
|
20
|
+
"yaml": "^2.3.4"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@types/node": "^20.11.19",
|
|
24
|
+
"tsx": "^4.7.1",
|
|
25
|
+
"typescript": "^5.3.3"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Composite ID Utilities
|
|
3
|
+
*
|
|
4
|
+
* Provides utilities for working with composite IDs in Memory Collection Pattern v2.
|
|
5
|
+
* Composite IDs preserve the source reference when memories are published to spaces or groups.
|
|
6
|
+
*
|
|
7
|
+
* Format: {userId}.{memoryId}
|
|
8
|
+
* Example: "user123.my-recipe"
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Components of a composite ID
|
|
13
|
+
*/
|
|
14
|
+
export interface CompositeIdComponents {
|
|
15
|
+
userId: string
|
|
16
|
+
memoryId: string
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Error thrown when composite ID is invalid
|
|
21
|
+
*/
|
|
22
|
+
export class InvalidCompositeIdError extends Error {
|
|
23
|
+
constructor(message: string) {
|
|
24
|
+
super(message)
|
|
25
|
+
this.name = 'InvalidCompositeIdError'
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Generate a composite ID from user ID and memory ID
|
|
31
|
+
*
|
|
32
|
+
* @param userId - User ID (must not contain dots)
|
|
33
|
+
* @param memoryId - Memory ID (must not contain dots)
|
|
34
|
+
* @returns Composite ID in format {userId}.{memoryId}
|
|
35
|
+
* @throws {InvalidCompositeIdError} If userId or memoryId contains dots
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* generateCompositeId('user123', 'my-recipe')
|
|
39
|
+
* // Returns: 'user123.my-recipe'
|
|
40
|
+
*/
|
|
41
|
+
export function generateCompositeId(userId: string, memoryId: string): string {
|
|
42
|
+
// Validate that neither component contains dots
|
|
43
|
+
if (userId.includes('.')) {
|
|
44
|
+
throw new InvalidCompositeIdError(
|
|
45
|
+
`User ID cannot contain dots: ${userId}`
|
|
46
|
+
)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (memoryId.includes('.')) {
|
|
50
|
+
throw new InvalidCompositeIdError(
|
|
51
|
+
`Memory ID cannot contain dots: ${memoryId}`
|
|
52
|
+
)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Validate that components are not empty
|
|
56
|
+
if (!userId.trim()) {
|
|
57
|
+
throw new InvalidCompositeIdError('User ID cannot be empty')
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (!memoryId.trim()) {
|
|
61
|
+
throw new InvalidCompositeIdError('Memory ID cannot be empty')
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return `${userId}.${memoryId}`
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Parse a composite ID into its components
|
|
69
|
+
*
|
|
70
|
+
* @param compositeId - Composite ID to parse
|
|
71
|
+
* @returns Object with userId and memoryId
|
|
72
|
+
* @throws {InvalidCompositeIdError} If composite ID format is invalid
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* parseCompositeId('user123.my-recipe')
|
|
76
|
+
* // Returns: { userId: 'user123', memoryId: 'my-recipe' }
|
|
77
|
+
*/
|
|
78
|
+
export function parseCompositeId(compositeId: string): CompositeIdComponents {
|
|
79
|
+
// Split on first dot only (in case memoryId was generated with dashes that look like dots)
|
|
80
|
+
const parts = compositeId.split('.')
|
|
81
|
+
|
|
82
|
+
if (parts.length !== 2) {
|
|
83
|
+
throw new InvalidCompositeIdError(
|
|
84
|
+
`Invalid composite ID format: ${compositeId}. Composite ID must be exactly 2 parts separated by a dot. Expected format: {userId}.{memoryId}`
|
|
85
|
+
)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const [userId, memoryId] = parts
|
|
89
|
+
|
|
90
|
+
// Validate components are not empty
|
|
91
|
+
if (!userId.trim()) {
|
|
92
|
+
throw new InvalidCompositeIdError(
|
|
93
|
+
`Invalid composite ID: ${compositeId}. User ID is empty`
|
|
94
|
+
)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (!memoryId.trim()) {
|
|
98
|
+
throw new InvalidCompositeIdError(
|
|
99
|
+
`Invalid composite ID: ${compositeId}. Memory ID is empty`
|
|
100
|
+
)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return { userId, memoryId }
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Check if a string is a composite ID
|
|
108
|
+
*
|
|
109
|
+
* @param id - String to check
|
|
110
|
+
* @returns true if valid composite ID, false otherwise
|
|
111
|
+
*
|
|
112
|
+
* @example
|
|
113
|
+
* isCompositeId('user123.my-recipe') // true
|
|
114
|
+
* isCompositeId('simple-id') // false
|
|
115
|
+
* isCompositeId('too.many.dots') // false
|
|
116
|
+
*/
|
|
117
|
+
export function isCompositeId(id: string): boolean {
|
|
118
|
+
try {
|
|
119
|
+
parseCompositeId(id)
|
|
120
|
+
return true
|
|
121
|
+
} catch (error) {
|
|
122
|
+
if (error instanceof InvalidCompositeIdError) {
|
|
123
|
+
return false
|
|
124
|
+
}
|
|
125
|
+
throw error
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Validate a composite ID (returns true on valid, throws on invalid)
|
|
131
|
+
*
|
|
132
|
+
* @param id - Composite ID to validate
|
|
133
|
+
* @returns true if valid
|
|
134
|
+
* @throws {InvalidCompositeIdError} If composite ID is invalid
|
|
135
|
+
*
|
|
136
|
+
* @example
|
|
137
|
+
* validateCompositeId('user123.my-recipe') // Returns true
|
|
138
|
+
* validateCompositeId('invalid') // Throws InvalidCompositeIdError
|
|
139
|
+
*/
|
|
140
|
+
export function validateCompositeId(id: string): true {
|
|
141
|
+
parseCompositeId(id) // Will throw if invalid
|
|
142
|
+
return true
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Extract user ID from a composite ID
|
|
147
|
+
*
|
|
148
|
+
* @param compositeId - Composite ID
|
|
149
|
+
* @returns User ID component
|
|
150
|
+
*
|
|
151
|
+
* @example
|
|
152
|
+
* getUserIdFromComposite('user123.my-recipe')
|
|
153
|
+
* // Returns: 'user123'
|
|
154
|
+
*/
|
|
155
|
+
export function getUserIdFromComposite(compositeId: string): string {
|
|
156
|
+
const { userId } = parseCompositeId(compositeId)
|
|
157
|
+
return userId
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Extract memory ID from a composite ID
|
|
162
|
+
*
|
|
163
|
+
* @param compositeId - Composite ID
|
|
164
|
+
* @returns Memory ID component
|
|
165
|
+
*
|
|
166
|
+
* @example
|
|
167
|
+
* getMemoryIdFromComposite('user123.my-recipe')
|
|
168
|
+
* // Returns: 'my-recipe'
|
|
169
|
+
*/
|
|
170
|
+
export function getMemoryIdFromComposite(compositeId: string): string {
|
|
171
|
+
const { memoryId } = parseCompositeId(compositeId)
|
|
172
|
+
return memoryId
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Check if an ID belongs to a specific user
|
|
177
|
+
*
|
|
178
|
+
* @param compositeId - Composite ID to check
|
|
179
|
+
* @param userId - User ID to match
|
|
180
|
+
* @returns true if composite ID belongs to user, false otherwise
|
|
181
|
+
*
|
|
182
|
+
* @example
|
|
183
|
+
* belongsToUser('user123.my-recipe', 'user123') // true
|
|
184
|
+
* belongsToUser('user123.my-recipe', 'user456') // false
|
|
185
|
+
*/
|
|
186
|
+
export function belongsToUser(compositeId: string, userId: string): boolean {
|
|
187
|
+
try {
|
|
188
|
+
const { userId: idUserId } = parseCompositeId(compositeId)
|
|
189
|
+
return idUserId === userId
|
|
190
|
+
} catch {
|
|
191
|
+
return false
|
|
192
|
+
}
|
|
193
|
+
}
|
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for Memory Collection Pattern v2 Core Infrastructure
|
|
3
|
+
*
|
|
4
|
+
* Tests core functionality of:
|
|
5
|
+
* - Dot notation collection utilities
|
|
6
|
+
* - Composite ID utilities
|
|
7
|
+
* - Tracking array management
|
|
8
|
+
* - Schema definitions
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import {
|
|
12
|
+
CollectionType,
|
|
13
|
+
getCollectionName,
|
|
14
|
+
parseCollectionName,
|
|
15
|
+
validateCollectionName,
|
|
16
|
+
isUserCollection,
|
|
17
|
+
isSpacesCollection,
|
|
18
|
+
isGroupCollection,
|
|
19
|
+
} from './dot-notation.js';
|
|
20
|
+
|
|
21
|
+
import {
|
|
22
|
+
generateCompositeId,
|
|
23
|
+
parseCompositeId,
|
|
24
|
+
isCompositeId,
|
|
25
|
+
validateCompositeId,
|
|
26
|
+
} from './composite-ids.js';
|
|
27
|
+
|
|
28
|
+
import {
|
|
29
|
+
addToSpaceIds,
|
|
30
|
+
removeFromSpaceIds,
|
|
31
|
+
addToGroupIds,
|
|
32
|
+
removeFromGroupIds,
|
|
33
|
+
isPublishedToSpace,
|
|
34
|
+
isPublishedToGroup,
|
|
35
|
+
getPublishedLocations,
|
|
36
|
+
isPublished,
|
|
37
|
+
getPublishedCount,
|
|
38
|
+
initializeTracking,
|
|
39
|
+
addMultipleSpaceIds,
|
|
40
|
+
addMultipleGroupIds,
|
|
41
|
+
type MemoryWithTracking,
|
|
42
|
+
} from './tracking-arrays.js';
|
|
43
|
+
|
|
44
|
+
import {
|
|
45
|
+
createUserCollectionSchema,
|
|
46
|
+
createSpaceCollectionSchema,
|
|
47
|
+
createGroupCollectionSchema,
|
|
48
|
+
getUserCollectionProperties,
|
|
49
|
+
getPublishedCollectionProperties,
|
|
50
|
+
validateV2CollectionName,
|
|
51
|
+
getCollectionType,
|
|
52
|
+
extractIdFromCollectionName,
|
|
53
|
+
} from '../schema/v2-collections.js';
|
|
54
|
+
|
|
55
|
+
// ============================================================================
|
|
56
|
+
// Dot Notation Collection Utilities Tests
|
|
57
|
+
// ============================================================================
|
|
58
|
+
|
|
59
|
+
describe('Dot Notation Collection Utilities', () => {
|
|
60
|
+
describe('getCollectionName', () => {
|
|
61
|
+
it('should generate user collection name', () => {
|
|
62
|
+
expect(getCollectionName(CollectionType.USERS, 'user123')).toBe('Memory_users_user123');
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('should generate spaces collection name', () => {
|
|
66
|
+
expect(getCollectionName(CollectionType.SPACES)).toBe('Memory_spaces_public');
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('should generate group collection name', () => {
|
|
70
|
+
expect(getCollectionName(CollectionType.GROUPS, 'group456')).toBe('Memory_groups_group456');
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('should throw error for user collection without ID', () => {
|
|
74
|
+
expect(() => getCollectionName(CollectionType.USERS)).toThrow('User ID is required');
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('should throw error for ID with invalid characters', () => {
|
|
78
|
+
expect(() => getCollectionName(CollectionType.USERS, 'user.123')).toThrow();
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
describe('parseCollectionName', () => {
|
|
83
|
+
it('should parse user collection name', () => {
|
|
84
|
+
const result = parseCollectionName('Memory_users_user123');
|
|
85
|
+
expect(result.type).toBe(CollectionType.USERS);
|
|
86
|
+
expect(result.id).toBe('user123');
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('should parse spaces collection name', () => {
|
|
90
|
+
const result = parseCollectionName('Memory_spaces_public');
|
|
91
|
+
expect(result.type).toBe(CollectionType.SPACES);
|
|
92
|
+
expect(result.id).toBeUndefined();
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it('should parse group collection name', () => {
|
|
96
|
+
const result = parseCollectionName('Memory_groups_group456');
|
|
97
|
+
expect(result.type).toBe(CollectionType.GROUPS);
|
|
98
|
+
expect(result.id).toBe('group456');
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
describe('Collection type checkers', () => {
|
|
103
|
+
it('should identify user collections', () => {
|
|
104
|
+
expect(isUserCollection('Memory_users_user123')).toBe(true);
|
|
105
|
+
expect(isUserCollection('Memory_spaces_public')).toBe(false);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it('should identify spaces collection', () => {
|
|
109
|
+
expect(isSpacesCollection('Memory_spaces_public')).toBe(true);
|
|
110
|
+
expect(isSpacesCollection('Memory_users_user123')).toBe(false);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it('should identify group collections', () => {
|
|
114
|
+
expect(isGroupCollection('Memory_groups_group456')).toBe(true);
|
|
115
|
+
expect(isGroupCollection('Memory_users_user123')).toBe(false);
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
// ============================================================================
|
|
121
|
+
// Composite ID Utilities Tests
|
|
122
|
+
// ============================================================================
|
|
123
|
+
|
|
124
|
+
describe('Composite ID Utilities', () => {
|
|
125
|
+
describe('generateCompositeId', () => {
|
|
126
|
+
it('should generate composite ID', () => {
|
|
127
|
+
expect(generateCompositeId('user123', 'my-recipe')).toBe('user123.my-recipe');
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it('should throw error for userId with dots', () => {
|
|
131
|
+
expect(() => generateCompositeId('user.123', 'recipe')).toThrow('cannot contain dots');
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it('should throw error for empty userId', () => {
|
|
135
|
+
expect(() => generateCompositeId('', 'recipe')).toThrow('cannot be empty');
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
describe('parseCompositeId', () => {
|
|
140
|
+
it('should parse composite ID', () => {
|
|
141
|
+
const result = parseCompositeId('user123.my-recipe');
|
|
142
|
+
expect(result.userId).toBe('user123');
|
|
143
|
+
expect(result.memoryId).toBe('my-recipe');
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
it('should throw error for invalid format', () => {
|
|
147
|
+
expect(() => parseCompositeId('invalid')).toThrow('must be exactly 2 parts');
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
describe('isCompositeId', () => {
|
|
152
|
+
it('should identify valid composite IDs', () => {
|
|
153
|
+
expect(isCompositeId('user123.my-recipe')).toBe(true);
|
|
154
|
+
expect(isCompositeId('simple-id')).toBe(false);
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
describe('validateCompositeId', () => {
|
|
159
|
+
it('should validate correct composite IDs', () => {
|
|
160
|
+
expect(validateCompositeId('user123.my-recipe')).toBe(true);
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
it('should throw error for invalid IDs', () => {
|
|
164
|
+
expect(() => validateCompositeId('invalid')).toThrow();
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
// ============================================================================
|
|
170
|
+
// Tracking Array Management Tests
|
|
171
|
+
// ============================================================================
|
|
172
|
+
|
|
173
|
+
describe('Tracking Array Management', () => {
|
|
174
|
+
describe('addToSpaceIds', () => {
|
|
175
|
+
it('should add space ID to existing arrays', () => {
|
|
176
|
+
const memory: MemoryWithTracking = { space_ids: [], group_ids: [] };
|
|
177
|
+
const result = addToSpaceIds(memory, 'cooking');
|
|
178
|
+
expect(result.space_ids).toEqual(['cooking']);
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
it('should not add duplicate space IDs', () => {
|
|
182
|
+
const memory: MemoryWithTracking = { space_ids: ['cooking'], group_ids: [] };
|
|
183
|
+
const result = addToSpaceIds(memory, 'cooking');
|
|
184
|
+
expect(result.space_ids).toEqual(['cooking']);
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
it('should be immutable', () => {
|
|
188
|
+
const memory: MemoryWithTracking = { space_ids: ['cooking'], group_ids: [] };
|
|
189
|
+
const result = addToSpaceIds(memory, 'recipes');
|
|
190
|
+
expect(memory.space_ids).toEqual(['cooking']); // Original unchanged
|
|
191
|
+
expect(result.space_ids).toEqual(['cooking', 'recipes']);
|
|
192
|
+
});
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
describe('removeFromSpaceIds', () => {
|
|
196
|
+
it('should remove space ID', () => {
|
|
197
|
+
const memory: MemoryWithTracking = { space_ids: ['cooking', 'recipes'], group_ids: [] };
|
|
198
|
+
const result = removeFromSpaceIds(memory, 'cooking');
|
|
199
|
+
expect(result.space_ids).toEqual(['recipes']);
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
describe('addToGroupIds', () => {
|
|
204
|
+
it('should add group ID', () => {
|
|
205
|
+
const memory: MemoryWithTracking = { space_ids: [], group_ids: ['family'] };
|
|
206
|
+
const result = addToGroupIds(memory, 'friends');
|
|
207
|
+
expect(result.group_ids).toEqual(['family', 'friends']);
|
|
208
|
+
});
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
describe('removeFromGroupIds', () => {
|
|
212
|
+
it('should remove group ID', () => {
|
|
213
|
+
const memory: MemoryWithTracking = { space_ids: [], group_ids: ['family', 'friends'] };
|
|
214
|
+
const result = removeFromGroupIds(memory, 'family');
|
|
215
|
+
expect(result.group_ids).toEqual(['friends']);
|
|
216
|
+
});
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
describe('Publication checks', () => {
|
|
220
|
+
it('should check if published to space', () => {
|
|
221
|
+
const memory: MemoryWithTracking = { space_ids: ['cooking'], group_ids: [] };
|
|
222
|
+
expect(isPublishedToSpace(memory, 'cooking')).toBe(true);
|
|
223
|
+
expect(isPublishedToSpace(memory, 'travel')).toBe(false);
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
it('should check if published to group', () => {
|
|
227
|
+
const memory: MemoryWithTracking = { space_ids: [], group_ids: ['family'] };
|
|
228
|
+
expect(isPublishedToGroup(memory, 'family')).toBe(true);
|
|
229
|
+
expect(isPublishedToGroup(memory, 'coworkers')).toBe(false);
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
it('should get publication locations', () => {
|
|
233
|
+
const memory: MemoryWithTracking = { space_ids: ['cooking'], group_ids: ['family'] };
|
|
234
|
+
const result = getPublishedLocations(memory);
|
|
235
|
+
expect(result).toEqual({ spaces: ['cooking'], groups: ['family'] });
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
it('should check if published anywhere', () => {
|
|
239
|
+
const memory1: MemoryWithTracking = { space_ids: ['cooking'], group_ids: [] };
|
|
240
|
+
expect(isPublished(memory1)).toBe(true);
|
|
241
|
+
|
|
242
|
+
const memory2: MemoryWithTracking = { space_ids: [], group_ids: [] };
|
|
243
|
+
expect(isPublished(memory2)).toBe(false);
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
it('should count publications', () => {
|
|
247
|
+
const memory: MemoryWithTracking = { space_ids: ['cooking', 'recipes'], group_ids: ['family'] };
|
|
248
|
+
expect(getPublishedCount(memory)).toBe(3);
|
|
249
|
+
});
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
describe('Batch operations', () => {
|
|
253
|
+
it('should add multiple space IDs', () => {
|
|
254
|
+
const memory: MemoryWithTracking = { space_ids: ['cooking'], group_ids: [] };
|
|
255
|
+
const result = addMultipleSpaceIds(memory, ['recipes', 'baking']);
|
|
256
|
+
expect(result.space_ids).toEqual(['cooking', 'recipes', 'baking']);
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
it('should add multiple group IDs', () => {
|
|
260
|
+
const memory: MemoryWithTracking = { space_ids: [], group_ids: ['family'] };
|
|
261
|
+
const result = addMultipleGroupIds(memory, ['friends', 'coworkers']);
|
|
262
|
+
expect(result.group_ids).toEqual(['family', 'friends', 'coworkers']);
|
|
263
|
+
});
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
describe('Utility functions', () => {
|
|
267
|
+
it('should initialize tracking arrays', () => {
|
|
268
|
+
const memory = { content: 'My recipe' };
|
|
269
|
+
const result = initializeTracking(memory);
|
|
270
|
+
expect(result.space_ids).toEqual([]);
|
|
271
|
+
expect(result.group_ids).toEqual([]);
|
|
272
|
+
});
|
|
273
|
+
});
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
// ============================================================================
|
|
277
|
+
// Schema Definitions Tests
|
|
278
|
+
// ============================================================================
|
|
279
|
+
|
|
280
|
+
describe('Schema Definitions', () => {
|
|
281
|
+
describe('Schema creation', () => {
|
|
282
|
+
it('should create user collection schema', () => {
|
|
283
|
+
const schema = createUserCollectionSchema('user123');
|
|
284
|
+
expect(schema.name).toBe('Memory_users_user123');
|
|
285
|
+
expect(schema.description).toContain('user123');
|
|
286
|
+
expect(schema.properties).toBeDefined();
|
|
287
|
+
expect(schema.vectorizers).toBeDefined();
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
it('should create space collection schema', () => {
|
|
291
|
+
const schema = createSpaceCollectionSchema();
|
|
292
|
+
expect(schema.name).toBe('Memory_spaces_public');
|
|
293
|
+
expect(schema.properties).toBeDefined();
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
it('should create group collection schema', () => {
|
|
297
|
+
const schema = createGroupCollectionSchema('group456');
|
|
298
|
+
expect(schema.name).toBe('Memory_groups_group456');
|
|
299
|
+
expect(schema.properties).toBeDefined();
|
|
300
|
+
});
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
describe('Property lists', () => {
|
|
304
|
+
it('should get user collection properties', () => {
|
|
305
|
+
const props = getUserCollectionProperties();
|
|
306
|
+
expect(props).not.toContain('id'); // 'id' is reserved by Weaviate
|
|
307
|
+
expect(props).toContain('content');
|
|
308
|
+
expect(props).toContain('space_ids');
|
|
309
|
+
expect(props).toContain('group_ids');
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
it('should get published collection properties', () => {
|
|
313
|
+
const props = getPublishedCollectionProperties();
|
|
314
|
+
expect(props).not.toContain('id'); // 'id' is reserved by Weaviate
|
|
315
|
+
expect(props).toContain('published_at');
|
|
316
|
+
expect(props).toContain('author_id');
|
|
317
|
+
});
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
describe('Collection name validation', () => {
|
|
321
|
+
it('should validate v2 collection names', () => {
|
|
322
|
+
expect(validateV2CollectionName('Memory_users_user123')).toBe(true);
|
|
323
|
+
expect(validateV2CollectionName('Memory_spaces_public')).toBe(true);
|
|
324
|
+
expect(validateV2CollectionName('Memory_groups_group456')).toBe(true);
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
it('should reject invalid collection names', () => {
|
|
328
|
+
expect(() => validateV2CollectionName('InvalidName')).toThrow('Invalid v2 collection name');
|
|
329
|
+
});
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
describe('Collection type detection', () => {
|
|
333
|
+
it('should detect collection types', () => {
|
|
334
|
+
expect(getCollectionType('Memory_users_user123')).toBe('users');
|
|
335
|
+
expect(getCollectionType('Memory_spaces_public')).toBe('spaces');
|
|
336
|
+
expect(getCollectionType('Memory_groups_group456')).toBe('groups');
|
|
337
|
+
});
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
describe('ID extraction', () => {
|
|
341
|
+
it('should extract user ID', () => {
|
|
342
|
+
expect(extractIdFromCollectionName('Memory_users_user123')).toBe('user123');
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
it('should extract group ID', () => {
|
|
346
|
+
expect(extractIdFromCollectionName('Memory_groups_group456')).toBe('group456');
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
it('should return null for spaces collection', () => {
|
|
350
|
+
expect(extractIdFromCollectionName('Memory_spaces_public')).toBeNull();
|
|
351
|
+
});
|
|
352
|
+
});
|
|
353
|
+
});
|