openclaw-clawmark 0.2.0 → 0.3.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/README.md +3 -0
- package/dist/index.js +7 -4
- package/dist/tools.d.ts +19 -1
- package/dist/tools.js +22 -1
- package/openclaw.plugin.json +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -82,6 +82,9 @@ incomplete it stays inert and logs the missing variable — it never breaks the
|
|
|
82
82
|
|
|
83
83
|
- `clawmark_set(key, value)` — remember a fact explicitly. User-set facts always win.
|
|
84
84
|
- `clawmark_search(query, limit?)` — search facts + recall excerpts from past sessions.
|
|
85
|
+
- `clawmark_reconcile(drain?)` — force the background jobs to run now (index new
|
|
86
|
+
messages, extract facts, prune) instead of waiting for the message-count or idle
|
|
87
|
+
triggers. Say "reconcile memory" to your agent and it should call this.
|
|
85
88
|
- `clawmark_review(days?)` — list extracted facts that haven't been reinforced recently,
|
|
86
89
|
so the agent can confirm them with you before they decay out.
|
|
87
90
|
- `clawmark_forget(key)` — delete a fact.
|
package/dist/index.js
CHANGED
|
@@ -27,7 +27,7 @@ const entry = definePluginEntry({
|
|
|
27
27
|
let jobsRunning = false;
|
|
28
28
|
const runJobs = async (opts = {}) => {
|
|
29
29
|
if (!runtime || jobsRunning)
|
|
30
|
-
return;
|
|
30
|
+
return null;
|
|
31
31
|
jobsRunning = true;
|
|
32
32
|
try {
|
|
33
33
|
const { db, source, embedder, config } = runtime;
|
|
@@ -35,12 +35,15 @@ const entry = definePluginEntry({
|
|
|
35
35
|
const extracted = await runExtractor(db, source, config, opts);
|
|
36
36
|
const pruned = pruneStaleFacts(db);
|
|
37
37
|
rotateEvents(db);
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
const result = { indexed: indexed.indexed, written: extracted.written, pruned };
|
|
39
|
+
if (result.indexed > 0 || result.written > 0 || result.pruned > 0) {
|
|
40
|
+
log.info(`jobs: indexed ${result.indexed} messages, wrote ${result.written} facts, pruned ${result.pruned} stale facts`);
|
|
40
41
|
}
|
|
42
|
+
return result;
|
|
41
43
|
}
|
|
42
44
|
catch (err) {
|
|
43
45
|
log.error(`background jobs failed: ${String(err)}`);
|
|
46
|
+
return null;
|
|
44
47
|
}
|
|
45
48
|
finally {
|
|
46
49
|
jobsRunning = false;
|
|
@@ -137,7 +140,7 @@ const entry = definePluginEntry({
|
|
|
137
140
|
/* never break the agent */
|
|
138
141
|
}
|
|
139
142
|
});
|
|
140
|
-
for (const tool of buildTools(() => runtime)) {
|
|
143
|
+
for (const tool of buildTools(() => runtime, (opts) => runJobs(opts))) {
|
|
141
144
|
try {
|
|
142
145
|
// Cast: our minimal ToolResult structurally matches AgentToolResult.
|
|
143
146
|
api.registerTool(tool, { optional: true });
|
package/dist/tools.d.ts
CHANGED
|
@@ -15,12 +15,20 @@ export interface ClawmarkRuntime {
|
|
|
15
15
|
embedder: EmbeddingClient;
|
|
16
16
|
config: ClawmarkConfig;
|
|
17
17
|
}
|
|
18
|
+
export interface JobsResult {
|
|
19
|
+
indexed: number;
|
|
20
|
+
written: number;
|
|
21
|
+
pruned: number;
|
|
22
|
+
}
|
|
23
|
+
export type RunJobsFn = (opts?: {
|
|
24
|
+
drain?: boolean;
|
|
25
|
+
}) => Promise<JobsResult | null>;
|
|
18
26
|
/**
|
|
19
27
|
* Tool definitions in the OpenClaw AgentTool shape. `clawmark_` prefix avoids
|
|
20
28
|
* collisions with native memory tools and other memory plugins. Runtime is resolved
|
|
21
29
|
* lazily so tools registered before gateway_start still work.
|
|
22
30
|
*/
|
|
23
|
-
export declare function buildTools(getRuntime: () => ClawmarkRuntime | null): ({
|
|
31
|
+
export declare function buildTools(getRuntime: () => ClawmarkRuntime | null, runJobs: RunJobsFn): ({
|
|
24
32
|
name: string;
|
|
25
33
|
label: string;
|
|
26
34
|
description: string;
|
|
@@ -44,6 +52,16 @@ export declare function buildTools(getRuntime: () => ClawmarkRuntime | null): ({
|
|
|
44
52
|
query: string;
|
|
45
53
|
limit?: number;
|
|
46
54
|
}): Promise<ToolResult>;
|
|
55
|
+
} | {
|
|
56
|
+
name: string;
|
|
57
|
+
label: string;
|
|
58
|
+
description: string;
|
|
59
|
+
parameters: import("@sinclair/typebox").TObject<{
|
|
60
|
+
drain: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TBoolean>;
|
|
61
|
+
}>;
|
|
62
|
+
execute(_id: string, params: {
|
|
63
|
+
drain?: boolean;
|
|
64
|
+
}): Promise<ToolResult>;
|
|
47
65
|
} | {
|
|
48
66
|
name: string;
|
|
49
67
|
label: string;
|
package/dist/tools.js
CHANGED
|
@@ -12,7 +12,7 @@ function text(value) {
|
|
|
12
12
|
* collisions with native memory tools and other memory plugins. Runtime is resolved
|
|
13
13
|
* lazily so tools registered before gateway_start still work.
|
|
14
14
|
*/
|
|
15
|
-
export function buildTools(getRuntime) {
|
|
15
|
+
export function buildTools(getRuntime, runJobs) {
|
|
16
16
|
const requireRuntime = () => {
|
|
17
17
|
const rt = getRuntime();
|
|
18
18
|
if (!rt)
|
|
@@ -62,6 +62,27 @@ export function buildTools(getRuntime) {
|
|
|
62
62
|
});
|
|
63
63
|
},
|
|
64
64
|
},
|
|
65
|
+
{
|
|
66
|
+
name: "clawmark_reconcile",
|
|
67
|
+
label: "Clawmark: reconcile memory now",
|
|
68
|
+
description: "Force the background memory jobs to run immediately instead of waiting for the " +
|
|
69
|
+
"message-count or idle triggers: index new messages into the recall store, " +
|
|
70
|
+
"extract durable facts from un-processed conversation, and prune stale facts. " +
|
|
71
|
+
"Use when the user asks to sync/reconcile/refresh memory or after an important " +
|
|
72
|
+
"conversation they want captured right away.",
|
|
73
|
+
parameters: Type.Object({
|
|
74
|
+
drain: Type.Optional(Type.Boolean({ description: "Process the entire backlog (default true); false = one incremental pass" })),
|
|
75
|
+
}),
|
|
76
|
+
async execute(_id, params) {
|
|
77
|
+
requireRuntime();
|
|
78
|
+
const result = await runJobs({ drain: params.drain ?? true });
|
|
79
|
+
if (result === null) {
|
|
80
|
+
return text("Reconcile already in progress (or plugin not initialized) — try again shortly.");
|
|
81
|
+
}
|
|
82
|
+
return text(`Reconciled: indexed ${result.indexed} new messages, extracted ${result.written} facts, ` +
|
|
83
|
+
`pruned ${result.pruned} stale facts.`);
|
|
84
|
+
},
|
|
85
|
+
},
|
|
65
86
|
{
|
|
66
87
|
name: "clawmark_review",
|
|
67
88
|
label: "Clawmark: review stale facts",
|
package/openclaw.plugin.json
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
"id": "clawmark",
|
|
3
3
|
"name": "Clawmark",
|
|
4
4
|
"description": "Durable facts and semantic recall for OpenClaw, derived from the message history you already keep. No duplicate message store; crash-safe by design.",
|
|
5
|
-
"version": "0.
|
|
5
|
+
"version": "0.3.0",
|
|
6
6
|
"contracts": {
|
|
7
|
-
"tools": ["clawmark_set", "clawmark_search", "clawmark_review", "clawmark_forget"]
|
|
7
|
+
"tools": ["clawmark_set", "clawmark_search", "clawmark_reconcile", "clawmark_review", "clawmark_forget"]
|
|
8
8
|
}
|
|
9
9
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openclaw-clawmark",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Clawmark — durable facts and semantic recall for OpenClaw, derived from the message history you already keep. No duplicate message store; crash-safe by design.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|