@unblocklabs/unblock-memory 0.7.3 → 0.8.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 +10 -10
- package/dist/src/agent-transcript.d.ts +36 -5
- package/dist/src/agent-transcript.js +101 -11
- package/dist/src/contracts.d.ts +1 -1
- package/dist/src/diagnostics.d.ts +5 -1
- package/dist/src/diagnostics.js +3 -0
- package/dist/src/inside-out-sources.js +21 -12
- package/dist/src/manager.d.ts +3 -2
- package/dist/src/manager.js +9 -3
- package/dist/src/memory-search.d.ts +31 -0
- package/dist/src/memory-search.js +61 -0
- package/dist/src/memory-whisperer.d.ts +2 -6
- package/dist/src/memory-whisperer.js +39 -73
- package/dist/src/plugin.js +72 -34
- package/dist/src/response-episodes.d.ts +3 -3
- package/dist/src/response-episodes.js +52 -13
- package/dist/src/response-text.js +13 -0
- package/dist/src/retrieval-telemetry.d.ts +3 -2
- package/dist/src/review-tools.js +1 -1
- package/dist/src/session-sync.d.ts +1 -1
- package/dist/src/session-sync.js +26 -14
- package/dist/src/training-candidates.d.ts +2 -2
- package/dist/src/training-candidates.js +2 -2
- package/dist/src/training-input.d.ts +4 -0
- package/dist/src/training-input.js +8 -6
- package/dist/src/training-queries.d.ts +2 -0
- package/dist/src/training.d.ts +2 -0
- package/dist/src/training.js +6 -1
- package/docs/configuration.md +3 -2
- package/docs/memory-training.md +3 -1
- package/docs/response-audit.md +2 -2
- package/docs/retrieval.md +59 -59
- package/openclaw.plugin.json +2 -2
- package/package.json +2 -2
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import { DatabaseSync } from "node:sqlite";
|
|
3
|
-
import {
|
|
3
|
+
import { AgentTranscriptReader } from "./agent-transcript.js";
|
|
4
4
|
import { messageText } from "./whisperer-context.js";
|
|
5
5
|
import { conversationUserText } from "./response-text.js";
|
|
6
6
|
import { prepareQueryConversation, QUERY_CONTRACT, QueryInputBudgetError } from "./query-contract.js";
|
|
@@ -133,12 +133,13 @@ export function trainingExamples(rows, renew) {
|
|
|
133
133
|
/** Only active events; no Markdown projections, archived branches, or tool bodies. */
|
|
134
134
|
export class TrainingTranscriptReader {
|
|
135
135
|
#db;
|
|
136
|
+
#transcripts;
|
|
136
137
|
#lineage;
|
|
137
138
|
constructor(path, agentId) {
|
|
138
139
|
this.#db = new DatabaseSync(path, { readOnly: true });
|
|
139
140
|
try {
|
|
140
141
|
this.#db.exec("PRAGMA query_only=ON; PRAGMA busy_timeout=1000");
|
|
141
|
-
|
|
142
|
+
this.#transcripts = new AgentTranscriptReader(this.#db, agentId, "Unsupported training transcript schema or agent");
|
|
142
143
|
const columns = this.#db.prepare("PRAGMA table_info(session_windows)").all().map(c => c.name);
|
|
143
144
|
this.#lineage = ["parent_session_key", "spawned_by", "plugin_owner_id", "hook_external_content_source"].every(c => columns.includes(c));
|
|
144
145
|
}
|
|
@@ -161,11 +162,12 @@ export class TrainingTranscriptReader {
|
|
|
161
162
|
/:(?:cron|subagent|heartbeat|hook)(?::|$)/i.test(String(session.session_key)) ||
|
|
162
163
|
session.parent_session_key || session.spawned_by || session.plugin_owner_id || session.hook_external_content_source)
|
|
163
164
|
return null;
|
|
164
|
-
const
|
|
165
|
-
if (
|
|
165
|
+
const snapshot = this.#transcripts.read(sessionId, { maxEvents: 50_000, maxBytes: 32_000_000 });
|
|
166
|
+
if (snapshot.kind === "oversized")
|
|
166
167
|
return { oversized: true };
|
|
167
|
-
|
|
168
|
-
|
|
168
|
+
if (snapshot.kind !== "ready")
|
|
169
|
+
return { unavailable: true };
|
|
170
|
+
return trainingExamples(snapshot.rows, renew);
|
|
169
171
|
}
|
|
170
172
|
finally {
|
|
171
173
|
this.#db.exec("COMMIT");
|
|
@@ -34,6 +34,7 @@ export declare function generateTrainingQueries(source: Source, store: TrainingS
|
|
|
34
34
|
sessions: number;
|
|
35
35
|
excludedSessions: number;
|
|
36
36
|
oversizedSessions: number;
|
|
37
|
+
unavailableSessions: number;
|
|
37
38
|
eligible: number;
|
|
38
39
|
users: number;
|
|
39
40
|
filtered: number;
|
|
@@ -79,6 +80,7 @@ export declare function evaluateTrainingQueries(source: Source, store: TrainingS
|
|
|
79
80
|
sessions: number;
|
|
80
81
|
excludedSessions: number;
|
|
81
82
|
oversizedSessions: number;
|
|
83
|
+
unavailableSessions: number;
|
|
82
84
|
eligible: number;
|
|
83
85
|
users: number;
|
|
84
86
|
filtered: number;
|
package/dist/src/training.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ export declare function collectTraining(source: Source, store?: TrainingStore, o
|
|
|
13
13
|
sessions: number;
|
|
14
14
|
excludedSessions: number;
|
|
15
15
|
oversizedSessions: number;
|
|
16
|
+
unavailableSessions: number;
|
|
16
17
|
eligible: number;
|
|
17
18
|
users: number;
|
|
18
19
|
filtered: number;
|
|
@@ -39,6 +40,7 @@ export declare function runTraining(source: Source, store: TrainingStore, config
|
|
|
39
40
|
sessions: number;
|
|
40
41
|
excludedSessions: number;
|
|
41
42
|
oversizedSessions: number;
|
|
43
|
+
unavailableSessions: number;
|
|
42
44
|
eligible: number;
|
|
43
45
|
users: number;
|
|
44
46
|
filtered: number;
|
package/dist/src/training.js
CHANGED
|
@@ -5,7 +5,7 @@ import { judgeTrainingInput, TRAINING_GATE_QUESTIONS } from "./training-gate.js"
|
|
|
5
5
|
export function collectTraining(source, store, options = {}) {
|
|
6
6
|
const since = options.since ?? 0, until = options.until ?? Number.MAX_SAFE_INTEGER;
|
|
7
7
|
const reader = new TrainingTranscriptReader(source.databasePath, source.agentId);
|
|
8
|
-
const result = { sessions: 0, excludedSessions: 0, oversizedSessions: 0, eligible: 0,
|
|
8
|
+
const result = { sessions: 0, excludedSessions: 0, oversizedSessions: 0, unavailableSessions: 0, eligible: 0,
|
|
9
9
|
users: 0, filtered: 0, oversized: 0, unanswered: 0, added: 0, changed: 0, unchanged: 0, retired: 0,
|
|
10
10
|
review: [] };
|
|
11
11
|
try {
|
|
@@ -14,6 +14,11 @@ export function collectTraining(source, store, options = {}) {
|
|
|
14
14
|
store?.renew();
|
|
15
15
|
const extracted = reader.read(id, () => store?.renew());
|
|
16
16
|
result.sessions++;
|
|
17
|
+
if (extracted && "unavailable" in extracted) {
|
|
18
|
+
result.unavailableSessions++;
|
|
19
|
+
store?.unavailable(id);
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
17
22
|
if (extracted && "oversized" in extracted) {
|
|
18
23
|
result.oversizedSessions++;
|
|
19
24
|
store?.unavailable(id);
|
package/docs/configuration.md
CHANGED
|
@@ -11,7 +11,8 @@ settings; a rotated credential file is reread without a restart.
|
|
|
11
11
|
|
|
12
12
|
| Feature | Required settings/dependencies | TypeSafe disabled / no key | Provider or unreadable-key failure |
|
|
13
13
|
| --- | --- | --- | --- |
|
|
14
|
-
|
|
|
14
|
+
| `memory_search` | Installed/enabled memory slot; configured corpora; TypeSafe key | Explicit unavailable error | Successful judged siblings returned with a partial warning; total failure is an error; no vector fallback |
|
|
15
|
+
| `memory_get` | Installed/enabled memory slot; configured corpora | Unchanged local indexed reads | Unchanged; its own indexing errors still matter |
|
|
15
16
|
| Skill Whisperer | `skillWhisperer.enabled`, skills corpus, host hooks | Best local vector candidate meeting `minScore` | Exclude failed candidates; successful siblings may qualify; no vector fallback |
|
|
16
17
|
| Memory Whisperer | `memoryWhisperer.enabled`, explicit approved corpora, host hooks | No hints | Exclude failed candidates; recall/deadline failures still suppress the turn |
|
|
17
18
|
| Complementary hints | Enabled Memory Whisperer + `complementaryHints` | No additional judgment; base hints also require a key | Keep baseline hints unless the total deadline expires |
|
|
@@ -202,7 +203,7 @@ contract; these tables explain their effects.
|
|
|
202
203
|
| `corpora[].kind` | Required for explicit entries | `files`, `sessions`, or `skills` |
|
|
203
204
|
| `corpora[].paths` | Required for files/skills | Nonempty exact-file/directory/glob list; workspace-relative, absolute or `~/`; directory means recursive Markdown; does not grant host write trust |
|
|
204
205
|
| `corpora[sessions].chatTypes` | `['channel','group']` | Nonempty subset of channel/group/direct; DMs require `direct` |
|
|
205
|
-
| `corpora[sessions].maxExpandedTokens` | `500` | 1–10,000;
|
|
206
|
+
| `corpora[sessions].maxExpandedTokens` | `500` | 1–10,000; internal host vector retrieval expands a full turn/message when it fits. Public search and Whisperer share the fixed 1,200-character complete-passage renderer with training. |
|
|
206
207
|
| `corpora[sessions].syncIntervalMinutes` | `60` | 0–1,440; zero manual-only; first scheduled sync after one interval; requires running Gateway |
|
|
207
208
|
| `keepEmbeddingModelWarm` | `true` | Retain embedding model/context after first use; false allows five-minute idle disposal |
|
|
208
209
|
| `analysis.executable` | Unset | Optional absolute local worker path; enables ability to recluster, not automatic scheduling |
|
package/docs/memory-training.md
CHANGED
|
@@ -78,7 +78,9 @@ bytes, so changed corpus content still invalidates caches.
|
|
|
78
78
|
|
|
79
79
|
## Input and historical boundaries
|
|
80
80
|
|
|
81
|
-
Read original agent SQLite active-branch conversations
|
|
81
|
+
Read original agent SQLite active-branch conversations through the shared read-only
|
|
82
|
+
adapter, including compressed payloads, while deferring cold or oversized sessions
|
|
83
|
+
without retiring their previously collected examples. This includes
|
|
82
84
|
direct/group/channel chats, excluding cron, heartbeat, spawned/subagent, hook/plugin
|
|
83
85
|
and untyped diagnostic sessions. Exclude explicit bots, synthetic messages,
|
|
84
86
|
analysis/thinking, errors and tool payloads. Ordinary older users need not have
|
package/docs/response-audit.md
CHANGED
|
@@ -202,8 +202,8 @@ factual verification. Week buckets
|
|
|
202
202
|
may be partial, and several exchanges in one session are not independent. Wilson
|
|
203
203
|
intervals are descriptive, not calibrated confidence about overall agent ability.
|
|
204
204
|
|
|
205
|
-
Each run selects at most 100 recent sessions
|
|
206
|
-
|
|
205
|
+
Each run selects at most 100 recent sessions containing approved-sender messages for inference,
|
|
206
|
+
each at most 2,000 active events/2M decoded UTF-8 bytes; episodes must fit 24K characters and six feedback messages without
|
|
207
207
|
truncating the answer. Coverage counts describe the scanned sessions; only episodes
|
|
208
208
|
within `lookbackDays` are judged. Caps, failures and no-feedback cases remain visible.
|
|
209
209
|
Saved sessions in the report window are also reconciled independently of that
|
package/docs/retrieval.md
CHANGED
|
@@ -6,26 +6,31 @@
|
|
|
6
6
|
|
|
7
7
|
`memory_search` searches every configured **non-skill** corpus for this agent by
|
|
8
8
|
default. Select named corpora, or use `["all"]` alone. An empty list or unknown
|
|
9
|
-
name is an error.
|
|
10
|
-
`
|
|
11
|
-
|
|
9
|
+
name is an error. Supply `bm25Query` (distinctive keywords/names) and
|
|
10
|
+
`vectorQuery` (a natural-language question describing the information needed).
|
|
11
|
+
Each lane retrieves ten candidates; complete passages are deduplicated and
|
|
12
|
+
independently judged by TypeSafe against `vectorQuery`. No query generation or
|
|
13
|
+
recall gate runs. Default: **5 results**, `minUsefulness: 0.7`;
|
|
14
|
+
`maxResults` is 1–20 and `minUsefulness` is 0–1. The old `query` and vector
|
|
15
|
+
`minScore` parameters are removed, not silently reinterpreted.
|
|
12
16
|
|
|
13
17
|
Example tool input (the `memory` corpus exists by default):
|
|
14
18
|
|
|
15
19
|
```json
|
|
16
|
-
{ "
|
|
20
|
+
{ "bm25Query": "staging rollout approval", "vectorQuery": "Who approved the staging rollout?", "corpora": ["memory"], "maxResults": 5 }
|
|
17
21
|
```
|
|
18
22
|
|
|
19
23
|
Results use compact JSON and carry `path`, `startLine`, `endLine`, `snippet`,
|
|
20
|
-
`corpus`, and `score
|
|
24
|
+
`corpus`, and a usefulness `score` rounded to hundredths. Ranking and threshold
|
|
21
25
|
filtering still use full precision. The constant `source` and top-level `provider`
|
|
22
26
|
fields are omitted; `path` plus line numbers replace the redundant `citation`.
|
|
23
27
|
Session hits also carry session metadata and, when available,
|
|
24
28
|
`messageTimestamp`: the original timestamp text (including timezone) of the message
|
|
25
29
|
containing the matched chunk. It stays tied to that message even when the excerpt
|
|
26
30
|
expands to the surrounding turn. Missing timestamps are omitted, not replaced by
|
|
27
|
-
session start time.
|
|
28
|
-
|
|
31
|
+
session start time. Usefulness is not confidence in the truth of a claim.
|
|
32
|
+
Passages retain complete evidence within 1,200 characters; oversized matches
|
|
33
|
+
are omitted, never trimmed into a misleading prefix.
|
|
29
34
|
|
|
30
35
|
Session `snippet` values are arrays of messages, in source order:
|
|
31
36
|
|
|
@@ -61,56 +66,40 @@ Search snippets are leads. Inspect attribution, qualifications, dates and adjace
|
|
|
61
66
|
context before relying on a factual claim. An old plan is not proof it happened,
|
|
62
67
|
and memory does not grant permission to act. No results may mean the wrong corpus,
|
|
63
68
|
a high threshold, an unsynced session or an unavailable index—not absence of the fact.
|
|
69
|
+
Search requires enabled TypeSafe and a configured key. It sends the semantic
|
|
70
|
+
query, candidate excerpts, dates, corpus and source paths to TypeSafe. Missing
|
|
71
|
+
credentials and total judging failure include an `error` alongside empty `results`;
|
|
72
|
+
partial judging failure includes a `warning` and only successfully judged results.
|
|
73
|
+
Oversized queries are rejected before credentials, retrieval or provider calls.
|
|
64
74
|
Search initialization errors include an `error` alongside empty `results`;
|
|
65
75
|
other failures may surface as tool errors. Investigate them instead of reporting
|
|
66
76
|
“nothing is remembered.”
|
|
77
|
+
`memory_diagnostics` exposes content-free manual-search measurements under
|
|
78
|
+
`whisperers.telemetry.operations.memorySearch`: end-to-end latency, retrieval and
|
|
79
|
+
judging time, candidate/result counts and outcomes (including partial failures).
|
|
80
|
+
These counters are separate from automatic `memoryWhisperer` and internal `vector`
|
|
81
|
+
retrieval; no query or evidence text is recorded.
|
|
67
82
|
|
|
68
83
|
Corpora and session filters select evidence; they are not audience ACLs. Normal
|
|
69
84
|
tools can access this agent's configured non-skill corpora, not just its current
|
|
70
85
|
chat. Only index material suitable for the agent's tool callers. Per-feature
|
|
71
86
|
TypeSafe allowlists do not restrict ordinary retrieval.
|
|
72
87
|
|
|
73
|
-
## QMD
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
expansion or local reranking. Explicit `lex`/`vec`/`hyde` variants share the
|
|
89
|
-
TypeSafe ranking policy by default. A supplied hypothetical `hyde` passage is
|
|
90
|
-
a retrieval input, not evidence. Scores across modes are not interchangeable.
|
|
91
|
-
|
|
92
|
-
**Migration:** Memory 0.3.22 removed the temporary `memory_xsearch` tool. QMD's
|
|
93
|
-
`query` provides that hybrid retrieval/ranking functionality; there is no plugin
|
|
94
|
-
`memory_query`, and `memory_search` did not become hybrid.
|
|
95
|
-
|
|
96
|
-
Standalone QMD is a separate entry point. Its project/named/global index is not
|
|
97
|
-
automatically this agent's `unblock-memory/index.sqlite`. Plugin corpus names
|
|
98
|
-
also are not QMD collection IDs: each configured path maps to a `source-<hash>`
|
|
99
|
-
collection, and a corpus can contain several. Establish the intended index,
|
|
100
|
-
collection scope and installed QMD version before using CLI/MCP as an alternative.
|
|
101
|
-
Do not run standalone collection/update/embed maintenance against a live
|
|
102
|
-
plugin-managed index as a casual search fallback.
|
|
103
|
-
|
|
104
|
-
QMD CLI/MCP read `TYPESAFE_API_KEY` or `TYPESAFE_API_KEY_FILE` from their own
|
|
105
|
-
process; SDK callers can supply credentials. Plugin `typesafe.apiKeyFile` does
|
|
106
|
-
not export a key to those processes. Ranked query sends the query, intent,
|
|
107
|
-
selected excerpts, source paths and evaluation time to TypeSafe. Missing keys or
|
|
108
|
-
scoring failures return errors, not vector fallback or a successful empty answer.
|
|
109
|
-
Use an explicitly local mode when appropriate.
|
|
110
|
-
|
|
111
|
-
See the [QMD guide](https://github.com/unblocklabs-ai/qmd#readme) for CLI/MCP syntax.
|
|
112
|
-
Private skill frontmatter retrieval and response-audit lexical investigations are
|
|
113
|
-
internal workflows, not extra public plugin search modes.
|
|
88
|
+
## QMD entry points
|
|
89
|
+
|
|
90
|
+
`memory_search` is the agent-facing ranked search. The QMD CLI `query`,
|
|
91
|
+
`search` and `deep-search` alias, MCP `query` tool, and HTTP `/query` and
|
|
92
|
+
`/search` routes are removed in the companion QMD change. Existing installations
|
|
93
|
+
retain those commands until that QMD change is released and installed.
|
|
94
|
+
|
|
95
|
+
QMD remains the local indexing/retrieval backend. Its BM25/vector SDK primitives,
|
|
96
|
+
vector-only `vsearch`, indexed reads, collection maintenance and benchmark APIs
|
|
97
|
+
remain available. Private skill retrieval and response-audit lexical investigations
|
|
98
|
+
are internal workflows, not extra public plugin search tools.
|
|
99
|
+
|
|
100
|
+
Standalone QMD and the plugin need not use the same index. Do not run standalone
|
|
101
|
+
collection/update/embed maintenance against a live plugin-managed index as a
|
|
102
|
+
casual search fallback.
|
|
114
103
|
|
|
115
104
|
## Sessions
|
|
116
105
|
|
|
@@ -127,7 +116,8 @@ corpora searchable. Supported fields are `startedFrom` and `startedTo`
|
|
|
127
116
|
|
|
128
117
|
```json
|
|
129
118
|
{
|
|
130
|
-
"
|
|
119
|
+
"bm25Query": "deployment decision",
|
|
120
|
+
"vectorQuery": "What deployment decision was made?",
|
|
131
121
|
"sessionFilter": {
|
|
132
122
|
"startedFrom": "2026-08-01T00:00:00Z",
|
|
133
123
|
"provider": "slack",
|
|
@@ -155,13 +145,19 @@ fits. The default is `500`; the original semantic chunk is preserved when
|
|
|
155
145
|
neither complete context fits, so expansion never clips the matched evidence.
|
|
156
146
|
Run
|
|
157
147
|
`memory_sync_sessions` to start a refresh, then use `memory_sync_status` to
|
|
158
|
-
check its progress or result. The read-only adapter
|
|
159
|
-
agent
|
|
160
|
-
|
|
148
|
+
check its progress or result. The shared read-only transcript adapter validates
|
|
149
|
+
agent identity and the storage capabilities it needs, rather than rejecting every
|
|
150
|
+
new schema number. It reads both text and bounded Zstd payloads (schema 23+),
|
|
151
|
+
counts decoded UTF-8 bytes for budgets, and preserves previous projections when
|
|
152
|
+
history is cold, oversized, or unreadable. Cold history is deferred until restored
|
|
153
|
+
by OpenClaw; the plugin never restores or migrates the source database. The public
|
|
154
|
+
full-transcript SDK reader currently permits restoration, while its read-only
|
|
155
|
+
catalog redacts and truncates text, so neither supplies this full-fidelity read-only
|
|
156
|
+
contract. Extraction retains its supported host cursor API. Projections are private derived Markdown under the
|
|
161
157
|
agent's `unblock-memory/sessions` state directory and can be rebuilt from
|
|
162
158
|
OpenClaw at any time. Their embedded text contains only `# Transcript` and
|
|
163
159
|
role-labeled, timestamped speaker messages; filtering metadata remains in the
|
|
164
|
-
session manifest. Projection
|
|
160
|
+
session manifest. Projection v8 retains message metadata and exact character
|
|
165
161
|
boundaries there, without duplicating message bodies. Readers use those boundaries
|
|
166
162
|
only when the projection hash matches the indexed document. Older/mismatched snapshots
|
|
167
163
|
use a conservative heading parser that skips code fences and blockquotes; an unfenced
|
|
@@ -294,7 +290,9 @@ through BM25 and vectors respectively, retrieving ten candidates per backend acr
|
|
|
294
290
|
the complete approved collection scope (not ten per collection). The lexical adapter
|
|
295
291
|
uses literal OR keywords; quotation marks do not enable exact-phrase matching.
|
|
296
292
|
API or generated-output failures skip the hint; there is no direct-vector fallback.
|
|
297
|
-
|
|
293
|
+
After query generation Whisperer uses the same discovery, deduplication and
|
|
294
|
+
ranking core as `memory_search`, but judges against the bounded conversation
|
|
295
|
+
rather than the explicit tool's semantic query alone. TypeSafe evaluates one independent
|
|
298
296
|
Noul question per candidate in its own concurrent HTTP request: would a careful
|
|
299
297
|
assistant use a specific factual detail from the excerpt when answering the current
|
|
300
298
|
request? Partial answers and concrete leads count; repeated facts, topic/name matches
|
|
@@ -309,16 +307,18 @@ Explicit configured thresholds are preserved. Evaluate it on your own conversati
|
|
|
309
307
|
**Privacy and budgets:** training and runtime prepare the same visible conversation:
|
|
310
308
|
at most 8,192 pinned-LFM tokens and 24,000 UTF-8 bytes after serialization. The whole
|
|
311
309
|
current request and most recent whole messages are retained; an oversized current
|
|
312
|
-
request skips automatic memory
|
|
313
|
-
|
|
310
|
+
request skips automatic memory before query generation or the TypeSafe recall gate.
|
|
311
|
+
Diagnostics count `input_too_large`; completed logs report `outcome: "skipped"` and
|
|
312
|
+
`reason: "input_too_large"`, without recording the input. The judge receives that
|
|
313
|
+
conversation plus one complete 1,200-character excerpt, its corpus/source path, all represented message timestamps,
|
|
314
314
|
and the request's evaluation time per HTTP request. A v2 query pair can therefore
|
|
315
315
|
produce up to twenty passage requests before deduplication and eligibility filtering.
|
|
316
316
|
Dates record when source messages were said, without inferring event dates.
|
|
317
317
|
Session excerpts retain a complete turn or message when it fits,
|
|
318
318
|
otherwise the complete matched chunk. Chunks exceeding the excerpt budget are
|
|
319
|
-
skipped, never sliced.
|
|
320
|
-
|
|
321
|
-
|
|
319
|
+
skipped, never sliced. Public `memory_search` and Whisperer use the same fixed
|
|
320
|
+
1,200-character renderer, independently of `sessions.maxExpandedTokens`.
|
|
321
|
+
That setting controls only internal host-vector retrieval expansion.
|
|
322
322
|
It does not fetch a complete historical transcript; the host may
|
|
323
323
|
already have compacted the available context. System messages, thinking blocks,
|
|
324
324
|
images, and tool-result messages are omitted;
|
package/openclaw.plugin.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "unblock-memory",
|
|
3
3
|
"name": "Unblock Memory",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.8.0",
|
|
5
5
|
"description": "Indexes, retrieves, and analyzes configured workspace memory with existing QMD vectors.",
|
|
6
6
|
"kind": "memory",
|
|
7
7
|
"activation": { "onStartup": true },
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
},
|
|
65
65
|
"typesafe.enabled": {
|
|
66
66
|
"label": "TypeSafe Judgments",
|
|
67
|
-
"help": "Shared provider gate for opted-in whisperers, people primer/save review, evidence/quality reviews and response audits. Does not enable features or approve corpora by itself.
|
|
67
|
+
"help": "Shared provider gate for opted-in whisperers, people primer/save review, evidence/quality reviews and response audits. Does not enable features or approve corpora by itself. Memory search discovers locally and uses TypeSafe to rank usefulness; People Whisperer injection stays local."
|
|
68
68
|
},
|
|
69
69
|
"typesafe.apiKey": { "label": "TypeSafe API Key", "sensitive": true },
|
|
70
70
|
"typesafe.timeoutMs": { "label": "TypeSafe Request Timeout", "help": "Per-request timeout, not the whole operation. People primer/dossier review use peoplePrimer.timeoutMs instead; Memory Whisperer has its own total deadline, and Skill Whisperer has a fixed 3-second total budget." },
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unblocklabs/unblock-memory",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "Workspace-native memory for OpenClaw, powered by QMD",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
50
|
"@huggingface/tokenizers": "0.2.0",
|
|
51
|
-
"@unblocklabs/qmd": "https://github.com/unblocklabs-ai/qmd/releases/download/
|
|
51
|
+
"@unblocklabs/qmd": "https://github.com/unblocklabs-ai/qmd/releases/download/v3.0.0/unblocklabs-qmd-3.0.0.tgz",
|
|
52
52
|
"chokidar": "5.0.0",
|
|
53
53
|
"js-tiktoken": "1.0.21",
|
|
54
54
|
"picomatch": "^4.0.5",
|