@prmichaelsen/remember-mcp 3.14.11 → 3.14.14
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/CHANGELOG.md +20 -0
- package/agent/milestones/milestone-18-performance-tuning.md +45 -0
- package/agent/progress.yaml +86 -2
- package/agent/tasks/task-77-parallelize-checkiffriend.md +62 -0
- package/agent/tasks/task-78-cache-checkiffriend.md +78 -0
- package/agent/tasks/task-79-memoize-core-services.md +75 -0
- package/agent/tasks/task-80-parallelize-startup-health-checks.md +57 -0
- package/agent/tasks/task-81-optimize-ghost-config-block-unblock.md +64 -0
- package/agent/tasks/task-82-native-weaviate-offset.md +69 -0
- package/agent/tasks/task-83-eliminate-redundant-validatetoken.md +53 -0
- package/agent/tasks/task-84-static-imports-server-factory.md +52 -0
- package/dist/core-services.d.ts +3 -1
- package/dist/server-factory.js +250 -482
- package/dist/server.js +29 -140
- package/dist/services/access-control.d.ts +5 -5
- package/dist/services/ghost-config.service.d.ts +2 -0
- package/package.json +1 -1
- package/src/core-services.ts +16 -2
- package/src/server-factory.ts +5 -3
- package/src/server.ts +5 -3
- package/src/services/access-control.spec.ts +11 -11
- package/src/services/access-control.ts +74 -8
- package/src/services/ghost-config.service.spec.ts +22 -15
- package/src/services/ghost-config.service.ts +9 -15
- package/src/tools/query-memory.ts +1 -2
- package/src/tools/search-memory.ts +5 -8
- package/dist/services/trust-enforcement.d.ts +0 -83
- package/dist/services/trust-enforcement.spec.d.ts +0 -2
- package/dist/utils/weaviate-filters.d.ts +0 -56
- package/dist/utils/weaviate-filters.spec.d.ts +0 -8
- package/src/services/trust-enforcement.spec.ts +0 -309
- package/src/services/trust-enforcement.ts +0 -197
- package/src/utils/weaviate-filters.spec.ts +0 -312
- package/src/utils/weaviate-filters.ts +0 -236
package/dist/server-factory.js
CHANGED
|
@@ -515,6 +515,21 @@ var init_logger = __esm({
|
|
|
515
515
|
});
|
|
516
516
|
|
|
517
517
|
// src/firestore/init.ts
|
|
518
|
+
var init_exports = {};
|
|
519
|
+
__export(init_exports, {
|
|
520
|
+
FieldValue: () => FieldValue,
|
|
521
|
+
addDocument: () => addDocument,
|
|
522
|
+
batchWrite: () => batchWrite,
|
|
523
|
+
deleteDocument: () => deleteDocument,
|
|
524
|
+
getDocument: () => getDocument,
|
|
525
|
+
initFirestore: () => initFirestore,
|
|
526
|
+
isFirestoreInitialized: () => isFirestoreInitialized,
|
|
527
|
+
queryDocuments: () => queryDocuments,
|
|
528
|
+
setDocument: () => setDocument,
|
|
529
|
+
testFirestoreConnection: () => testFirestoreConnection,
|
|
530
|
+
updateDocument: () => updateDocument,
|
|
531
|
+
verifyIdToken: () => verifyIdToken
|
|
532
|
+
});
|
|
518
533
|
import { initializeApp } from "@prmichaelsen/firebase-admin-sdk-v8";
|
|
519
534
|
import {
|
|
520
535
|
getDocument,
|
|
@@ -555,370 +570,35 @@ function initFirestore() {
|
|
|
555
570
|
throw error;
|
|
556
571
|
}
|
|
557
572
|
}
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
"src/firestore/init.ts"() {
|
|
561
|
-
"use strict";
|
|
562
|
-
init_config();
|
|
563
|
-
init_logger();
|
|
564
|
-
initialized = false;
|
|
565
|
-
}
|
|
566
|
-
});
|
|
567
|
-
|
|
568
|
-
// src/services/trust-enforcement.ts
|
|
569
|
-
function buildTrustFilter2(collection, accessorTrustLevel) {
|
|
570
|
-
return collection.filter.byProperty("trust_score").lessThanOrEqual(accessorTrustLevel);
|
|
571
|
-
}
|
|
572
|
-
function isTrustSufficient2(memoryTrust, accessorTrust) {
|
|
573
|
-
return accessorTrust >= memoryTrust;
|
|
573
|
+
function isFirestoreInitialized() {
|
|
574
|
+
return initialized;
|
|
574
575
|
}
|
|
575
|
-
|
|
576
|
-
"src/services/trust-enforcement.ts"() {
|
|
577
|
-
"use strict";
|
|
578
|
-
}
|
|
579
|
-
});
|
|
580
|
-
|
|
581
|
-
// src/firestore/paths.ts
|
|
582
|
-
function getBasePrefix2() {
|
|
583
|
-
const environment = process.env.ENVIRONMENT;
|
|
584
|
-
if (environment && environment !== "production" && environment !== "prod") {
|
|
585
|
-
return `${environment}.${APP_NAME2}`;
|
|
586
|
-
}
|
|
587
|
-
const isDevelopment = process.env.NODE_ENV === "development";
|
|
588
|
-
if (isDevelopment) {
|
|
589
|
-
const customPrefix = process.env.DB_PREFIX;
|
|
590
|
-
if (customPrefix) {
|
|
591
|
-
return customPrefix;
|
|
592
|
-
}
|
|
593
|
-
return `e0.${APP_NAME2}`;
|
|
594
|
-
}
|
|
595
|
-
return APP_NAME2;
|
|
596
|
-
}
|
|
597
|
-
var APP_NAME2, BASE2;
|
|
598
|
-
var init_paths = __esm({
|
|
599
|
-
"src/firestore/paths.ts"() {
|
|
600
|
-
"use strict";
|
|
601
|
-
APP_NAME2 = "remember-mcp";
|
|
602
|
-
BASE2 = getBasePrefix2();
|
|
603
|
-
}
|
|
604
|
-
});
|
|
605
|
-
|
|
606
|
-
// src/types/ghost-config.ts
|
|
607
|
-
var DEFAULT_GHOST_CONFIG2;
|
|
608
|
-
var init_ghost_config = __esm({
|
|
609
|
-
"src/types/ghost-config.ts"() {
|
|
610
|
-
"use strict";
|
|
611
|
-
DEFAULT_GHOST_CONFIG2 = {
|
|
612
|
-
enabled: false,
|
|
613
|
-
public_ghost_enabled: false,
|
|
614
|
-
default_friend_trust: 0.25,
|
|
615
|
-
default_public_trust: 0,
|
|
616
|
-
per_user_trust: {},
|
|
617
|
-
blocked_users: [],
|
|
618
|
-
enforcement_mode: "query"
|
|
619
|
-
};
|
|
620
|
-
}
|
|
621
|
-
});
|
|
622
|
-
|
|
623
|
-
// src/services/ghost-config.service.ts
|
|
624
|
-
var ghost_config_service_exports = {};
|
|
625
|
-
__export(ghost_config_service_exports, {
|
|
626
|
-
FirestoreGhostConfigProvider: () => FirestoreGhostConfigProvider2,
|
|
627
|
-
blockUser: () => blockUser2,
|
|
628
|
-
getGhostConfig: () => getGhostConfig2,
|
|
629
|
-
isGhostEnabled: () => isGhostEnabled2,
|
|
630
|
-
removeUserTrust: () => removeUserTrust2,
|
|
631
|
-
setGhostConfigFields: () => setGhostConfigFields2,
|
|
632
|
-
setUserTrust: () => setUserTrust2,
|
|
633
|
-
unblockUser: () => unblockUser2,
|
|
634
|
-
validateGhostConfigUpdate: () => validateGhostConfigUpdate2
|
|
635
|
-
});
|
|
636
|
-
function getGhostConfigPath(ownerUserId) {
|
|
637
|
-
return {
|
|
638
|
-
collectionPath: `${BASE2}.users/${ownerUserId}/ghost_config`,
|
|
639
|
-
docId: "settings"
|
|
640
|
-
};
|
|
641
|
-
}
|
|
642
|
-
async function getGhostConfig2(ownerUserId) {
|
|
576
|
+
async function testFirestoreConnection() {
|
|
643
577
|
try {
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
if (!doc) {
|
|
647
|
-
return { ...DEFAULT_GHOST_CONFIG2 };
|
|
578
|
+
if (!initialized) {
|
|
579
|
+
throw new Error("Firestore not initialized");
|
|
648
580
|
}
|
|
649
|
-
|
|
581
|
+
const { getDocument: getDocument3 } = await import("@prmichaelsen/firebase-admin-sdk-v8");
|
|
582
|
+
await getDocument3("_health_check", "test");
|
|
583
|
+
logger.info("Firestore connection test successful", {
|
|
584
|
+
module: "firestore-init"
|
|
585
|
+
});
|
|
586
|
+
return true;
|
|
650
587
|
} catch (error) {
|
|
651
|
-
logger.error("
|
|
652
|
-
|
|
653
|
-
ownerUserId,
|
|
588
|
+
logger.error("Firestore connection test failed", {
|
|
589
|
+
module: "firestore-init",
|
|
654
590
|
error: error instanceof Error ? error.message : String(error)
|
|
655
591
|
});
|
|
656
|
-
return
|
|
657
|
-
}
|
|
658
|
-
}
|
|
659
|
-
async function setGhostConfigFields2(ownerUserId, config2) {
|
|
660
|
-
const { collectionPath, docId } = getGhostConfigPath(ownerUserId);
|
|
661
|
-
await setDocument(collectionPath, docId, config2, { merge: true });
|
|
662
|
-
logger.info("Ghost config updated", {
|
|
663
|
-
service: SERVICE,
|
|
664
|
-
ownerUserId,
|
|
665
|
-
updatedKeys: Object.keys(config2)
|
|
666
|
-
});
|
|
667
|
-
return getGhostConfig2(ownerUserId);
|
|
668
|
-
}
|
|
669
|
-
async function setUserTrust2(ownerUserId, targetUserId, trustLevel) {
|
|
670
|
-
if (trustLevel < 0 || trustLevel > 1) {
|
|
671
|
-
throw new Error(`Trust level must be between 0 and 1, got ${trustLevel}`);
|
|
672
|
-
}
|
|
673
|
-
const current = await getGhostConfig2(ownerUserId);
|
|
674
|
-
const per_user_trust = { ...current.per_user_trust, [targetUserId]: trustLevel };
|
|
675
|
-
const { collectionPath, docId } = getGhostConfigPath(ownerUserId);
|
|
676
|
-
await setDocument(collectionPath, docId, { per_user_trust }, { merge: true });
|
|
677
|
-
logger.info("User trust level set", {
|
|
678
|
-
service: SERVICE,
|
|
679
|
-
ownerUserId,
|
|
680
|
-
targetUserId,
|
|
681
|
-
trustLevel
|
|
682
|
-
});
|
|
683
|
-
}
|
|
684
|
-
async function removeUserTrust2(ownerUserId, targetUserId) {
|
|
685
|
-
const current = await getGhostConfig2(ownerUserId);
|
|
686
|
-
const per_user_trust = { ...current.per_user_trust };
|
|
687
|
-
delete per_user_trust[targetUserId];
|
|
688
|
-
const { collectionPath, docId } = getGhostConfigPath(ownerUserId);
|
|
689
|
-
await setDocument(collectionPath, docId, { per_user_trust }, { merge: true });
|
|
690
|
-
logger.info("User trust override removed", {
|
|
691
|
-
service: SERVICE,
|
|
692
|
-
ownerUserId,
|
|
693
|
-
targetUserId
|
|
694
|
-
});
|
|
695
|
-
}
|
|
696
|
-
async function blockUser2(ownerUserId, targetUserId) {
|
|
697
|
-
const current = await getGhostConfig2(ownerUserId);
|
|
698
|
-
if (current.blocked_users.includes(targetUserId)) {
|
|
699
|
-
return;
|
|
700
|
-
}
|
|
701
|
-
const blocked_users = [...current.blocked_users, targetUserId];
|
|
702
|
-
const { collectionPath, docId } = getGhostConfigPath(ownerUserId);
|
|
703
|
-
await setDocument(collectionPath, docId, { blocked_users }, { merge: true });
|
|
704
|
-
logger.info("User blocked from ghost access", {
|
|
705
|
-
service: SERVICE,
|
|
706
|
-
ownerUserId,
|
|
707
|
-
targetUserId
|
|
708
|
-
});
|
|
709
|
-
}
|
|
710
|
-
async function unblockUser2(ownerUserId, targetUserId) {
|
|
711
|
-
const current = await getGhostConfig2(ownerUserId);
|
|
712
|
-
if (!current.blocked_users.includes(targetUserId)) {
|
|
713
|
-
return;
|
|
714
|
-
}
|
|
715
|
-
const blocked_users = current.blocked_users.filter((id) => id !== targetUserId);
|
|
716
|
-
const { collectionPath, docId } = getGhostConfigPath(ownerUserId);
|
|
717
|
-
await setDocument(collectionPath, docId, { blocked_users }, { merge: true });
|
|
718
|
-
logger.info("User unblocked from ghost access", {
|
|
719
|
-
service: SERVICE,
|
|
720
|
-
ownerUserId,
|
|
721
|
-
targetUserId
|
|
722
|
-
});
|
|
723
|
-
}
|
|
724
|
-
async function isGhostEnabled2(ownerUserId) {
|
|
725
|
-
const config2 = await getGhostConfig2(ownerUserId);
|
|
726
|
-
return config2.enabled;
|
|
727
|
-
}
|
|
728
|
-
function validateGhostConfigUpdate2(config2) {
|
|
729
|
-
if (config2.default_friend_trust !== void 0) {
|
|
730
|
-
if (config2.default_friend_trust < 0 || config2.default_friend_trust > 1) {
|
|
731
|
-
throw new Error(`default_friend_trust must be between 0 and 1, got ${config2.default_friend_trust}`);
|
|
732
|
-
}
|
|
733
|
-
}
|
|
734
|
-
if (config2.default_public_trust !== void 0) {
|
|
735
|
-
if (config2.default_public_trust < 0 || config2.default_public_trust > 1) {
|
|
736
|
-
throw new Error(`default_public_trust must be between 0 and 1, got ${config2.default_public_trust}`);
|
|
737
|
-
}
|
|
738
|
-
}
|
|
739
|
-
if (config2.enforcement_mode !== void 0) {
|
|
740
|
-
const valid = ["query", "prompt", "hybrid"];
|
|
741
|
-
if (!valid.includes(config2.enforcement_mode)) {
|
|
742
|
-
throw new Error(`enforcement_mode must be one of ${valid.join(", ")}, got ${config2.enforcement_mode}`);
|
|
743
|
-
}
|
|
744
|
-
}
|
|
745
|
-
if (config2.per_user_trust !== void 0) {
|
|
746
|
-
for (const [userId, level] of Object.entries(config2.per_user_trust)) {
|
|
747
|
-
if (level < 0 || level > 1) {
|
|
748
|
-
throw new Error(`Trust level for ${userId} must be between 0 and 1, got ${level}`);
|
|
749
|
-
}
|
|
750
|
-
}
|
|
592
|
+
return false;
|
|
751
593
|
}
|
|
752
594
|
}
|
|
753
|
-
var
|
|
754
|
-
var
|
|
755
|
-
"src/
|
|
595
|
+
var initialized;
|
|
596
|
+
var init_init = __esm({
|
|
597
|
+
"src/firestore/init.ts"() {
|
|
756
598
|
"use strict";
|
|
757
|
-
|
|
758
|
-
init_paths();
|
|
599
|
+
init_config();
|
|
759
600
|
init_logger();
|
|
760
|
-
|
|
761
|
-
SERVICE = "GhostConfigService";
|
|
762
|
-
FirestoreGhostConfigProvider2 = class {
|
|
763
|
-
async getGhostConfig(ownerUserId) {
|
|
764
|
-
const config2 = await getGhostConfig2(ownerUserId);
|
|
765
|
-
if (!config2.enabled) {
|
|
766
|
-
return null;
|
|
767
|
-
}
|
|
768
|
-
return config2;
|
|
769
|
-
}
|
|
770
|
-
};
|
|
771
|
-
}
|
|
772
|
-
});
|
|
773
|
-
|
|
774
|
-
// src/services/access-control.ts
|
|
775
|
-
var access_control_exports = {};
|
|
776
|
-
__export(access_control_exports, {
|
|
777
|
-
InMemoryEscalationStore: () => InMemoryEscalationStore2,
|
|
778
|
-
StubGhostConfigProvider: () => StubGhostConfigProvider2,
|
|
779
|
-
checkMemoryAccess: () => checkMemoryAccess2,
|
|
780
|
-
formatAccessResultMessage: () => formatAccessResultMessage2,
|
|
781
|
-
handleInsufficientTrust: () => handleInsufficientTrust2,
|
|
782
|
-
isMemoryBlocked: () => isMemoryBlocked2,
|
|
783
|
-
resetBlock: () => resetBlock2,
|
|
784
|
-
resolveAccessorTrustLevel: () => resolveAccessorTrustLevel2
|
|
785
|
-
});
|
|
786
|
-
async function checkMemoryAccess2(accessorUserId, memory, ghostConfigProvider, escalationStore) {
|
|
787
|
-
const ownerUserId = memory.user_id;
|
|
788
|
-
const memoryId = memory.id;
|
|
789
|
-
if (accessorUserId === ownerUserId) {
|
|
790
|
-
return { status: "granted", memory, access_level: "owner" };
|
|
791
|
-
}
|
|
792
|
-
const ghostConfig = await ghostConfigProvider.getGhostConfig(ownerUserId);
|
|
793
|
-
if (!ghostConfig || !ghostConfig.enabled) {
|
|
794
|
-
return { status: "no_permission", owner_user_id: ownerUserId, accessor_user_id: accessorUserId };
|
|
795
|
-
}
|
|
796
|
-
if (ghostConfig.blocked_users.includes(accessorUserId)) {
|
|
797
|
-
return { status: "no_permission", owner_user_id: ownerUserId, accessor_user_id: accessorUserId };
|
|
798
|
-
}
|
|
799
|
-
const block = await escalationStore.getBlock(ownerUserId, accessorUserId, memoryId);
|
|
800
|
-
if (block) {
|
|
801
|
-
return {
|
|
802
|
-
status: "blocked",
|
|
803
|
-
memory_id: memoryId,
|
|
804
|
-
reason: block.reason,
|
|
805
|
-
blocked_at: block.blocked_at
|
|
806
|
-
};
|
|
807
|
-
}
|
|
808
|
-
const accessorTrust = resolveAccessorTrustLevel2(ghostConfig, accessorUserId);
|
|
809
|
-
const memoryTrust = memory.trust;
|
|
810
|
-
if (!isTrustSufficient2(memoryTrust, accessorTrust)) {
|
|
811
|
-
const result = await handleInsufficientTrust2(
|
|
812
|
-
ownerUserId,
|
|
813
|
-
accessorUserId,
|
|
814
|
-
memoryId,
|
|
815
|
-
memoryTrust,
|
|
816
|
-
accessorTrust,
|
|
817
|
-
escalationStore
|
|
818
|
-
);
|
|
819
|
-
return result;
|
|
820
|
-
}
|
|
821
|
-
return { status: "granted", memory, access_level: "trusted" };
|
|
822
|
-
}
|
|
823
|
-
async function handleInsufficientTrust2(ownerUserId, accessorUserId, memoryId, requiredTrust, actualTrust, escalationStore) {
|
|
824
|
-
const attempt = await escalationStore.incrementAttempts(ownerUserId, accessorUserId, memoryId);
|
|
825
|
-
if (attempt.count >= MAX_ATTEMPTS_BEFORE_BLOCK2) {
|
|
826
|
-
const block = {
|
|
827
|
-
blocked_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
828
|
-
reason: `Access blocked after ${attempt.count} unauthorized attempts`,
|
|
829
|
-
attempt_count: attempt.count
|
|
830
|
-
};
|
|
831
|
-
await escalationStore.setBlock(ownerUserId, accessorUserId, memoryId, block);
|
|
832
|
-
return {
|
|
833
|
-
status: "blocked",
|
|
834
|
-
memory_id: memoryId,
|
|
835
|
-
reason: block.reason,
|
|
836
|
-
blocked_at: block.blocked_at
|
|
837
|
-
};
|
|
838
|
-
}
|
|
839
|
-
return {
|
|
840
|
-
status: "insufficient_trust",
|
|
841
|
-
memory_id: memoryId,
|
|
842
|
-
required_trust: requiredTrust,
|
|
843
|
-
actual_trust: Math.max(0, actualTrust - TRUST_PENALTY2),
|
|
844
|
-
attempts_remaining: MAX_ATTEMPTS_BEFORE_BLOCK2 - attempt.count
|
|
845
|
-
};
|
|
846
|
-
}
|
|
847
|
-
async function isMemoryBlocked2(ownerUserId, accessorUserId, memoryId, escalationStore) {
|
|
848
|
-
const block = await escalationStore.getBlock(ownerUserId, accessorUserId, memoryId);
|
|
849
|
-
return block !== null;
|
|
850
|
-
}
|
|
851
|
-
async function resetBlock2(ownerUserId, accessorUserId, memoryId, escalationStore) {
|
|
852
|
-
await escalationStore.removeBlock(ownerUserId, accessorUserId, memoryId);
|
|
853
|
-
}
|
|
854
|
-
function resolveAccessorTrustLevel2(ghostConfig, accessorUserId) {
|
|
855
|
-
if (accessorUserId in ghostConfig.per_user_trust) {
|
|
856
|
-
return ghostConfig.per_user_trust[accessorUserId];
|
|
857
|
-
}
|
|
858
|
-
return ghostConfig.default_public_trust ?? 0;
|
|
859
|
-
}
|
|
860
|
-
function formatAccessResultMessage2(result) {
|
|
861
|
-
switch (result.status) {
|
|
862
|
-
case "granted":
|
|
863
|
-
return result.access_level === "owner" ? "Access granted (owner)." : "Access granted (trusted).";
|
|
864
|
-
case "insufficient_trust":
|
|
865
|
-
return `Insufficient trust level. Required: ${result.required_trust.toFixed(2)}, actual: ${result.actual_trust.toFixed(2)}. ${result.attempts_remaining} attempt(s) remaining before access is blocked.`;
|
|
866
|
-
case "blocked":
|
|
867
|
-
return `Access blocked: ${result.reason}`;
|
|
868
|
-
case "no_permission":
|
|
869
|
-
return "No permission to access this user's memories.";
|
|
870
|
-
case "not_found":
|
|
871
|
-
return `Memory ${result.memory_id} not found.`;
|
|
872
|
-
case "deleted":
|
|
873
|
-
return `Memory ${result.memory_id} was deleted on ${result.deleted_at}.`;
|
|
874
|
-
}
|
|
875
|
-
}
|
|
876
|
-
var StubGhostConfigProvider2, InMemoryEscalationStore2, TRUST_PENALTY2, MAX_ATTEMPTS_BEFORE_BLOCK2;
|
|
877
|
-
var init_access_control = __esm({
|
|
878
|
-
"src/services/access-control.ts"() {
|
|
879
|
-
"use strict";
|
|
880
|
-
init_trust_enforcement();
|
|
881
|
-
StubGhostConfigProvider2 = class {
|
|
882
|
-
configs = /* @__PURE__ */ new Map();
|
|
883
|
-
async getGhostConfig(ownerUserId) {
|
|
884
|
-
return this.configs.get(ownerUserId) ?? null;
|
|
885
|
-
}
|
|
886
|
-
/** Test helper: set a GhostConfig for a user */
|
|
887
|
-
setGhostConfig(ownerUserId, config2) {
|
|
888
|
-
this.configs.set(ownerUserId, config2);
|
|
889
|
-
}
|
|
890
|
-
};
|
|
891
|
-
InMemoryEscalationStore2 = class {
|
|
892
|
-
blocks = /* @__PURE__ */ new Map();
|
|
893
|
-
attempts = /* @__PURE__ */ new Map();
|
|
894
|
-
key(ownerUserId, accessorUserId, memoryId) {
|
|
895
|
-
return `${ownerUserId}:${accessorUserId}:${memoryId}`;
|
|
896
|
-
}
|
|
897
|
-
async getBlock(ownerUserId, accessorUserId, memoryId) {
|
|
898
|
-
return this.blocks.get(this.key(ownerUserId, accessorUserId, memoryId)) ?? null;
|
|
899
|
-
}
|
|
900
|
-
async setBlock(ownerUserId, accessorUserId, memoryId, block) {
|
|
901
|
-
this.blocks.set(this.key(ownerUserId, accessorUserId, memoryId), block);
|
|
902
|
-
}
|
|
903
|
-
async removeBlock(ownerUserId, accessorUserId, memoryId) {
|
|
904
|
-
this.blocks.delete(this.key(ownerUserId, accessorUserId, memoryId));
|
|
905
|
-
}
|
|
906
|
-
async getAttempts(ownerUserId, accessorUserId, memoryId) {
|
|
907
|
-
return this.attempts.get(this.key(ownerUserId, accessorUserId, memoryId)) ?? null;
|
|
908
|
-
}
|
|
909
|
-
async incrementAttempts(ownerUserId, accessorUserId, memoryId) {
|
|
910
|
-
const k = this.key(ownerUserId, accessorUserId, memoryId);
|
|
911
|
-
const existing = this.attempts.get(k);
|
|
912
|
-
const record = {
|
|
913
|
-
count: (existing?.count ?? 0) + 1,
|
|
914
|
-
last_attempt_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
915
|
-
};
|
|
916
|
-
this.attempts.set(k, record);
|
|
917
|
-
return record;
|
|
918
|
-
}
|
|
919
|
-
};
|
|
920
|
-
TRUST_PENALTY2 = 0.1;
|
|
921
|
-
MAX_ATTEMPTS_BEFORE_BLOCK2 = 3;
|
|
601
|
+
initialized = false;
|
|
922
602
|
}
|
|
923
603
|
});
|
|
924
604
|
|
|
@@ -3992,16 +3672,22 @@ function getMemoryCollection(userId) {
|
|
|
3992
3672
|
var coreLogger = createLogger("info");
|
|
3993
3673
|
var tokenService = new ConfirmationTokenService(coreLogger);
|
|
3994
3674
|
var preferencesService = new PreferencesDatabaseService(coreLogger);
|
|
3675
|
+
var coreServicesCache = /* @__PURE__ */ new Map();
|
|
3995
3676
|
function createCoreServices(userId) {
|
|
3677
|
+
const cached = coreServicesCache.get(userId);
|
|
3678
|
+
if (cached)
|
|
3679
|
+
return cached;
|
|
3996
3680
|
const collection = getMemoryCollection(userId);
|
|
3997
3681
|
const weaviateClient = getWeaviateClient();
|
|
3998
|
-
|
|
3682
|
+
const services = {
|
|
3999
3683
|
memory: new MemoryService(collection, userId, coreLogger),
|
|
4000
3684
|
relationship: new RelationshipService(collection, userId, coreLogger),
|
|
4001
3685
|
space: new SpaceService(weaviateClient, collection, userId, tokenService, coreLogger),
|
|
4002
3686
|
preferences: preferencesService,
|
|
4003
3687
|
token: tokenService
|
|
4004
3688
|
};
|
|
3689
|
+
coreServicesCache.set(userId, services);
|
|
3690
|
+
return services;
|
|
4005
3691
|
}
|
|
4006
3692
|
|
|
4007
3693
|
// src/tools/create-memory.ts
|
|
@@ -4131,114 +3817,6 @@ async function handleCreateMemory(args, userId, authContext, context) {
|
|
|
4131
3817
|
|
|
4132
3818
|
// src/tools/search-memory.ts
|
|
4133
3819
|
init_logger();
|
|
4134
|
-
|
|
4135
|
-
// src/utils/weaviate-filters.ts
|
|
4136
|
-
import { Filters as Filters6 } from "weaviate-client";
|
|
4137
|
-
function buildCombinedSearchFilters2(collection, filters) {
|
|
4138
|
-
const memoryFilters = buildDocTypeFilters2(collection, "memory", filters);
|
|
4139
|
-
const relationshipFilters = buildDocTypeFilters2(collection, "relationship", filters);
|
|
4140
|
-
const validFilters = [memoryFilters, relationshipFilters].filter((f) => f !== void 0 && f !== null);
|
|
4141
|
-
if (validFilters.length === 0) {
|
|
4142
|
-
return void 0;
|
|
4143
|
-
} else if (validFilters.length === 1) {
|
|
4144
|
-
return validFilters[0];
|
|
4145
|
-
} else {
|
|
4146
|
-
return combineFiltersWithOr2(validFilters);
|
|
4147
|
-
}
|
|
4148
|
-
}
|
|
4149
|
-
function buildDocTypeFilters2(collection, docType, filters) {
|
|
4150
|
-
const filterList = [];
|
|
4151
|
-
filterList.push(
|
|
4152
|
-
collection.filter.byProperty("doc_type").equal(docType)
|
|
4153
|
-
);
|
|
4154
|
-
if (docType === "memory" && filters?.types && filters.types.length > 0) {
|
|
4155
|
-
if (filters.types.length === 1) {
|
|
4156
|
-
filterList.push(
|
|
4157
|
-
collection.filter.byProperty("content_type").equal(filters.types[0])
|
|
4158
|
-
);
|
|
4159
|
-
} else {
|
|
4160
|
-
filterList.push(
|
|
4161
|
-
collection.filter.byProperty("content_type").containsAny(filters.types)
|
|
4162
|
-
);
|
|
4163
|
-
}
|
|
4164
|
-
}
|
|
4165
|
-
if (filters?.weight_min !== void 0) {
|
|
4166
|
-
filterList.push(
|
|
4167
|
-
collection.filter.byProperty("weight").greaterThanOrEqual(filters.weight_min)
|
|
4168
|
-
);
|
|
4169
|
-
}
|
|
4170
|
-
if (filters?.weight_max !== void 0) {
|
|
4171
|
-
filterList.push(
|
|
4172
|
-
collection.filter.byProperty("weight").lessThanOrEqual(filters.weight_max)
|
|
4173
|
-
);
|
|
4174
|
-
}
|
|
4175
|
-
if (filters?.trust_min !== void 0) {
|
|
4176
|
-
filterList.push(
|
|
4177
|
-
collection.filter.byProperty("trust_score").greaterThanOrEqual(filters.trust_min)
|
|
4178
|
-
);
|
|
4179
|
-
}
|
|
4180
|
-
if (filters?.trust_max !== void 0) {
|
|
4181
|
-
filterList.push(
|
|
4182
|
-
collection.filter.byProperty("trust_score").lessThanOrEqual(filters.trust_max)
|
|
4183
|
-
);
|
|
4184
|
-
}
|
|
4185
|
-
if (filters?.date_from) {
|
|
4186
|
-
filterList.push(
|
|
4187
|
-
collection.filter.byProperty("created_at").greaterThanOrEqual(new Date(filters.date_from))
|
|
4188
|
-
);
|
|
4189
|
-
}
|
|
4190
|
-
if (filters?.date_to) {
|
|
4191
|
-
filterList.push(
|
|
4192
|
-
collection.filter.byProperty("created_at").lessThanOrEqual(new Date(filters.date_to))
|
|
4193
|
-
);
|
|
4194
|
-
}
|
|
4195
|
-
if (filters?.tags && filters.tags.length > 0) {
|
|
4196
|
-
if (filters.tags.length === 1) {
|
|
4197
|
-
filterList.push(
|
|
4198
|
-
collection.filter.byProperty("tags").containsAny([filters.tags[0]])
|
|
4199
|
-
);
|
|
4200
|
-
} else {
|
|
4201
|
-
filterList.push(
|
|
4202
|
-
collection.filter.byProperty("tags").containsAny(filters.tags)
|
|
4203
|
-
);
|
|
4204
|
-
}
|
|
4205
|
-
}
|
|
4206
|
-
return combineFiltersWithAnd2(filterList);
|
|
4207
|
-
}
|
|
4208
|
-
function buildMemoryOnlyFilters2(collection, filters) {
|
|
4209
|
-
return buildDocTypeFilters2(collection, "memory", filters);
|
|
4210
|
-
}
|
|
4211
|
-
function combineFiltersWithAnd2(filters) {
|
|
4212
|
-
const validFilters = filters.filter((f) => f !== void 0 && f !== null);
|
|
4213
|
-
if (validFilters.length === 0) {
|
|
4214
|
-
return void 0;
|
|
4215
|
-
}
|
|
4216
|
-
if (validFilters.length === 1) {
|
|
4217
|
-
return validFilters[0];
|
|
4218
|
-
}
|
|
4219
|
-
return Filters6.and(...validFilters);
|
|
4220
|
-
}
|
|
4221
|
-
function combineFiltersWithOr2(filters) {
|
|
4222
|
-
const validFilters = filters.filter((f) => f !== void 0 && f !== null);
|
|
4223
|
-
if (validFilters.length === 0) {
|
|
4224
|
-
return void 0;
|
|
4225
|
-
}
|
|
4226
|
-
if (validFilters.length === 1) {
|
|
4227
|
-
return validFilters[0];
|
|
4228
|
-
}
|
|
4229
|
-
return Filters6.or(...validFilters);
|
|
4230
|
-
}
|
|
4231
|
-
function buildDeletedFilter2(collection, deletedFilter = "exclude") {
|
|
4232
|
-
if (deletedFilter === "exclude") {
|
|
4233
|
-
return collection.filter.byProperty("deleted_at").isNull(true);
|
|
4234
|
-
} else if (deletedFilter === "only") {
|
|
4235
|
-
return collection.filter.byProperty("deleted_at").isNull(false);
|
|
4236
|
-
}
|
|
4237
|
-
return null;
|
|
4238
|
-
}
|
|
4239
|
-
|
|
4240
|
-
// src/tools/search-memory.ts
|
|
4241
|
-
init_trust_enforcement();
|
|
4242
3820
|
var searchMemoryTool = {
|
|
4243
3821
|
name: "remember_search_memory",
|
|
4244
3822
|
description: `Search memories AND relationships using hybrid semantic and keyword search.
|
|
@@ -4369,16 +3947,16 @@ async function handleSearchMemory(args, userId, authContext) {
|
|
|
4369
3947
|
const alpha = args.alpha ?? 0.7;
|
|
4370
3948
|
const limit = args.limit ?? 10;
|
|
4371
3949
|
const offset = args.offset ?? 0;
|
|
4372
|
-
const deletedFilter =
|
|
4373
|
-
const trustFilter = ghostMode ?
|
|
4374
|
-
const searchFilters = includeRelationships ?
|
|
3950
|
+
const deletedFilter = buildDeletedFilter(collection, args.deleted_filter || "exclude");
|
|
3951
|
+
const trustFilter = ghostMode ? buildTrustFilter(collection, ghostMode.accessor_trust_level) : null;
|
|
3952
|
+
const searchFilters = includeRelationships ? buildCombinedSearchFilters(collection, args.filters) : buildMemoryOnlyFilters(collection, args.filters);
|
|
4375
3953
|
const hasExplicitTypeFilter = args.filters?.types && args.filters.types.length > 0;
|
|
4376
3954
|
const ghostExclusionFilter = !hasExplicitTypeFilter ? collection.filter.byProperty("content_type").notEqual("ghost") : null;
|
|
4377
|
-
const combinedFilters =
|
|
3955
|
+
const combinedFilters = combineFiltersWithAnd([deletedFilter, trustFilter, ghostExclusionFilter, searchFilters].filter((f) => f !== null));
|
|
4378
3956
|
const searchOptions = {
|
|
4379
3957
|
alpha,
|
|
4380
|
-
limit
|
|
4381
|
-
|
|
3958
|
+
limit,
|
|
3959
|
+
offset
|
|
4382
3960
|
};
|
|
4383
3961
|
if (combinedFilters) {
|
|
4384
3962
|
searchOptions.filters = combinedFilters;
|
|
@@ -4390,10 +3968,9 @@ async function handleSearchMemory(args, userId, authContext) {
|
|
|
4390
3968
|
deletedFilter: args.deleted_filter || "exclude"
|
|
4391
3969
|
});
|
|
4392
3970
|
const results = await collection.query.hybrid(args.query, searchOptions);
|
|
4393
|
-
const paginatedResults = results.objects.slice(offset);
|
|
4394
3971
|
const memories = [];
|
|
4395
3972
|
const relationships = [];
|
|
4396
|
-
for (const obj of
|
|
3973
|
+
for (const obj of results.objects) {
|
|
4397
3974
|
const doc = {
|
|
4398
3975
|
id: obj.uuid,
|
|
4399
3976
|
...obj.properties
|
|
@@ -4709,7 +4286,6 @@ async function handleFindSimilar(args, userId, authContext) {
|
|
|
4709
4286
|
|
|
4710
4287
|
// src/tools/query-memory.ts
|
|
4711
4288
|
init_logger();
|
|
4712
|
-
init_trust_enforcement();
|
|
4713
4289
|
var queryMemoryTool = {
|
|
4714
4290
|
name: "remember_query_memory",
|
|
4715
4291
|
description: `Query memories using natural language for RAG (Retrieval-Augmented Generation).
|
|
@@ -4837,12 +4413,12 @@ async function handleQueryMemory(args, userId, authContext) {
|
|
|
4837
4413
|
const minRelevance = args.min_relevance ?? 0.6;
|
|
4838
4414
|
const includeContext = args.include_context ?? true;
|
|
4839
4415
|
const format = args.format ?? "detailed";
|
|
4840
|
-
const deletedFilter =
|
|
4841
|
-
const trustFilter = ghostMode ?
|
|
4842
|
-
const searchFilters =
|
|
4416
|
+
const deletedFilter = buildDeletedFilter(collection, args.deleted_filter || "exclude");
|
|
4417
|
+
const trustFilter = ghostMode ? buildTrustFilter(collection, ghostMode.accessor_trust_level) : null;
|
|
4418
|
+
const searchFilters = buildCombinedSearchFilters(collection, args.filters);
|
|
4843
4419
|
const hasExplicitTypeFilter = args.filters?.types && args.filters.types.length > 0;
|
|
4844
4420
|
const ghostExclusionFilter = !hasExplicitTypeFilter ? collection.filter.byProperty("content_type").notEqual("ghost") : null;
|
|
4845
|
-
const combinedFilters =
|
|
4421
|
+
const combinedFilters = combineFiltersWithAnd([deletedFilter, trustFilter, ghostExclusionFilter, searchFilters].filter((f) => f !== null));
|
|
4846
4422
|
const searchOptions = {
|
|
4847
4423
|
limit,
|
|
4848
4424
|
distance: 1 - minRelevance,
|
|
@@ -5954,7 +5530,7 @@ async function handleDeny(args, userId, authContext) {
|
|
|
5954
5530
|
}
|
|
5955
5531
|
|
|
5956
5532
|
// src/tools/search-space.ts
|
|
5957
|
-
import { Filters as
|
|
5533
|
+
import { Filters as Filters6 } from "weaviate-client";
|
|
5958
5534
|
var searchSpaceTool = {
|
|
5959
5535
|
name: "remember_search_space",
|
|
5960
5536
|
description: `Search shared spaces and/or groups to discover memories from other users.
|
|
@@ -6342,8 +5918,153 @@ async function handleModerate(args, userId, authContext) {
|
|
|
6342
5918
|
}
|
|
6343
5919
|
}
|
|
6344
5920
|
|
|
5921
|
+
// src/services/ghost-config.service.ts
|
|
5922
|
+
init_init();
|
|
5923
|
+
|
|
5924
|
+
// src/firestore/paths.ts
|
|
5925
|
+
var APP_NAME2 = "remember-mcp";
|
|
5926
|
+
function getBasePrefix2() {
|
|
5927
|
+
const environment = process.env.ENVIRONMENT;
|
|
5928
|
+
if (environment && environment !== "production" && environment !== "prod") {
|
|
5929
|
+
return `${environment}.${APP_NAME2}`;
|
|
5930
|
+
}
|
|
5931
|
+
const isDevelopment = process.env.NODE_ENV === "development";
|
|
5932
|
+
if (isDevelopment) {
|
|
5933
|
+
const customPrefix = process.env.DB_PREFIX;
|
|
5934
|
+
if (customPrefix) {
|
|
5935
|
+
return customPrefix;
|
|
5936
|
+
}
|
|
5937
|
+
return `e0.${APP_NAME2}`;
|
|
5938
|
+
}
|
|
5939
|
+
return APP_NAME2;
|
|
5940
|
+
}
|
|
5941
|
+
var BASE2 = getBasePrefix2();
|
|
5942
|
+
|
|
5943
|
+
// src/services/ghost-config.service.ts
|
|
5944
|
+
init_logger();
|
|
5945
|
+
|
|
5946
|
+
// src/types/ghost-config.ts
|
|
5947
|
+
var DEFAULT_GHOST_CONFIG2 = {
|
|
5948
|
+
enabled: false,
|
|
5949
|
+
public_ghost_enabled: false,
|
|
5950
|
+
default_friend_trust: 0.25,
|
|
5951
|
+
default_public_trust: 0,
|
|
5952
|
+
per_user_trust: {},
|
|
5953
|
+
blocked_users: [],
|
|
5954
|
+
enforcement_mode: "query"
|
|
5955
|
+
};
|
|
5956
|
+
|
|
5957
|
+
// src/services/ghost-config.service.ts
|
|
5958
|
+
var SERVICE = "GhostConfigService";
|
|
5959
|
+
function getGhostConfigPath(ownerUserId) {
|
|
5960
|
+
return {
|
|
5961
|
+
collectionPath: `${BASE2}.users/${ownerUserId}/ghost_config`,
|
|
5962
|
+
docId: "settings"
|
|
5963
|
+
};
|
|
5964
|
+
}
|
|
5965
|
+
async function getGhostConfig2(ownerUserId) {
|
|
5966
|
+
try {
|
|
5967
|
+
const { collectionPath, docId } = getGhostConfigPath(ownerUserId);
|
|
5968
|
+
const doc = await getDocument(collectionPath, docId);
|
|
5969
|
+
if (!doc) {
|
|
5970
|
+
return { ...DEFAULT_GHOST_CONFIG2 };
|
|
5971
|
+
}
|
|
5972
|
+
return { ...DEFAULT_GHOST_CONFIG2, ...doc };
|
|
5973
|
+
} catch (error) {
|
|
5974
|
+
logger.error("Failed to get ghost config", {
|
|
5975
|
+
service: SERVICE,
|
|
5976
|
+
ownerUserId,
|
|
5977
|
+
error: error instanceof Error ? error.message : String(error)
|
|
5978
|
+
});
|
|
5979
|
+
return { ...DEFAULT_GHOST_CONFIG2 };
|
|
5980
|
+
}
|
|
5981
|
+
}
|
|
5982
|
+
async function setGhostConfigFields2(ownerUserId, config2) {
|
|
5983
|
+
const { collectionPath, docId } = getGhostConfigPath(ownerUserId);
|
|
5984
|
+
await setDocument(collectionPath, docId, config2, { merge: true });
|
|
5985
|
+
logger.info("Ghost config updated", {
|
|
5986
|
+
service: SERVICE,
|
|
5987
|
+
ownerUserId,
|
|
5988
|
+
updatedKeys: Object.keys(config2)
|
|
5989
|
+
});
|
|
5990
|
+
return getGhostConfig2(ownerUserId);
|
|
5991
|
+
}
|
|
5992
|
+
async function setUserTrust2(ownerUserId, targetUserId, trustLevel) {
|
|
5993
|
+
if (trustLevel < 0 || trustLevel > 1) {
|
|
5994
|
+
throw new Error(`Trust level must be between 0 and 1, got ${trustLevel}`);
|
|
5995
|
+
}
|
|
5996
|
+
const current = await getGhostConfig2(ownerUserId);
|
|
5997
|
+
const per_user_trust = { ...current.per_user_trust, [targetUserId]: trustLevel };
|
|
5998
|
+
const { collectionPath, docId } = getGhostConfigPath(ownerUserId);
|
|
5999
|
+
await setDocument(collectionPath, docId, { per_user_trust }, { merge: true });
|
|
6000
|
+
logger.info("User trust level set", {
|
|
6001
|
+
service: SERVICE,
|
|
6002
|
+
ownerUserId,
|
|
6003
|
+
targetUserId,
|
|
6004
|
+
trustLevel
|
|
6005
|
+
});
|
|
6006
|
+
}
|
|
6007
|
+
async function removeUserTrust2(ownerUserId, targetUserId) {
|
|
6008
|
+
const current = await getGhostConfig2(ownerUserId);
|
|
6009
|
+
const per_user_trust = { ...current.per_user_trust };
|
|
6010
|
+
delete per_user_trust[targetUserId];
|
|
6011
|
+
const { collectionPath, docId } = getGhostConfigPath(ownerUserId);
|
|
6012
|
+
await setDocument(collectionPath, docId, { per_user_trust }, { merge: true });
|
|
6013
|
+
logger.info("User trust override removed", {
|
|
6014
|
+
service: SERVICE,
|
|
6015
|
+
ownerUserId,
|
|
6016
|
+
targetUserId
|
|
6017
|
+
});
|
|
6018
|
+
}
|
|
6019
|
+
async function blockUser2(ownerUserId, targetUserId) {
|
|
6020
|
+
const { collectionPath, docId } = getGhostConfigPath(ownerUserId);
|
|
6021
|
+
await setDocument(collectionPath, docId, {
|
|
6022
|
+
blocked_users: FieldValue.arrayUnion(targetUserId)
|
|
6023
|
+
}, { merge: true });
|
|
6024
|
+
logger.info("User blocked from ghost access", {
|
|
6025
|
+
service: SERVICE,
|
|
6026
|
+
ownerUserId,
|
|
6027
|
+
targetUserId
|
|
6028
|
+
});
|
|
6029
|
+
}
|
|
6030
|
+
async function unblockUser2(ownerUserId, targetUserId) {
|
|
6031
|
+
const { collectionPath, docId } = getGhostConfigPath(ownerUserId);
|
|
6032
|
+
await setDocument(collectionPath, docId, {
|
|
6033
|
+
blocked_users: FieldValue.arrayRemove(targetUserId)
|
|
6034
|
+
}, { merge: true });
|
|
6035
|
+
logger.info("User unblocked from ghost access", {
|
|
6036
|
+
service: SERVICE,
|
|
6037
|
+
ownerUserId,
|
|
6038
|
+
targetUserId
|
|
6039
|
+
});
|
|
6040
|
+
}
|
|
6041
|
+
function validateGhostConfigUpdate2(config2) {
|
|
6042
|
+
if (config2.default_friend_trust !== void 0) {
|
|
6043
|
+
if (config2.default_friend_trust < 0 || config2.default_friend_trust > 1) {
|
|
6044
|
+
throw new Error(`default_friend_trust must be between 0 and 1, got ${config2.default_friend_trust}`);
|
|
6045
|
+
}
|
|
6046
|
+
}
|
|
6047
|
+
if (config2.default_public_trust !== void 0) {
|
|
6048
|
+
if (config2.default_public_trust < 0 || config2.default_public_trust > 1) {
|
|
6049
|
+
throw new Error(`default_public_trust must be between 0 and 1, got ${config2.default_public_trust}`);
|
|
6050
|
+
}
|
|
6051
|
+
}
|
|
6052
|
+
if (config2.enforcement_mode !== void 0) {
|
|
6053
|
+
const valid = ["query", "prompt", "hybrid"];
|
|
6054
|
+
if (!valid.includes(config2.enforcement_mode)) {
|
|
6055
|
+
throw new Error(`enforcement_mode must be one of ${valid.join(", ")}, got ${config2.enforcement_mode}`);
|
|
6056
|
+
}
|
|
6057
|
+
}
|
|
6058
|
+
if (config2.per_user_trust !== void 0) {
|
|
6059
|
+
for (const [userId, level] of Object.entries(config2.per_user_trust)) {
|
|
6060
|
+
if (level < 0 || level > 1) {
|
|
6061
|
+
throw new Error(`Trust level for ${userId} must be between 0 and 1, got ${level}`);
|
|
6062
|
+
}
|
|
6063
|
+
}
|
|
6064
|
+
}
|
|
6065
|
+
}
|
|
6066
|
+
|
|
6345
6067
|
// src/tools/ghost-config.ts
|
|
6346
|
-
init_ghost_config_service();
|
|
6347
6068
|
var ghostConfigTool = {
|
|
6348
6069
|
name: "remember_ghost_config",
|
|
6349
6070
|
description: `Manage ghost/persona configuration. Controls who can interact with your ghost and at what trust level.
|
|
@@ -6519,6 +6240,55 @@ async function handleGhostConfig(args, userId, authContext) {
|
|
|
6519
6240
|
}
|
|
6520
6241
|
}
|
|
6521
6242
|
|
|
6243
|
+
// src/services/access-control.ts
|
|
6244
|
+
async function resolveAccessorTrustLevel2(ghostConfig, ownerUserId, accessorUserId) {
|
|
6245
|
+
if (accessorUserId in ghostConfig.per_user_trust) {
|
|
6246
|
+
return ghostConfig.per_user_trust[accessorUserId];
|
|
6247
|
+
}
|
|
6248
|
+
const isFriend = await checkIfFriend(ownerUserId, accessorUserId);
|
|
6249
|
+
if (isFriend) {
|
|
6250
|
+
return ghostConfig.default_friend_trust ?? 0.25;
|
|
6251
|
+
}
|
|
6252
|
+
return ghostConfig.default_public_trust ?? 0;
|
|
6253
|
+
}
|
|
6254
|
+
var friendCache = /* @__PURE__ */ new Map();
|
|
6255
|
+
var FRIEND_CACHE_TTL_MS = 6e4;
|
|
6256
|
+
async function checkIfFriend(ownerUserId, accessorUserId) {
|
|
6257
|
+
const cacheKey = [ownerUserId, accessorUserId].sort().join(":");
|
|
6258
|
+
const cached = friendCache.get(cacheKey);
|
|
6259
|
+
if (cached && Date.now() < cached.expiresAt) {
|
|
6260
|
+
return cached.result;
|
|
6261
|
+
}
|
|
6262
|
+
try {
|
|
6263
|
+
const { queryDocuments: queryDocuments3 } = await Promise.resolve().then(() => (init_init(), init_exports));
|
|
6264
|
+
const BASE3 = process.env.FIRESTORE_BASE_PATH || "agentbase";
|
|
6265
|
+
const [forward, reverse] = await Promise.all([
|
|
6266
|
+
queryDocuments3(`${BASE3}.relationships`, {
|
|
6267
|
+
where: [
|
|
6268
|
+
{ field: "from_user_id", op: "==", value: ownerUserId },
|
|
6269
|
+
{ field: "to_user_id", op: "==", value: accessorUserId },
|
|
6270
|
+
{ field: "friend", op: "==", value: true }
|
|
6271
|
+
],
|
|
6272
|
+
limit: 1
|
|
6273
|
+
}),
|
|
6274
|
+
queryDocuments3(`${BASE3}.relationships`, {
|
|
6275
|
+
where: [
|
|
6276
|
+
{ field: "from_user_id", op: "==", value: accessorUserId },
|
|
6277
|
+
{ field: "to_user_id", op: "==", value: ownerUserId },
|
|
6278
|
+
{ field: "friend", op: "==", value: true }
|
|
6279
|
+
],
|
|
6280
|
+
limit: 1
|
|
6281
|
+
})
|
|
6282
|
+
]);
|
|
6283
|
+
const result = forward.length > 0 || reverse.length > 0;
|
|
6284
|
+
friendCache.set(cacheKey, { result, expiresAt: Date.now() + FRIEND_CACHE_TTL_MS });
|
|
6285
|
+
return result;
|
|
6286
|
+
} catch (error) {
|
|
6287
|
+
console.error("[checkIfFriend] Error checking friend status:", error);
|
|
6288
|
+
return false;
|
|
6289
|
+
}
|
|
6290
|
+
}
|
|
6291
|
+
|
|
6522
6292
|
// src/server-factory.ts
|
|
6523
6293
|
var databasesInitialized = false;
|
|
6524
6294
|
var initializationPromise = null;
|
|
@@ -6570,10 +6340,8 @@ async function createServer(accessToken, userId, options = {}) {
|
|
|
6570
6340
|
);
|
|
6571
6341
|
let resolvedGhostMode;
|
|
6572
6342
|
if (options.ghostMode) {
|
|
6573
|
-
const
|
|
6574
|
-
const
|
|
6575
|
-
const ghostConfig = await getGhostConfig3(options.ghostMode.owner_user_id);
|
|
6576
|
-
const trustLevel = resolveAccessorTrustLevel3(ghostConfig, options.ghostMode.accessor_user_id);
|
|
6343
|
+
const ghostConfig = await getGhostConfig2(options.ghostMode.owner_user_id);
|
|
6344
|
+
const trustLevel = await resolveAccessorTrustLevel2(ghostConfig, options.ghostMode.owner_user_id, options.ghostMode.accessor_user_id);
|
|
6577
6345
|
resolvedGhostMode = {
|
|
6578
6346
|
owner_user_id: options.ghostMode.owner_user_id,
|
|
6579
6347
|
accessor_user_id: options.ghostMode.accessor_user_id,
|