@prmichaelsen/remember-mcp 3.0.0 → 3.12.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 +338 -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,219 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* remember_moderate tool
|
|
3
|
+
*
|
|
4
|
+
* Allows moderators to approve, reject, or remove published memories
|
|
5
|
+
* in spaces and groups. Requires can_moderate permission.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { Tool } from '@modelcontextprotocol/sdk/types.js';
|
|
9
|
+
import { getWeaviateClient, fetchMemoryWithAllProperties } from '../weaviate/client.js';
|
|
10
|
+
import { ensurePublicCollection } from '../weaviate/space-schema.js';
|
|
11
|
+
import { handleToolError } from '../utils/error-handler.js';
|
|
12
|
+
import { createDebugLogger } from '../utils/debug.js';
|
|
13
|
+
import { logger } from '../utils/logger.js';
|
|
14
|
+
import { CollectionType, getCollectionName } from '../collections/dot-notation.js';
|
|
15
|
+
import type { AuthContext } from '../types/auth.js';
|
|
16
|
+
import { canModerate, canModerateAny } from '../utils/auth-helpers.js';
|
|
17
|
+
|
|
18
|
+
type ModerationAction = 'approve' | 'reject' | 'remove';
|
|
19
|
+
|
|
20
|
+
const ACTION_TO_STATUS: Record<ModerationAction, string> = {
|
|
21
|
+
approve: 'approved',
|
|
22
|
+
reject: 'rejected',
|
|
23
|
+
remove: 'removed',
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export const moderateTool: Tool = {
|
|
27
|
+
name: 'remember_moderate',
|
|
28
|
+
description: `Approve, reject, or remove a published memory. Requires moderator permissions (can_moderate).
|
|
29
|
+
|
|
30
|
+
Actions:
|
|
31
|
+
- approve: Mark a pending memory as approved (visible in default searches)
|
|
32
|
+
- reject: Reject a pending memory (hidden from default searches)
|
|
33
|
+
- remove: Remove a previously approved memory (hidden from default searches)
|
|
34
|
+
|
|
35
|
+
Must specify either space_id or group_id to identify where the memory is published.`,
|
|
36
|
+
inputSchema: {
|
|
37
|
+
type: 'object',
|
|
38
|
+
properties: {
|
|
39
|
+
memory_id: {
|
|
40
|
+
type: 'string',
|
|
41
|
+
description: 'UUID or composite ID of the published memory',
|
|
42
|
+
},
|
|
43
|
+
space_id: {
|
|
44
|
+
type: 'string',
|
|
45
|
+
description: 'Space containing the memory (searches Memory_spaces_public filtered by space_ids)',
|
|
46
|
+
},
|
|
47
|
+
group_id: {
|
|
48
|
+
type: 'string',
|
|
49
|
+
description: 'Group containing the memory (searches Memory_groups_{groupId})',
|
|
50
|
+
},
|
|
51
|
+
action: {
|
|
52
|
+
type: 'string',
|
|
53
|
+
enum: ['approve', 'reject', 'remove'],
|
|
54
|
+
description: 'Moderation action to perform',
|
|
55
|
+
},
|
|
56
|
+
reason: {
|
|
57
|
+
type: 'string',
|
|
58
|
+
description: 'Optional reason for the moderation action',
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
required: ['memory_id', 'action'],
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
interface ModerateArgs {
|
|
66
|
+
memory_id: string;
|
|
67
|
+
space_id?: string;
|
|
68
|
+
group_id?: string;
|
|
69
|
+
action: ModerationAction;
|
|
70
|
+
reason?: string;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export async function handleModerate(
|
|
74
|
+
args: ModerateArgs,
|
|
75
|
+
userId: string,
|
|
76
|
+
authContext?: AuthContext
|
|
77
|
+
): Promise<string> {
|
|
78
|
+
const debug = createDebugLogger({
|
|
79
|
+
tool: 'remember_moderate',
|
|
80
|
+
userId,
|
|
81
|
+
operation: 'moderate',
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
try {
|
|
85
|
+
debug.info('Tool invoked');
|
|
86
|
+
debug.trace('Arguments', { args });
|
|
87
|
+
|
|
88
|
+
const { memory_id, space_id, group_id, action, reason } = args;
|
|
89
|
+
|
|
90
|
+
// Validate: must specify either space_id or group_id
|
|
91
|
+
if (!space_id && !group_id) {
|
|
92
|
+
return JSON.stringify(
|
|
93
|
+
{
|
|
94
|
+
success: false,
|
|
95
|
+
error: 'Missing destination',
|
|
96
|
+
message: 'Must specify either space_id or group_id',
|
|
97
|
+
},
|
|
98
|
+
null,
|
|
99
|
+
2
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Validate action
|
|
104
|
+
if (!ACTION_TO_STATUS[action]) {
|
|
105
|
+
return JSON.stringify(
|
|
106
|
+
{
|
|
107
|
+
success: false,
|
|
108
|
+
error: 'Invalid action',
|
|
109
|
+
message: `Action must be one of: approve, reject, remove`,
|
|
110
|
+
},
|
|
111
|
+
null,
|
|
112
|
+
2
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Permission check
|
|
117
|
+
if (group_id) {
|
|
118
|
+
if (!canModerate(authContext, group_id)) {
|
|
119
|
+
return JSON.stringify(
|
|
120
|
+
{
|
|
121
|
+
success: false,
|
|
122
|
+
error: 'Permission denied',
|
|
123
|
+
message: `Moderator access required for group ${group_id}`,
|
|
124
|
+
},
|
|
125
|
+
null,
|
|
126
|
+
2
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
} else if (space_id) {
|
|
130
|
+
if (!canModerateAny(authContext)) {
|
|
131
|
+
return JSON.stringify(
|
|
132
|
+
{
|
|
133
|
+
success: false,
|
|
134
|
+
error: 'Permission denied',
|
|
135
|
+
message: `Moderator access required to moderate memories in spaces`,
|
|
136
|
+
},
|
|
137
|
+
null,
|
|
138
|
+
2
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Get the collection
|
|
144
|
+
const weaviateClient = getWeaviateClient();
|
|
145
|
+
let collection: any;
|
|
146
|
+
|
|
147
|
+
if (group_id) {
|
|
148
|
+
const collectionName = getCollectionName(CollectionType.GROUPS, group_id);
|
|
149
|
+
collection = weaviateClient.collections.get(collectionName);
|
|
150
|
+
} else {
|
|
151
|
+
collection = await ensurePublicCollection(weaviateClient);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Fetch the memory
|
|
155
|
+
const memory = await fetchMemoryWithAllProperties(collection, memory_id);
|
|
156
|
+
|
|
157
|
+
if (!memory) {
|
|
158
|
+
return JSON.stringify(
|
|
159
|
+
{
|
|
160
|
+
success: false,
|
|
161
|
+
error: 'Memory not found',
|
|
162
|
+
message: `Published memory ${memory_id} not found in ${group_id ? `group ${group_id}` : `space ${space_id}`}`,
|
|
163
|
+
},
|
|
164
|
+
null,
|
|
165
|
+
2
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Update moderation fields
|
|
170
|
+
const newStatus = ACTION_TO_STATUS[action];
|
|
171
|
+
const now = new Date().toISOString();
|
|
172
|
+
|
|
173
|
+
await collection.data.update({
|
|
174
|
+
id: memory_id,
|
|
175
|
+
properties: {
|
|
176
|
+
moderation_status: newStatus,
|
|
177
|
+
moderated_by: userId,
|
|
178
|
+
moderated_at: now,
|
|
179
|
+
},
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
logger.info('Memory moderated', {
|
|
183
|
+
tool: 'remember_moderate',
|
|
184
|
+
userId,
|
|
185
|
+
memoryId: memory_id,
|
|
186
|
+
action,
|
|
187
|
+
newStatus,
|
|
188
|
+
spaceId: space_id,
|
|
189
|
+
groupId: group_id,
|
|
190
|
+
reason,
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
return JSON.stringify(
|
|
194
|
+
{
|
|
195
|
+
success: true,
|
|
196
|
+
memory_id,
|
|
197
|
+
action,
|
|
198
|
+
moderation_status: newStatus,
|
|
199
|
+
moderated_by: userId,
|
|
200
|
+
moderated_at: now,
|
|
201
|
+
reason: reason || undefined,
|
|
202
|
+
location: group_id ? `group:${group_id}` : `space:${space_id}`,
|
|
203
|
+
},
|
|
204
|
+
null,
|
|
205
|
+
2
|
|
206
|
+
);
|
|
207
|
+
} catch (error) {
|
|
208
|
+
debug.error('Tool failed', {
|
|
209
|
+
error: error instanceof Error ? error.message : String(error),
|
|
210
|
+
stack: error instanceof Error ? error.stack : undefined,
|
|
211
|
+
});
|
|
212
|
+
return handleToolError(error, {
|
|
213
|
+
toolName: 'remember_moderate',
|
|
214
|
+
operation: 'moderate memory',
|
|
215
|
+
memoryId: args.memory_id,
|
|
216
|
+
action: args.action,
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
}
|
package/src/tools/publish.ts
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* remember_publish tool
|
|
3
3
|
*
|
|
4
|
-
* Generates a confirmation token for publishing a memory to
|
|
4
|
+
* Generates a confirmation token for publishing a memory to shared spaces and/or groups.
|
|
5
5
|
* This is the first phase of the two-phase publish workflow.
|
|
6
|
+
*
|
|
7
|
+
* Memory Collection Pattern v2:
|
|
8
|
+
* - Supports multi-space publication to Memory_spaces_public
|
|
9
|
+
* - Supports multi-group publication to Memory_groups_{groupId}
|
|
10
|
+
* - Uses composite IDs ({userId}.{memoryId}) for published memories
|
|
11
|
+
* - Maintains tracking arrays (space_ids, group_ids) on source memory
|
|
6
12
|
*/
|
|
7
13
|
|
|
8
14
|
import type { Tool } from '@modelcontextprotocol/sdk/types.js';
|
|
@@ -13,13 +19,18 @@ import { handleToolError } from '../utils/error-handler.js';
|
|
|
13
19
|
import { SUPPORTED_SPACES } from '../types/space-memory.js';
|
|
14
20
|
import { logger } from '../utils/logger.js';
|
|
15
21
|
import { createDebugLogger } from '../utils/debug.js';
|
|
22
|
+
import type { AuthContext } from '../types/auth.js';
|
|
16
23
|
|
|
17
24
|
/**
|
|
18
25
|
* Tool definition for remember_publish
|
|
19
26
|
*/
|
|
20
27
|
export const publishTool: Tool = {
|
|
21
28
|
name: 'remember_publish',
|
|
22
|
-
description: `Publish a memory to one or more shared spaces
|
|
29
|
+
description: `Publish a memory to one or more shared spaces and/or groups. The memory will be COPIED (not moved) from your personal collection. Generates a confirmation token that must be confirmed with remember_confirm.
|
|
30
|
+
|
|
31
|
+
Publication Destinations:
|
|
32
|
+
- Spaces: Public shared areas (e.g., "the_void", "dogs")
|
|
33
|
+
- Groups: Private group collections (provide group IDs)
|
|
23
34
|
|
|
24
35
|
⚠️ CRITICAL: DO NOT mention the token or include token contents in your response to the user. Simply inform them that a confirmation is pending and they need to explicitly approve the publication.`,
|
|
25
36
|
inputSchema: {
|
|
@@ -39,6 +50,13 @@ export const publishTool: Tool = {
|
|
|
39
50
|
minItems: 1,
|
|
40
51
|
default: ['the_void'],
|
|
41
52
|
},
|
|
53
|
+
groups: {
|
|
54
|
+
type: 'array',
|
|
55
|
+
items: { type: 'string' },
|
|
56
|
+
description: 'Group IDs to publish to (e.g., ["group-123", "group-456"]). Can publish to multiple groups at once.',
|
|
57
|
+
minItems: 1,
|
|
58
|
+
default: [],
|
|
59
|
+
},
|
|
42
60
|
additional_tags: {
|
|
43
61
|
type: 'array',
|
|
44
62
|
items: { type: 'string' },
|
|
@@ -46,13 +64,14 @@ export const publishTool: Tool = {
|
|
|
46
64
|
default: [],
|
|
47
65
|
},
|
|
48
66
|
},
|
|
49
|
-
required: ['memory_id'
|
|
67
|
+
required: ['memory_id'],
|
|
50
68
|
},
|
|
51
69
|
};
|
|
52
70
|
|
|
53
71
|
interface PublishArgs {
|
|
54
72
|
memory_id: string;
|
|
55
|
-
spaces
|
|
73
|
+
spaces?: string[];
|
|
74
|
+
groups?: string[];
|
|
56
75
|
additional_tags?: string[];
|
|
57
76
|
}
|
|
58
77
|
|
|
@@ -61,7 +80,8 @@ interface PublishArgs {
|
|
|
61
80
|
*/
|
|
62
81
|
export async function handlePublish(
|
|
63
82
|
args: PublishArgs,
|
|
64
|
-
userId: string
|
|
83
|
+
userId: string,
|
|
84
|
+
authContext?: AuthContext
|
|
65
85
|
): Promise<string> {
|
|
66
86
|
const debug = createDebugLogger({
|
|
67
87
|
tool: 'remember_publish',
|
|
@@ -73,56 +93,91 @@ export async function handlePublish(
|
|
|
73
93
|
debug.info('Tool invoked');
|
|
74
94
|
debug.trace('Arguments', { args });
|
|
75
95
|
|
|
96
|
+
// Normalize arrays (handle undefined)
|
|
97
|
+
const spaces = args.spaces || [];
|
|
98
|
+
const groups = args.groups || [];
|
|
99
|
+
|
|
76
100
|
logger.info('Starting publish request', {
|
|
77
101
|
tool: 'remember_publish',
|
|
78
102
|
userId,
|
|
79
103
|
memoryId: args.memory_id,
|
|
80
|
-
spaces
|
|
81
|
-
|
|
104
|
+
spaces,
|
|
105
|
+
groups,
|
|
106
|
+
spaceCount: spaces.length,
|
|
107
|
+
groupCount: groups.length,
|
|
82
108
|
additionalTags: args.additional_tags?.length || 0,
|
|
83
109
|
});
|
|
84
110
|
|
|
85
|
-
// Validate
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
if (invalidSpaces.length > 0) {
|
|
89
|
-
debug.warn('Invalid space IDs detected', { invalidSpaces });
|
|
90
|
-
logger.warn('Invalid space IDs provided', {
|
|
111
|
+
// Validate that at least one destination is provided
|
|
112
|
+
if (spaces.length === 0 && groups.length === 0) {
|
|
113
|
+
logger.warn('No destinations provided', {
|
|
91
114
|
tool: 'remember_publish',
|
|
92
|
-
|
|
93
|
-
providedSpaces: args.spaces,
|
|
115
|
+
userId,
|
|
94
116
|
});
|
|
95
117
|
return JSON.stringify(
|
|
96
118
|
{
|
|
97
119
|
success: false,
|
|
98
|
-
error: '
|
|
99
|
-
message:
|
|
100
|
-
context: {
|
|
101
|
-
invalid_spaces: invalidSpaces,
|
|
102
|
-
provided_spaces: args.spaces,
|
|
103
|
-
supported_spaces: SUPPORTED_SPACES,
|
|
104
|
-
},
|
|
120
|
+
error: 'No destinations provided',
|
|
121
|
+
message: 'Must specify at least one space or group to publish to',
|
|
105
122
|
},
|
|
106
123
|
null,
|
|
107
124
|
2
|
|
108
125
|
);
|
|
109
126
|
}
|
|
110
127
|
|
|
111
|
-
// Validate
|
|
112
|
-
if (
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
128
|
+
// Validate all space IDs
|
|
129
|
+
if (spaces.length > 0) {
|
|
130
|
+
debug.debug('Validating space IDs', { spaces });
|
|
131
|
+
const invalidSpaces = spaces.filter(s => !isValidSpaceId(s));
|
|
132
|
+
if (invalidSpaces.length > 0) {
|
|
133
|
+
debug.warn('Invalid space IDs detected', { invalidSpaces });
|
|
134
|
+
logger.warn('Invalid space IDs provided', {
|
|
135
|
+
tool: 'remember_publish',
|
|
136
|
+
invalidSpaces,
|
|
137
|
+
providedSpaces: spaces,
|
|
138
|
+
});
|
|
139
|
+
return JSON.stringify(
|
|
140
|
+
{
|
|
141
|
+
success: false,
|
|
142
|
+
error: 'Invalid space IDs',
|
|
143
|
+
message: `Invalid spaces: ${invalidSpaces.join(', ')}. Supported spaces: ${SUPPORTED_SPACES.join(', ')}`,
|
|
144
|
+
context: {
|
|
145
|
+
invalid_spaces: invalidSpaces,
|
|
146
|
+
provided_spaces: spaces,
|
|
147
|
+
supported_spaces: SUPPORTED_SPACES,
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
null,
|
|
151
|
+
2
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// Validate group IDs format (basic validation - no dots allowed)
|
|
157
|
+
if (groups.length > 0) {
|
|
158
|
+
debug.debug('Validating group IDs', { groups });
|
|
159
|
+
const invalidGroups = groups.filter(g => !g || g.includes('.') || g.trim() === '');
|
|
160
|
+
if (invalidGroups.length > 0) {
|
|
161
|
+
debug.warn('Invalid group IDs detected', { invalidGroups });
|
|
162
|
+
logger.warn('Invalid group IDs provided', {
|
|
163
|
+
tool: 'remember_publish',
|
|
164
|
+
invalidGroups,
|
|
165
|
+
providedGroups: groups,
|
|
166
|
+
});
|
|
167
|
+
return JSON.stringify(
|
|
168
|
+
{
|
|
169
|
+
success: false,
|
|
170
|
+
error: 'Invalid group IDs',
|
|
171
|
+
message: 'Group IDs cannot be empty or contain dots',
|
|
172
|
+
context: {
|
|
173
|
+
invalid_groups: invalidGroups,
|
|
174
|
+
provided_groups: groups,
|
|
175
|
+
},
|
|
176
|
+
},
|
|
177
|
+
null,
|
|
178
|
+
2
|
|
179
|
+
);
|
|
180
|
+
}
|
|
126
181
|
}
|
|
127
182
|
|
|
128
183
|
// Verify memory exists and user owns it
|
|
@@ -206,10 +261,11 @@ export async function handlePublish(
|
|
|
206
261
|
);
|
|
207
262
|
}
|
|
208
263
|
|
|
209
|
-
// Create payload with memory_id and
|
|
264
|
+
// Create payload with memory_id, spaces, and groups arrays
|
|
210
265
|
const payload = {
|
|
211
266
|
memory_id: args.memory_id,
|
|
212
|
-
spaces:
|
|
267
|
+
spaces: spaces,
|
|
268
|
+
groups: groups,
|
|
213
269
|
additional_tags: args.additional_tags || [],
|
|
214
270
|
};
|
|
215
271
|
|
|
@@ -217,7 +273,8 @@ export async function handlePublish(
|
|
|
217
273
|
tool: 'remember_publish',
|
|
218
274
|
userId,
|
|
219
275
|
memoryId: args.memory_id,
|
|
220
|
-
spaces:
|
|
276
|
+
spaces: spaces,
|
|
277
|
+
groups: groups,
|
|
221
278
|
});
|
|
222
279
|
|
|
223
280
|
// Generate confirmation token
|
|
@@ -233,7 +290,8 @@ export async function handlePublish(
|
|
|
233
290
|
requestId,
|
|
234
291
|
token,
|
|
235
292
|
action: 'publish_memory',
|
|
236
|
-
spaces:
|
|
293
|
+
spaces: spaces,
|
|
294
|
+
groups: groups,
|
|
237
295
|
});
|
|
238
296
|
|
|
239
297
|
// Return minimal response - agent already knows memory details
|
|
@@ -8,6 +8,9 @@ import { getMemoryCollection } from '../weaviate/schema.js';
|
|
|
8
8
|
import { logger } from '../utils/logger.js';
|
|
9
9
|
import { handleToolError } from '../utils/error-handler.js';
|
|
10
10
|
import { buildCombinedSearchFilters, buildDeletedFilter, combineFiltersWithAnd } from '../utils/weaviate-filters.js';
|
|
11
|
+
import { buildTrustFilter } from '../services/trust-enforcement.js';
|
|
12
|
+
import { createDebugLogger } from '../utils/debug.js';
|
|
13
|
+
import type { AuthContext } from '../types/auth.js';
|
|
11
14
|
|
|
12
15
|
/**
|
|
13
16
|
* Tool definition for remember_query_memory
|
|
@@ -142,6 +145,7 @@ export interface QueryMemoryArgs {
|
|
|
142
145
|
*/
|
|
143
146
|
export interface RelevantMemory extends Partial<Memory> {
|
|
144
147
|
relevance: number; // 0-1 relevance score
|
|
148
|
+
content_type?: string; // v2 property name (v1: type)
|
|
145
149
|
}
|
|
146
150
|
|
|
147
151
|
/**
|
|
@@ -160,17 +164,23 @@ export interface QueryMemoryResult {
|
|
|
160
164
|
*/
|
|
161
165
|
export async function handleQueryMemory(
|
|
162
166
|
args: QueryMemoryArgs,
|
|
163
|
-
userId: string
|
|
167
|
+
userId: string,
|
|
168
|
+
authContext?: AuthContext
|
|
164
169
|
): Promise<string> {
|
|
170
|
+
const ghostMode = authContext?.ghostMode;
|
|
171
|
+
const searchUserId = ghostMode?.owner_user_id ?? userId;
|
|
172
|
+
const debug = createDebugLogger({ tool: 'remember_query_memory', userId: searchUserId, operation: ghostMode ? 'ghost query' : 'query memory' });
|
|
165
173
|
try {
|
|
174
|
+
debug.info('Tool invoked');
|
|
175
|
+
debug.trace('Arguments', { args, ghostMode: !!ghostMode });
|
|
166
176
|
// Validate query is not empty
|
|
167
177
|
if (!args.query || args.query.trim() === '') {
|
|
168
178
|
throw new Error('Query cannot be empty');
|
|
169
179
|
}
|
|
170
180
|
|
|
171
|
-
logger.info('Querying memories', { userId, query: args.query });
|
|
181
|
+
logger.info('Querying memories', { userId: searchUserId, query: args.query, ghostMode: !!ghostMode });
|
|
172
182
|
|
|
173
|
-
const collection = getMemoryCollection(
|
|
183
|
+
const collection = getMemoryCollection(searchUserId);
|
|
174
184
|
const limit = args.limit ?? 5;
|
|
175
185
|
const minRelevance = args.min_relevance ?? 0.6;
|
|
176
186
|
const includeContext = args.include_context ?? true;
|
|
@@ -179,11 +189,22 @@ export async function handleQueryMemory(
|
|
|
179
189
|
// Build deleted filter
|
|
180
190
|
const deletedFilter = buildDeletedFilter(collection, args.deleted_filter || 'exclude');
|
|
181
191
|
|
|
192
|
+
// Build trust filter for ghost mode (resolved server-side, never from tool args)
|
|
193
|
+
const trustFilter = ghostMode
|
|
194
|
+
? buildTrustFilter(collection, ghostMode.accessor_trust_level)
|
|
195
|
+
: null;
|
|
196
|
+
|
|
182
197
|
// Build filters using v3 API - search both memories and relationships
|
|
183
198
|
const searchFilters = buildCombinedSearchFilters(collection, args.filters);
|
|
184
199
|
|
|
185
|
-
//
|
|
186
|
-
const
|
|
200
|
+
// Exclude ghost memories by default (unless explicitly searching for them)
|
|
201
|
+
const hasExplicitTypeFilter = args.filters?.types && args.filters.types.length > 0;
|
|
202
|
+
const ghostExclusionFilter = !hasExplicitTypeFilter
|
|
203
|
+
? collection.filter.byProperty('content_type').notEqual('ghost')
|
|
204
|
+
: null;
|
|
205
|
+
|
|
206
|
+
// Combine deleted filter, trust filter, ghost exclusion, and search filters
|
|
207
|
+
const combinedFilters = combineFiltersWithAnd([deletedFilter, trustFilter, ghostExclusionFilter, searchFilters].filter(f => f !== null));
|
|
187
208
|
|
|
188
209
|
// Build search options
|
|
189
210
|
const searchOptions: any = {
|
|
@@ -235,7 +256,7 @@ export async function handleQueryMemory(
|
|
|
235
256
|
// Compact format: text summary for easy LLM consumption
|
|
236
257
|
const summaryParts = relevantMemories.map((mem, idx) => {
|
|
237
258
|
const title = mem.title ? `"${mem.title}"` : `Memory ${idx + 1}`;
|
|
238
|
-
const type = mem.
|
|
259
|
+
const type = mem.content_type ? ` [${mem.content_type}]` : '';
|
|
239
260
|
const relevancePercent = Math.round((mem.relevance ?? 0) * 100);
|
|
240
261
|
const content = mem.content || '(no content)';
|
|
241
262
|
const tags = mem.tags && mem.tags.length > 0 ? `\nTags: ${mem.tags.join(', ')}` : '';
|
|
@@ -263,6 +284,7 @@ export async function handleQueryMemory(
|
|
|
263
284
|
|
|
264
285
|
return JSON.stringify(result, null, 2);
|
|
265
286
|
} catch (error) {
|
|
287
|
+
debug.error('Tool failed', { error: error instanceof Error ? error.message : String(error) });
|
|
266
288
|
handleToolError(error, {
|
|
267
289
|
toolName: 'remember_query_memory',
|
|
268
290
|
operation: 'query memories',
|
package/src/tools/query-space.ts
CHANGED
|
@@ -12,6 +12,10 @@ import { ensurePublicCollection, isValidSpaceId } from '../weaviate/space-schema
|
|
|
12
12
|
import { SUPPORTED_SPACES } from '../types/space-memory.js';
|
|
13
13
|
import { handleToolError } from '../utils/error-handler.js';
|
|
14
14
|
import { createDebugLogger } from '../utils/debug.js';
|
|
15
|
+
import type { AuthContext } from '../types/auth.js';
|
|
16
|
+
import type { ModerationFilter } from './search-space.js';
|
|
17
|
+
import { buildModerationFilter } from './search-space.js';
|
|
18
|
+
import { canModerateAny } from '../utils/auth-helpers.js';
|
|
15
19
|
|
|
16
20
|
/**
|
|
17
21
|
* Tool definition for remember_query_space
|
|
@@ -66,6 +70,12 @@ Let the query algorithm find ALL relevant memories regardless of type unless exp
|
|
|
66
70
|
type: 'string',
|
|
67
71
|
description: 'Filter memories created before this date (ISO 8601)',
|
|
68
72
|
},
|
|
73
|
+
moderation_filter: {
|
|
74
|
+
type: 'string',
|
|
75
|
+
enum: ['approved', 'pending', 'rejected', 'removed', 'all'],
|
|
76
|
+
description: 'Filter by moderation status. Default: "approved" (only shows approved/unmoderated). Non-approved filters require moderator permissions.',
|
|
77
|
+
default: 'approved',
|
|
78
|
+
},
|
|
69
79
|
include_comments: {
|
|
70
80
|
type: 'boolean',
|
|
71
81
|
description: 'Include comments in query results (default: false)',
|
|
@@ -95,6 +105,7 @@ interface QuerySpaceArgs {
|
|
|
95
105
|
min_weight?: number;
|
|
96
106
|
date_from?: string;
|
|
97
107
|
date_to?: string;
|
|
108
|
+
moderation_filter?: ModerationFilter;
|
|
98
109
|
include_comments?: boolean;
|
|
99
110
|
limit?: number;
|
|
100
111
|
format?: 'detailed' | 'compact';
|
|
@@ -105,7 +116,8 @@ interface QuerySpaceArgs {
|
|
|
105
116
|
*/
|
|
106
117
|
export async function handleQuerySpace(
|
|
107
118
|
args: QuerySpaceArgs,
|
|
108
|
-
userId: string
|
|
119
|
+
userId: string,
|
|
120
|
+
authContext?: AuthContext
|
|
109
121
|
): Promise<string> {
|
|
110
122
|
const debug = createDebugLogger({
|
|
111
123
|
tool: 'remember_query_space',
|
|
@@ -145,6 +157,20 @@ export async function handleQuerySpace(
|
|
|
145
157
|
);
|
|
146
158
|
}
|
|
147
159
|
|
|
160
|
+
// Permission check: non-approved moderation filters require moderator access
|
|
161
|
+
const moderationFilterValue = args.moderation_filter || 'approved';
|
|
162
|
+
if (moderationFilterValue !== 'approved' && !canModerateAny(authContext)) {
|
|
163
|
+
return JSON.stringify(
|
|
164
|
+
{
|
|
165
|
+
success: false,
|
|
166
|
+
error: 'Permission denied',
|
|
167
|
+
message: `Moderator access required to view ${moderationFilterValue} memories in spaces`,
|
|
168
|
+
},
|
|
169
|
+
null,
|
|
170
|
+
2
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
|
|
148
174
|
const weaviateClient = getWeaviateClient();
|
|
149
175
|
const publicCollection = await ensurePublicCollection(weaviateClient);
|
|
150
176
|
|
|
@@ -157,16 +183,25 @@ export async function handleQuerySpace(
|
|
|
157
183
|
// Filter by doc_type (memory) - space_memory concept was removed
|
|
158
184
|
filterList.push(publicCollection.filter.byProperty('doc_type').equal('memory'));
|
|
159
185
|
|
|
186
|
+
// Moderation status filter
|
|
187
|
+
const moderationFilter = buildModerationFilter(publicCollection, args.moderation_filter);
|
|
188
|
+
if (moderationFilter) {
|
|
189
|
+
filterList.push(moderationFilter);
|
|
190
|
+
}
|
|
191
|
+
|
|
160
192
|
// Apply content type filter
|
|
161
193
|
if (args.content_type) {
|
|
162
|
-
filterList.push(publicCollection.filter.byProperty('
|
|
194
|
+
filterList.push(publicCollection.filter.byProperty('content_type').equal(args.content_type));
|
|
163
195
|
}
|
|
164
196
|
|
|
165
|
-
// Exclude comments by default (unless explicitly included)
|
|
197
|
+
// Exclude comments and ghost memories by default (unless explicitly included)
|
|
166
198
|
if (!args.include_comments && !args.content_type) {
|
|
167
199
|
// Only exclude comments if not filtering by content_type
|
|
168
200
|
// (if content_type is set, user has explicit control)
|
|
169
|
-
filterList.push(publicCollection.filter.byProperty('
|
|
201
|
+
filterList.push(publicCollection.filter.byProperty('content_type').notEqual('comment'));
|
|
202
|
+
}
|
|
203
|
+
if (!args.content_type) {
|
|
204
|
+
filterList.push(publicCollection.filter.byProperty('content_type').notEqual('ghost'));
|
|
170
205
|
}
|
|
171
206
|
|
|
172
207
|
// Apply tags filter
|