@remnic/core 9.7.10 → 9.7.11
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/dist/access-boundary.d.ts +1 -1
- package/dist/access-boundary.js +1 -1
- package/dist/access-cli.js +7 -7
- package/dist/access-http.d.ts +2 -1
- package/dist/access-http.js +5 -5
- package/dist/access-mcp.js +4 -4
- package/dist/access-operations-batch.js +2 -2
- package/dist/access-operations.d.ts +4 -4
- package/dist/access-operations.js +3 -3
- package/dist/access-schema.d.ts +64 -64
- package/dist/access-surface-catalog.js +2 -0
- package/dist/access-surface-catalog.js.map +1 -1
- package/dist/{chunk-N3LWQJ6Y.js → chunk-5U65RIVI.js} +294 -2
- package/dist/chunk-5U65RIVI.js.map +1 -0
- package/dist/{chunk-UZRIKUFS.js → chunk-6LM6PPDX.js} +3 -1
- package/dist/chunk-6LM6PPDX.js.map +1 -0
- package/dist/chunk-7XRUYC6G.js +1794 -0
- package/dist/chunk-7XRUYC6G.js.map +1 -0
- package/dist/{chunk-VDLMAJXS.js → chunk-GHVJASQ4.js} +2 -2
- package/dist/{chunk-7EX4YOKH.js → chunk-JYRFO4EH.js} +2 -2
- package/dist/{chunk-QVALQE4P.js → chunk-QHT4W3RU.js} +126 -8
- package/dist/chunk-QHT4W3RU.js.map +1 -0
- package/dist/{chunk-7CKS4AXY.js → chunk-W6R43NLA.js} +3 -3
- package/dist/cli.js +6 -6
- package/dist/index.d.ts +3990 -4
- package/dist/index.js +54 -7
- package/dist/orchestrator.js +7 -7
- package/dist/schemas.d.ts +52 -52
- package/dist/shared-context/manager.d.ts +8 -8
- package/dist/transfer/types.d.ts +66 -66
- package/package.json +2 -2
- package/src/access-boundary.ts +2 -0
- package/src/access-http.ts +147 -6
- package/src/access-mcp-cancellation.test.ts +2 -2
- package/src/access-operations.ts +2 -0
- package/src/access-surface-catalog.ts +2 -0
- package/src/index.ts +53 -0
- package/src/relay/mission-access.test.ts +379 -0
- package/src/relay/mission-access.ts +125 -0
- package/src/relay/mission-fixture.ts +301 -0
- package/src/relay/mission.test.ts +964 -0
- package/src/relay/mission.ts +1725 -0
- package/dist/chunk-FNJX2O6G.js +0 -467
- package/dist/chunk-FNJX2O6G.js.map +0 -1
- package/dist/chunk-N3LWQJ6Y.js.map +0 -1
- package/dist/chunk-QVALQE4P.js.map +0 -1
- package/dist/chunk-UZRIKUFS.js.map +0 -1
- /package/dist/{chunk-VDLMAJXS.js.map → chunk-GHVJASQ4.js.map} +0 -0
- /package/dist/{chunk-7EX4YOKH.js.map → chunk-JYRFO4EH.js.map} +0 -0
- /package/dist/{chunk-7CKS4AXY.js.map → chunk-W6R43NLA.js.map} +0 -0
package/dist/transfer/types.d.ts
CHANGED
|
@@ -20,26 +20,26 @@ declare const ExportManifestV1Schema: z.ZodObject<{
|
|
|
20
20
|
bytes: number;
|
|
21
21
|
}>, "many">;
|
|
22
22
|
}, "strip", z.ZodTypeAny, {
|
|
23
|
-
|
|
23
|
+
format: "openclaw-engram-export";
|
|
24
24
|
createdAt: string;
|
|
25
|
+
pluginVersion: string;
|
|
25
26
|
files: {
|
|
26
27
|
path: string;
|
|
27
28
|
sha256: string;
|
|
28
29
|
bytes: number;
|
|
29
30
|
}[];
|
|
30
|
-
|
|
31
|
-
pluginVersion: string;
|
|
31
|
+
schemaVersion: 1;
|
|
32
32
|
includesTranscripts: boolean;
|
|
33
33
|
}, {
|
|
34
|
-
|
|
34
|
+
format: "openclaw-engram-export";
|
|
35
35
|
createdAt: string;
|
|
36
|
+
pluginVersion: string;
|
|
36
37
|
files: {
|
|
37
38
|
path: string;
|
|
38
39
|
sha256: string;
|
|
39
40
|
bytes: number;
|
|
40
41
|
}[];
|
|
41
|
-
|
|
42
|
-
pluginVersion: string;
|
|
42
|
+
schemaVersion: 1;
|
|
43
43
|
includesTranscripts: boolean;
|
|
44
44
|
}>;
|
|
45
45
|
type ExportManifestV1 = z.infer<typeof ExportManifestV1Schema>;
|
|
@@ -75,26 +75,26 @@ declare const ExportBundleV1Schema: z.ZodObject<{
|
|
|
75
75
|
bytes: number;
|
|
76
76
|
}>, "many">;
|
|
77
77
|
}, "strip", z.ZodTypeAny, {
|
|
78
|
-
|
|
78
|
+
format: "openclaw-engram-export";
|
|
79
79
|
createdAt: string;
|
|
80
|
+
pluginVersion: string;
|
|
80
81
|
files: {
|
|
81
82
|
path: string;
|
|
82
83
|
sha256: string;
|
|
83
84
|
bytes: number;
|
|
84
85
|
}[];
|
|
85
|
-
|
|
86
|
-
pluginVersion: string;
|
|
86
|
+
schemaVersion: 1;
|
|
87
87
|
includesTranscripts: boolean;
|
|
88
88
|
}, {
|
|
89
|
-
|
|
89
|
+
format: "openclaw-engram-export";
|
|
90
90
|
createdAt: string;
|
|
91
|
+
pluginVersion: string;
|
|
91
92
|
files: {
|
|
92
93
|
path: string;
|
|
93
94
|
sha256: string;
|
|
94
95
|
bytes: number;
|
|
95
96
|
}[];
|
|
96
|
-
|
|
97
|
-
pluginVersion: string;
|
|
97
|
+
schemaVersion: 1;
|
|
98
98
|
includesTranscripts: boolean;
|
|
99
99
|
}>;
|
|
100
100
|
records: z.ZodArray<z.ZodObject<{
|
|
@@ -109,15 +109,15 @@ declare const ExportBundleV1Schema: z.ZodObject<{
|
|
|
109
109
|
}>, "many">;
|
|
110
110
|
}, "strip", z.ZodTypeAny, {
|
|
111
111
|
manifest: {
|
|
112
|
-
|
|
112
|
+
format: "openclaw-engram-export";
|
|
113
113
|
createdAt: string;
|
|
114
|
+
pluginVersion: string;
|
|
114
115
|
files: {
|
|
115
116
|
path: string;
|
|
116
117
|
sha256: string;
|
|
117
118
|
bytes: number;
|
|
118
119
|
}[];
|
|
119
|
-
|
|
120
|
-
pluginVersion: string;
|
|
120
|
+
schemaVersion: 1;
|
|
121
121
|
includesTranscripts: boolean;
|
|
122
122
|
};
|
|
123
123
|
records: {
|
|
@@ -126,15 +126,15 @@ declare const ExportBundleV1Schema: z.ZodObject<{
|
|
|
126
126
|
}[];
|
|
127
127
|
}, {
|
|
128
128
|
manifest: {
|
|
129
|
-
|
|
129
|
+
format: "openclaw-engram-export";
|
|
130
130
|
createdAt: string;
|
|
131
|
+
pluginVersion: string;
|
|
131
132
|
files: {
|
|
132
133
|
path: string;
|
|
133
134
|
sha256: string;
|
|
134
135
|
bytes: number;
|
|
135
136
|
}[];
|
|
136
|
-
|
|
137
|
-
pluginVersion: string;
|
|
137
|
+
schemaVersion: 1;
|
|
138
138
|
includesTranscripts: boolean;
|
|
139
139
|
};
|
|
140
140
|
records: {
|
|
@@ -319,10 +319,10 @@ declare const CapsuleBlockSchema: z.ZodObject<{
|
|
|
319
319
|
identityAnchors: boolean;
|
|
320
320
|
peerProfiles: boolean;
|
|
321
321
|
};
|
|
322
|
-
|
|
322
|
+
description: string;
|
|
323
323
|
id: string;
|
|
324
|
+
schemaVersion: string;
|
|
324
325
|
version: string;
|
|
325
|
-
description: string;
|
|
326
326
|
parentCapsule: string | null;
|
|
327
327
|
retrievalPolicy: {
|
|
328
328
|
tierWeights: Record<string, number>;
|
|
@@ -340,10 +340,10 @@ declare const CapsuleBlockSchema: z.ZodObject<{
|
|
|
340
340
|
identityAnchors: boolean;
|
|
341
341
|
peerProfiles: boolean;
|
|
342
342
|
};
|
|
343
|
-
|
|
343
|
+
description: string;
|
|
344
344
|
id: string;
|
|
345
|
+
schemaVersion: string;
|
|
345
346
|
version: string;
|
|
346
|
-
description: string;
|
|
347
347
|
parentCapsule: string | null;
|
|
348
348
|
retrievalPolicy: {
|
|
349
349
|
tierWeights: Record<string, number>;
|
|
@@ -470,10 +470,10 @@ declare const ExportManifestV2Schema: z.ZodObject<{
|
|
|
470
470
|
identityAnchors: boolean;
|
|
471
471
|
peerProfiles: boolean;
|
|
472
472
|
};
|
|
473
|
-
|
|
473
|
+
description: string;
|
|
474
474
|
id: string;
|
|
475
|
+
schemaVersion: string;
|
|
475
476
|
version: string;
|
|
476
|
-
description: string;
|
|
477
477
|
parentCapsule: string | null;
|
|
478
478
|
retrievalPolicy: {
|
|
479
479
|
tierWeights: Record<string, number>;
|
|
@@ -491,10 +491,10 @@ declare const ExportManifestV2Schema: z.ZodObject<{
|
|
|
491
491
|
identityAnchors: boolean;
|
|
492
492
|
peerProfiles: boolean;
|
|
493
493
|
};
|
|
494
|
-
|
|
494
|
+
description: string;
|
|
495
495
|
id: string;
|
|
496
|
+
schemaVersion: string;
|
|
496
497
|
version: string;
|
|
497
|
-
description: string;
|
|
498
498
|
parentCapsule: string | null;
|
|
499
499
|
retrievalPolicy: {
|
|
500
500
|
tierWeights: Record<string, number>;
|
|
@@ -507,16 +507,14 @@ declare const ExportManifestV2Schema: z.ZodObject<{
|
|
|
507
507
|
} | null | undefined;
|
|
508
508
|
}>;
|
|
509
509
|
}, "strip", z.ZodTypeAny, {
|
|
510
|
-
|
|
510
|
+
format: "openclaw-engram-export";
|
|
511
511
|
createdAt: string;
|
|
512
|
+
pluginVersion: string;
|
|
512
513
|
files: {
|
|
513
514
|
path: string;
|
|
514
515
|
sha256: string;
|
|
515
516
|
bytes: number;
|
|
516
517
|
}[];
|
|
517
|
-
format: "openclaw-engram-export";
|
|
518
|
-
pluginVersion: string;
|
|
519
|
-
includesTranscripts: boolean;
|
|
520
518
|
capsule: {
|
|
521
519
|
includes: {
|
|
522
520
|
procedural: boolean;
|
|
@@ -524,10 +522,10 @@ declare const ExportManifestV2Schema: z.ZodObject<{
|
|
|
524
522
|
identityAnchors: boolean;
|
|
525
523
|
peerProfiles: boolean;
|
|
526
524
|
};
|
|
527
|
-
|
|
525
|
+
description: string;
|
|
528
526
|
id: string;
|
|
527
|
+
schemaVersion: string;
|
|
529
528
|
version: string;
|
|
530
|
-
description: string;
|
|
531
529
|
parentCapsule: string | null;
|
|
532
530
|
retrievalPolicy: {
|
|
533
531
|
tierWeights: Record<string, number>;
|
|
@@ -539,17 +537,17 @@ declare const ExportManifestV2Schema: z.ZodObject<{
|
|
|
539
537
|
forkRoot: string;
|
|
540
538
|
} | null;
|
|
541
539
|
};
|
|
542
|
-
}, {
|
|
543
540
|
schemaVersion: 2;
|
|
541
|
+
includesTranscripts: boolean;
|
|
542
|
+
}, {
|
|
543
|
+
format: "openclaw-engram-export";
|
|
544
544
|
createdAt: string;
|
|
545
|
+
pluginVersion: string;
|
|
545
546
|
files: {
|
|
546
547
|
path: string;
|
|
547
548
|
sha256: string;
|
|
548
549
|
bytes: number;
|
|
549
550
|
}[];
|
|
550
|
-
format: "openclaw-engram-export";
|
|
551
|
-
pluginVersion: string;
|
|
552
|
-
includesTranscripts: boolean;
|
|
553
551
|
capsule: {
|
|
554
552
|
includes: {
|
|
555
553
|
procedural: boolean;
|
|
@@ -557,10 +555,10 @@ declare const ExportManifestV2Schema: z.ZodObject<{
|
|
|
557
555
|
identityAnchors: boolean;
|
|
558
556
|
peerProfiles: boolean;
|
|
559
557
|
};
|
|
560
|
-
|
|
558
|
+
description: string;
|
|
561
559
|
id: string;
|
|
560
|
+
schemaVersion: string;
|
|
562
561
|
version: string;
|
|
563
|
-
description: string;
|
|
564
562
|
parentCapsule: string | null;
|
|
565
563
|
retrievalPolicy: {
|
|
566
564
|
tierWeights: Record<string, number>;
|
|
@@ -572,6 +570,8 @@ declare const ExportManifestV2Schema: z.ZodObject<{
|
|
|
572
570
|
forkRoot: string;
|
|
573
571
|
} | null | undefined;
|
|
574
572
|
};
|
|
573
|
+
schemaVersion: 2;
|
|
574
|
+
includesTranscripts: boolean;
|
|
575
575
|
}>;
|
|
576
576
|
type ExportManifestV2 = z.infer<typeof ExportManifestV2Schema>;
|
|
577
577
|
declare const ExportBundleV2Schema: z.ZodObject<{
|
|
@@ -689,10 +689,10 @@ declare const ExportBundleV2Schema: z.ZodObject<{
|
|
|
689
689
|
identityAnchors: boolean;
|
|
690
690
|
peerProfiles: boolean;
|
|
691
691
|
};
|
|
692
|
-
|
|
692
|
+
description: string;
|
|
693
693
|
id: string;
|
|
694
|
+
schemaVersion: string;
|
|
694
695
|
version: string;
|
|
695
|
-
description: string;
|
|
696
696
|
parentCapsule: string | null;
|
|
697
697
|
retrievalPolicy: {
|
|
698
698
|
tierWeights: Record<string, number>;
|
|
@@ -710,10 +710,10 @@ declare const ExportBundleV2Schema: z.ZodObject<{
|
|
|
710
710
|
identityAnchors: boolean;
|
|
711
711
|
peerProfiles: boolean;
|
|
712
712
|
};
|
|
713
|
-
|
|
713
|
+
description: string;
|
|
714
714
|
id: string;
|
|
715
|
+
schemaVersion: string;
|
|
715
716
|
version: string;
|
|
716
|
-
description: string;
|
|
717
717
|
parentCapsule: string | null;
|
|
718
718
|
retrievalPolicy: {
|
|
719
719
|
tierWeights: Record<string, number>;
|
|
@@ -726,16 +726,14 @@ declare const ExportBundleV2Schema: z.ZodObject<{
|
|
|
726
726
|
} | null | undefined;
|
|
727
727
|
}>;
|
|
728
728
|
}, "strip", z.ZodTypeAny, {
|
|
729
|
-
|
|
729
|
+
format: "openclaw-engram-export";
|
|
730
730
|
createdAt: string;
|
|
731
|
+
pluginVersion: string;
|
|
731
732
|
files: {
|
|
732
733
|
path: string;
|
|
733
734
|
sha256: string;
|
|
734
735
|
bytes: number;
|
|
735
736
|
}[];
|
|
736
|
-
format: "openclaw-engram-export";
|
|
737
|
-
pluginVersion: string;
|
|
738
|
-
includesTranscripts: boolean;
|
|
739
737
|
capsule: {
|
|
740
738
|
includes: {
|
|
741
739
|
procedural: boolean;
|
|
@@ -743,10 +741,10 @@ declare const ExportBundleV2Schema: z.ZodObject<{
|
|
|
743
741
|
identityAnchors: boolean;
|
|
744
742
|
peerProfiles: boolean;
|
|
745
743
|
};
|
|
746
|
-
|
|
744
|
+
description: string;
|
|
747
745
|
id: string;
|
|
746
|
+
schemaVersion: string;
|
|
748
747
|
version: string;
|
|
749
|
-
description: string;
|
|
750
748
|
parentCapsule: string | null;
|
|
751
749
|
retrievalPolicy: {
|
|
752
750
|
tierWeights: Record<string, number>;
|
|
@@ -758,17 +756,17 @@ declare const ExportBundleV2Schema: z.ZodObject<{
|
|
|
758
756
|
forkRoot: string;
|
|
759
757
|
} | null;
|
|
760
758
|
};
|
|
761
|
-
}, {
|
|
762
759
|
schemaVersion: 2;
|
|
760
|
+
includesTranscripts: boolean;
|
|
761
|
+
}, {
|
|
762
|
+
format: "openclaw-engram-export";
|
|
763
763
|
createdAt: string;
|
|
764
|
+
pluginVersion: string;
|
|
764
765
|
files: {
|
|
765
766
|
path: string;
|
|
766
767
|
sha256: string;
|
|
767
768
|
bytes: number;
|
|
768
769
|
}[];
|
|
769
|
-
format: "openclaw-engram-export";
|
|
770
|
-
pluginVersion: string;
|
|
771
|
-
includesTranscripts: boolean;
|
|
772
770
|
capsule: {
|
|
773
771
|
includes: {
|
|
774
772
|
procedural: boolean;
|
|
@@ -776,10 +774,10 @@ declare const ExportBundleV2Schema: z.ZodObject<{
|
|
|
776
774
|
identityAnchors: boolean;
|
|
777
775
|
peerProfiles: boolean;
|
|
778
776
|
};
|
|
779
|
-
|
|
777
|
+
description: string;
|
|
780
778
|
id: string;
|
|
779
|
+
schemaVersion: string;
|
|
781
780
|
version: string;
|
|
782
|
-
description: string;
|
|
783
781
|
parentCapsule: string | null;
|
|
784
782
|
retrievalPolicy: {
|
|
785
783
|
tierWeights: Record<string, number>;
|
|
@@ -791,6 +789,8 @@ declare const ExportBundleV2Schema: z.ZodObject<{
|
|
|
791
789
|
forkRoot: string;
|
|
792
790
|
} | null | undefined;
|
|
793
791
|
};
|
|
792
|
+
schemaVersion: 2;
|
|
793
|
+
includesTranscripts: boolean;
|
|
794
794
|
}>;
|
|
795
795
|
records: z.ZodArray<z.ZodObject<{
|
|
796
796
|
path: z.ZodString;
|
|
@@ -804,16 +804,14 @@ declare const ExportBundleV2Schema: z.ZodObject<{
|
|
|
804
804
|
}>, "many">;
|
|
805
805
|
}, "strip", z.ZodTypeAny, {
|
|
806
806
|
manifest: {
|
|
807
|
-
|
|
807
|
+
format: "openclaw-engram-export";
|
|
808
808
|
createdAt: string;
|
|
809
|
+
pluginVersion: string;
|
|
809
810
|
files: {
|
|
810
811
|
path: string;
|
|
811
812
|
sha256: string;
|
|
812
813
|
bytes: number;
|
|
813
814
|
}[];
|
|
814
|
-
format: "openclaw-engram-export";
|
|
815
|
-
pluginVersion: string;
|
|
816
|
-
includesTranscripts: boolean;
|
|
817
815
|
capsule: {
|
|
818
816
|
includes: {
|
|
819
817
|
procedural: boolean;
|
|
@@ -821,10 +819,10 @@ declare const ExportBundleV2Schema: z.ZodObject<{
|
|
|
821
819
|
identityAnchors: boolean;
|
|
822
820
|
peerProfiles: boolean;
|
|
823
821
|
};
|
|
824
|
-
|
|
822
|
+
description: string;
|
|
825
823
|
id: string;
|
|
824
|
+
schemaVersion: string;
|
|
826
825
|
version: string;
|
|
827
|
-
description: string;
|
|
828
826
|
parentCapsule: string | null;
|
|
829
827
|
retrievalPolicy: {
|
|
830
828
|
tierWeights: Record<string, number>;
|
|
@@ -836,6 +834,8 @@ declare const ExportBundleV2Schema: z.ZodObject<{
|
|
|
836
834
|
forkRoot: string;
|
|
837
835
|
} | null;
|
|
838
836
|
};
|
|
837
|
+
schemaVersion: 2;
|
|
838
|
+
includesTranscripts: boolean;
|
|
839
839
|
};
|
|
840
840
|
records: {
|
|
841
841
|
content: string;
|
|
@@ -843,16 +843,14 @@ declare const ExportBundleV2Schema: z.ZodObject<{
|
|
|
843
843
|
}[];
|
|
844
844
|
}, {
|
|
845
845
|
manifest: {
|
|
846
|
-
|
|
846
|
+
format: "openclaw-engram-export";
|
|
847
847
|
createdAt: string;
|
|
848
|
+
pluginVersion: string;
|
|
848
849
|
files: {
|
|
849
850
|
path: string;
|
|
850
851
|
sha256: string;
|
|
851
852
|
bytes: number;
|
|
852
853
|
}[];
|
|
853
|
-
format: "openclaw-engram-export";
|
|
854
|
-
pluginVersion: string;
|
|
855
|
-
includesTranscripts: boolean;
|
|
856
854
|
capsule: {
|
|
857
855
|
includes: {
|
|
858
856
|
procedural: boolean;
|
|
@@ -860,10 +858,10 @@ declare const ExportBundleV2Schema: z.ZodObject<{
|
|
|
860
858
|
identityAnchors: boolean;
|
|
861
859
|
peerProfiles: boolean;
|
|
862
860
|
};
|
|
863
|
-
|
|
861
|
+
description: string;
|
|
864
862
|
id: string;
|
|
863
|
+
schemaVersion: string;
|
|
865
864
|
version: string;
|
|
866
|
-
description: string;
|
|
867
865
|
parentCapsule: string | null;
|
|
868
866
|
retrievalPolicy: {
|
|
869
867
|
tierWeights: Record<string, number>;
|
|
@@ -875,6 +873,8 @@ declare const ExportBundleV2Schema: z.ZodObject<{
|
|
|
875
873
|
forkRoot: string;
|
|
876
874
|
} | null | undefined;
|
|
877
875
|
};
|
|
876
|
+
schemaVersion: 2;
|
|
877
|
+
includesTranscripts: boolean;
|
|
878
878
|
};
|
|
879
879
|
records: {
|
|
880
880
|
content: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remnic/core",
|
|
3
|
-
"version": "9.7.
|
|
3
|
+
"version": "9.7.11",
|
|
4
4
|
"description": "Framework-agnostic Remnic memory engine — orchestrator, storage, extraction, search, trust zones",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -3010,7 +3010,7 @@
|
|
|
3010
3010
|
"core"
|
|
3011
3011
|
],
|
|
3012
3012
|
"peerDependencies": {
|
|
3013
|
-
"@remnic/coding-graph": "^9.7.
|
|
3013
|
+
"@remnic/coding-graph": "^9.7.11"
|
|
3014
3014
|
},
|
|
3015
3015
|
"peerDependenciesMeta": {
|
|
3016
3016
|
"@remnic/coding-graph": {
|
package/src/access-boundary.ts
CHANGED
|
@@ -102,6 +102,8 @@ export const OPERATION_NAMES = [
|
|
|
102
102
|
"shared_context_write_output",
|
|
103
103
|
"shared_feedback_record",
|
|
104
104
|
"shared_priorities_append",
|
|
105
|
+
"relay_mission_append",
|
|
106
|
+
"relay_mission_read",
|
|
105
107
|
"shared_context_cross_signals_run",
|
|
106
108
|
"shared_context_curate_daily",
|
|
107
109
|
"compounding_weekly_synthesize",
|
package/src/access-http.ts
CHANGED
|
@@ -53,6 +53,7 @@ import { handleChatMessage, handleChatEventsSSE } from "./chat/chat-http.js";
|
|
|
53
53
|
import { cleanupExpiredChatSessions, enforceChatSessionNamespace } from "./chat/chat-session.js";
|
|
54
54
|
import { isDefaultReviewNamespace, listPairs, readPair } from "./contradiction/contradiction-review.js";
|
|
55
55
|
import { isValidResolutionVerb, executeResolution } from "./contradiction/resolution.js";
|
|
56
|
+
import { RelayMissionStoreError } from "./relay/mission.js";
|
|
56
57
|
|
|
57
58
|
export interface AccessHttpReadinessState {
|
|
58
59
|
ready: boolean;
|
|
@@ -339,6 +340,22 @@ function decodePeerIdSegment(raw: string): string {
|
|
|
339
340
|
}
|
|
340
341
|
}
|
|
341
342
|
|
|
343
|
+
function decodeRelayMissionIdSegment(raw: string): string {
|
|
344
|
+
try {
|
|
345
|
+
return decodeURIComponent(raw);
|
|
346
|
+
} catch {
|
|
347
|
+
throw new EngramAccessInputError(
|
|
348
|
+
"missionId path segment is not valid percent-encoded input",
|
|
349
|
+
);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
function rejectBlankRelayNamespace(value: string | null | undefined): void {
|
|
354
|
+
if (value !== undefined && value !== null && value.trim().length === 0) {
|
|
355
|
+
throw new EngramAccessInputError("Relay namespace must not be blank when provided");
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
342
359
|
function codingContextFromProjectTag(projectTag: string): {
|
|
343
360
|
projectId: string;
|
|
344
361
|
branch: string | null;
|
|
@@ -378,7 +395,7 @@ export class EngramAccessHttpServer {
|
|
|
378
395
|
res: ServerResponse,
|
|
379
396
|
ctx: { authorized: boolean },
|
|
380
397
|
) => Promise<boolean>;
|
|
381
|
-
private readonly
|
|
398
|
+
private readonly writeRequestSlots: Array<{ readonly recordedAt: number }> = [];
|
|
382
399
|
private readonly writeRateLimitMaxRequests: number;
|
|
383
400
|
private readonly writeRateLimitWindowMs: number;
|
|
384
401
|
private readonly mcpServer: EngramMcpServer;
|
|
@@ -499,6 +516,20 @@ export class EngramAccessHttpServer {
|
|
|
499
516
|
this.respondJson(res, 400, { error: err.message, code: "correction_contract_error" });
|
|
500
517
|
return;
|
|
501
518
|
}
|
|
519
|
+
if (err instanceof RelayMissionStoreError) {
|
|
520
|
+
const status = err.code === "idempotency_conflict"
|
|
521
|
+
? 409
|
|
522
|
+
: err.code === "limit_exceeded"
|
|
523
|
+
? 413
|
|
524
|
+
: err.code === "lock_unavailable"
|
|
525
|
+
? 503
|
|
526
|
+
: 500;
|
|
527
|
+
this.respondJson(res, status, {
|
|
528
|
+
error: status >= 500 ? "relay_backend_unavailable" : err.message,
|
|
529
|
+
code: `relay_${err.code}`,
|
|
530
|
+
});
|
|
531
|
+
return;
|
|
532
|
+
}
|
|
502
533
|
if (res.headersSent) {
|
|
503
534
|
res.destroy(err as Error);
|
|
504
535
|
return;
|
|
@@ -1670,6 +1701,103 @@ export class EngramAccessHttpServer {
|
|
|
1670
1701
|
return;
|
|
1671
1702
|
}
|
|
1672
1703
|
|
|
1704
|
+
// Remnic Relay mission receipts (issue #1966). These two routes share the
|
|
1705
|
+
// access-boundary schemas and namespace-resolved storage contract. The
|
|
1706
|
+
// browser receives an already-reduced snapshot; it never scans general
|
|
1707
|
+
// memories, recall logs, or production state.
|
|
1708
|
+
const relayEventMatch = /^\/engram\/v1\/relay\/missions\/([^/]+)\/events$/.exec(pathname);
|
|
1709
|
+
if (req.method === "POST" && relayEventMatch) {
|
|
1710
|
+
const missionId = decodeRelayMissionIdSegment(relayEventMatch[1] ?? "");
|
|
1711
|
+
const body = await this.readJsonBody(req);
|
|
1712
|
+
const unexpectedFields = Object.keys(body).filter(
|
|
1713
|
+
(key) => key !== "namespace" && key !== "event",
|
|
1714
|
+
);
|
|
1715
|
+
if (unexpectedFields.length > 0) {
|
|
1716
|
+
throw new EngramAccessInputError(
|
|
1717
|
+
`Relay append body contains unexpected field(s): ${unexpectedFields.sort().join(", ")}`,
|
|
1718
|
+
);
|
|
1719
|
+
}
|
|
1720
|
+
if (!Object.prototype.hasOwnProperty.call(body, "event")) {
|
|
1721
|
+
throw new EngramAccessInputError("Relay append body must contain an event object");
|
|
1722
|
+
}
|
|
1723
|
+
if (
|
|
1724
|
+
Object.prototype.hasOwnProperty.call(body, "namespace") &&
|
|
1725
|
+
body.namespace !== undefined &&
|
|
1726
|
+
body.namespace !== null &&
|
|
1727
|
+
typeof body.namespace !== "string"
|
|
1728
|
+
) {
|
|
1729
|
+
throw new EngramAccessInputError("namespace must be a string when provided");
|
|
1730
|
+
}
|
|
1731
|
+
rejectBlankRelayNamespace(
|
|
1732
|
+
typeof body.namespace === "string" ? body.namespace : undefined,
|
|
1733
|
+
);
|
|
1734
|
+
const namespace = this.resolveNamespace(
|
|
1735
|
+
req,
|
|
1736
|
+
typeof body.namespace === "string" ? body.namespace : undefined,
|
|
1737
|
+
);
|
|
1738
|
+
const op = getOperation("relay_mission_append");
|
|
1739
|
+
if (!op) {
|
|
1740
|
+
throw new Error("access-boundary: operation not registered: relay_mission_append");
|
|
1741
|
+
}
|
|
1742
|
+
let releaseWriteQuota: (() => void) | undefined;
|
|
1743
|
+
try {
|
|
1744
|
+
const output = (await op.run(
|
|
1745
|
+
{ missionId, namespace, event: body.event },
|
|
1746
|
+
{
|
|
1747
|
+
service: this.service,
|
|
1748
|
+
authenticatedPrincipal: this.resolveRequestPrincipal(req),
|
|
1749
|
+
hooks: {
|
|
1750
|
+
enforceWriteQuota: () => {
|
|
1751
|
+
releaseWriteQuota ??= this.reserveWriteRateLimitSlot();
|
|
1752
|
+
},
|
|
1753
|
+
},
|
|
1754
|
+
},
|
|
1755
|
+
)) as { result: { appended: boolean; replayed: boolean; event: unknown } };
|
|
1756
|
+
if (output.result.appended) {
|
|
1757
|
+
// The reservation is now the committed quota hit. Do not record a
|
|
1758
|
+
// second timestamp after the append returns.
|
|
1759
|
+
releaseWriteQuota = undefined;
|
|
1760
|
+
}
|
|
1761
|
+
this.respondJson(res, output.result.appended ? 201 : 200, output.result);
|
|
1762
|
+
} finally {
|
|
1763
|
+
// Replays never invoke the hook. If a future store path invokes it but
|
|
1764
|
+
// does not append, or persistence throws after reservation, return the
|
|
1765
|
+
// slot so a failed write cannot exhaust the rolling window.
|
|
1766
|
+
releaseWriteQuota?.();
|
|
1767
|
+
}
|
|
1768
|
+
return;
|
|
1769
|
+
}
|
|
1770
|
+
|
|
1771
|
+
const relayMissionMatch = /^\/engram\/v1\/relay\/missions\/([^/]+)$/.exec(pathname);
|
|
1772
|
+
if (req.method === "GET" && relayMissionMatch) {
|
|
1773
|
+
const missionId = decodeRelayMissionIdSegment(relayMissionMatch[1] ?? "");
|
|
1774
|
+
rejectBlankRelayNamespace(parsed.searchParams.get("namespace"));
|
|
1775
|
+
const namespace = this.resolveNamespace(
|
|
1776
|
+
req,
|
|
1777
|
+
parsed.searchParams.get("namespace") ?? undefined,
|
|
1778
|
+
);
|
|
1779
|
+
const op = getOperation("relay_mission_read");
|
|
1780
|
+
if (!op) {
|
|
1781
|
+
throw new Error("access-boundary: operation not registered: relay_mission_read");
|
|
1782
|
+
}
|
|
1783
|
+
const output = (await op.run(
|
|
1784
|
+
{
|
|
1785
|
+
missionId,
|
|
1786
|
+
namespace,
|
|
1787
|
+
since: parsed.searchParams.get("since") ?? undefined,
|
|
1788
|
+
until: parsed.searchParams.get("until") ?? undefined,
|
|
1789
|
+
limit: parsed.searchParams.get("limit") ?? undefined,
|
|
1790
|
+
},
|
|
1791
|
+
{
|
|
1792
|
+
service: this.service,
|
|
1793
|
+
authenticatedPrincipal: this.resolveRequestPrincipal(req),
|
|
1794
|
+
},
|
|
1795
|
+
)) as { result: unknown };
|
|
1796
|
+
res.setHeader("cache-control", "no-store");
|
|
1797
|
+
this.respondJson(res, 200, output.result);
|
|
1798
|
+
return;
|
|
1799
|
+
}
|
|
1800
|
+
|
|
1673
1801
|
if (req.method === "POST" && pathname === "/engram/v1/memories") {
|
|
1674
1802
|
// Migrated through the access boundary (issue #1525): the registry
|
|
1675
1803
|
// entry owns schema validation, normalization, and service dispatch.
|
|
@@ -3711,18 +3839,31 @@ export class EngramAccessHttpServer {
|
|
|
3711
3839
|
private ensureWriteRateLimitAvailable(): void {
|
|
3712
3840
|
const now = Date.now();
|
|
3713
3841
|
while (
|
|
3714
|
-
this.
|
|
3715
|
-
now - (this.
|
|
3842
|
+
this.writeRequestSlots.length > 0 &&
|
|
3843
|
+
now - (this.writeRequestSlots[0]?.recordedAt ?? 0) > this.writeRateLimitWindowMs
|
|
3716
3844
|
) {
|
|
3717
|
-
this.
|
|
3845
|
+
this.writeRequestSlots.shift();
|
|
3718
3846
|
}
|
|
3719
|
-
if (this.
|
|
3847
|
+
if (this.writeRequestSlots.length >= this.writeRateLimitMaxRequests) {
|
|
3720
3848
|
throw new HttpError(429, "write_rate_limited", "write_rate_limited");
|
|
3721
3849
|
}
|
|
3722
3850
|
}
|
|
3723
3851
|
|
|
3724
3852
|
private recordWriteRateLimitHit(): void {
|
|
3725
|
-
this.
|
|
3853
|
+
this.writeRequestSlots.push({ recordedAt: Date.now() });
|
|
3854
|
+
}
|
|
3855
|
+
|
|
3856
|
+
private reserveWriteRateLimitSlot(): () => void {
|
|
3857
|
+
this.ensureWriteRateLimitAvailable();
|
|
3858
|
+
const slot = { recordedAt: Date.now() };
|
|
3859
|
+
this.writeRequestSlots.push(slot);
|
|
3860
|
+
let active = true;
|
|
3861
|
+
return () => {
|
|
3862
|
+
if (!active) return;
|
|
3863
|
+
active = false;
|
|
3864
|
+
const index = this.writeRequestSlots.indexOf(slot);
|
|
3865
|
+
if (index >= 0) this.writeRequestSlots.splice(index, 1);
|
|
3866
|
+
};
|
|
3726
3867
|
}
|
|
3727
3868
|
|
|
3728
3869
|
private shouldCountWriteRateLimit(response: { dryRun?: boolean; idempotencyReplay?: boolean }): boolean {
|
|
@@ -282,7 +282,7 @@ test("MCP write quota is recorded after commit even when the client disconnects
|
|
|
282
282
|
});
|
|
283
283
|
const serverHost = server as unknown as {
|
|
284
284
|
mcpServer: EngramMcpServer;
|
|
285
|
-
|
|
285
|
+
writeRequestSlots: Array<{ readonly recordedAt: number }>;
|
|
286
286
|
};
|
|
287
287
|
const originalHandleRequest = serverHost.mcpServer.handleRequest.bind(serverHost.mcpServer);
|
|
288
288
|
serverHost.mcpServer.handleRequest = async (request, options) => {
|
|
@@ -318,7 +318,7 @@ test("MCP write quota is recorded after commit even when the client disconnects
|
|
|
318
318
|
|
|
319
319
|
await waitFor(operationSettled.promise);
|
|
320
320
|
await new Promise<void>((resolve) => setImmediate(resolve));
|
|
321
|
-
assert.equal(serverHost.
|
|
321
|
+
assert.equal(serverHost.writeRequestSlots.length, 1);
|
|
322
322
|
assert.equal(responseStarted, false, "the disconnected client must not receive the committed write response");
|
|
323
323
|
} finally {
|
|
324
324
|
releaseOperation.resolve();
|
package/src/access-operations.ts
CHANGED
|
@@ -678,6 +678,8 @@ export const codegraphIngestTracesOperation = defineOperation<
|
|
|
678
678
|
// Batch-migrated operations (issue #1525): registers all remaining
|
|
679
679
|
// handlers through the boundary as a side effect of importing this module.
|
|
680
680
|
import "./access-operations-batch.js";
|
|
681
|
+
// Remnic Relay mission evidence operations (issue #1966).
|
|
682
|
+
import "./relay/mission-access.js";
|
|
681
683
|
|
|
682
684
|
export const REGISTERED_OPERATIONS = [
|
|
683
685
|
memoryGetOperation.spec.name,
|
|
@@ -193,6 +193,8 @@ export const HTTP_ROUTES: readonly HttpRouteEntry[] = [
|
|
|
193
193
|
{ method: "POST", pathname: "/engram/v1/lcm/compaction/flush", operation: "lcm_compaction_flush" },
|
|
194
194
|
{ method: "POST", pathname: "/engram/v1/lcm/compaction/record", operation: "lcm_compaction_record" },
|
|
195
195
|
{ method: "GET", pathname: "/engram/v1/lcm/status", operation: "lcm_status" },
|
|
196
|
+
{ method: "GET", pathname: "/engram/v1/relay/missions/:id", operation: "relay_mission_read" },
|
|
197
|
+
{ method: "POST", pathname: "/engram/v1/relay/missions/:id/events", operation: "relay_mission_append" },
|
|
196
198
|
// Correction Contract (issue #1580) — plan/apply/pending.
|
|
197
199
|
{ method: "POST", pathname: "/engram/v1/correction/plan", operation: "memory_correct_plan" },
|
|
198
200
|
{ method: "POST", pathname: "/engram/v1/correction/apply", operation: "memory_correct_apply" },
|