@prmichaelsen/remember-mcp 2.8.0 → 3.0.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 +1 -1
- package/CHANGELOG.md +130 -0
- package/README.md +95 -1
- package/agent/commands/acp.command-create.md +0 -1
- package/agent/commands/acp.design-create.md +0 -1
- package/agent/commands/acp.init.md +0 -1
- package/agent/commands/acp.package-create.md +0 -1
- package/agent/commands/acp.package-info.md +0 -1
- package/agent/commands/acp.package-install.md +0 -1
- package/agent/commands/acp.package-list.md +0 -1
- package/agent/commands/acp.package-publish.md +0 -1
- package/agent/commands/acp.package-remove.md +0 -1
- package/agent/commands/acp.package-search.md +0 -1
- package/agent/commands/acp.package-update.md +0 -1
- package/agent/commands/acp.package-validate.md +0 -1
- package/agent/commands/acp.pattern-create.md +0 -1
- package/agent/commands/acp.plan.md +0 -1
- package/agent/commands/acp.proceed.md +0 -1
- package/agent/commands/acp.project-create.md +0 -1
- package/agent/commands/acp.project-list.md +0 -1
- package/agent/commands/acp.project-set.md +0 -1
- package/agent/commands/acp.report.md +0 -1
- package/agent/commands/acp.resume.md +0 -1
- package/agent/commands/acp.status.md +0 -1
- package/agent/commands/acp.sync.md +0 -1
- package/agent/commands/acp.task-create.md +0 -1
- package/agent/commands/acp.update.md +0 -1
- package/agent/commands/acp.validate.md +0 -1
- package/agent/commands/acp.version-check-for-updates.md +0 -1
- package/agent/commands/acp.version-check.md +0 -1
- package/agent/commands/acp.version-update.md +0 -1
- package/agent/commands/command.template.md +0 -5
- package/agent/commands/git.commit.md +0 -1
- package/agent/commands/git.init.md +0 -1
- package/agent/design/soft-delete-system.md +291 -0
- package/agent/milestones/milestone-13-soft-delete-system.md +306 -0
- package/agent/package.template.yaml +0 -17
- package/agent/progress.yaml +136 -2
- package/agent/scripts/acp.install.sh +4 -84
- package/agent/scripts/acp.package-install.sh +33 -112
- package/agent/scripts/acp.package-validate.sh +0 -99
- package/agent/tasks/task-70-add-soft-delete-schema-fields.md +165 -0
- package/agent/tasks/task-71-implement-delete-confirmation-flow.md +257 -0
- package/agent/tasks/task-72-add-deleted-filter-to-search-tools.md +18 -0
- package/agent/tasks/task-73-update-relationship-handling.md +18 -0
- package/agent/tasks/task-74-add-unit-tests-soft-delete.md +18 -0
- package/agent/tasks/task-75-update-documentation-changelog.md +26 -0
- package/dist/server-factory.js +677 -501
- package/dist/server.js +677 -501
- package/dist/tools/delete-memory.d.ts +5 -30
- package/dist/tools/find-similar.d.ts +8 -1
- package/dist/tools/query-memory.d.ts +8 -1
- package/dist/tools/search-memory.d.ts +6 -0
- package/dist/tools/search-relationship.d.ts +8 -1
- package/dist/types/memory.d.ts +8 -0
- package/dist/types/space-memory.d.ts +3 -0
- package/dist/utils/weaviate-filters.d.ts +19 -0
- package/dist/weaviate/client.d.ts +1 -1
- package/package.json +1 -1
- package/src/tools/confirm.ts +65 -1
- package/src/tools/create-relationship.ts +14 -1
- package/src/tools/delete-memory.ts +91 -63
- package/src/tools/find-similar.ts +30 -5
- package/src/tools/query-memory.ts +18 -5
- package/src/tools/search-memory.ts +18 -5
- package/src/tools/search-relationship.ts +19 -5
- package/src/tools/update-memory.ts +8 -0
- package/src/types/memory.ts +11 -0
- package/src/types/space-memory.ts +5 -0
- package/src/utils/weaviate-filters.ts +28 -1
- package/src/weaviate/client.ts +5 -0
- package/src/weaviate/schema.ts +17 -0
- package/src/weaviate/space-schema.spec.ts +5 -2
- package/src/weaviate/space-schema.ts +17 -5
package/dist/server.js
CHANGED
|
@@ -790,7 +790,11 @@ var ALL_MEMORY_PROPERTIES = [
|
|
|
790
790
|
"attribution",
|
|
791
791
|
"published_at",
|
|
792
792
|
"discovery_count",
|
|
793
|
-
"space_memory_id"
|
|
793
|
+
"space_memory_id",
|
|
794
|
+
// Soft delete fields
|
|
795
|
+
"deleted_at",
|
|
796
|
+
"deleted_by",
|
|
797
|
+
"deletion_reason"
|
|
794
798
|
];
|
|
795
799
|
async function fetchMemoryWithAllProperties(collection, memoryId) {
|
|
796
800
|
const debug = createDebugLogger({
|
|
@@ -1128,6 +1132,22 @@ async function createMemoryCollection(userId) {
|
|
|
1128
1132
|
name: "moderation_flags",
|
|
1129
1133
|
dataType: "text[]",
|
|
1130
1134
|
description: 'Per-space moderation flags (format: "{space_id}:{flag_type}")'
|
|
1135
|
+
},
|
|
1136
|
+
// Soft delete fields
|
|
1137
|
+
{
|
|
1138
|
+
name: "deleted_at",
|
|
1139
|
+
dataType: "date",
|
|
1140
|
+
description: "Timestamp when memory was soft-deleted (null = not deleted)"
|
|
1141
|
+
},
|
|
1142
|
+
{
|
|
1143
|
+
name: "deleted_by",
|
|
1144
|
+
dataType: "text",
|
|
1145
|
+
description: "User ID who deleted the memory"
|
|
1146
|
+
},
|
|
1147
|
+
{
|
|
1148
|
+
name: "deletion_reason",
|
|
1149
|
+
dataType: "text",
|
|
1150
|
+
description: "Optional reason for deletion"
|
|
1131
1151
|
}
|
|
1132
1152
|
]
|
|
1133
1153
|
});
|
|
@@ -1831,6 +1851,14 @@ function combineFiltersWithOr(filters) {
|
|
|
1831
1851
|
}
|
|
1832
1852
|
return Filters.or(...validFilters);
|
|
1833
1853
|
}
|
|
1854
|
+
function buildDeletedFilter(collection, deletedFilter = "exclude") {
|
|
1855
|
+
if (deletedFilter === "exclude") {
|
|
1856
|
+
return collection.filter.byProperty("deleted_at").isNull(true);
|
|
1857
|
+
} else if (deletedFilter === "only") {
|
|
1858
|
+
return collection.filter.byProperty("deleted_at").isNull(false);
|
|
1859
|
+
}
|
|
1860
|
+
return null;
|
|
1861
|
+
}
|
|
1834
1862
|
|
|
1835
1863
|
// src/tools/search-memory.ts
|
|
1836
1864
|
var searchMemoryTool = {
|
|
@@ -1931,6 +1959,12 @@ var searchMemoryTool = {
|
|
|
1931
1959
|
type: "boolean",
|
|
1932
1960
|
description: "Include relationships in results. Default: true (searches both memories and relationships)",
|
|
1933
1961
|
default: true
|
|
1962
|
+
},
|
|
1963
|
+
deleted_filter: {
|
|
1964
|
+
type: "string",
|
|
1965
|
+
enum: ["exclude", "include", "only"],
|
|
1966
|
+
default: "exclude",
|
|
1967
|
+
description: 'Filter deleted memories: "exclude" (default, hide deleted), "include" (show all), "only" (show only deleted)'
|
|
1934
1968
|
}
|
|
1935
1969
|
},
|
|
1936
1970
|
required: ["query"]
|
|
@@ -1951,19 +1985,22 @@ async function handleSearchMemory(args, userId) {
|
|
|
1951
1985
|
const alpha = args.alpha ?? 0.7;
|
|
1952
1986
|
const limit = args.limit ?? 10;
|
|
1953
1987
|
const offset = args.offset ?? 0;
|
|
1954
|
-
const
|
|
1988
|
+
const deletedFilter = buildDeletedFilter(collection, args.deleted_filter || "exclude");
|
|
1989
|
+
const searchFilters = includeRelationships ? buildCombinedSearchFilters(collection, args.filters) : buildMemoryOnlyFilters(collection, args.filters);
|
|
1990
|
+
const combinedFilters = combineFiltersWithAnd([deletedFilter, searchFilters].filter((f) => f !== null));
|
|
1955
1991
|
const searchOptions = {
|
|
1956
1992
|
alpha,
|
|
1957
1993
|
limit: limit + offset
|
|
1958
1994
|
// Get extra for offset
|
|
1959
1995
|
};
|
|
1960
|
-
if (
|
|
1961
|
-
searchOptions.filters =
|
|
1996
|
+
if (combinedFilters) {
|
|
1997
|
+
searchOptions.filters = combinedFilters;
|
|
1962
1998
|
}
|
|
1963
1999
|
logger.info("Weaviate query", {
|
|
1964
2000
|
query: args.query,
|
|
1965
2001
|
searchOptions: JSON.stringify(searchOptions, null, 2),
|
|
1966
|
-
hasFilters: !!
|
|
2002
|
+
hasFilters: !!combinedFilters,
|
|
2003
|
+
deletedFilter: args.deleted_filter || "exclude"
|
|
1967
2004
|
});
|
|
1968
2005
|
const results = await collection.query.hybrid(args.query, searchOptions);
|
|
1969
2006
|
const paginatedResults = results.objects.slice(offset);
|
|
@@ -2007,142 +2044,407 @@ async function handleSearchMemory(args, userId) {
|
|
|
2007
2044
|
}
|
|
2008
2045
|
|
|
2009
2046
|
// src/tools/delete-memory.ts
|
|
2047
|
+
import { Filters as Filters2 } from "weaviate-client";
|
|
2048
|
+
|
|
2049
|
+
// src/services/confirmation-token.service.ts
|
|
2050
|
+
import { randomUUID } from "crypto";
|
|
2010
2051
|
init_logger();
|
|
2011
|
-
var
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2052
|
+
var ConfirmationTokenService = class {
|
|
2053
|
+
EXPIRY_MINUTES = 5;
|
|
2054
|
+
/**
|
|
2055
|
+
* Create a new confirmation request
|
|
2056
|
+
*
|
|
2057
|
+
* @param userId - User ID who initiated the request
|
|
2058
|
+
* @param action - Action type (e.g., 'publish_memory')
|
|
2059
|
+
* @param payload - Data to store with the request
|
|
2060
|
+
* @param targetCollection - Optional target collection (e.g., 'the_void')
|
|
2061
|
+
* @returns Request ID and token
|
|
2062
|
+
*/
|
|
2063
|
+
async createRequest(userId, action, payload, targetCollection) {
|
|
2064
|
+
try {
|
|
2065
|
+
const token = randomUUID();
|
|
2066
|
+
const now = /* @__PURE__ */ new Date();
|
|
2067
|
+
const expiresAt = new Date(now.getTime() + this.EXPIRY_MINUTES * 60 * 1e3);
|
|
2068
|
+
const request = {
|
|
2069
|
+
user_id: userId,
|
|
2070
|
+
token,
|
|
2071
|
+
action,
|
|
2072
|
+
target_collection: targetCollection,
|
|
2073
|
+
payload,
|
|
2074
|
+
created_at: now.toISOString(),
|
|
2075
|
+
expires_at: expiresAt.toISOString(),
|
|
2076
|
+
status: "pending"
|
|
2077
|
+
};
|
|
2078
|
+
const collectionPath = `users/${userId}/requests`;
|
|
2079
|
+
logger.info("Creating confirmation request", {
|
|
2080
|
+
service: "ConfirmationTokenService",
|
|
2081
|
+
userId,
|
|
2082
|
+
action,
|
|
2083
|
+
targetCollection,
|
|
2084
|
+
collectionPath,
|
|
2085
|
+
payloadKeys: Object.keys(payload)
|
|
2086
|
+
});
|
|
2087
|
+
logger.debug("Calling Firestore addDocument", {
|
|
2088
|
+
service: "ConfirmationTokenService",
|
|
2089
|
+
collectionPath
|
|
2090
|
+
});
|
|
2091
|
+
const docRef = await addDocument(collectionPath, request);
|
|
2092
|
+
logger.debug("Firestore addDocument returned", {
|
|
2093
|
+
service: "ConfirmationTokenService",
|
|
2094
|
+
hasDocRef: !!docRef,
|
|
2095
|
+
hasId: !!docRef?.id,
|
|
2096
|
+
docRefId: docRef?.id
|
|
2097
|
+
});
|
|
2098
|
+
if (!docRef) {
|
|
2099
|
+
const error = new Error("Firestore addDocument returned null/undefined");
|
|
2100
|
+
logger.error("CRITICAL: addDocument returned null", {
|
|
2101
|
+
service: "ConfirmationTokenService",
|
|
2102
|
+
userId,
|
|
2103
|
+
collectionPath
|
|
2104
|
+
});
|
|
2105
|
+
throw error;
|
|
2033
2106
|
}
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
returnProperties: ["user_id", "doc_type", "relationships"]
|
|
2044
|
-
});
|
|
2045
|
-
if (!memory) {
|
|
2046
|
-
throw new Error(`Memory not found: ${args.memory_id}`);
|
|
2047
|
-
}
|
|
2048
|
-
if (memory.properties.user_id !== userId) {
|
|
2049
|
-
throw new Error("Unauthorized: Cannot delete another user's memory");
|
|
2050
|
-
}
|
|
2051
|
-
if (memory.properties.doc_type !== "memory") {
|
|
2052
|
-
throw new Error("Cannot delete relationships using this tool. Use remember_delete_relationship instead.");
|
|
2053
|
-
}
|
|
2054
|
-
let relationshipsDeleted = 0;
|
|
2055
|
-
if (args.delete_relationships && memory.properties.relationships) {
|
|
2056
|
-
const relationshipIds = memory.properties.relationships;
|
|
2057
|
-
for (const relId of relationshipIds) {
|
|
2058
|
-
try {
|
|
2059
|
-
await collection.data.deleteById(relId);
|
|
2060
|
-
relationshipsDeleted++;
|
|
2061
|
-
} catch (error) {
|
|
2062
|
-
logger.warn(`Failed to delete relationship ${relId}:`, error);
|
|
2063
|
-
}
|
|
2107
|
+
if (!docRef.id) {
|
|
2108
|
+
const error = new Error("Firestore addDocument returned docRef without ID");
|
|
2109
|
+
logger.error("CRITICAL: docRef has no ID", {
|
|
2110
|
+
service: "ConfirmationTokenService",
|
|
2111
|
+
userId,
|
|
2112
|
+
collectionPath,
|
|
2113
|
+
docRef
|
|
2114
|
+
});
|
|
2115
|
+
throw error;
|
|
2064
2116
|
}
|
|
2117
|
+
logger.info("Confirmation request created successfully", {
|
|
2118
|
+
service: "ConfirmationTokenService",
|
|
2119
|
+
requestId: docRef.id,
|
|
2120
|
+
token,
|
|
2121
|
+
expiresAt: request.expires_at
|
|
2122
|
+
});
|
|
2123
|
+
return { requestId: docRef.id, token };
|
|
2124
|
+
} catch (error) {
|
|
2125
|
+
logger.error("Failed to create confirmation request", {
|
|
2126
|
+
service: "ConfirmationTokenService",
|
|
2127
|
+
error: error instanceof Error ? error.message : String(error),
|
|
2128
|
+
stack: error instanceof Error ? error.stack : void 0,
|
|
2129
|
+
userId,
|
|
2130
|
+
action,
|
|
2131
|
+
collectionPath: `users/${userId}/requests`
|
|
2132
|
+
});
|
|
2133
|
+
throw error;
|
|
2065
2134
|
}
|
|
2066
|
-
|
|
2067
|
-
|
|
2135
|
+
}
|
|
2136
|
+
/**
|
|
2137
|
+
* Validate and retrieve a confirmation request
|
|
2138
|
+
*
|
|
2139
|
+
* @param userId - User ID
|
|
2140
|
+
* @param token - Confirmation token
|
|
2141
|
+
* @returns Request with request_id if valid, null otherwise
|
|
2142
|
+
*/
|
|
2143
|
+
async validateToken(userId, token) {
|
|
2144
|
+
const collectionPath = `users/${userId}/requests`;
|
|
2145
|
+
logger.debug("Validating confirmation token", {
|
|
2146
|
+
service: "ConfirmationTokenService",
|
|
2068
2147
|
userId,
|
|
2069
|
-
|
|
2070
|
-
|
|
2148
|
+
token,
|
|
2149
|
+
collectionPath
|
|
2071
2150
|
});
|
|
2072
|
-
const
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2151
|
+
const queryOptions = {
|
|
2152
|
+
where: [
|
|
2153
|
+
{ field: "token", op: "==", value: token },
|
|
2154
|
+
{ field: "status", op: "==", value: "pending" }
|
|
2155
|
+
],
|
|
2156
|
+
limit: 1
|
|
2077
2157
|
};
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2158
|
+
const results = await queryDocuments(collectionPath, queryOptions);
|
|
2159
|
+
logger.debug("Token query results", {
|
|
2160
|
+
service: "ConfirmationTokenService",
|
|
2161
|
+
resultsFound: results.length,
|
|
2162
|
+
hasResults: results.length > 0
|
|
2163
|
+
});
|
|
2164
|
+
if (results.length === 0) {
|
|
2165
|
+
logger.info("Token not found or not pending", {
|
|
2166
|
+
service: "ConfirmationTokenService",
|
|
2167
|
+
userId
|
|
2168
|
+
});
|
|
2169
|
+
return null;
|
|
2170
|
+
}
|
|
2171
|
+
const doc = results[0];
|
|
2172
|
+
const request = doc.data;
|
|
2173
|
+
logger.info("Confirmation request found", {
|
|
2174
|
+
service: "ConfirmationTokenService",
|
|
2175
|
+
requestId: doc.id,
|
|
2176
|
+
action: request.action,
|
|
2177
|
+
status: request.status,
|
|
2178
|
+
expiresAt: request.expires_at
|
|
2086
2179
|
});
|
|
2180
|
+
const expiresAt = new Date(request.expires_at);
|
|
2181
|
+
if (expiresAt.getTime() < Date.now()) {
|
|
2182
|
+
logger.info("Token expired", {
|
|
2183
|
+
service: "ConfirmationTokenService",
|
|
2184
|
+
requestId: doc.id,
|
|
2185
|
+
expiresAt: request.expires_at
|
|
2186
|
+
});
|
|
2187
|
+
await this.updateStatus(userId, doc.id, "expired");
|
|
2188
|
+
return null;
|
|
2189
|
+
}
|
|
2190
|
+
return {
|
|
2191
|
+
...request,
|
|
2192
|
+
request_id: doc.id
|
|
2193
|
+
};
|
|
2087
2194
|
}
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2195
|
+
/**
|
|
2196
|
+
* Confirm a request
|
|
2197
|
+
*
|
|
2198
|
+
* @param userId - User ID
|
|
2199
|
+
* @param token - Confirmation token
|
|
2200
|
+
* @returns Confirmed request if valid, null otherwise
|
|
2201
|
+
*/
|
|
2202
|
+
async confirmRequest(userId, token) {
|
|
2203
|
+
const request = await this.validateToken(userId, token);
|
|
2204
|
+
if (!request) {
|
|
2205
|
+
return null;
|
|
2206
|
+
}
|
|
2207
|
+
await this.updateStatus(userId, request.request_id, "confirmed");
|
|
2208
|
+
return {
|
|
2209
|
+
...request,
|
|
2210
|
+
status: "confirmed",
|
|
2211
|
+
confirmed_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
2212
|
+
};
|
|
2213
|
+
}
|
|
2214
|
+
/**
|
|
2215
|
+
* Deny a request
|
|
2216
|
+
*
|
|
2217
|
+
* @param userId - User ID
|
|
2218
|
+
* @param token - Confirmation token
|
|
2219
|
+
* @returns True if denied successfully, false otherwise
|
|
2220
|
+
*/
|
|
2221
|
+
async denyRequest(userId, token) {
|
|
2222
|
+
const request = await this.validateToken(userId, token);
|
|
2223
|
+
if (!request) {
|
|
2224
|
+
return false;
|
|
2225
|
+
}
|
|
2226
|
+
await this.updateStatus(userId, request.request_id, "denied");
|
|
2227
|
+
return true;
|
|
2228
|
+
}
|
|
2229
|
+
/**
|
|
2230
|
+
* Retract a request
|
|
2231
|
+
*
|
|
2232
|
+
* @param userId - User ID
|
|
2233
|
+
* @param token - Confirmation token
|
|
2234
|
+
* @returns True if retracted successfully, false otherwise
|
|
2235
|
+
*/
|
|
2236
|
+
async retractRequest(userId, token) {
|
|
2237
|
+
const request = await this.validateToken(userId, token);
|
|
2238
|
+
if (!request) {
|
|
2239
|
+
return false;
|
|
2240
|
+
}
|
|
2241
|
+
await this.updateStatus(userId, request.request_id, "retracted");
|
|
2242
|
+
return true;
|
|
2243
|
+
}
|
|
2244
|
+
/**
|
|
2245
|
+
* Update request status
|
|
2246
|
+
*
|
|
2247
|
+
* @param userId - User ID
|
|
2248
|
+
* @param requestId - Request document ID
|
|
2249
|
+
* @param status - New status
|
|
2250
|
+
*/
|
|
2251
|
+
async updateStatus(userId, requestId, status) {
|
|
2252
|
+
const collectionPath = `users/${userId}/requests`;
|
|
2253
|
+
const updateData = {
|
|
2254
|
+
status
|
|
2255
|
+
};
|
|
2256
|
+
if (status === "confirmed") {
|
|
2257
|
+
updateData.confirmed_at = (/* @__PURE__ */ new Date()).toISOString();
|
|
2258
|
+
}
|
|
2259
|
+
await updateDocument(collectionPath, requestId, updateData);
|
|
2260
|
+
}
|
|
2261
|
+
/**
|
|
2262
|
+
* Clean up expired requests (optional - Firestore TTL handles deletion)
|
|
2263
|
+
*
|
|
2264
|
+
* Note: Configure Firestore TTL policy on 'requests' collection group
|
|
2265
|
+
* with 'expires_at' field for automatic deletion within 24 hours.
|
|
2266
|
+
*
|
|
2267
|
+
* This method is optional for immediate cleanup if needed.
|
|
2268
|
+
*
|
|
2269
|
+
* @returns Count of deleted requests
|
|
2270
|
+
*/
|
|
2271
|
+
async cleanupExpired() {
|
|
2272
|
+
logger.warn("cleanupExpired not implemented - relying on Firestore TTL", {
|
|
2273
|
+
service: "ConfirmationTokenService",
|
|
2274
|
+
note: "Configure Firestore TTL policy on requests collection group"
|
|
2275
|
+
});
|
|
2276
|
+
return 0;
|
|
2277
|
+
}
|
|
2278
|
+
};
|
|
2279
|
+
var confirmationTokenService = new ConfirmationTokenService();
|
|
2280
|
+
|
|
2281
|
+
// src/tools/delete-memory.ts
|
|
2282
|
+
init_logger();
|
|
2283
|
+
var deleteMemoryTool = {
|
|
2284
|
+
name: "remember_delete_memory",
|
|
2285
|
+
description: `Request to delete a memory. Requires confirmation via remember_confirm.
|
|
2286
|
+
|
|
2287
|
+
\u26A0\uFE0F **IMPORTANT**: This is a two-step process:
|
|
2288
|
+
1. Call remember_delete_memory to request deletion (returns token)
|
|
2289
|
+
2. User must confirm via remember_confirm with the token
|
|
2290
|
+
|
|
2291
|
+
The memory will be soft-deleted (marked as deleted but not removed from database).
|
|
2292
|
+
|
|
2293
|
+
Examples:
|
|
2294
|
+
- "Delete that old camping note"
|
|
2295
|
+
- "Remove the recipe I saved yesterday"
|
|
2296
|
+
`,
|
|
2297
|
+
inputSchema: {
|
|
2298
|
+
type: "object",
|
|
2299
|
+
properties: {
|
|
2300
|
+
memory_id: {
|
|
2301
|
+
type: "string",
|
|
2302
|
+
description: "ID of the memory to delete"
|
|
2303
|
+
},
|
|
2304
|
+
reason: {
|
|
2305
|
+
type: "string",
|
|
2306
|
+
description: "Optional reason for deletion"
|
|
2307
|
+
}
|
|
2308
|
+
},
|
|
2309
|
+
required: ["memory_id"]
|
|
2310
|
+
}
|
|
2311
|
+
};
|
|
2312
|
+
async function handleDeleteMemory(args, userId) {
|
|
2313
|
+
try {
|
|
2314
|
+
logger.info("Requesting memory deletion", {
|
|
2315
|
+
userId,
|
|
2316
|
+
memoryId: args.memory_id,
|
|
2317
|
+
hasReason: !!args.reason
|
|
2318
|
+
});
|
|
2319
|
+
const { memory_id, reason } = args;
|
|
2320
|
+
const client2 = getWeaviateClient();
|
|
2321
|
+
const collectionName = `Memory_${sanitizeUserId(userId)}`;
|
|
2322
|
+
const collection = client2.collections.get(collectionName);
|
|
2323
|
+
const memory = await fetchMemoryWithAllProperties(collection, memory_id);
|
|
2324
|
+
if (!memory) {
|
|
2325
|
+
throw new Error(`Memory not found: ${memory_id}`);
|
|
2326
|
+
}
|
|
2327
|
+
if (memory.properties.user_id !== userId) {
|
|
2328
|
+
throw new Error(`Cannot delete memory: not owned by user ${userId}`);
|
|
2329
|
+
}
|
|
2330
|
+
if (memory.properties.doc_type !== "memory") {
|
|
2331
|
+
throw new Error("Cannot delete relationships using this tool. Use remember_delete_relationship instead.");
|
|
2332
|
+
}
|
|
2333
|
+
if (memory.properties.deleted_at) {
|
|
2334
|
+
throw new Error(`Memory ${memory_id} is already deleted`);
|
|
2335
|
+
}
|
|
2336
|
+
const relationshipsResult = await collection.query.fetchObjects({
|
|
2337
|
+
filters: Filters2.and(
|
|
2338
|
+
collection.filter.byProperty("doc_type").equal("relationship"),
|
|
2339
|
+
collection.filter.byProperty("memory_ids").containsAny([memory_id])
|
|
2340
|
+
),
|
|
2341
|
+
limit: 100
|
|
2342
|
+
});
|
|
2343
|
+
const orphanedRelationships = relationshipsResult.objects.map((r) => r.uuid);
|
|
2344
|
+
logger.info("Found relationships to orphan", {
|
|
2345
|
+
userId,
|
|
2346
|
+
memoryId: memory_id,
|
|
2347
|
+
relationshipCount: orphanedRelationships.length
|
|
2348
|
+
});
|
|
2349
|
+
const { requestId, token } = await confirmationTokenService.createRequest(
|
|
2350
|
+
userId,
|
|
2351
|
+
"delete_memory",
|
|
2352
|
+
{
|
|
2353
|
+
memory_id,
|
|
2354
|
+
reason: reason || null
|
|
2355
|
+
}
|
|
2356
|
+
);
|
|
2357
|
+
const expiresAt = new Date(Date.now() + 5 * 60 * 1e3);
|
|
2358
|
+
logger.info("Delete confirmation token created", {
|
|
2359
|
+
userId,
|
|
2360
|
+
memoryId: memory_id,
|
|
2361
|
+
requestId,
|
|
2362
|
+
token,
|
|
2363
|
+
expiresAt: expiresAt.toISOString()
|
|
2364
|
+
});
|
|
2365
|
+
return JSON.stringify(
|
|
2366
|
+
{
|
|
2367
|
+
success: true,
|
|
2368
|
+
token,
|
|
2369
|
+
expires_at: expiresAt.toISOString(),
|
|
2370
|
+
preview: {
|
|
2371
|
+
memory_id,
|
|
2372
|
+
content: memory.properties.content?.substring(0, 200) + (memory.properties.content?.length > 200 ? "..." : ""),
|
|
2373
|
+
type: memory.properties.type,
|
|
2374
|
+
relationships_count: orphanedRelationships.length,
|
|
2375
|
+
will_orphan: orphanedRelationships
|
|
2376
|
+
},
|
|
2377
|
+
message: `Deletion requested. Use remember_confirm with token to complete deletion. Token expires in 5 minutes.`
|
|
2378
|
+
},
|
|
2379
|
+
null,
|
|
2380
|
+
2
|
|
2381
|
+
);
|
|
2382
|
+
} catch (error) {
|
|
2383
|
+
handleToolError(error, {
|
|
2384
|
+
toolName: "remember_delete_memory",
|
|
2385
|
+
userId,
|
|
2386
|
+
operation: "request delete",
|
|
2387
|
+
memoryId: args.memory_id
|
|
2388
|
+
});
|
|
2389
|
+
}
|
|
2390
|
+
}
|
|
2391
|
+
|
|
2392
|
+
// src/tools/update-memory.ts
|
|
2393
|
+
init_logger();
|
|
2394
|
+
var updateMemoryTool = {
|
|
2395
|
+
name: "remember_update_memory",
|
|
2396
|
+
description: `Update an existing memory with partial updates.
|
|
2397
|
+
|
|
2398
|
+
Supports updating any field except id, user_id, doc_type, created_at.
|
|
2399
|
+
Version number is automatically incremented and updated_at is set.
|
|
2400
|
+
Only provided fields are updated (partial updates supported).
|
|
2401
|
+
|
|
2402
|
+
Examples:
|
|
2403
|
+
- "Update that camping note to add more details"
|
|
2404
|
+
- "Change the weight of my recipe memory"
|
|
2405
|
+
- "Add tags to the meeting note from yesterday"
|
|
2406
|
+
`,
|
|
2407
|
+
inputSchema: {
|
|
2408
|
+
type: "object",
|
|
2409
|
+
properties: {
|
|
2410
|
+
memory_id: {
|
|
2411
|
+
type: "string",
|
|
2412
|
+
description: "ID of the memory to update"
|
|
2413
|
+
},
|
|
2414
|
+
content: {
|
|
2415
|
+
type: "string",
|
|
2416
|
+
description: "Updated memory content"
|
|
2417
|
+
},
|
|
2418
|
+
title: {
|
|
2419
|
+
type: "string",
|
|
2420
|
+
description: "Updated title"
|
|
2421
|
+
},
|
|
2422
|
+
type: {
|
|
2423
|
+
type: "string",
|
|
2424
|
+
description: "Updated content type"
|
|
2425
|
+
},
|
|
2426
|
+
weight: {
|
|
2427
|
+
type: "number",
|
|
2428
|
+
description: "Updated significance/priority (0-1)",
|
|
2429
|
+
minimum: 0,
|
|
2430
|
+
maximum: 1
|
|
2431
|
+
},
|
|
2432
|
+
trust: {
|
|
2433
|
+
type: "number",
|
|
2434
|
+
description: "Updated access control level (0-1)",
|
|
2435
|
+
minimum: 0,
|
|
2436
|
+
maximum: 1
|
|
2437
|
+
},
|
|
2438
|
+
tags: {
|
|
2439
|
+
type: "array",
|
|
2440
|
+
items: { type: "string" },
|
|
2441
|
+
description: "Updated tags (replaces existing tags)"
|
|
2442
|
+
},
|
|
2443
|
+
references: {
|
|
2444
|
+
type: "array",
|
|
2445
|
+
items: { type: "string" },
|
|
2446
|
+
description: "Updated source URLs (replaces existing references)"
|
|
2447
|
+
},
|
|
2146
2448
|
structured_content: {
|
|
2147
2449
|
type: "object",
|
|
2148
2450
|
description: "Updated structured content"
|
|
@@ -2190,6 +2492,10 @@ async function handleUpdateMemory(args, userId) {
|
|
|
2190
2492
|
if (existingMemory.properties.doc_type !== "memory") {
|
|
2191
2493
|
throw new Error("Cannot update relationships using this tool. Use remember_update_relationship instead.");
|
|
2192
2494
|
}
|
|
2495
|
+
if (existingMemory.properties.deleted_at) {
|
|
2496
|
+
const deletedAt = typeof existingMemory.properties.deleted_at === "string" ? existingMemory.properties.deleted_at : new Date(existingMemory.properties.deleted_at).toISOString();
|
|
2497
|
+
throw new Error(`Cannot update deleted memory: ${args.memory_id}. Memory was deleted on ${deletedAt}.`);
|
|
2498
|
+
}
|
|
2193
2499
|
const updates = {};
|
|
2194
2500
|
const updatedFields = [];
|
|
2195
2501
|
if (args.content !== void 0) {
|
|
@@ -2357,6 +2663,12 @@ var findSimilarTool = {
|
|
|
2357
2663
|
type: "boolean",
|
|
2358
2664
|
description: "Include relationships in results. Default: false",
|
|
2359
2665
|
default: false
|
|
2666
|
+
},
|
|
2667
|
+
deleted_filter: {
|
|
2668
|
+
type: "string",
|
|
2669
|
+
enum: ["exclude", "include", "only"],
|
|
2670
|
+
default: "exclude",
|
|
2671
|
+
description: 'Filter deleted memories: "exclude" (default, hide deleted), "include" (show all), "only" (show only deleted)'
|
|
2360
2672
|
}
|
|
2361
2673
|
}
|
|
2362
2674
|
}
|
|
@@ -2373,6 +2685,7 @@ async function handleFindSimilar(args, userId) {
|
|
|
2373
2685
|
const collection = getMemoryCollection(userId);
|
|
2374
2686
|
const limit = args.limit ?? 10;
|
|
2375
2687
|
const minSimilarity = args.min_similarity ?? 0.7;
|
|
2688
|
+
const deletedFilter = buildDeletedFilter(collection, args.deleted_filter || "exclude");
|
|
2376
2689
|
let results;
|
|
2377
2690
|
if (args.memory_id) {
|
|
2378
2691
|
const memory = await collection.query.fetchObjectById(args.memory_id, {
|
|
@@ -2387,20 +2700,28 @@ async function handleFindSimilar(args, userId) {
|
|
|
2387
2700
|
if (memory.properties.doc_type !== "memory") {
|
|
2388
2701
|
throw new Error("Can only find similar memories for memory documents, not relationships");
|
|
2389
2702
|
}
|
|
2390
|
-
|
|
2703
|
+
const searchOptions = {
|
|
2391
2704
|
limit: limit + 1,
|
|
2392
2705
|
// +1 to exclude the source memory itself
|
|
2393
2706
|
distance: 1 - minSimilarity,
|
|
2394
2707
|
// Convert similarity to distance
|
|
2395
2708
|
returnMetadata: ["distance"]
|
|
2396
|
-
}
|
|
2709
|
+
};
|
|
2710
|
+
if (deletedFilter) {
|
|
2711
|
+
searchOptions.filters = deletedFilter;
|
|
2712
|
+
}
|
|
2713
|
+
results = await collection.query.nearObject(args.memory_id, searchOptions);
|
|
2397
2714
|
results.objects = results.objects.filter((obj) => obj.uuid !== args.memory_id);
|
|
2398
2715
|
} else {
|
|
2399
|
-
|
|
2716
|
+
const searchOptions = {
|
|
2400
2717
|
limit,
|
|
2401
2718
|
distance: 1 - minSimilarity,
|
|
2402
2719
|
returnMetadata: ["distance"]
|
|
2403
|
-
}
|
|
2720
|
+
};
|
|
2721
|
+
if (deletedFilter) {
|
|
2722
|
+
searchOptions.filters = deletedFilter;
|
|
2723
|
+
}
|
|
2724
|
+
results = await collection.query.nearText(args.text, searchOptions);
|
|
2404
2725
|
}
|
|
2405
2726
|
if (!args.include_relationships) {
|
|
2406
2727
|
results.objects = results.objects.filter(
|
|
@@ -2547,6 +2868,12 @@ var queryMemoryTool = {
|
|
|
2547
2868
|
description: 'Output format: "detailed" (full objects) or "compact" (text summary). Default: detailed',
|
|
2548
2869
|
enum: ["detailed", "compact"],
|
|
2549
2870
|
default: "detailed"
|
|
2871
|
+
},
|
|
2872
|
+
deleted_filter: {
|
|
2873
|
+
type: "string",
|
|
2874
|
+
enum: ["exclude", "include", "only"],
|
|
2875
|
+
default: "exclude",
|
|
2876
|
+
description: 'Filter deleted memories: "exclude" (default, hide deleted), "include" (show all), "only" (show only deleted)'
|
|
2550
2877
|
}
|
|
2551
2878
|
},
|
|
2552
2879
|
required: ["query"]
|
|
@@ -2563,15 +2890,17 @@ async function handleQueryMemory(args, userId) {
|
|
|
2563
2890
|
const minRelevance = args.min_relevance ?? 0.6;
|
|
2564
2891
|
const includeContext = args.include_context ?? true;
|
|
2565
2892
|
const format = args.format ?? "detailed";
|
|
2566
|
-
const
|
|
2893
|
+
const deletedFilter = buildDeletedFilter(collection, args.deleted_filter || "exclude");
|
|
2894
|
+
const searchFilters = buildCombinedSearchFilters(collection, args.filters);
|
|
2895
|
+
const combinedFilters = combineFiltersWithAnd([deletedFilter, searchFilters].filter((f) => f !== null));
|
|
2567
2896
|
const searchOptions = {
|
|
2568
2897
|
limit,
|
|
2569
2898
|
distance: 1 - minRelevance,
|
|
2570
2899
|
// Convert relevance to distance
|
|
2571
2900
|
returnMetadata: ["distance"]
|
|
2572
2901
|
};
|
|
2573
|
-
if (
|
|
2574
|
-
searchOptions.filters =
|
|
2902
|
+
if (combinedFilters) {
|
|
2903
|
+
searchOptions.filters = combinedFilters;
|
|
2575
2904
|
}
|
|
2576
2905
|
const results = await collection.query.nearText(args.query, searchOptions);
|
|
2577
2906
|
const relevantMemories = results.objects.map((obj) => {
|
|
@@ -2702,7 +3031,7 @@ async function handleCreateRelationship(args, userId, context) {
|
|
|
2702
3031
|
args.memory_ids.map(async (memoryId) => {
|
|
2703
3032
|
try {
|
|
2704
3033
|
const memory = await collection.query.fetchObjectById(memoryId, {
|
|
2705
|
-
returnProperties: ["user_id", "doc_type", "relationships"]
|
|
3034
|
+
returnProperties: ["user_id", "doc_type", "relationships", "deleted_at"]
|
|
2706
3035
|
});
|
|
2707
3036
|
if (!memory) {
|
|
2708
3037
|
logger.warn("Memory not found", { userId, memoryId });
|
|
@@ -2724,6 +3053,15 @@ async function handleCreateRelationship(args, userId, context) {
|
|
|
2724
3053
|
});
|
|
2725
3054
|
return { memoryId, error: "Cannot create relationship with non-memory document" };
|
|
2726
3055
|
}
|
|
3056
|
+
if (memory.properties.deleted_at) {
|
|
3057
|
+
const deletedAt = typeof memory.properties.deleted_at === "string" ? memory.properties.deleted_at : new Date(memory.properties.deleted_at).toISOString();
|
|
3058
|
+
logger.warn("Attempt to create relationship with deleted memory", {
|
|
3059
|
+
userId,
|
|
3060
|
+
memoryId,
|
|
3061
|
+
deletedAt
|
|
3062
|
+
});
|
|
3063
|
+
return { memoryId, error: `Memory is deleted (deleted on ${deletedAt})` };
|
|
3064
|
+
}
|
|
2727
3065
|
return {
|
|
2728
3066
|
memoryId,
|
|
2729
3067
|
memory,
|
|
@@ -2970,7 +3308,7 @@ async function handleUpdateRelationship(args, userId) {
|
|
|
2970
3308
|
}
|
|
2971
3309
|
|
|
2972
3310
|
// src/tools/search-relationship.ts
|
|
2973
|
-
import { Filters as
|
|
3311
|
+
import { Filters as Filters3 } from "weaviate-client";
|
|
2974
3312
|
init_logger();
|
|
2975
3313
|
var searchRelationshipTool = {
|
|
2976
3314
|
name: "remember_search_relationship",
|
|
@@ -3024,6 +3362,12 @@ var searchRelationshipTool = {
|
|
|
3024
3362
|
type: "number",
|
|
3025
3363
|
description: "Offset for pagination (default: 0)",
|
|
3026
3364
|
minimum: 0
|
|
3365
|
+
},
|
|
3366
|
+
deleted_filter: {
|
|
3367
|
+
type: "string",
|
|
3368
|
+
enum: ["exclude", "include", "only"],
|
|
3369
|
+
default: "exclude",
|
|
3370
|
+
description: 'Filter deleted memories: "exclude" (default, hide deleted), "include" (show all), "only" (show only deleted)'
|
|
3027
3371
|
}
|
|
3028
3372
|
},
|
|
3029
3373
|
required: ["query"]
|
|
@@ -3039,7 +3383,11 @@ async function handleSearchRelationship(args, userId) {
|
|
|
3039
3383
|
const collection = getMemoryCollection(userId);
|
|
3040
3384
|
const limit = args.limit ?? 10;
|
|
3041
3385
|
const offset = args.offset ?? 0;
|
|
3386
|
+
const deletedFilter = buildDeletedFilter(collection, args.deleted_filter || "exclude");
|
|
3042
3387
|
const filterList = [];
|
|
3388
|
+
if (deletedFilter) {
|
|
3389
|
+
filterList.push(deletedFilter);
|
|
3390
|
+
}
|
|
3043
3391
|
filterList.push(
|
|
3044
3392
|
collection.filter.byProperty("doc_type").equal("relationship")
|
|
3045
3393
|
);
|
|
@@ -3052,7 +3400,7 @@ async function handleSearchRelationship(args, userId) {
|
|
|
3052
3400
|
const typeFilters = args.relationship_types.map(
|
|
3053
3401
|
(type) => collection.filter.byProperty("relationship_type").equal(type)
|
|
3054
3402
|
);
|
|
3055
|
-
filterList.push(
|
|
3403
|
+
filterList.push(Filters3.or(...typeFilters));
|
|
3056
3404
|
}
|
|
3057
3405
|
}
|
|
3058
3406
|
if (args.strength_min !== void 0) {
|
|
@@ -3070,7 +3418,7 @@ async function handleSearchRelationship(args, userId) {
|
|
|
3070
3418
|
collection.filter.byProperty("tags").containsAny(args.tags)
|
|
3071
3419
|
);
|
|
3072
3420
|
}
|
|
3073
|
-
const combinedFilters =
|
|
3421
|
+
const combinedFilters = combineFiltersWithAnd(filterList);
|
|
3074
3422
|
const searchOptions = {
|
|
3075
3423
|
alpha: 1,
|
|
3076
3424
|
// Pure semantic search for relationships
|
|
@@ -3540,369 +3888,137 @@ Common examples:
|
|
|
3540
3888
|
type: "object",
|
|
3541
3889
|
properties: {
|
|
3542
3890
|
preferences: {
|
|
3543
|
-
...getPreferencesSchema(),
|
|
3544
|
-
description: "Partial preferences object with fields to update"
|
|
3545
|
-
}
|
|
3546
|
-
},
|
|
3547
|
-
required: ["preferences"]
|
|
3548
|
-
}
|
|
3549
|
-
};
|
|
3550
|
-
function formatPreferenceChangeMessage(updates) {
|
|
3551
|
-
const changes = [];
|
|
3552
|
-
if (updates.templates) {
|
|
3553
|
-
if (updates.templates.auto_suggest !== void 0) {
|
|
3554
|
-
changes.push(
|
|
3555
|
-
updates.templates.auto_suggest ? "Template suggestions enabled" : "Template suggestions disabled"
|
|
3556
|
-
);
|
|
3557
|
-
}
|
|
3558
|
-
if (updates.templates.suppressed_categories) {
|
|
3559
|
-
changes.push(`Suppressed categories: ${updates.templates.suppressed_categories.join(", ")}`);
|
|
3560
|
-
}
|
|
3561
|
-
}
|
|
3562
|
-
if (updates.search) {
|
|
3563
|
-
if (updates.search.default_limit !== void 0) {
|
|
3564
|
-
changes.push(`Search limit set to ${updates.search.default_limit}`);
|
|
3565
|
-
}
|
|
3566
|
-
if (updates.search.default_alpha !== void 0) {
|
|
3567
|
-
changes.push(`Search alpha set to ${updates.search.default_alpha}`);
|
|
3568
|
-
}
|
|
3569
|
-
}
|
|
3570
|
-
if (updates.privacy) {
|
|
3571
|
-
if (updates.privacy.default_trust_level !== void 0) {
|
|
3572
|
-
changes.push(`Default trust level set to ${updates.privacy.default_trust_level}`);
|
|
3573
|
-
}
|
|
3574
|
-
}
|
|
3575
|
-
if (updates.location) {
|
|
3576
|
-
if (updates.location.auto_capture !== void 0) {
|
|
3577
|
-
changes.push(
|
|
3578
|
-
updates.location.auto_capture ? "Location auto-capture enabled" : "Location auto-capture disabled"
|
|
3579
|
-
);
|
|
3580
|
-
}
|
|
3581
|
-
}
|
|
3582
|
-
if (changes.length === 0) {
|
|
3583
|
-
return "Preferences updated successfully";
|
|
3584
|
-
}
|
|
3585
|
-
return `Preferences updated: ${changes.join(", ")}`;
|
|
3586
|
-
}
|
|
3587
|
-
async function handleSetPreference(args, userId) {
|
|
3588
|
-
try {
|
|
3589
|
-
const { preferences } = args;
|
|
3590
|
-
logger.info("Setting preferences", { userId, updates: Object.keys(preferences) });
|
|
3591
|
-
const updatedPreferences = await PreferencesDatabaseService.updatePreferences(
|
|
3592
|
-
userId,
|
|
3593
|
-
preferences
|
|
3594
|
-
);
|
|
3595
|
-
const message = formatPreferenceChangeMessage(preferences);
|
|
3596
|
-
const result = {
|
|
3597
|
-
success: true,
|
|
3598
|
-
updated_preferences: updatedPreferences,
|
|
3599
|
-
message
|
|
3600
|
-
};
|
|
3601
|
-
logger.info("Preferences set successfully", { userId });
|
|
3602
|
-
return JSON.stringify(result, null, 2);
|
|
3603
|
-
} catch (error) {
|
|
3604
|
-
handleToolError(error, {
|
|
3605
|
-
toolName: "remember_set_preference",
|
|
3606
|
-
operation: "set preference",
|
|
3607
|
-
userId,
|
|
3608
|
-
preferencesProvided: Object.keys(args.preferences || {}).length
|
|
3609
|
-
});
|
|
3610
|
-
}
|
|
3611
|
-
}
|
|
3612
|
-
|
|
3613
|
-
// src/tools/get-preferences.ts
|
|
3614
|
-
init_logger();
|
|
3615
|
-
var getPreferencesTool = {
|
|
3616
|
-
name: "remember_get_preferences",
|
|
3617
|
-
description: `Get current user preferences.
|
|
3618
|
-
|
|
3619
|
-
Use this to understand user's current settings before suggesting changes
|
|
3620
|
-
or to explain why system is behaving a certain way.
|
|
3621
|
-
|
|
3622
|
-
Returns the complete preferences object or filtered by category.
|
|
3623
|
-
If preferences don't exist, returns defaults.
|
|
3624
|
-
|
|
3625
|
-
${getPreferenceDescription()}
|
|
3626
|
-
`,
|
|
3627
|
-
inputSchema: {
|
|
3628
|
-
type: "object",
|
|
3629
|
-
properties: {
|
|
3630
|
-
category: {
|
|
3631
|
-
type: "string",
|
|
3632
|
-
enum: ["templates", "search", "location", "privacy", "notifications", "display"],
|
|
3633
|
-
description: "Optional category to filter preferences"
|
|
3634
|
-
}
|
|
3635
|
-
}
|
|
3636
|
-
}
|
|
3637
|
-
};
|
|
3638
|
-
async function handleGetPreferences(args, userId) {
|
|
3639
|
-
try {
|
|
3640
|
-
const { category } = args;
|
|
3641
|
-
logger.info("Getting preferences", { userId, category });
|
|
3642
|
-
const preferences = await PreferencesDatabaseService.getPreferences(userId);
|
|
3643
|
-
const isDefault = !preferences.created_at || preferences.created_at === preferences.updated_at;
|
|
3644
|
-
let result;
|
|
3645
|
-
let message;
|
|
3646
|
-
if (category) {
|
|
3647
|
-
if (!PREFERENCE_CATEGORIES.includes(category)) {
|
|
3648
|
-
throw new Error(`Invalid category: ${category}. Valid categories: ${PREFERENCE_CATEGORIES.join(", ")}`);
|
|
3649
|
-
}
|
|
3650
|
-
result = {
|
|
3651
|
-
[category]: preferences[category]
|
|
3652
|
-
};
|
|
3653
|
-
message = isDefault ? `Showing default ${category} preferences (user has not customized preferences yet).` : `Showing current ${category} preferences.`;
|
|
3654
|
-
} else {
|
|
3655
|
-
result = preferences;
|
|
3656
|
-
message = isDefault ? "Showing default preferences (user has not customized preferences yet)." : "Showing current user preferences.";
|
|
3657
|
-
}
|
|
3658
|
-
const response = {
|
|
3659
|
-
preferences: result,
|
|
3660
|
-
is_default: isDefault,
|
|
3661
|
-
message
|
|
3662
|
-
};
|
|
3663
|
-
logger.info("Preferences retrieved successfully", { userId, category, isDefault });
|
|
3664
|
-
return JSON.stringify(response, null, 2);
|
|
3665
|
-
} catch (error) {
|
|
3666
|
-
handleToolError(error, {
|
|
3667
|
-
toolName: "remember_get_preferences",
|
|
3668
|
-
operation: "get preferences",
|
|
3669
|
-
userId,
|
|
3670
|
-
category: args.category
|
|
3671
|
-
});
|
|
3672
|
-
}
|
|
3673
|
-
}
|
|
3674
|
-
|
|
3675
|
-
// src/services/confirmation-token.service.ts
|
|
3676
|
-
import { randomUUID } from "crypto";
|
|
3677
|
-
init_logger();
|
|
3678
|
-
var ConfirmationTokenService = class {
|
|
3679
|
-
EXPIRY_MINUTES = 5;
|
|
3680
|
-
/**
|
|
3681
|
-
* Create a new confirmation request
|
|
3682
|
-
*
|
|
3683
|
-
* @param userId - User ID who initiated the request
|
|
3684
|
-
* @param action - Action type (e.g., 'publish_memory')
|
|
3685
|
-
* @param payload - Data to store with the request
|
|
3686
|
-
* @param targetCollection - Optional target collection (e.g., 'the_void')
|
|
3687
|
-
* @returns Request ID and token
|
|
3688
|
-
*/
|
|
3689
|
-
async createRequest(userId, action, payload, targetCollection) {
|
|
3690
|
-
try {
|
|
3691
|
-
const token = randomUUID();
|
|
3692
|
-
const now = /* @__PURE__ */ new Date();
|
|
3693
|
-
const expiresAt = new Date(now.getTime() + this.EXPIRY_MINUTES * 60 * 1e3);
|
|
3694
|
-
const request = {
|
|
3695
|
-
user_id: userId,
|
|
3696
|
-
token,
|
|
3697
|
-
action,
|
|
3698
|
-
target_collection: targetCollection,
|
|
3699
|
-
payload,
|
|
3700
|
-
created_at: now.toISOString(),
|
|
3701
|
-
expires_at: expiresAt.toISOString(),
|
|
3702
|
-
status: "pending"
|
|
3703
|
-
};
|
|
3704
|
-
const collectionPath = `users/${userId}/requests`;
|
|
3705
|
-
logger.info("Creating confirmation request", {
|
|
3706
|
-
service: "ConfirmationTokenService",
|
|
3707
|
-
userId,
|
|
3708
|
-
action,
|
|
3709
|
-
targetCollection,
|
|
3710
|
-
collectionPath,
|
|
3711
|
-
payloadKeys: Object.keys(payload)
|
|
3712
|
-
});
|
|
3713
|
-
logger.debug("Calling Firestore addDocument", {
|
|
3714
|
-
service: "ConfirmationTokenService",
|
|
3715
|
-
collectionPath
|
|
3716
|
-
});
|
|
3717
|
-
const docRef = await addDocument(collectionPath, request);
|
|
3718
|
-
logger.debug("Firestore addDocument returned", {
|
|
3719
|
-
service: "ConfirmationTokenService",
|
|
3720
|
-
hasDocRef: !!docRef,
|
|
3721
|
-
hasId: !!docRef?.id,
|
|
3722
|
-
docRefId: docRef?.id
|
|
3723
|
-
});
|
|
3724
|
-
if (!docRef) {
|
|
3725
|
-
const error = new Error("Firestore addDocument returned null/undefined");
|
|
3726
|
-
logger.error("CRITICAL: addDocument returned null", {
|
|
3727
|
-
service: "ConfirmationTokenService",
|
|
3728
|
-
userId,
|
|
3729
|
-
collectionPath
|
|
3730
|
-
});
|
|
3731
|
-
throw error;
|
|
3732
|
-
}
|
|
3733
|
-
if (!docRef.id) {
|
|
3734
|
-
const error = new Error("Firestore addDocument returned docRef without ID");
|
|
3735
|
-
logger.error("CRITICAL: docRef has no ID", {
|
|
3736
|
-
service: "ConfirmationTokenService",
|
|
3737
|
-
userId,
|
|
3738
|
-
collectionPath,
|
|
3739
|
-
docRef
|
|
3740
|
-
});
|
|
3741
|
-
throw error;
|
|
3742
|
-
}
|
|
3743
|
-
logger.info("Confirmation request created successfully", {
|
|
3744
|
-
service: "ConfirmationTokenService",
|
|
3745
|
-
requestId: docRef.id,
|
|
3746
|
-
token,
|
|
3747
|
-
expiresAt: request.expires_at
|
|
3748
|
-
});
|
|
3749
|
-
return { requestId: docRef.id, token };
|
|
3750
|
-
} catch (error) {
|
|
3751
|
-
logger.error("Failed to create confirmation request", {
|
|
3752
|
-
service: "ConfirmationTokenService",
|
|
3753
|
-
error: error instanceof Error ? error.message : String(error),
|
|
3754
|
-
stack: error instanceof Error ? error.stack : void 0,
|
|
3755
|
-
userId,
|
|
3756
|
-
action,
|
|
3757
|
-
collectionPath: `users/${userId}/requests`
|
|
3758
|
-
});
|
|
3759
|
-
throw error;
|
|
3760
|
-
}
|
|
3761
|
-
}
|
|
3762
|
-
/**
|
|
3763
|
-
* Validate and retrieve a confirmation request
|
|
3764
|
-
*
|
|
3765
|
-
* @param userId - User ID
|
|
3766
|
-
* @param token - Confirmation token
|
|
3767
|
-
* @returns Request with request_id if valid, null otherwise
|
|
3768
|
-
*/
|
|
3769
|
-
async validateToken(userId, token) {
|
|
3770
|
-
const collectionPath = `users/${userId}/requests`;
|
|
3771
|
-
logger.debug("Validating confirmation token", {
|
|
3772
|
-
service: "ConfirmationTokenService",
|
|
3773
|
-
userId,
|
|
3774
|
-
token,
|
|
3775
|
-
collectionPath
|
|
3776
|
-
});
|
|
3777
|
-
const queryOptions = {
|
|
3778
|
-
where: [
|
|
3779
|
-
{ field: "token", op: "==", value: token },
|
|
3780
|
-
{ field: "status", op: "==", value: "pending" }
|
|
3781
|
-
],
|
|
3782
|
-
limit: 1
|
|
3783
|
-
};
|
|
3784
|
-
const results = await queryDocuments(collectionPath, queryOptions);
|
|
3785
|
-
logger.debug("Token query results", {
|
|
3786
|
-
service: "ConfirmationTokenService",
|
|
3787
|
-
resultsFound: results.length,
|
|
3788
|
-
hasResults: results.length > 0
|
|
3789
|
-
});
|
|
3790
|
-
if (results.length === 0) {
|
|
3791
|
-
logger.info("Token not found or not pending", {
|
|
3792
|
-
service: "ConfirmationTokenService",
|
|
3793
|
-
userId
|
|
3794
|
-
});
|
|
3795
|
-
return null;
|
|
3891
|
+
...getPreferencesSchema(),
|
|
3892
|
+
description: "Partial preferences object with fields to update"
|
|
3893
|
+
}
|
|
3894
|
+
},
|
|
3895
|
+
required: ["preferences"]
|
|
3896
|
+
}
|
|
3897
|
+
};
|
|
3898
|
+
function formatPreferenceChangeMessage(updates) {
|
|
3899
|
+
const changes = [];
|
|
3900
|
+
if (updates.templates) {
|
|
3901
|
+
if (updates.templates.auto_suggest !== void 0) {
|
|
3902
|
+
changes.push(
|
|
3903
|
+
updates.templates.auto_suggest ? "Template suggestions enabled" : "Template suggestions disabled"
|
|
3904
|
+
);
|
|
3796
3905
|
}
|
|
3797
|
-
|
|
3798
|
-
|
|
3799
|
-
logger.info("Confirmation request found", {
|
|
3800
|
-
service: "ConfirmationTokenService",
|
|
3801
|
-
requestId: doc.id,
|
|
3802
|
-
action: request.action,
|
|
3803
|
-
status: request.status,
|
|
3804
|
-
expiresAt: request.expires_at
|
|
3805
|
-
});
|
|
3806
|
-
const expiresAt = new Date(request.expires_at);
|
|
3807
|
-
if (expiresAt.getTime() < Date.now()) {
|
|
3808
|
-
logger.info("Token expired", {
|
|
3809
|
-
service: "ConfirmationTokenService",
|
|
3810
|
-
requestId: doc.id,
|
|
3811
|
-
expiresAt: request.expires_at
|
|
3812
|
-
});
|
|
3813
|
-
await this.updateStatus(userId, doc.id, "expired");
|
|
3814
|
-
return null;
|
|
3906
|
+
if (updates.templates.suppressed_categories) {
|
|
3907
|
+
changes.push(`Suppressed categories: ${updates.templates.suppressed_categories.join(", ")}`);
|
|
3815
3908
|
}
|
|
3816
|
-
return {
|
|
3817
|
-
...request,
|
|
3818
|
-
request_id: doc.id
|
|
3819
|
-
};
|
|
3820
3909
|
}
|
|
3821
|
-
|
|
3822
|
-
|
|
3823
|
-
|
|
3824
|
-
|
|
3825
|
-
|
|
3826
|
-
|
|
3827
|
-
*/
|
|
3828
|
-
async confirmRequest(userId, token) {
|
|
3829
|
-
const request = await this.validateToken(userId, token);
|
|
3830
|
-
if (!request) {
|
|
3831
|
-
return null;
|
|
3910
|
+
if (updates.search) {
|
|
3911
|
+
if (updates.search.default_limit !== void 0) {
|
|
3912
|
+
changes.push(`Search limit set to ${updates.search.default_limit}`);
|
|
3913
|
+
}
|
|
3914
|
+
if (updates.search.default_alpha !== void 0) {
|
|
3915
|
+
changes.push(`Search alpha set to ${updates.search.default_alpha}`);
|
|
3832
3916
|
}
|
|
3833
|
-
await this.updateStatus(userId, request.request_id, "confirmed");
|
|
3834
|
-
return {
|
|
3835
|
-
...request,
|
|
3836
|
-
status: "confirmed",
|
|
3837
|
-
confirmed_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
3838
|
-
};
|
|
3839
3917
|
}
|
|
3840
|
-
|
|
3841
|
-
|
|
3842
|
-
|
|
3843
|
-
* @param userId - User ID
|
|
3844
|
-
* @param token - Confirmation token
|
|
3845
|
-
* @returns True if denied successfully, false otherwise
|
|
3846
|
-
*/
|
|
3847
|
-
async denyRequest(userId, token) {
|
|
3848
|
-
const request = await this.validateToken(userId, token);
|
|
3849
|
-
if (!request) {
|
|
3850
|
-
return false;
|
|
3918
|
+
if (updates.privacy) {
|
|
3919
|
+
if (updates.privacy.default_trust_level !== void 0) {
|
|
3920
|
+
changes.push(`Default trust level set to ${updates.privacy.default_trust_level}`);
|
|
3851
3921
|
}
|
|
3852
|
-
await this.updateStatus(userId, request.request_id, "denied");
|
|
3853
|
-
return true;
|
|
3854
3922
|
}
|
|
3855
|
-
|
|
3856
|
-
|
|
3857
|
-
|
|
3858
|
-
|
|
3859
|
-
|
|
3860
|
-
* @returns True if retracted successfully, false otherwise
|
|
3861
|
-
*/
|
|
3862
|
-
async retractRequest(userId, token) {
|
|
3863
|
-
const request = await this.validateToken(userId, token);
|
|
3864
|
-
if (!request) {
|
|
3865
|
-
return false;
|
|
3923
|
+
if (updates.location) {
|
|
3924
|
+
if (updates.location.auto_capture !== void 0) {
|
|
3925
|
+
changes.push(
|
|
3926
|
+
updates.location.auto_capture ? "Location auto-capture enabled" : "Location auto-capture disabled"
|
|
3927
|
+
);
|
|
3866
3928
|
}
|
|
3867
|
-
await this.updateStatus(userId, request.request_id, "retracted");
|
|
3868
|
-
return true;
|
|
3869
3929
|
}
|
|
3870
|
-
|
|
3871
|
-
|
|
3872
|
-
|
|
3873
|
-
|
|
3874
|
-
|
|
3875
|
-
|
|
3876
|
-
|
|
3877
|
-
|
|
3878
|
-
|
|
3879
|
-
const
|
|
3880
|
-
|
|
3930
|
+
if (changes.length === 0) {
|
|
3931
|
+
return "Preferences updated successfully";
|
|
3932
|
+
}
|
|
3933
|
+
return `Preferences updated: ${changes.join(", ")}`;
|
|
3934
|
+
}
|
|
3935
|
+
async function handleSetPreference(args, userId) {
|
|
3936
|
+
try {
|
|
3937
|
+
const { preferences } = args;
|
|
3938
|
+
logger.info("Setting preferences", { userId, updates: Object.keys(preferences) });
|
|
3939
|
+
const updatedPreferences = await PreferencesDatabaseService.updatePreferences(
|
|
3940
|
+
userId,
|
|
3941
|
+
preferences
|
|
3942
|
+
);
|
|
3943
|
+
const message = formatPreferenceChangeMessage(preferences);
|
|
3944
|
+
const result = {
|
|
3945
|
+
success: true,
|
|
3946
|
+
updated_preferences: updatedPreferences,
|
|
3947
|
+
message
|
|
3881
3948
|
};
|
|
3882
|
-
|
|
3883
|
-
|
|
3949
|
+
logger.info("Preferences set successfully", { userId });
|
|
3950
|
+
return JSON.stringify(result, null, 2);
|
|
3951
|
+
} catch (error) {
|
|
3952
|
+
handleToolError(error, {
|
|
3953
|
+
toolName: "remember_set_preference",
|
|
3954
|
+
operation: "set preference",
|
|
3955
|
+
userId,
|
|
3956
|
+
preferencesProvided: Object.keys(args.preferences || {}).length
|
|
3957
|
+
});
|
|
3958
|
+
}
|
|
3959
|
+
}
|
|
3960
|
+
|
|
3961
|
+
// src/tools/get-preferences.ts
|
|
3962
|
+
init_logger();
|
|
3963
|
+
var getPreferencesTool = {
|
|
3964
|
+
name: "remember_get_preferences",
|
|
3965
|
+
description: `Get current user preferences.
|
|
3966
|
+
|
|
3967
|
+
Use this to understand user's current settings before suggesting changes
|
|
3968
|
+
or to explain why system is behaving a certain way.
|
|
3969
|
+
|
|
3970
|
+
Returns the complete preferences object or filtered by category.
|
|
3971
|
+
If preferences don't exist, returns defaults.
|
|
3972
|
+
|
|
3973
|
+
${getPreferenceDescription()}
|
|
3974
|
+
`,
|
|
3975
|
+
inputSchema: {
|
|
3976
|
+
type: "object",
|
|
3977
|
+
properties: {
|
|
3978
|
+
category: {
|
|
3979
|
+
type: "string",
|
|
3980
|
+
enum: ["templates", "search", "location", "privacy", "notifications", "display"],
|
|
3981
|
+
description: "Optional category to filter preferences"
|
|
3982
|
+
}
|
|
3884
3983
|
}
|
|
3885
|
-
await updateDocument(collectionPath, requestId, updateData);
|
|
3886
3984
|
}
|
|
3887
|
-
|
|
3888
|
-
|
|
3889
|
-
|
|
3890
|
-
|
|
3891
|
-
|
|
3892
|
-
|
|
3893
|
-
|
|
3894
|
-
|
|
3895
|
-
|
|
3896
|
-
|
|
3897
|
-
|
|
3898
|
-
|
|
3899
|
-
|
|
3900
|
-
|
|
3985
|
+
};
|
|
3986
|
+
async function handleGetPreferences(args, userId) {
|
|
3987
|
+
try {
|
|
3988
|
+
const { category } = args;
|
|
3989
|
+
logger.info("Getting preferences", { userId, category });
|
|
3990
|
+
const preferences = await PreferencesDatabaseService.getPreferences(userId);
|
|
3991
|
+
const isDefault = !preferences.created_at || preferences.created_at === preferences.updated_at;
|
|
3992
|
+
let result;
|
|
3993
|
+
let message;
|
|
3994
|
+
if (category) {
|
|
3995
|
+
if (!PREFERENCE_CATEGORIES.includes(category)) {
|
|
3996
|
+
throw new Error(`Invalid category: ${category}. Valid categories: ${PREFERENCE_CATEGORIES.join(", ")}`);
|
|
3997
|
+
}
|
|
3998
|
+
result = {
|
|
3999
|
+
[category]: preferences[category]
|
|
4000
|
+
};
|
|
4001
|
+
message = isDefault ? `Showing default ${category} preferences (user has not customized preferences yet).` : `Showing current ${category} preferences.`;
|
|
4002
|
+
} else {
|
|
4003
|
+
result = preferences;
|
|
4004
|
+
message = isDefault ? "Showing default preferences (user has not customized preferences yet)." : "Showing current user preferences.";
|
|
4005
|
+
}
|
|
4006
|
+
const response = {
|
|
4007
|
+
preferences: result,
|
|
4008
|
+
is_default: isDefault,
|
|
4009
|
+
message
|
|
4010
|
+
};
|
|
4011
|
+
logger.info("Preferences retrieved successfully", { userId, category, isDefault });
|
|
4012
|
+
return JSON.stringify(response, null, 2);
|
|
4013
|
+
} catch (error) {
|
|
4014
|
+
handleToolError(error, {
|
|
4015
|
+
toolName: "remember_get_preferences",
|
|
4016
|
+
operation: "get preferences",
|
|
4017
|
+
userId,
|
|
4018
|
+
category: args.category
|
|
3901
4019
|
});
|
|
3902
|
-
return 0;
|
|
3903
4020
|
}
|
|
3904
|
-
}
|
|
3905
|
-
var confirmationTokenService = new ConfirmationTokenService();
|
|
4021
|
+
}
|
|
3906
4022
|
|
|
3907
4023
|
// src/weaviate/space-schema.ts
|
|
3908
4024
|
init_space_memory();
|
|
@@ -3944,11 +4060,6 @@ async function createSpaceCollection(client2, spaceId) {
|
|
|
3944
4060
|
dataType: "text[]",
|
|
3945
4061
|
description: 'Spaces this memory is published to (e.g., ["the_void", "dogs"])'
|
|
3946
4062
|
},
|
|
3947
|
-
{
|
|
3948
|
-
name: "space_id",
|
|
3949
|
-
dataType: "text",
|
|
3950
|
-
description: "DEPRECATED: Use spaces array instead. Will be removed in v3.0.0."
|
|
3951
|
-
},
|
|
3952
4063
|
{
|
|
3953
4064
|
name: "author_id",
|
|
3954
4065
|
dataType: "text",
|
|
@@ -4173,6 +4284,22 @@ async function createSpaceCollection(client2, spaceId) {
|
|
|
4173
4284
|
name: "moderation_flags",
|
|
4174
4285
|
dataType: "text[]",
|
|
4175
4286
|
description: 'Per-space moderation flags (format: "{space_id}:{flag_type}")'
|
|
4287
|
+
},
|
|
4288
|
+
// Soft delete fields
|
|
4289
|
+
{
|
|
4290
|
+
name: "deleted_at",
|
|
4291
|
+
dataType: "date",
|
|
4292
|
+
description: "Timestamp when memory was soft-deleted (null = not deleted)"
|
|
4293
|
+
},
|
|
4294
|
+
{
|
|
4295
|
+
name: "deleted_by",
|
|
4296
|
+
dataType: "text",
|
|
4297
|
+
description: "User ID who deleted the memory"
|
|
4298
|
+
},
|
|
4299
|
+
{
|
|
4300
|
+
name: "deletion_reason",
|
|
4301
|
+
dataType: "text",
|
|
4302
|
+
description: "Optional reason for deletion"
|
|
4176
4303
|
}
|
|
4177
4304
|
]
|
|
4178
4305
|
});
|
|
@@ -4472,6 +4599,9 @@ async function handleConfirm(args, userId) {
|
|
|
4472
4599
|
if (request.action === "publish_memory") {
|
|
4473
4600
|
return await executePublishMemory(request, userId);
|
|
4474
4601
|
}
|
|
4602
|
+
if (request.action === "delete_memory") {
|
|
4603
|
+
return await executeDeleteMemory(request, userId);
|
|
4604
|
+
}
|
|
4475
4605
|
throw new Error(`Unknown action type: ${request.action}`);
|
|
4476
4606
|
} catch (error) {
|
|
4477
4607
|
debug.error("Tool failed", {
|
|
@@ -4684,6 +4814,52 @@ async function executePublishMemory(request, userId) {
|
|
|
4684
4814
|
});
|
|
4685
4815
|
}
|
|
4686
4816
|
}
|
|
4817
|
+
async function executeDeleteMemory(request, userId) {
|
|
4818
|
+
try {
|
|
4819
|
+
logger.info("Executing delete memory action", {
|
|
4820
|
+
function: "executeDeleteMemory",
|
|
4821
|
+
userId,
|
|
4822
|
+
memoryId: request.payload.memory_id,
|
|
4823
|
+
hasReason: !!request.payload.reason
|
|
4824
|
+
});
|
|
4825
|
+
const { memory_id, reason } = request.payload;
|
|
4826
|
+
const client2 = getWeaviateClient();
|
|
4827
|
+
const collectionName = `Memory_${sanitizeUserId(userId)}`;
|
|
4828
|
+
const collection = client2.collections.get(collectionName);
|
|
4829
|
+
await collection.data.update({
|
|
4830
|
+
id: memory_id,
|
|
4831
|
+
properties: {
|
|
4832
|
+
deleted_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4833
|
+
deleted_by: userId,
|
|
4834
|
+
deletion_reason: reason || null
|
|
4835
|
+
}
|
|
4836
|
+
});
|
|
4837
|
+
logger.info("Memory soft-deleted successfully", {
|
|
4838
|
+
function: "executeDeleteMemory",
|
|
4839
|
+
userId,
|
|
4840
|
+
memoryId: memory_id,
|
|
4841
|
+
deletedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
4842
|
+
});
|
|
4843
|
+
return JSON.stringify(
|
|
4844
|
+
{
|
|
4845
|
+
success: true,
|
|
4846
|
+
memory_id,
|
|
4847
|
+
message: "Memory deleted successfully"
|
|
4848
|
+
},
|
|
4849
|
+
null,
|
|
4850
|
+
2
|
|
4851
|
+
);
|
|
4852
|
+
} catch (error) {
|
|
4853
|
+
logger.error("Failed to execute delete memory", {
|
|
4854
|
+
function: "executeDeleteMemory",
|
|
4855
|
+
userId,
|
|
4856
|
+
memoryId: request.payload.memory_id,
|
|
4857
|
+
error: error instanceof Error ? error.message : String(error),
|
|
4858
|
+
stack: error instanceof Error ? error.stack : void 0
|
|
4859
|
+
});
|
|
4860
|
+
throw error;
|
|
4861
|
+
}
|
|
4862
|
+
}
|
|
4687
4863
|
|
|
4688
4864
|
// src/tools/deny.ts
|
|
4689
4865
|
var denyTool = {
|
|
@@ -4742,7 +4918,7 @@ async function handleDeny(args, userId) {
|
|
|
4742
4918
|
}
|
|
4743
4919
|
|
|
4744
4920
|
// src/tools/search-space.ts
|
|
4745
|
-
import { Filters as
|
|
4921
|
+
import { Filters as Filters4 } from "weaviate-client";
|
|
4746
4922
|
init_space_memory();
|
|
4747
4923
|
var searchSpaceTool = {
|
|
4748
4924
|
name: "remember_search_space",
|
|
@@ -4885,7 +5061,7 @@ async function handleSearchSpace(args, userId) {
|
|
|
4885
5061
|
if (args.date_to) {
|
|
4886
5062
|
filterList.push(publicCollection.filter.byProperty("created_at").lessOrEqual(new Date(args.date_to)));
|
|
4887
5063
|
}
|
|
4888
|
-
const whereFilter = filterList.length > 0 ?
|
|
5064
|
+
const whereFilter = filterList.length > 0 ? Filters4.and(...filterList) : void 0;
|
|
4889
5065
|
debug.debug("Executing hybrid search", {
|
|
4890
5066
|
query: args.query,
|
|
4891
5067
|
filterCount: filterList.length,
|
|
@@ -4935,7 +5111,7 @@ async function handleSearchSpace(args, userId) {
|
|
|
4935
5111
|
}
|
|
4936
5112
|
|
|
4937
5113
|
// src/tools/query-space.ts
|
|
4938
|
-
import { Filters as
|
|
5114
|
+
import { Filters as Filters5 } from "weaviate-client";
|
|
4939
5115
|
init_space_memory();
|
|
4940
5116
|
var querySpaceTool = {
|
|
4941
5117
|
name: "remember_query_space",
|
|
@@ -5065,7 +5241,7 @@ async function handleQuerySpace(args, userId) {
|
|
|
5065
5241
|
if (args.date_to) {
|
|
5066
5242
|
filterList.push(publicCollection.filter.byProperty("created_at").lessOrEqual(new Date(args.date_to)));
|
|
5067
5243
|
}
|
|
5068
|
-
const whereFilter = filterList.length > 0 ?
|
|
5244
|
+
const whereFilter = filterList.length > 0 ? Filters5.and(...filterList) : void 0;
|
|
5069
5245
|
debug.debug("Executing semantic query", {
|
|
5070
5246
|
question: args.question,
|
|
5071
5247
|
filterCount: filterList.length,
|