@ghilteras/opencode-agent-memory 0.4.3 → 0.5.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.
@@ -1,158 +0,0 @@
1
- import { describe, expect, test } from "bun:test";
2
-
3
- import type { MemoryBlock } from "./memory";
4
- import { renderMemoryBlocks } from "./prompt";
5
-
6
- describe("renderMemoryBlocks", () => {
7
- test("renders stable xml with line numbers", () => {
8
- const xml = renderMemoryBlocks([
9
- {
10
- scope: "global",
11
- label: "human",
12
- description: "User prefs",
13
- limit: 10,
14
- readOnly: false,
15
- value: "line one\nline two",
16
- filePath: "/tmp/human.md",
17
- lastModified: new Date("2025-01-15T10:30:00Z"),
18
- },
19
- ]);
20
-
21
- expect(xml).toContain("<memory_blocks>");
22
- expect(xml).toContain("The following memory blocks are currently engaged");
23
- expect(xml).toContain("<human>");
24
- expect(xml).toContain("<warning>");
25
- expect(xml).toContain("Do NOT include line number prefixes");
26
- expect(xml).toContain("1→ line one");
27
- expect(xml).toContain("2→ line two");
28
- });
29
-
30
- test("includes memory instructions section", () => {
31
- const xml = renderMemoryBlocks([
32
- {
33
- scope: "global",
34
- label: "human",
35
- description: "User prefs",
36
- limit: 10,
37
- readOnly: false,
38
- value: "hi",
39
- filePath: "/tmp/human.md",
40
- lastModified: new Date("2025-01-15T10:30:00Z"),
41
- },
42
- ]);
43
-
44
- expect(xml).toContain("<memory_instructions>");
45
- expect(xml).toContain("<memory_editing>");
46
- expect(xml).toContain("persistent memory");
47
- expect(xml).toContain("<memory_scopes>");
48
- expect(xml).toContain("</memory_instructions>");
49
- });
50
-
51
- test("includes per-block last_modified in metadata", () => {
52
- const xml = renderMemoryBlocks([
53
- {
54
- scope: "global",
55
- label: "human",
56
- description: "User prefs",
57
- limit: 10,
58
- readOnly: false,
59
- value: "hi",
60
- filePath: "/tmp/human.md",
61
- lastModified: new Date("2025-01-15T10:30:00Z"),
62
- },
63
- ]);
64
-
65
- expect(xml).toContain("last_modified=2025-01-15T10:30:00.000Z");
66
- expect(xml).not.toContain("<memory_metadata>");
67
- expect(xml).not.toContain("The current system date is:");
68
- });
69
-
70
- test("does not contain volatile new Date() content", () => {
71
- const block: MemoryBlock = {
72
- scope: "global",
73
- label: "human",
74
- description: "User prefs",
75
- limit: 10,
76
- readOnly: false,
77
- value: "hi",
78
- filePath: "/tmp/human.md",
79
- lastModified: new Date("2025-01-15T10:30:00Z"),
80
- };
81
- const xml = renderMemoryBlocks([block]);
82
- const xml2 = renderMemoryBlocks([block]);
83
-
84
- expect(xml).toBe(xml2);
85
- });
86
-
87
- test("handles empty value gracefully", () => {
88
- const xml = renderMemoryBlocks([
89
- {
90
- scope: "project",
91
- label: "notes",
92
- description: "Project notes",
93
- limit: 1000,
94
- readOnly: false,
95
- value: "",
96
- filePath: "/tmp/notes.md",
97
- lastModified: new Date("2025-01-15T10:30:00Z"),
98
- },
99
- ]);
100
-
101
- expect(xml).toContain("<notes>");
102
- expect(xml).toContain("<value>\n\n</value>");
103
- // Empty value - the value section should be truly empty
104
- const valueMatch = xml.match(/<value>\n(.*?)\n<\/value>/s);
105
- expect(valueMatch).toBeTruthy();
106
- expect(valueMatch![1]).toBe("");
107
- });
108
-
109
- test("renders complete output structure", () => {
110
- const xml = renderMemoryBlocks([
111
- {
112
- scope: "global",
113
- label: "persona",
114
- description: "Your persona",
115
- limit: 5000,
116
- readOnly: false,
117
- value: "I am helpful\nand concise",
118
- filePath: "/tmp/persona.md",
119
- lastModified: new Date("2025-01-15T08:00:00Z"),
120
- },
121
- {
122
- scope: "project",
123
- label: "project",
124
- description: "Project info",
125
- limit: 5000,
126
- readOnly: true,
127
- value: "This is a TypeScript project",
128
- filePath: "/tmp/project.md",
129
- lastModified: new Date("2025-01-15T10:30:00Z"),
130
- },
131
- ]);
132
-
133
- // Check overall structure order
134
- const instructionsIndex = xml.indexOf("<memory_instructions>");
135
- const blocksIndex = xml.indexOf("<memory_blocks>");
136
-
137
- expect(instructionsIndex).toBeLessThan(blocksIndex);
138
- expect(xml).not.toContain("<memory_metadata>");
139
-
140
- // Check both blocks present
141
- expect(xml).toContain("<persona>");
142
- expect(xml).toContain("</persona>");
143
- expect(xml).toContain("<project>");
144
- expect(xml).toContain("</project>");
145
-
146
- // Check per-block last_modified timestamps
147
- expect(xml).toContain("last_modified=2025-01-15T08:00:00.000Z");
148
- expect(xml).toContain("last_modified=2025-01-15T10:30:00.000Z");
149
-
150
- // Check line numbers in multi-line value
151
- expect(xml).toContain("1→ I am helpful");
152
- expect(xml).toContain("2→ and concise");
153
-
154
- // Check read_only rendered
155
- expect(xml).toContain("read_only=true");
156
- expect(xml).toContain("read_only=false");
157
- });
158
- });
package/src/prompt.ts DELETED
@@ -1,58 +0,0 @@
1
- import type { MemoryBlock } from "./memory";
2
- import { MEMORY_INSTRUCTIONS } from "./letta";
3
-
4
- const LINE_NUMBER_WARNING =
5
- "# NOTE: Line numbers shown below (with arrows like '1→') are to help during editing. Do NOT include line number prefixes in your memory edit tool calls.";
6
-
7
- export function renderMemoryBlocks(blocks: MemoryBlock[]): string {
8
- if (blocks.length === 0) {
9
- return "";
10
- }
11
-
12
- const parts: string[] = [
13
- MEMORY_INSTRUCTIONS,
14
- "",
15
- "<memory_blocks>",
16
- "The following memory blocks are currently engaged in your core memory unit:",
17
- "",
18
- ];
19
-
20
- for (const block of blocks) {
21
- // escape xml
22
- const desc = block.description
23
- .replaceAll("&", "&amp;")
24
- .replaceAll("<", "&lt;")
25
- .replaceAll(">", "&gt;");
26
-
27
- const numberedValue = block.value
28
- ? block.value.split("\n").map((line, i) => `${i + 1}→ ${line}`).join("\n")
29
- : "";
30
-
31
- const memoryBlock = `<${block.label}>
32
- <description>
33
- ${desc}
34
- </description>
35
- <metadata>
36
- ${[
37
- `- chars_current=${block.value.length}`,
38
- `- chars_limit=${block.limit}`,
39
- `- read_only=${block.readOnly}`,
40
- `- scope=${block.scope}`,
41
- `- last_modified=${block.lastModified.toISOString()}`,
42
- ].join("\n")}
43
- </metadata>
44
- <warning>
45
- ${LINE_NUMBER_WARNING}
46
- </warning>
47
- <value>
48
- ${numberedValue}
49
- </value>
50
- </${block.label}>`;
51
-
52
- parts.push(memoryBlock);
53
- }
54
-
55
- parts.push("</memory_blocks>");
56
-
57
- return parts.join("\n");
58
- }