@tpsdev-ai/openclaw-flair 0.3.0 → 0.4.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.
- package/index.ts +44 -8
- package/package.json +7 -5
package/index.ts
CHANGED
|
@@ -87,13 +87,19 @@ async function syncWorkspaceToFlair(
|
|
|
87
87
|
|
|
88
88
|
// ─── Auto-capture helpers ─────────────────────────────────────────────────────
|
|
89
89
|
|
|
90
|
+
// Auto-capture triggers — conservative patterns that indicate genuinely
|
|
91
|
+
// important context, not casual conversation. The LLM has memory_store
|
|
92
|
+
// for explicit saves; auto-capture is a safety net for things it misses.
|
|
90
93
|
const CAPTURE_TRIGGERS = [
|
|
91
|
-
/\b(remember|note
|
|
92
|
-
/\b(
|
|
93
|
-
/\b(decided|agreed|
|
|
94
|
+
/\b(remember this|note for future|important lesson|key decision|for the record)\b/i,
|
|
95
|
+
/\b(my name is|call me|i go by)\b/i,
|
|
96
|
+
/\b(we decided|final decision|agreed to|commitment:)\b/i,
|
|
94
97
|
];
|
|
95
98
|
|
|
99
|
+
const MIN_CAPTURE_LENGTH = 30; // skip very short messages
|
|
100
|
+
|
|
96
101
|
function shouldCapture(text: string): boolean {
|
|
102
|
+
if (text.length < MIN_CAPTURE_LENGTH) return false;
|
|
97
103
|
return CAPTURE_TRIGGERS.some((re) => re.test(text));
|
|
98
104
|
}
|
|
99
105
|
|
|
@@ -144,14 +150,22 @@ export default {
|
|
|
144
150
|
api.logger.info("openclaw-flair: auto mode — agentId will be resolved from session context");
|
|
145
151
|
}
|
|
146
152
|
const maxRecall = cfg.maxRecallResults ?? DEFAULT_MAX_RECALL;
|
|
147
|
-
const autoCapture = cfg.autoCapture ??
|
|
153
|
+
const autoCapture = cfg.autoCapture ?? false; // opt-in — trust the LLM to use memory_store
|
|
148
154
|
const autoRecall = cfg.autoRecall ?? true;
|
|
149
155
|
|
|
156
|
+
// Per-session agentId — set from config, env, or session context.
|
|
157
|
+
// IMPORTANT: Only update from before_agent_start if it matches our configured agent,
|
|
158
|
+
// NOT from other agents' cron jobs sharing the same gateway.
|
|
150
159
|
let currentAgentId: string | undefined = isAutoMode ? fallbackAgentId ?? undefined : cfg.agentId;
|
|
160
|
+
const configuredAgentId = cfg.agentId && cfg.agentId !== "auto" ? cfg.agentId : fallbackAgentId;
|
|
151
161
|
|
|
152
162
|
api.on("before_agent_start", async (event: any, ctx: any) => {
|
|
153
163
|
const eventAgentId = ctx?.agentId || (event as any).agentId;
|
|
154
|
-
if
|
|
164
|
+
// Only adopt the session agentId if we don't already have one configured,
|
|
165
|
+
// or if it matches our configured agent. Don't let kern's cron overwrite flint's agentId.
|
|
166
|
+
if (eventAgentId && (!configuredAgentId || eventAgentId === configuredAgentId)) {
|
|
167
|
+
currentAgentId = eventAgentId;
|
|
168
|
+
}
|
|
155
169
|
|
|
156
170
|
if (eventAgentId) {
|
|
157
171
|
try {
|
|
@@ -242,15 +256,37 @@ export default {
|
|
|
242
256
|
try {
|
|
243
257
|
const client = getCurrentClient();
|
|
244
258
|
const memId = `${client.agentId}-${Date.now()}`;
|
|
245
|
-
|
|
259
|
+
// If superseding an old memory, archive it
|
|
260
|
+
if (supersedes) {
|
|
261
|
+
try {
|
|
262
|
+
const old = await client.memory.get(supersedes);
|
|
263
|
+
if (old) {
|
|
264
|
+
await client.request("PUT", `/Memory/${supersedes}`, {
|
|
265
|
+
...old,
|
|
266
|
+
archived: true,
|
|
267
|
+
archivedAt: new Date().toISOString(),
|
|
268
|
+
supersededBy: memId,
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
} catch {
|
|
272
|
+
// Old memory not found — continue with the write
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
const result = await client.memory.write(text, {
|
|
246
277
|
id: memId,
|
|
247
278
|
tags,
|
|
248
279
|
durability: durability as any,
|
|
249
280
|
type: type as any,
|
|
281
|
+
dedup: !supersedes, // skip dedup when explicitly superseding
|
|
282
|
+
dedupThreshold: 0.7,
|
|
250
283
|
});
|
|
284
|
+
const wasDeduped = result.id !== memId;
|
|
251
285
|
return {
|
|
252
|
-
content: [{ type: "text", text:
|
|
253
|
-
|
|
286
|
+
content: [{ type: "text", text: wasDeduped
|
|
287
|
+
? `Similar memory already exists (id: ${result.id}): ${result.content?.slice(0, 200)}`
|
|
288
|
+
: `Memory stored (id: ${memId})` }],
|
|
289
|
+
details: { id: result.id, deduplicated: wasDeduped },
|
|
254
290
|
};
|
|
255
291
|
} catch (err: any) {
|
|
256
292
|
api.logger.warn(`openclaw-flair: store failed: ${err.message}`);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tpsdev-ai/openclaw-flair",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "OpenClaw memory plugin for Flair
|
|
3
|
+
"version": "0.4.0",
|
|
4
|
+
"description": "OpenClaw memory plugin for Flair \u2014 agent identity and semantic memory",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
|
7
7
|
"exports": {
|
|
@@ -30,7 +30,9 @@
|
|
|
30
30
|
},
|
|
31
31
|
"homepage": "https://github.com/tpsdev-ai/flair/tree/main/plugins/openclaw-flair",
|
|
32
32
|
"openclaw": {
|
|
33
|
-
"extensions": [
|
|
33
|
+
"extensions": [
|
|
34
|
+
"./index.ts"
|
|
35
|
+
]
|
|
34
36
|
},
|
|
35
37
|
"peerDependencies": {
|
|
36
38
|
"openclaw": ">=2026.3.7"
|
|
@@ -40,6 +42,6 @@
|
|
|
40
42
|
},
|
|
41
43
|
"dependencies": {
|
|
42
44
|
"@sinclair/typebox": "^0.34.0",
|
|
43
|
-
"@tpsdev-ai/flair-client": "^0.
|
|
45
|
+
"@tpsdev-ai/flair-client": "^0.2.0"
|
|
44
46
|
}
|
|
45
|
-
}
|
|
47
|
+
}
|