@clawmem-ai/clawmem 0.1.16 → 0.1.17
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/README.md +5 -7
- package/openclaw.plugin.json +4 -31
- package/package.json +12 -5
- package/skills/clawmem/SKILL.md +5 -5
- package/skills/clawmem/references/collaboration.md +43 -1
- package/skills/clawmem/references/schema.md +2 -1
- package/src/config.test.ts +0 -3
- package/src/config.ts +0 -3
- package/src/conversation.test.ts +63 -13
- package/src/conversation.ts +89 -392
- package/src/github-client.test.ts +101 -0
- package/src/github-client.ts +59 -0
- package/src/memory.test.ts +131 -46
- package/src/memory.ts +81 -392
- package/src/service.test.ts +118 -0
- package/src/service.ts +728 -419
- package/src/state.test.ts +47 -16
- package/src/state.ts +87 -119
- package/src/types.ts +9 -26
package/src/service.test.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
|
+
buildClawMemPromptSection,
|
|
2
3
|
buildAutoRecallContext,
|
|
4
|
+
createClawMemPlugin,
|
|
3
5
|
extractPromptTextForRecall,
|
|
4
6
|
resolveOpenClawHostVersion,
|
|
5
7
|
resolvePromptHookMode,
|
|
@@ -75,6 +77,118 @@ function testBuildAutoRecallContext(): void {
|
|
|
75
77
|
assert(context.includes("- [11] OpenClaw main agent identity uses Gandalf."), "expected memories to be listed as bullets");
|
|
76
78
|
}
|
|
77
79
|
|
|
80
|
+
function testBuildClawMemPromptSection(): void {
|
|
81
|
+
const lines = buildClawMemPromptSection({
|
|
82
|
+
availableTools: new Set([
|
|
83
|
+
"memory_recall",
|
|
84
|
+
"memory_list",
|
|
85
|
+
"memory_get",
|
|
86
|
+
"memory_repos",
|
|
87
|
+
"memory_labels",
|
|
88
|
+
"memory_store",
|
|
89
|
+
"memory_update",
|
|
90
|
+
"memory_forget",
|
|
91
|
+
]),
|
|
92
|
+
});
|
|
93
|
+
const prompt = lines.join("\n");
|
|
94
|
+
|
|
95
|
+
assert(lines[0] === "## ClawMem", "expected a stable heading for always-on ClawMem guidance");
|
|
96
|
+
assert(prompt.includes("active long-term memory system"), "expected the prompt to frame ClawMem as the active memory system");
|
|
97
|
+
assert(prompt.includes("`memory_recall`, `memory_list`, and `memory_get`"), "expected explicit retrieval guidance");
|
|
98
|
+
assert(prompt.includes("`memory_store` and `memory_update`"), "expected explicit save guidance");
|
|
99
|
+
assert(prompt.includes("`memory_forget`"), "expected explicit stale-memory guidance");
|
|
100
|
+
assert(prompt.includes("Store one durable fact per memory."), "expected one-fact-per-memory guidance");
|
|
101
|
+
assert(prompt.includes("Skip temporary requests, tool chatter"), "expected anti-noise write guardrails");
|
|
102
|
+
assert(prompt.includes("explicit short `title` plus a fuller `detail`"), "expected explicit title guidance");
|
|
103
|
+
assert(prompt.includes("user's current language"), "expected language guidance for new memories");
|
|
104
|
+
assert(prompt.includes("`memory_labels`"), "expected schema reuse guidance to mention memory_labels");
|
|
105
|
+
assert(prompt.includes("translated or near-duplicate variant"), "expected anti-duplication schema guidance");
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function createFakePluginApi(options?: {
|
|
109
|
+
slot?: string;
|
|
110
|
+
exposeCapability?: boolean;
|
|
111
|
+
}) {
|
|
112
|
+
let registeredCapability: { promptBuilder?: typeof buildClawMemPromptSection } | undefined;
|
|
113
|
+
let registeredPromptSection: typeof buildClawMemPromptSection | undefined;
|
|
114
|
+
const api = {
|
|
115
|
+
id: "clawmem",
|
|
116
|
+
name: "ClawMem",
|
|
117
|
+
source: "test",
|
|
118
|
+
registrationMode: "test",
|
|
119
|
+
config: {},
|
|
120
|
+
pluginConfig: {},
|
|
121
|
+
logger: {
|
|
122
|
+
info: () => {},
|
|
123
|
+
warn: () => {},
|
|
124
|
+
},
|
|
125
|
+
runtime: {
|
|
126
|
+
version: "2026.4.9",
|
|
127
|
+
config: {
|
|
128
|
+
loadConfig: () => ({
|
|
129
|
+
plugins: {
|
|
130
|
+
slots: {
|
|
131
|
+
memory: options?.slot ?? "clawmem",
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
}),
|
|
135
|
+
},
|
|
136
|
+
events: {
|
|
137
|
+
onSessionTranscriptUpdate: () => () => {},
|
|
138
|
+
},
|
|
139
|
+
subagent: {},
|
|
140
|
+
},
|
|
141
|
+
on: () => {},
|
|
142
|
+
registerTool: () => {},
|
|
143
|
+
registerService: () => {},
|
|
144
|
+
...(options?.exposeCapability === false
|
|
145
|
+
? {}
|
|
146
|
+
: {
|
|
147
|
+
registerMemoryCapability: (capability: { promptBuilder?: typeof buildClawMemPromptSection }) => {
|
|
148
|
+
registeredCapability = capability;
|
|
149
|
+
},
|
|
150
|
+
}),
|
|
151
|
+
registerMemoryPromptSection: (builder: typeof buildClawMemPromptSection) => {
|
|
152
|
+
registeredPromptSection = builder;
|
|
153
|
+
},
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
return {
|
|
157
|
+
api,
|
|
158
|
+
getRegisteredCapability: () => registeredCapability,
|
|
159
|
+
getRegisteredPromptSection: () => registeredPromptSection,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function testRegistersAlwaysOnMemoryPromptCapability(): void {
|
|
164
|
+
const fake = createFakePluginApi();
|
|
165
|
+
createClawMemPlugin(fake.api as never);
|
|
166
|
+
|
|
167
|
+
const capability = fake.getRegisteredCapability();
|
|
168
|
+
assert(Boolean(capability?.promptBuilder), "expected ClawMem to register a memory prompt builder");
|
|
169
|
+
const prompt = capability?.promptBuilder?.({ availableTools: new Set(["memory_recall", "memory_store"]) }).join("\n") ?? "";
|
|
170
|
+
assert(prompt.includes("## ClawMem"), "expected the registered prompt builder to emit ClawMem guidance");
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function testFallsBackToLegacyMemoryPromptSectionRegistration(): void {
|
|
174
|
+
const fake = createFakePluginApi({ exposeCapability: false });
|
|
175
|
+
createClawMemPlugin(fake.api as never);
|
|
176
|
+
|
|
177
|
+
assert(!fake.getRegisteredCapability(), "expected no memory capability registration when the host lacks that API");
|
|
178
|
+
const builder = fake.getRegisteredPromptSection();
|
|
179
|
+
assert(Boolean(builder), "expected fallback registration through registerMemoryPromptSection");
|
|
180
|
+
const prompt = builder?.({ availableTools: new Set(["memory_recall"]) }).join("\n") ?? "";
|
|
181
|
+
assert(prompt.includes("## ClawMem"), "expected the fallback builder to emit ClawMem guidance");
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function testSkipsAlwaysOnPromptWhenClawMemIsNotSelectedMemoryPlugin(): void {
|
|
185
|
+
const fake = createFakePluginApi({ slot: "other-memory" });
|
|
186
|
+
createClawMemPlugin(fake.api as never);
|
|
187
|
+
|
|
188
|
+
assert(!fake.getRegisteredCapability(), "expected no memory prompt registration when ClawMem is not the selected memory plugin");
|
|
189
|
+
assert(!fake.getRegisteredPromptSection(), "expected no legacy prompt registration when ClawMem is not selected");
|
|
190
|
+
}
|
|
191
|
+
|
|
78
192
|
function testResolveHostVersionFromRuntime(): void {
|
|
79
193
|
const version = resolveOpenClawHostVersion({ runtime: { version: "2026.3.28" } } as never);
|
|
80
194
|
assert(version === "2026.3.28", "expected runtime.version to take precedence");
|
|
@@ -139,11 +253,15 @@ testExtractPromptFallsBackToLatestUserMessage();
|
|
|
139
253
|
testExtractPromptFromPromptField();
|
|
140
254
|
testExtractPromptFromStructuredContent();
|
|
141
255
|
testBuildAutoRecallContext();
|
|
256
|
+
testBuildClawMemPromptSection();
|
|
142
257
|
testResolveHostVersionFromRuntime();
|
|
143
258
|
testResolveHostVersionFromEnvFallback();
|
|
144
259
|
testIgnoresNpmPackageVersionFallback();
|
|
145
260
|
testResolvePromptHookModeModern();
|
|
146
261
|
testResolvePromptHookModeLegacy();
|
|
147
262
|
testResolvePromptHookModeLegacyForUnknownVersion();
|
|
263
|
+
testRegistersAlwaysOnMemoryPromptCapability();
|
|
264
|
+
testFallsBackToLegacyMemoryPromptSectionRegistration();
|
|
265
|
+
testSkipsAlwaysOnPromptWhenClawMemIsNotSelectedMemoryPlugin();
|
|
148
266
|
|
|
149
267
|
console.log("service tests passed");
|