pi-observational-memory 2.3.0 → 2.4.1

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/src/types.ts CHANGED
@@ -4,6 +4,8 @@ export type Relevance = "low" | "medium" | "high" | "critical";
4
4
 
5
5
  export const RELEVANCE_VALUES: readonly Relevance[] = ["low", "medium", "high", "critical"] as const;
6
6
 
7
+ export const MEMORY_ID_PATTERN = /^[a-f0-9]{12}$/;
8
+
7
9
  export interface ObservationRecord {
8
10
  id: string;
9
11
  content: string;
@@ -12,15 +14,41 @@ export interface ObservationRecord {
12
14
  sourceEntryIds?: string[];
13
15
  }
14
16
 
15
- export type Reflection = string;
17
+ export type LegacyReflection = string;
18
+
19
+ export interface ReflectionRecord {
20
+ id: string;
21
+ content: string;
22
+ supportingObservationIds: string[];
23
+ legacy?: boolean;
24
+ }
25
+
26
+ export type MemoryReflection = LegacyReflection | ReflectionRecord;
27
+
28
+ /**
29
+ * Current runtime reflection alias used by pre-v4 consumers. Later producer/consumer
30
+ * steps should migrate surfaces that need id-bearing records to MemoryReflection.
31
+ */
32
+ export type Reflection = LegacyReflection;
16
33
 
17
- export interface MemoryDetails {
34
+ export interface MemoryDetailsV3 {
18
35
  type: "observational-memory";
19
36
  version: 3;
20
37
  observations: ObservationRecord[];
21
- reflections: Reflection[];
38
+ reflections: LegacyReflection[];
22
39
  }
23
40
 
41
+ export interface MemoryDetailsV4 {
42
+ type: "observational-memory";
43
+ version: 4;
44
+ observations: ObservationRecord[];
45
+ reflections: MemoryReflection[];
46
+ }
47
+
48
+ export type SupportedMemoryDetails = MemoryDetailsV3 | MemoryDetailsV4;
49
+
50
+ export type MemoryDetails = MemoryDetailsV3;
51
+
24
52
  export interface ObservationEntryData {
25
53
  records: ObservationRecord[];
26
54
  coversFromId: string;
@@ -44,14 +72,51 @@ function isObservationRecord(v: unknown): v is ObservationRecord {
44
72
  return false;
45
73
  }
46
74
  if (o.sourceEntryIds === undefined) return true;
47
- return (
48
- Array.isArray(o.sourceEntryIds) &&
49
- o.sourceEntryIds.length > 0 &&
50
- o.sourceEntryIds.every((id) => typeof id === "string" && id.length > 0)
51
- );
75
+ return isNonEmptyStringArray(o.sourceEntryIds);
52
76
  }
53
77
 
54
- export function isMemoryDetails(d: unknown): d is MemoryDetails {
78
+ function isNonEmptyStringArray(v: unknown): v is string[] {
79
+ return Array.isArray(v) && v.length > 0 && v.every((id) => typeof id === "string" && id.length > 0);
80
+ }
81
+
82
+ function isEmptyStringArray(v: unknown): v is string[] {
83
+ return Array.isArray(v) && v.length === 0;
84
+ }
85
+
86
+ export function isReflectionRecord(v: unknown): v is ReflectionRecord {
87
+ if (!v || typeof v !== "object") return false;
88
+ const o = v as Record<string, unknown>;
89
+ if (
90
+ typeof o.id !== "string" ||
91
+ !MEMORY_ID_PATTERN.test(o.id) ||
92
+ typeof o.content !== "string" ||
93
+ o.content.trim().length === 0 ||
94
+ /[\r\n]/.test(o.content)
95
+ ) {
96
+ return false;
97
+ }
98
+ if (o.legacy !== undefined && typeof o.legacy !== "boolean") return false;
99
+ if (o.legacy === true) return isEmptyStringArray(o.supportingObservationIds);
100
+ return isNonEmptyStringArray(o.supportingObservationIds);
101
+ }
102
+
103
+ export function isMemoryReflection(v: unknown): v is MemoryReflection {
104
+ return typeof v === "string" || isReflectionRecord(v);
105
+ }
106
+
107
+ export function reflectionContent(reflection: MemoryReflection): string {
108
+ return typeof reflection === "string" ? reflection : reflection.content;
109
+ }
110
+
111
+ export function reflectionId(reflection: MemoryReflection): string | undefined {
112
+ return typeof reflection === "string" ? undefined : reflection.id;
113
+ }
114
+
115
+ export function reflectionToPromptLine(reflection: MemoryReflection): string {
116
+ return typeof reflection === "string" ? reflection : `[${reflection.id}] ${reflection.content}`;
117
+ }
118
+
119
+ export function isMemoryDetailsV3(d: unknown): d is MemoryDetailsV3 {
55
120
  if (!d || typeof d !== "object") return false;
56
121
  const o = d as Record<string, unknown>;
57
122
  if (o.type !== "observational-memory" || o.version !== 3) return false;
@@ -60,6 +125,23 @@ export function isMemoryDetails(d: unknown): d is MemoryDetails {
60
125
  return o.reflections.every((r) => typeof r === "string");
61
126
  }
62
127
 
128
+ export function isMemoryDetailsV4(d: unknown): d is MemoryDetailsV4 {
129
+ if (!d || typeof d !== "object") return false;
130
+ const o = d as Record<string, unknown>;
131
+ if (o.type !== "observational-memory" || o.version !== 4) return false;
132
+ if (!Array.isArray(o.observations) || !Array.isArray(o.reflections)) return false;
133
+ if (!o.observations.every(isObservationRecord)) return false;
134
+ return o.reflections.every(isMemoryReflection);
135
+ }
136
+
137
+ export function isSupportedMemoryDetails(d: unknown): d is SupportedMemoryDetails {
138
+ return isMemoryDetailsV3(d) || isMemoryDetailsV4(d);
139
+ }
140
+
141
+ export function isMemoryDetails(d: unknown): d is MemoryDetails {
142
+ return isMemoryDetailsV3(d);
143
+ }
144
+
63
145
  export function isObservationEntryData(d: unknown): d is ObservationEntryData {
64
146
  if (!d || typeof d !== "object") return false;
65
147
  const o = d as Record<string, unknown>;