@xdarkicex/openclaw-memory-libravdb 1.4.52 → 1.4.54
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 +1 -1
- package/dist/dream-promotion.js +32 -7
- package/dist/index.js +43 -15
- package/docs/configuration.md +1 -1
- package/docs/features.md +5 -4
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -154,7 +154,7 @@ openclaw memory search "prior context"
|
|
|
154
154
|
openclaw memory export --user-id <userId>
|
|
155
155
|
openclaw memory flush --user-id <userId>
|
|
156
156
|
openclaw memory journal --limit 50
|
|
157
|
-
openclaw memory dream-promote --user-id <userId> --dream-file
|
|
157
|
+
openclaw memory dream-promote --user-id <userId> --dream-file ~/DREAMS.md
|
|
158
158
|
```
|
|
159
159
|
|
|
160
160
|
Use [Install](./docs/install.md) for service lifecycle commands and
|
package/dist/dream-promotion.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import fsp from "node:fs/promises";
|
|
3
|
+
import os from "node:os";
|
|
3
4
|
import path from "node:path";
|
|
4
5
|
import { getHashBackendName, hashBytes } from "./markdown-hash.js";
|
|
5
6
|
import { formatError } from "./format-error.js";
|
|
@@ -10,9 +11,16 @@ const DEFAULT_MIN_UNIQUE_QUERIES = 2;
|
|
|
10
11
|
const DREAM_PROMOTION_VERSION = 1;
|
|
11
12
|
const DREAM_SOURCE_KIND = "dream";
|
|
12
13
|
export function createDreamPromotionHandle(cfg, getRpc, logger = console, fsApi = createRealFsApi()) {
|
|
13
|
-
const diaryPath = normalizeDiaryPath(cfg.dreamPromotionDiaryPath);
|
|
14
14
|
const userId = cfg.dreamPromotionUserId?.trim() ?? "";
|
|
15
|
-
if (cfg.dreamPromotionEnabled !== true || !
|
|
15
|
+
if (cfg.dreamPromotionEnabled !== true || !userId) {
|
|
16
|
+
return {
|
|
17
|
+
async start() { },
|
|
18
|
+
async refresh() { },
|
|
19
|
+
async stop() { },
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
const diaryPath = normalizeDiaryPath(cfg.dreamPromotionDiaryPath);
|
|
23
|
+
if (!diaryPath) {
|
|
16
24
|
return {
|
|
17
25
|
async start() { },
|
|
18
26
|
async refresh() { },
|
|
@@ -114,10 +122,9 @@ export function createDreamPromotionHandle(cfg, getRpc, logger = console, fsApi
|
|
|
114
122
|
sourceMtimeMs: stat.mtimeMs,
|
|
115
123
|
ingestVersion: DREAM_PROMOTION_VERSION,
|
|
116
124
|
hashBackend: getHashBackendName(),
|
|
117
|
-
entries: candidates.map((candidate
|
|
125
|
+
entries: candidates.map((candidate) => ({
|
|
118
126
|
...candidate,
|
|
119
127
|
sourceLine: candidate.line,
|
|
120
|
-
line: index + 1,
|
|
121
128
|
})),
|
|
122
129
|
};
|
|
123
130
|
await rpc.call("promote_dream_entries", params);
|
|
@@ -203,10 +210,9 @@ export async function promoteDreamDiaryFile(rpc, opts) {
|
|
|
203
210
|
sourceMtimeMs: sourceMtimeMs ?? 0,
|
|
204
211
|
ingestVersion: DREAM_PROMOTION_VERSION,
|
|
205
212
|
hashBackend: getHashBackendName(),
|
|
206
|
-
entries: candidates.map((candidate
|
|
213
|
+
entries: candidates.map((candidate) => ({
|
|
207
214
|
...candidate,
|
|
208
215
|
sourceLine: candidate.line,
|
|
209
|
-
line: index + 1,
|
|
210
216
|
})),
|
|
211
217
|
});
|
|
212
218
|
}
|
|
@@ -343,7 +349,26 @@ function normalizeDiaryPath(value) {
|
|
|
343
349
|
if (!trimmed) {
|
|
344
350
|
return "";
|
|
345
351
|
}
|
|
346
|
-
|
|
352
|
+
// Reject traversal components — even though path.resolve collapses them,
|
|
353
|
+
// their presence signals an attempt to escape intended boundaries.
|
|
354
|
+
const segments = trimmed.split(/[/\\]+/);
|
|
355
|
+
if (segments.some((s) => s === "..")) {
|
|
356
|
+
throw new Error(`dream diary path must not contain ".." traversal: ${trimmed}`);
|
|
357
|
+
}
|
|
358
|
+
const resolved = path.resolve(trimmed);
|
|
359
|
+
// Restrict to known-safe locations to prevent arbitrary file reads.
|
|
360
|
+
// Allowed roots: home directory and the configured OpenClaw state dir.
|
|
361
|
+
const allowedRoots = [
|
|
362
|
+
os.homedir(),
|
|
363
|
+
process.env.OPENCLAW_STATE_DIR,
|
|
364
|
+
]
|
|
365
|
+
.filter((r) => typeof r === "string" && r.trim().length > 0)
|
|
366
|
+
.map((root) => path.resolve(root));
|
|
367
|
+
const isAllowed = allowedRoots.some((root) => resolved.startsWith(root + path.sep) || resolved === root);
|
|
368
|
+
if (!isAllowed) {
|
|
369
|
+
throw new Error(`dream diary path must be within an allowed root: ${allowedRoots.join(", ")}. Got: ${resolved}`);
|
|
370
|
+
}
|
|
371
|
+
return resolved;
|
|
347
372
|
}
|
|
348
373
|
function createRealFsApi() {
|
|
349
374
|
return {
|
package/dist/index.js
CHANGED
|
@@ -9467,7 +9467,7 @@ var require_service_config = __commonJS({
|
|
|
9467
9467
|
exports2.validateRetryThrottling = validateRetryThrottling;
|
|
9468
9468
|
exports2.validateServiceConfig = validateServiceConfig;
|
|
9469
9469
|
exports2.extractAndSelectServiceConfig = extractAndSelectServiceConfig;
|
|
9470
|
-
var
|
|
9470
|
+
var os3 = __require("os");
|
|
9471
9471
|
var constants_1 = require_constants();
|
|
9472
9472
|
var DURATION_REGEX = /^\d+(\.\d{1,9})?s$/;
|
|
9473
9473
|
var CLIENT_LANGUAGE_STRING = "node";
|
|
@@ -9766,7 +9766,7 @@ var require_service_config = __commonJS({
|
|
|
9766
9766
|
if (Array.isArray(validatedConfig.clientHostname)) {
|
|
9767
9767
|
let hostnameMatched = false;
|
|
9768
9768
|
for (const hostname2 of validatedConfig.clientHostname) {
|
|
9769
|
-
if (hostname2 ===
|
|
9769
|
+
if (hostname2 === os3.hostname()) {
|
|
9770
9770
|
hostnameMatched = true;
|
|
9771
9771
|
}
|
|
9772
9772
|
}
|
|
@@ -24066,7 +24066,7 @@ var require_subchannel_call = __commonJS({
|
|
|
24066
24066
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
24067
24067
|
exports2.Http2SubchannelCall = void 0;
|
|
24068
24068
|
var http2 = __require("http2");
|
|
24069
|
-
var
|
|
24069
|
+
var os3 = __require("os");
|
|
24070
24070
|
var constants_1 = require_constants();
|
|
24071
24071
|
var metadata_1 = require_metadata();
|
|
24072
24072
|
var stream_decoder_1 = require_stream_decoder();
|
|
@@ -24074,7 +24074,7 @@ var require_subchannel_call = __commonJS({
|
|
|
24074
24074
|
var constants_2 = require_constants();
|
|
24075
24075
|
var TRACER_NAME = "subchannel_call";
|
|
24076
24076
|
function getSystemErrorName(errno) {
|
|
24077
|
-
for (const [name, num] of Object.entries(
|
|
24077
|
+
for (const [name, num] of Object.entries(os3.constants.errno)) {
|
|
24078
24078
|
if (num === errno) {
|
|
24079
24079
|
return name;
|
|
24080
24080
|
}
|
|
@@ -32292,6 +32292,7 @@ function formatError(error) {
|
|
|
32292
32292
|
// src/dream-promotion.ts
|
|
32293
32293
|
import fs from "node:fs";
|
|
32294
32294
|
import fsp from "node:fs/promises";
|
|
32295
|
+
import os from "node:os";
|
|
32295
32296
|
import path from "node:path";
|
|
32296
32297
|
|
|
32297
32298
|
// src/markdown-hash.ts
|
|
@@ -32505,9 +32506,19 @@ var DEFAULT_DEBOUNCE_MS = 150;
|
|
|
32505
32506
|
var DREAM_PROMOTION_VERSION = 1;
|
|
32506
32507
|
var DREAM_SOURCE_KIND = "dream";
|
|
32507
32508
|
function createDreamPromotionHandle(cfg, getRpc, logger = console, fsApi = createRealFsApi()) {
|
|
32508
|
-
const diaryPath = normalizeDiaryPath(cfg.dreamPromotionDiaryPath);
|
|
32509
32509
|
const userId = cfg.dreamPromotionUserId?.trim() ?? "";
|
|
32510
|
-
if (cfg.dreamPromotionEnabled !== true || !
|
|
32510
|
+
if (cfg.dreamPromotionEnabled !== true || !userId) {
|
|
32511
|
+
return {
|
|
32512
|
+
async start() {
|
|
32513
|
+
},
|
|
32514
|
+
async refresh() {
|
|
32515
|
+
},
|
|
32516
|
+
async stop() {
|
|
32517
|
+
}
|
|
32518
|
+
};
|
|
32519
|
+
}
|
|
32520
|
+
const diaryPath = normalizeDiaryPath(cfg.dreamPromotionDiaryPath);
|
|
32521
|
+
if (!diaryPath) {
|
|
32511
32522
|
return {
|
|
32512
32523
|
async start() {
|
|
32513
32524
|
},
|
|
@@ -32612,10 +32623,9 @@ function createDreamPromotionHandle(cfg, getRpc, logger = console, fsApi = creat
|
|
|
32612
32623
|
sourceMtimeMs: stat.mtimeMs,
|
|
32613
32624
|
ingestVersion: DREAM_PROMOTION_VERSION,
|
|
32614
32625
|
hashBackend: getHashBackendName(),
|
|
32615
|
-
entries: candidates.map((candidate
|
|
32626
|
+
entries: candidates.map((candidate) => ({
|
|
32616
32627
|
...candidate,
|
|
32617
|
-
sourceLine: candidate.line
|
|
32618
|
-
line: index + 1
|
|
32628
|
+
sourceLine: candidate.line
|
|
32619
32629
|
}))
|
|
32620
32630
|
};
|
|
32621
32631
|
await rpc.call("promote_dream_entries", params);
|
|
@@ -32698,10 +32708,9 @@ async function promoteDreamDiaryFile(rpc, opts) {
|
|
|
32698
32708
|
sourceMtimeMs: sourceMtimeMs ?? 0,
|
|
32699
32709
|
ingestVersion: DREAM_PROMOTION_VERSION,
|
|
32700
32710
|
hashBackend: getHashBackendName(),
|
|
32701
|
-
entries: candidates.map((candidate
|
|
32711
|
+
entries: candidates.map((candidate) => ({
|
|
32702
32712
|
...candidate,
|
|
32703
|
-
sourceLine: candidate.line
|
|
32704
|
-
line: index + 1
|
|
32713
|
+
sourceLine: candidate.line
|
|
32705
32714
|
}))
|
|
32706
32715
|
});
|
|
32707
32716
|
}
|
|
@@ -32838,7 +32847,26 @@ function normalizeDiaryPath(value) {
|
|
|
32838
32847
|
if (!trimmed) {
|
|
32839
32848
|
return "";
|
|
32840
32849
|
}
|
|
32841
|
-
|
|
32850
|
+
const segments = trimmed.split(/[/\\]+/);
|
|
32851
|
+
if (segments.some((s) => s === "..")) {
|
|
32852
|
+
throw new Error(
|
|
32853
|
+
`dream diary path must not contain ".." traversal: ${trimmed}`
|
|
32854
|
+
);
|
|
32855
|
+
}
|
|
32856
|
+
const resolved = path.resolve(trimmed);
|
|
32857
|
+
const allowedRoots = [
|
|
32858
|
+
os.homedir(),
|
|
32859
|
+
process.env.OPENCLAW_STATE_DIR
|
|
32860
|
+
].filter((r) => typeof r === "string" && r.trim().length > 0).map((root) => path.resolve(root));
|
|
32861
|
+
const isAllowed = allowedRoots.some(
|
|
32862
|
+
(root) => resolved.startsWith(root + path.sep) || resolved === root
|
|
32863
|
+
);
|
|
32864
|
+
if (!isAllowed) {
|
|
32865
|
+
throw new Error(
|
|
32866
|
+
`dream diary path must be within an allowed root: ${allowedRoots.join(", ")}. Got: ${resolved}`
|
|
32867
|
+
);
|
|
32868
|
+
}
|
|
32869
|
+
return resolved;
|
|
32842
32870
|
}
|
|
32843
32871
|
function createRealFsApi() {
|
|
32844
32872
|
return {
|
|
@@ -39326,7 +39354,7 @@ var GrpcKernelClient = class {
|
|
|
39326
39354
|
// src/sidecar.ts
|
|
39327
39355
|
import fs3 from "node:fs";
|
|
39328
39356
|
import net from "node:net";
|
|
39329
|
-
import
|
|
39357
|
+
import os2 from "node:os";
|
|
39330
39358
|
import path4 from "node:path";
|
|
39331
39359
|
var STARTUP_CONNECT_MAX_RETRIES = 5;
|
|
39332
39360
|
var STARTUP_CONNECT_BASE_DELAY_MS = 100;
|
|
@@ -39568,7 +39596,7 @@ function resolveConfiguredEndpoint(cfg) {
|
|
|
39568
39596
|
function daemonProvisioningHint() {
|
|
39569
39597
|
return "If you installed the npm package, install and start libravdbd separately; the package does not provision the daemon binary, ONNX Runtime, or model assets.";
|
|
39570
39598
|
}
|
|
39571
|
-
function defaultEndpoint(platform = process.platform, homeDir =
|
|
39599
|
+
function defaultEndpoint(platform = process.platform, homeDir = os2.homedir(), pathExists = fs3.existsSync) {
|
|
39572
39600
|
const envEndpoint = process.env.LIBRAVDB_RPC_ENDPOINT?.trim();
|
|
39573
39601
|
if (envEndpoint && isConfiguredEndpoint(envEndpoint)) {
|
|
39574
39602
|
return envEndpoint;
|
package/docs/configuration.md
CHANGED
|
@@ -103,7 +103,7 @@ The plugin exposes `ingestionGateThreshold` for host-side gating decisions:
|
|
|
103
103
|
| Key | Type | Default | Notes |
|
|
104
104
|
|---|---|---|---|
|
|
105
105
|
| `dreamPromotionEnabled` | boolean | `false` | Enable dream diary promotion |
|
|
106
|
-
| `dreamPromotionDiaryPath` | string | — | Path to dream diary markdown file |
|
|
106
|
+
| `dreamPromotionDiaryPath` | string | — | Path to dream diary markdown file under the operator home directory or `OPENCLAW_STATE_DIR` |
|
|
107
107
|
| `dreamPromotionUserId` | string | — | User ID for dream collection scoping |
|
|
108
108
|
| `dreamPromotionDebounceMs` | number | `150` | Debounce window for dream diary changes |
|
|
109
109
|
|
package/docs/features.md
CHANGED
|
@@ -105,11 +105,12 @@ Automatic diary watching:
|
|
|
105
105
|
Manual run:
|
|
106
106
|
|
|
107
107
|
```bash
|
|
108
|
-
openclaw memory dream-promote --user-id <userId> --dream-file
|
|
108
|
+
openclaw memory dream-promote --user-id <userId> --dream-file ~/DREAMS.md
|
|
109
109
|
```
|
|
110
110
|
|
|
111
|
-
|
|
112
|
-
|
|
111
|
+
Dream diary files must live under the operator's home directory or the configured
|
|
112
|
+
`OPENCLAW_STATE_DIR`. The manual command and watcher both use the same sidecar
|
|
113
|
+
promotion RPC, so admission gates and provenance metadata are identical.
|
|
113
114
|
|
|
114
115
|
## Memory CLI
|
|
115
116
|
|
|
@@ -126,7 +127,7 @@ CLI API.
|
|
|
126
127
|
| `openclaw memory flush --user-id <userId>` | Delete one durable user namespace after confirmation. |
|
|
127
128
|
| `openclaw memory flush --session-key <sessionKey>` | Delete a namespace derived from a session key after confirmation. |
|
|
128
129
|
| `openclaw memory journal --limit 50` | Inspect bounded lifecycle hints recorded by the sidecar. |
|
|
129
|
-
| `openclaw memory dream-promote --user-id <userId> --dream-file <path>` | Promote vetted dream diary bullets
|
|
130
|
+
| `openclaw memory dream-promote --user-id <userId> --dream-file <path>` | Promote vetted dream diary bullets from a file under the operator home directory or `OPENCLAW_STATE_DIR`. |
|
|
130
131
|
|
|
131
132
|
Use `--yes` with `flush` only when you intentionally want to skip the
|
|
132
133
|
confirmation prompt.
|
package/openclaw.plugin.json
CHANGED