pi-observational-memory 2.4.3 → 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.
@@ -0,0 +1,200 @@
1
+ export const OM_OBSERVATIONS_RECORDED = "om.observations.recorded";
2
+ export const OM_REFLECTIONS_RECORDED = "om.reflections.recorded";
3
+ export const OM_OBSERVATIONS_DROPPED = "om.observations.dropped";
4
+ export const OM_FOLDED = "om.folded";
5
+
6
+ export const RELEVANCE_VALUES = ["low", "medium", "high", "critical"] as const;
7
+ export type Relevance = (typeof RELEVANCE_VALUES)[number];
8
+
9
+ export const MEMORY_ID_PATTERN = /^[a-f0-9]{12}$/;
10
+
11
+ export type Entry = {
12
+ type: string;
13
+ id: string;
14
+ timestamp?: string;
15
+ message?: unknown;
16
+ content?: unknown;
17
+ customType?: string;
18
+ summary?: unknown;
19
+ fromId?: string;
20
+ data?: unknown;
21
+ details?: unknown;
22
+ firstKeptEntryId?: string;
23
+ };
24
+
25
+ export type Observation = {
26
+ id: string;
27
+ content: string;
28
+ timestamp: string;
29
+ relevance: Relevance;
30
+ sourceEntryIds: string[];
31
+ tokenCount: number;
32
+ };
33
+
34
+ export type Reflection = {
35
+ id: string;
36
+ content: string;
37
+ supportingObservationIds: string[];
38
+ tokenCount: number;
39
+ };
40
+
41
+ export type ObservationsRecordedEntryData = {
42
+ observations: Observation[];
43
+ coversUpToId: string;
44
+ };
45
+
46
+ export type ReflectionsRecordedEntryData = {
47
+ reflections: Reflection[];
48
+ coversUpToId: string;
49
+ };
50
+
51
+ export type ObservationsDroppedEntryData = {
52
+ observationIds: string[];
53
+ coversUpToId: string;
54
+ };
55
+
56
+ export type MemoryDetails = {
57
+ type: typeof OM_FOLDED;
58
+ version: 1;
59
+ fullFold: boolean;
60
+ observations: Observation[];
61
+ reflections: Reflection[];
62
+ };
63
+
64
+ export type V3MemoryCustomType =
65
+ | typeof OM_OBSERVATIONS_RECORDED
66
+ | typeof OM_REFLECTIONS_RECORDED
67
+ | typeof OM_OBSERVATIONS_DROPPED;
68
+
69
+ export function isRelevance(value: unknown): value is Relevance {
70
+ return typeof value === "string" && (RELEVANCE_VALUES as readonly string[]).includes(value);
71
+ }
72
+
73
+ export function isNonEmptyString(value: unknown): value is string {
74
+ return typeof value === "string" && value.length > 0;
75
+ }
76
+
77
+ export function isNonEmptyStringArray(value: unknown): value is string[] {
78
+ return Array.isArray(value) && value.length > 0 && value.every(isNonEmptyString);
79
+ }
80
+
81
+ export function isMemoryId(value: unknown): value is string {
82
+ return typeof value === "string" && MEMORY_ID_PATTERN.test(value);
83
+ }
84
+
85
+ function isTokenCount(value: unknown): value is number {
86
+ return typeof value === "number" && Number.isFinite(value) && value >= 0;
87
+ }
88
+
89
+ function isPlainRecord(value: unknown): value is Record<string, unknown> {
90
+ return !!value && typeof value === "object";
91
+ }
92
+
93
+ export function isObservation(value: unknown): value is Observation {
94
+ if (!isPlainRecord(value)) return false;
95
+ return (
96
+ isMemoryId(value.id) &&
97
+ isNonEmptyString(value.content) &&
98
+ isNonEmptyString(value.timestamp) &&
99
+ isRelevance(value.relevance) &&
100
+ isNonEmptyStringArray(value.sourceEntryIds) &&
101
+ isTokenCount(value.tokenCount)
102
+ );
103
+ }
104
+
105
+ export function isReflection(value: unknown): value is Reflection {
106
+ if (!isPlainRecord(value)) return false;
107
+ return (
108
+ isMemoryId(value.id) &&
109
+ isNonEmptyString(value.content) &&
110
+ !/\r|\n/.test(value.content) &&
111
+ isNonEmptyStringArray(value.supportingObservationIds) &&
112
+ isTokenCount(value.tokenCount)
113
+ );
114
+ }
115
+
116
+ export function isObservationsRecordedData(value: unknown): value is ObservationsRecordedEntryData {
117
+ if (!isPlainRecord(value)) return false;
118
+ return (
119
+ Array.isArray(value.observations) &&
120
+ value.observations.length > 0 &&
121
+ value.observations.every(isObservation) &&
122
+ isNonEmptyString(value.coversUpToId)
123
+ );
124
+ }
125
+
126
+ export function isReflectionsRecordedData(value: unknown): value is ReflectionsRecordedEntryData {
127
+ if (!isPlainRecord(value)) return false;
128
+ return (
129
+ Array.isArray(value.reflections) &&
130
+ value.reflections.length > 0 &&
131
+ value.reflections.every(isReflection) &&
132
+ isNonEmptyString(value.coversUpToId)
133
+ );
134
+ }
135
+
136
+ export function isObservationsDroppedData(value: unknown): value is ObservationsDroppedEntryData {
137
+ if (!isPlainRecord(value)) return false;
138
+ return isNonEmptyStringArray(value.observationIds) && isNonEmptyString(value.coversUpToId);
139
+ }
140
+
141
+ export function isMemoryDetails(value: unknown): value is MemoryDetails {
142
+ if (!isPlainRecord(value)) return false;
143
+ return (
144
+ value.type === OM_FOLDED &&
145
+ value.version === 1 &&
146
+ typeof value.fullFold === "boolean" &&
147
+ Array.isArray(value.observations) &&
148
+ value.observations.every(isObservation) &&
149
+ Array.isArray(value.reflections) &&
150
+ value.reflections.every(isReflection)
151
+ );
152
+ }
153
+
154
+ export function isObservationsRecordedEntry(entry: Entry): entry is Entry & {
155
+ type: "custom";
156
+ customType: typeof OM_OBSERVATIONS_RECORDED;
157
+ data: ObservationsRecordedEntryData;
158
+ } {
159
+ return entry.type === "custom" && entry.customType === OM_OBSERVATIONS_RECORDED && isObservationsRecordedData(entry.data);
160
+ }
161
+
162
+ export function isReflectionsRecordedEntry(entry: Entry): entry is Entry & {
163
+ type: "custom";
164
+ customType: typeof OM_REFLECTIONS_RECORDED;
165
+ data: ReflectionsRecordedEntryData;
166
+ } {
167
+ return entry.type === "custom" && entry.customType === OM_REFLECTIONS_RECORDED && isReflectionsRecordedData(entry.data);
168
+ }
169
+
170
+ export function isObservationsDroppedEntry(entry: Entry): entry is Entry & {
171
+ type: "custom";
172
+ customType: typeof OM_OBSERVATIONS_DROPPED;
173
+ data: ObservationsDroppedEntryData;
174
+ } {
175
+ return entry.type === "custom" && entry.customType === OM_OBSERVATIONS_DROPPED && isObservationsDroppedData(entry.data);
176
+ }
177
+
178
+ export function buildObservationsRecordedData(
179
+ observations: Observation[],
180
+ coversUpToId: string,
181
+ ): ObservationsRecordedEntryData | undefined {
182
+ if (observations.length === 0 || !isNonEmptyString(coversUpToId)) return undefined;
183
+ return { observations, coversUpToId };
184
+ }
185
+
186
+ export function buildReflectionsRecordedData(
187
+ reflections: Reflection[],
188
+ coversUpToId: string,
189
+ ): ReflectionsRecordedEntryData | undefined {
190
+ if (reflections.length === 0 || !isNonEmptyString(coversUpToId)) return undefined;
191
+ return { reflections, coversUpToId };
192
+ }
193
+
194
+ export function buildObservationsDroppedData(
195
+ observationIds: string[],
196
+ coversUpToId: string,
197
+ ): ObservationsDroppedEntryData | undefined {
198
+ if (observationIds.length === 0 || !isNonEmptyString(coversUpToId)) return undefined;
199
+ return { observationIds, coversUpToId };
200
+ }
package/src/tokens.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { estimateTokens as estimateMessageTokens } from "@mariozechner/pi-coding-agent";
1
+ import { estimateTokens as estimateMessageTokens } from "@earendil-works/pi-coding-agent";
2
2
 
3
3
  export function estimateStringTokens(text: string): number {
4
4
  return Math.ceil(text.length / 4);