@unblocklabs/unblock-memory 0.3.6 → 0.3.8
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 +28 -44
- package/dist/src/config.d.ts +0 -3
- package/dist/src/config.js +11 -9
- package/dist/src/people-evidence.d.ts +7 -0
- package/dist/src/people-evidence.js +50 -17
- package/dist/src/people-hooks.js +62 -25
- package/dist/src/people-refinement.d.ts +8 -66
- package/dist/src/people-refinement.js +10 -234
- package/dist/src/people-store.d.ts +20 -9
- package/dist/src/people-store.js +137 -64
- package/dist/src/people-tools.d.ts +1 -1
- package/dist/src/people-tools.js +66 -20
- package/dist/src/plugin.js +0 -2
- package/openclaw.plugin.json +6 -14
- package/package.json +1 -1
- package/dist/src/people-cli.d.ts +0 -4
- package/dist/src/people-cli.js +0 -47
package/dist/src/people-tools.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { jsonResult } from "openclaw/plugin-sdk/agent-runtime";
|
|
2
|
+
import { resolveAgentDir } from "openclaw/plugin-sdk/memory-core-host-engine-foundation";
|
|
2
3
|
import { Type } from "typebox";
|
|
3
4
|
import { Value } from "typebox/value";
|
|
4
5
|
import { renderPeopleWhisper } from "./people-hooks.js";
|
|
6
|
+
import { nextPeopleRefinement } from "./people-refinement.js";
|
|
7
|
+
import { PERSON_DOSSIER_SCHEMA } from "./people-store.js";
|
|
5
8
|
import { createOpenClawSlackDirectory, syncSlackDirectory, } from "./slack-directory.js";
|
|
6
9
|
const nonEmpty = Type.String({ pattern: "\\S", maxLength: 1000 });
|
|
7
10
|
const inspectParameters = Type.Union([
|
|
@@ -40,13 +43,30 @@ const inspectParameters = Type.Union([
|
|
|
40
43
|
description: "Maximum actionable todos to return.",
|
|
41
44
|
})),
|
|
42
45
|
}, { additionalProperties: false }),
|
|
46
|
+
Type.Object({
|
|
47
|
+
view: Type.Literal("refinement_next"),
|
|
48
|
+
evidenceLimit: Type.Optional(Type.Integer({ minimum: 1, maximum: 50 })),
|
|
49
|
+
}, { additionalProperties: false }),
|
|
43
50
|
]);
|
|
44
51
|
const updateParameters = Type.Union([
|
|
45
52
|
Type.Object({
|
|
46
|
-
action: Type.Literal("
|
|
53
|
+
action: Type.Literal("set_injection"),
|
|
54
|
+
personId: nonEmpty,
|
|
55
|
+
enabled: Type.Boolean(),
|
|
56
|
+
}, { additionalProperties: false }),
|
|
57
|
+
Type.Object({
|
|
58
|
+
action: Type.Literal("replace_dossier"),
|
|
59
|
+
personId: nonEmpty,
|
|
60
|
+
dossier: Type.Optional(PERSON_DOSSIER_SCHEMA),
|
|
61
|
+
consumedEvidenceLocators: Type.Optional(Type.Array(Type.String({ pattern: "^session:.+:event:\\d+$", maxLength: 1000 }), {
|
|
62
|
+
minItems: 1,
|
|
63
|
+
maxItems: 50,
|
|
64
|
+
uniqueItems: true,
|
|
65
|
+
})),
|
|
66
|
+
}, { additionalProperties: false }),
|
|
67
|
+
Type.Object({
|
|
68
|
+
action: Type.Literal("delete_dossier"),
|
|
47
69
|
personId: nonEmpty,
|
|
48
|
-
refinementEnabled: Type.Optional(Type.Boolean()),
|
|
49
|
-
injectionEnabled: Type.Optional(Type.Boolean()),
|
|
50
70
|
}, { additionalProperties: false }),
|
|
51
71
|
Type.Object({
|
|
52
72
|
action: Type.Literal("set_company"),
|
|
@@ -74,7 +94,7 @@ const syncParameters = Type.Object({
|
|
|
74
94
|
}, { additionalProperties: false });
|
|
75
95
|
function context(ctx) {
|
|
76
96
|
const cfg = ctx.getRuntimeConfig?.() ?? ctx.runtimeConfig ?? ctx.config;
|
|
77
|
-
return cfg && ctx.agentId ? { agentId: ctx.agentId } : undefined;
|
|
97
|
+
return cfg && ctx.agentId ? { agentId: ctx.agentId, cfg } : undefined;
|
|
78
98
|
}
|
|
79
99
|
function personView(stores, agentId, selector, maxChars) {
|
|
80
100
|
const store = stores.get(agentId);
|
|
@@ -99,18 +119,35 @@ function personView(stores, agentId, selector, maxChars) {
|
|
|
99
119
|
}
|
|
100
120
|
function createInspectTool(stores, config, ctx) {
|
|
101
121
|
const active = context(ctx);
|
|
102
|
-
if (!active
|
|
122
|
+
if (!active)
|
|
103
123
|
return null;
|
|
104
124
|
return {
|
|
105
125
|
name: "memory_people_inspect",
|
|
106
126
|
label: "Inspect People Memory",
|
|
107
|
-
description: "Inspect
|
|
127
|
+
description: "Inspect a person, list actionable people todos, or read the next person's unseen interaction evidence for dossier refinement.",
|
|
108
128
|
parameters: inspectParameters,
|
|
109
129
|
async execute(_toolCallId, raw) {
|
|
110
130
|
const input = Value.Parse(inspectParameters, raw);
|
|
111
131
|
if (input.view === "person") {
|
|
112
132
|
return jsonResult(personView(stores, active.agentId, input, config.whisperer.maxChars));
|
|
113
133
|
}
|
|
134
|
+
if (input.view === "refinement_next") {
|
|
135
|
+
try {
|
|
136
|
+
const refinement = nextPeopleRefinement({
|
|
137
|
+
store: stores.get(active.agentId),
|
|
138
|
+
agentId: active.agentId,
|
|
139
|
+
agentDatabasePath: `${resolveAgentDir(active.cfg, active.agentId)}/openclaw-agent.sqlite`,
|
|
140
|
+
evidenceLimit: input.evidenceLimit,
|
|
141
|
+
});
|
|
142
|
+
return jsonResult(refinement ? { status: "ok", refinement } : { status: "empty" });
|
|
143
|
+
}
|
|
144
|
+
catch (error) {
|
|
145
|
+
return jsonResult({
|
|
146
|
+
status: "unavailable",
|
|
147
|
+
error: error instanceof Error ? error.message : String(error),
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
}
|
|
114
151
|
return jsonResult({
|
|
115
152
|
status: "ok",
|
|
116
153
|
todos: stores.get(active.agentId).listTodos(input.limit ?? 20),
|
|
@@ -120,27 +157,40 @@ function createInspectTool(stores, config, ctx) {
|
|
|
120
157
|
}
|
|
121
158
|
function createUpdateTool(stores, ctx) {
|
|
122
159
|
const active = context(ctx);
|
|
123
|
-
if (!active
|
|
160
|
+
if (!active)
|
|
124
161
|
return null;
|
|
125
162
|
return {
|
|
126
163
|
name: "memory_people_update",
|
|
127
164
|
label: "Update People Memory",
|
|
128
|
-
description: "
|
|
165
|
+
description: "Update a dossier, one person's injection preference, company, todo, or person status.",
|
|
129
166
|
parameters: updateParameters,
|
|
130
167
|
async execute(_toolCallId, raw) {
|
|
131
|
-
if (ctx.senderIsOwner !== true)
|
|
132
|
-
return jsonResult({ status: "forbidden", error: "owner authorization required" });
|
|
133
168
|
const input = Value.Parse(updateParameters, raw);
|
|
134
169
|
const store = stores.get(active.agentId);
|
|
135
|
-
if (input.action === "
|
|
136
|
-
|
|
170
|
+
if (input.action === "set_injection") {
|
|
171
|
+
const person = store.setInjection(input.personId, input.enabled);
|
|
172
|
+
return jsonResult(person ? { status: "ok", person } : { status: "not_found" });
|
|
173
|
+
}
|
|
174
|
+
if (input.action === "replace_dossier") {
|
|
175
|
+
if (input.dossier === undefined && input.consumedEvidenceLocators === undefined) {
|
|
137
176
|
return jsonResult({
|
|
138
177
|
status: "invalid",
|
|
139
|
-
error: "
|
|
178
|
+
error: "replace_dossier requires a dossier or consumed evidence locators",
|
|
140
179
|
});
|
|
141
180
|
}
|
|
142
|
-
|
|
143
|
-
|
|
181
|
+
try {
|
|
182
|
+
const dossier = store.replaceDossier(input.personId, input.dossier, input.consumedEvidenceLocators);
|
|
183
|
+
return jsonResult({ status: "ok", dossier });
|
|
184
|
+
}
|
|
185
|
+
catch (error) {
|
|
186
|
+
if (error instanceof Error && error.message.startsWith("person not found:")) {
|
|
187
|
+
return jsonResult({ status: "not_found" });
|
|
188
|
+
}
|
|
189
|
+
throw error;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
if (input.action === "delete_dossier") {
|
|
193
|
+
return jsonResult(store.deleteDossier(input.personId) ? { status: "ok" } : { status: "not_found" });
|
|
144
194
|
}
|
|
145
195
|
if (input.action === "set_company") {
|
|
146
196
|
const company = store.setCompany(input.personId, {
|
|
@@ -165,7 +215,7 @@ function createUpdateTool(stores, ctx) {
|
|
|
165
215
|
}
|
|
166
216
|
function createSyncTool(stores, reader, ctx) {
|
|
167
217
|
const active = context(ctx);
|
|
168
|
-
if (!active
|
|
218
|
+
if (!active)
|
|
169
219
|
return null;
|
|
170
220
|
return {
|
|
171
221
|
name: "memory_people_sync",
|
|
@@ -174,8 +224,6 @@ function createSyncTool(stores, reader, ctx) {
|
|
|
174
224
|
parameters: syncParameters,
|
|
175
225
|
async execute(_toolCallId, raw) {
|
|
176
226
|
const input = Value.Parse(syncParameters, raw);
|
|
177
|
-
if (ctx.senderIsOwner !== true)
|
|
178
|
-
return jsonResult({ status: "forbidden", error: "owner authorization required" });
|
|
179
227
|
try {
|
|
180
228
|
return jsonResult(await syncSlackDirectory({
|
|
181
229
|
store: stores.get(active.agentId),
|
|
@@ -196,11 +244,9 @@ function createSyncTool(stores, reader, ctx) {
|
|
|
196
244
|
export function registerPeopleTools(api, stores, config, directoryReader) {
|
|
197
245
|
api.registerTool((ctx) => createInspectTool(stores, config, ctx), {
|
|
198
246
|
names: ["memory_people_inspect"],
|
|
199
|
-
optional: true,
|
|
200
247
|
});
|
|
201
248
|
api.registerTool((ctx) => createUpdateTool(stores, ctx), {
|
|
202
249
|
names: ["memory_people_update"],
|
|
203
|
-
optional: true,
|
|
204
250
|
});
|
|
205
251
|
api.registerTool((ctx) => createSyncTool(stores, directoryReader ??
|
|
206
252
|
createOpenClawSlackDirectory({
|
package/dist/src/plugin.js
CHANGED
|
@@ -2,7 +2,6 @@ import { Type } from "typebox";
|
|
|
2
2
|
import { Value } from "typebox/value";
|
|
3
3
|
import { jsonResult } from "openclaw/plugin-sdk/agent-runtime";
|
|
4
4
|
import { resolveConfig } from "./config.js";
|
|
5
|
-
import { registerPeopleCli } from "./people-cli.js";
|
|
6
5
|
import { registerPeopleHooks } from "./people-hooks.js";
|
|
7
6
|
import { PeopleStores } from "./people-store.js";
|
|
8
7
|
import { registerPeopleTools } from "./people-tools.js";
|
|
@@ -386,7 +385,6 @@ export function resolveFlushPlan(params = {}) {
|
|
|
386
385
|
}
|
|
387
386
|
export function registerUnblockMemory(api) {
|
|
388
387
|
const config = resolveConfig(api.pluginConfig);
|
|
389
|
-
registerPeopleCli(api, config.people);
|
|
390
388
|
if (api.registrationMode === "cli-metadata")
|
|
391
389
|
return;
|
|
392
390
|
const runtime = new QmdMemoryRuntime(config.corpora, {
|
package/openclaw.plugin.json
CHANGED
|
@@ -1,18 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "unblock-memory",
|
|
3
3
|
"name": "Unblock Memory",
|
|
4
|
-
"version": "0.3.
|
|
4
|
+
"version": "0.3.8",
|
|
5
5
|
"description": "Indexes, retrieves, and analyzes configured workspace memory with existing QMD vectors.",
|
|
6
6
|
"kind": "memory",
|
|
7
7
|
"activation": { "onStartup": false },
|
|
8
8
|
"skills": ["./skills"],
|
|
9
|
-
"cliCommands": [
|
|
10
|
-
{
|
|
11
|
-
"name": "unblock-memory",
|
|
12
|
-
"description": "Unblock Memory administration",
|
|
13
|
-
"hasSubcommands": true
|
|
14
|
-
}
|
|
15
|
-
],
|
|
16
9
|
"contracts": {
|
|
17
10
|
"tools": [
|
|
18
11
|
"memory_search",
|
|
@@ -37,8 +30,8 @@
|
|
|
37
30
|
"memory_fetch_cluster": { "replaySafe": true },
|
|
38
31
|
"memory_list_maintenance_tasks": { "replaySafe": true },
|
|
39
32
|
"memory_update_maintenance_task": { "sideEffecting": true },
|
|
40
|
-
"memory_people_inspect": { "replaySafe": true
|
|
41
|
-
"memory_people_update": { "sideEffecting": true
|
|
33
|
+
"memory_people_inspect": { "replaySafe": true },
|
|
34
|
+
"memory_people_update": { "sideEffecting": true },
|
|
42
35
|
"memory_people_sync": { "sideEffecting": true, "optional": true }
|
|
43
36
|
},
|
|
44
37
|
"uiHints": {
|
|
@@ -147,11 +140,11 @@
|
|
|
147
140
|
"enabled": { "type": "boolean", "default": false },
|
|
148
141
|
"refinement": {
|
|
149
142
|
"type": "object",
|
|
143
|
+
"description": "Deprecated compatibility field; accepted but ignored.",
|
|
150
144
|
"additionalProperties": false,
|
|
151
145
|
"properties": {
|
|
152
|
-
"maxPeoplePerRun": { "type": "integer", "minimum": 1, "maximum": 50
|
|
153
|
-
}
|
|
154
|
-
"default": { "maxPeoplePerRun": 10 }
|
|
146
|
+
"maxPeoplePerRun": { "type": "integer", "minimum": 1, "maximum": 50 }
|
|
147
|
+
}
|
|
155
148
|
},
|
|
156
149
|
"whisperer": {
|
|
157
150
|
"type": "object",
|
|
@@ -173,7 +166,6 @@
|
|
|
173
166
|
},
|
|
174
167
|
"default": {
|
|
175
168
|
"enabled": false,
|
|
176
|
-
"refinement": { "maxPeoplePerRun": 10 },
|
|
177
169
|
"whisperer": { "enabled": false, "maxChars": 1200 },
|
|
178
170
|
"todos": { "maxOpen": 1000 }
|
|
179
171
|
}
|
package/package.json
CHANGED
package/dist/src/people-cli.d.ts
DELETED
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/plugin-entry";
|
|
2
|
-
import type { UnblockMemoryConfig } from "./config.js";
|
|
3
|
-
import { type PeopleRefinementRunner } from "./people-refinement.js";
|
|
4
|
-
export declare function registerPeopleCli(api: OpenClawPluginApi, config: UnblockMemoryConfig["people"], runner?: PeopleRefinementRunner): void;
|
package/dist/src/people-cli.js
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { join } from "node:path";
|
|
2
|
-
import { resolveAgentDir } from "openclaw/plugin-sdk/memory-core-host-engine-foundation";
|
|
3
|
-
import { PeopleStores } from "./people-store.js";
|
|
4
|
-
import { codexPeopleRefinementRunner, refinePeople, } from "./people-refinement.js";
|
|
5
|
-
export function registerPeopleCli(api, config, runner = codexPeopleRefinementRunner) {
|
|
6
|
-
api.registerCli(({ program, config: openClawConfig }) => {
|
|
7
|
-
const root = program.command("unblock-memory").description("Unblock Memory administration");
|
|
8
|
-
const people = root.command("people").description("Maintain the agent-local people store");
|
|
9
|
-
people
|
|
10
|
-
.command("refine")
|
|
11
|
-
.description("Refine stale enabled people with Codex")
|
|
12
|
-
.requiredOption("--agent <id>", "Agent id")
|
|
13
|
-
.action(async (options) => {
|
|
14
|
-
const agentId = options.agent.trim();
|
|
15
|
-
if (!agentId)
|
|
16
|
-
throw new Error("--agent must be a non-empty string");
|
|
17
|
-
if (!config.enabled)
|
|
18
|
-
throw new Error("PeopleSQL is disabled");
|
|
19
|
-
const stores = new PeopleStores({
|
|
20
|
-
maxOpenTodos: config.todos.maxOpen,
|
|
21
|
-
maxBlurbChars: config.whisperer.maxChars,
|
|
22
|
-
});
|
|
23
|
-
try {
|
|
24
|
-
const summary = await refinePeople({
|
|
25
|
-
store: stores.get(agentId),
|
|
26
|
-
agentId,
|
|
27
|
-
agentDatabasePath: join(resolveAgentDir(openClawConfig, agentId), "openclaw-agent.sqlite"),
|
|
28
|
-
candidateLimit: config.refinement.maxPeoplePerRun,
|
|
29
|
-
maxBlurbChars: config.whisperer.maxChars,
|
|
30
|
-
runner,
|
|
31
|
-
});
|
|
32
|
-
process.stdout.write(`${JSON.stringify(summary)}\n`);
|
|
33
|
-
}
|
|
34
|
-
finally {
|
|
35
|
-
stores.closeAll();
|
|
36
|
-
}
|
|
37
|
-
});
|
|
38
|
-
}, {
|
|
39
|
-
descriptors: [
|
|
40
|
-
{
|
|
41
|
-
name: "unblock-memory",
|
|
42
|
-
description: "Unblock Memory administration",
|
|
43
|
-
hasSubcommands: true,
|
|
44
|
-
},
|
|
45
|
-
],
|
|
46
|
-
});
|
|
47
|
-
}
|