@xdarkicex/openclaw-memory-libravdb 1.5.5 → 1.6.1
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/dist/cli.js +19 -21
- package/dist/context-engine.d.ts +3 -3
- package/dist/context-engine.js +19 -123
- package/dist/dream-promotion.d.ts +4 -6
- package/dist/dream-promotion.js +22 -13
- package/dist/index.js +25240 -29191
- package/dist/ingest-queue.d.ts +9 -2
- package/dist/ingest-queue.js +13 -5
- package/dist/libravdb-client.d.ts +59 -0
- package/dist/libravdb-client.js +296 -0
- package/dist/markdown-ingest.d.ts +2 -5
- package/dist/markdown-ingest.js +40 -8
- package/dist/memory-provider.d.ts +2 -2
- package/dist/memory-provider.js +1 -1
- package/dist/memory-runtime.d.ts +4 -33
- package/dist/memory-runtime.js +40 -51
- package/dist/plugin-runtime.d.ts +4 -6
- package/dist/plugin-runtime.js +33 -72
- package/dist/types.d.ts +1 -21
- package/openclaw.plugin.json +1 -1
- package/package.json +7 -4
- package/dist/grpc-client.d.ts +0 -44
- package/dist/grpc-client.js +0 -188
- package/dist/rpc-protobuf-codecs.d.ts +0 -71
- package/dist/rpc-protobuf-codecs.js +0 -91
- package/dist/rpc.d.ts +0 -15
- package/dist/rpc.js +0 -203
- package/dist/sidecar.d.ts +0 -40
- package/dist/sidecar.js +0 -588
package/dist/ingest-queue.d.ts
CHANGED
|
@@ -41,13 +41,20 @@ interface IngestFeedback {
|
|
|
41
41
|
walDepth?: number;
|
|
42
42
|
walCapacity?: number;
|
|
43
43
|
}
|
|
44
|
+
interface IngestMarkdownDocumentResponse {
|
|
45
|
+
ok: boolean;
|
|
46
|
+
feedback?: IngestFeedback;
|
|
47
|
+
}
|
|
44
48
|
export declare class IngestQueue {
|
|
45
49
|
private readonly queue;
|
|
46
|
-
private readonly
|
|
50
|
+
private readonly ingestDocument;
|
|
51
|
+
private readonly deleteDocument;
|
|
47
52
|
private readonly logger;
|
|
48
53
|
private readonly options;
|
|
49
54
|
private running;
|
|
50
|
-
constructor(
|
|
55
|
+
constructor(ingestDocument: (params: IngestMarkdownDocumentParams) => Promise<IngestMarkdownDocumentResponse>, deleteDocument: (params: {
|
|
56
|
+
sourceDoc: string;
|
|
57
|
+
}) => Promise<unknown>, logger: LoggerLike, options?: Partial<IngestQueueOptions>);
|
|
51
58
|
enqueueIngest(sourceDoc: string, text: string, baseParams: Omit<IngestMarkdownDocumentParams, "sourceDoc" | "text" | "mode">, maxChunkTokens?: number): Promise<IngestFeedback | undefined>;
|
|
52
59
|
private ingestWithRetry;
|
|
53
60
|
enqueueDelete(sourceDoc: string): Promise<void>;
|
package/dist/ingest-queue.js
CHANGED
|
@@ -6,12 +6,14 @@ const DEFAULT_OPTIONS = {
|
|
|
6
6
|
};
|
|
7
7
|
export class IngestQueue {
|
|
8
8
|
queue = [];
|
|
9
|
-
|
|
9
|
+
ingestDocument;
|
|
10
|
+
deleteDocument;
|
|
10
11
|
logger;
|
|
11
12
|
options;
|
|
12
13
|
running = false;
|
|
13
|
-
constructor(
|
|
14
|
-
this.
|
|
14
|
+
constructor(ingestDocument, deleteDocument, logger, options = {}) {
|
|
15
|
+
this.ingestDocument = ingestDocument;
|
|
16
|
+
this.deleteDocument = deleteDocument;
|
|
15
17
|
this.logger = logger;
|
|
16
18
|
this.options = { ...DEFAULT_OPTIONS, ...options };
|
|
17
19
|
if (!(this.options.chunkTokens > 0)) {
|
|
@@ -71,10 +73,16 @@ export class IngestQueue {
|
|
|
71
73
|
return lastFeedback;
|
|
72
74
|
}
|
|
73
75
|
async ingestWithRetry(params) {
|
|
74
|
-
return withRetry(() =>
|
|
76
|
+
return withRetry(async () => {
|
|
77
|
+
const resp = await this.ingestDocument(params);
|
|
78
|
+
if (!resp.ok) {
|
|
79
|
+
throw new Error(`ingest_markdown_document(${params.sourceDoc}) mode=${params.mode} returned ok=false`);
|
|
80
|
+
}
|
|
81
|
+
return resp;
|
|
82
|
+
}, this.options.maxRetries, this.options.retryBaseDelayMs, this.logger, `ingest_markdown_document(${params.sourceDoc})`);
|
|
75
83
|
}
|
|
76
84
|
async enqueueDelete(sourceDoc) {
|
|
77
|
-
await withRetry(() => this.
|
|
85
|
+
await withRetry(() => this.deleteDocument({ sourceDoc }), this.options.maxRetries, this.options.retryBaseDelayMs, this.logger, `delete_authored_document(${sourceDoc})`);
|
|
78
86
|
}
|
|
79
87
|
}
|
|
80
88
|
function splitIntoChunks(text, maxTokens) {
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { Interceptor } from "@connectrpc/connect";
|
|
2
|
+
import type { PartialMessage } from "@bufbuild/protobuf";
|
|
3
|
+
import type { AfterTurnKernelRequest, AfterTurnKernelResponse, AssembleContextInternalRequest, AssembleContextInternalResponse, BootstrapSessionKernelRequest, BootstrapSessionKernelResponse, CompactSessionRequest, CompactSessionResponse, DeleteAuthoredDocumentRequest, DeleteAuthoredDocumentResponse, DreamPromotionResponse, ExportMemoryRequest, ExportMemoryResponse, FlushNamespaceRequest, FlushNamespaceResponse, FlushRequest, FlushResponse, HealthRequest, HealthResponse, IngestMarkdownDocumentRequest, IngestMarkdownDocumentResponse, IngestMessageKernelRequest, IngestMessageKernelResponse, ListCollectionRequest, ListCollectionResponse, ListLifecycleJournalRequest, ListLifecycleJournalResponse, MarkMemorySupersededRequest, MarkMemorySupersededResponse, MemoryStatusRequest, MemoryStatusResponse, PromoteDreamEntriesRequest, RankCandidatesRequest, RankCandidatesResponse, RebuildIndexRequest, RebuildIndexResponse, ReindexAuthoredDocumentRequest, ReindexAuthoredDocumentResponse, SearchTextCollectionsRequest, SearchTextRequest, SearchTextResponse, SessionLifecycleHintRequest, SessionLifecycleHintResponse } from "@xdarkicex/libravdb-contracts";
|
|
4
|
+
export interface LibravDBClientOptions {
|
|
5
|
+
endpoint?: string;
|
|
6
|
+
secret?: string;
|
|
7
|
+
timeoutMs?: number;
|
|
8
|
+
tlsCaPath?: string;
|
|
9
|
+
tlsMode?: "auto" | "tls" | "insecure";
|
|
10
|
+
tlsClientCertPath?: string;
|
|
11
|
+
tlsClientKeyPath?: string;
|
|
12
|
+
}
|
|
13
|
+
export declare function resolveClientEndpoint(configuredEndpoint?: string): string;
|
|
14
|
+
interface RpcMutex {
|
|
15
|
+
current: Promise<void>;
|
|
16
|
+
lock(): Promise<() => void>;
|
|
17
|
+
}
|
|
18
|
+
export interface AuthInterceptorState {
|
|
19
|
+
readonly secret: string | undefined;
|
|
20
|
+
nonceHex: string | undefined;
|
|
21
|
+
bootstrap(): Promise<void>;
|
|
22
|
+
readonly rpcMutex: RpcMutex;
|
|
23
|
+
}
|
|
24
|
+
export declare function createAuthInterceptor(state: AuthInterceptorState): Interceptor;
|
|
25
|
+
export declare class LibravDBClient {
|
|
26
|
+
private client;
|
|
27
|
+
private readonly secret;
|
|
28
|
+
private nonceHex;
|
|
29
|
+
private closed;
|
|
30
|
+
constructor(options?: LibravDBClientOptions);
|
|
31
|
+
bootstrapHandshake(): Promise<void>;
|
|
32
|
+
private guardOpen;
|
|
33
|
+
health(req?: PartialMessage<HealthRequest>): Promise<HealthResponse>;
|
|
34
|
+
status(req?: PartialMessage<MemoryStatusRequest>): Promise<MemoryStatusResponse>;
|
|
35
|
+
flush(req?: PartialMessage<FlushRequest>): Promise<FlushResponse>;
|
|
36
|
+
sessionLifecycleHint(req: PartialMessage<SessionLifecycleHintRequest>): Promise<SessionLifecycleHintResponse>;
|
|
37
|
+
listLifecycleJournal(req: PartialMessage<ListLifecycleJournalRequest>): Promise<ListLifecycleJournalResponse>;
|
|
38
|
+
ingestMarkdownDocument(req: PartialMessage<IngestMarkdownDocumentRequest>): Promise<IngestMarkdownDocumentResponse>;
|
|
39
|
+
promoteDreamEntries(req: PartialMessage<PromoteDreamEntriesRequest>): Promise<DreamPromotionResponse>;
|
|
40
|
+
reindexAuthoredDocument(req: PartialMessage<ReindexAuthoredDocumentRequest>): Promise<ReindexAuthoredDocumentResponse>;
|
|
41
|
+
deleteAuthoredDocument(req: PartialMessage<DeleteAuthoredDocumentRequest>): Promise<DeleteAuthoredDocumentResponse>;
|
|
42
|
+
markMemorySuperseded(req: PartialMessage<MarkMemorySupersededRequest>): Promise<MarkMemorySupersededResponse>;
|
|
43
|
+
searchText(req: PartialMessage<SearchTextRequest>): Promise<SearchTextResponse>;
|
|
44
|
+
searchTextCollections(req: PartialMessage<SearchTextCollectionsRequest>): Promise<SearchTextResponse>;
|
|
45
|
+
listCollection(req: PartialMessage<ListCollectionRequest>): Promise<ListCollectionResponse>;
|
|
46
|
+
exportMemory(req: PartialMessage<ExportMemoryRequest>): Promise<ExportMemoryResponse>;
|
|
47
|
+
flushNamespace(req: PartialMessage<FlushNamespaceRequest>): Promise<FlushNamespaceResponse>;
|
|
48
|
+
rebuildIndex(req: PartialMessage<RebuildIndexRequest>, opts?: {
|
|
49
|
+
timeoutMs?: number;
|
|
50
|
+
}): Promise<RebuildIndexResponse>;
|
|
51
|
+
bootstrapSessionKernel(req: PartialMessage<BootstrapSessionKernelRequest>): Promise<BootstrapSessionKernelResponse>;
|
|
52
|
+
ingestMessageKernel(req: PartialMessage<IngestMessageKernelRequest>): Promise<IngestMessageKernelResponse>;
|
|
53
|
+
afterTurnKernel(req: PartialMessage<AfterTurnKernelRequest>): Promise<AfterTurnKernelResponse>;
|
|
54
|
+
assembleContextInternal(req: PartialMessage<AssembleContextInternalRequest>): Promise<AssembleContextInternalResponse>;
|
|
55
|
+
compactSession(req: PartialMessage<CompactSessionRequest>): Promise<CompactSessionResponse>;
|
|
56
|
+
rankCandidates(req: PartialMessage<RankCandidatesRequest>): Promise<RankCandidatesResponse>;
|
|
57
|
+
close(): void;
|
|
58
|
+
}
|
|
59
|
+
export {};
|
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
import { createPromiseClient } from "@connectrpc/connect";
|
|
2
|
+
import { createGrpcTransport } from "@connectrpc/connect-node";
|
|
3
|
+
import { LibravDB } from "@xdarkicex/libravdb-contracts/client";
|
|
4
|
+
import { createHmac } from "node:crypto";
|
|
5
|
+
import fs from "node:fs";
|
|
6
|
+
import net from "node:net";
|
|
7
|
+
import os from "node:os";
|
|
8
|
+
import path from "node:path";
|
|
9
|
+
export function resolveClientEndpoint(configuredEndpoint) {
|
|
10
|
+
if (configuredEndpoint && configuredEndpoint !== "auto")
|
|
11
|
+
return configuredEndpoint;
|
|
12
|
+
if (process.env.LIBRAVDB_GRPC_ENDPOINT)
|
|
13
|
+
return process.env.LIBRAVDB_GRPC_ENDPOINT;
|
|
14
|
+
if (process.platform === "win32")
|
|
15
|
+
return "tcp:127.0.0.1:37421";
|
|
16
|
+
const sockName = "libravdb.sock";
|
|
17
|
+
const candidateDirs = [
|
|
18
|
+
path.join(os.homedir(), ".libravdbd", "run"),
|
|
19
|
+
"/opt/homebrew/var/libravdbd/run",
|
|
20
|
+
"/usr/local/var/libravdbd/run",
|
|
21
|
+
];
|
|
22
|
+
for (const dir of candidateDirs) {
|
|
23
|
+
const fullPath = path.join(dir, sockName);
|
|
24
|
+
if (fs.existsSync(fullPath))
|
|
25
|
+
return `unix:${fullPath}`;
|
|
26
|
+
}
|
|
27
|
+
return `unix:${path.join(os.homedir(), ".libravdbd", "run", sockName)}`;
|
|
28
|
+
}
|
|
29
|
+
function createRpcMutex() {
|
|
30
|
+
return {
|
|
31
|
+
current: Promise.resolve(),
|
|
32
|
+
async lock() {
|
|
33
|
+
let release;
|
|
34
|
+
const p = new Promise(r => release = r);
|
|
35
|
+
const prev = this.current;
|
|
36
|
+
this.current = prev.then(() => p);
|
|
37
|
+
await prev;
|
|
38
|
+
return release;
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
export function createAuthInterceptor(state) {
|
|
43
|
+
return (next) => async (req) => {
|
|
44
|
+
// Health does not participate in the nonce chain — bypass the
|
|
45
|
+
// mutex entirely so recovery can call Health without deadlocking.
|
|
46
|
+
if (req.method.name === "Health") {
|
|
47
|
+
return next(req);
|
|
48
|
+
}
|
|
49
|
+
const release = await state.rpcMutex.lock();
|
|
50
|
+
try {
|
|
51
|
+
// Lost the nonce? Recover inside the lock so queued requests
|
|
52
|
+
// wait for the chain to be restored instead of failing spuriously.
|
|
53
|
+
if (state.secret && !state.nonceHex) {
|
|
54
|
+
await state.bootstrap();
|
|
55
|
+
if (!state.nonceHex) {
|
|
56
|
+
throw new Error("LibraVDB: bootstrap handshake did not return a nonce");
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
if (state.secret && state.nonceHex) {
|
|
60
|
+
const hmac = createHmac("sha256", state.secret);
|
|
61
|
+
hmac.update(state.nonceHex);
|
|
62
|
+
req.header.set("x-libravdb-nonce", state.nonceHex);
|
|
63
|
+
req.header.set("x-libravdb-auth", hmac.digest("hex"));
|
|
64
|
+
}
|
|
65
|
+
let res;
|
|
66
|
+
try {
|
|
67
|
+
res = await next(req);
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
if (state.secret && state.nonceHex) {
|
|
71
|
+
state.nonceHex = undefined;
|
|
72
|
+
}
|
|
73
|
+
throw error;
|
|
74
|
+
}
|
|
75
|
+
if (state.secret) {
|
|
76
|
+
const nextNonce = res.header.get("x-libravdb-nonce") || res.trailer.get("x-libravdb-nonce");
|
|
77
|
+
if (nextNonce) {
|
|
78
|
+
state.nonceHex = nextNonce;
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
state.nonceHex = undefined;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return res;
|
|
85
|
+
}
|
|
86
|
+
finally {
|
|
87
|
+
release();
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
export class LibravDBClient {
|
|
92
|
+
client;
|
|
93
|
+
secret;
|
|
94
|
+
nonceHex;
|
|
95
|
+
closed = false;
|
|
96
|
+
constructor(options = {}) {
|
|
97
|
+
this.secret = options.secret ?? loadSecretFromEnv();
|
|
98
|
+
const rawEndpoint = resolveClientEndpoint(options.endpoint);
|
|
99
|
+
const isUnix = rawEndpoint.startsWith("unix:");
|
|
100
|
+
const socketPath = isUnix ? rawEndpoint.slice(5) : undefined;
|
|
101
|
+
const credMode = resolveCredentialMode(rawEndpoint, options.tlsMode);
|
|
102
|
+
const isInsecure = isUnix || credMode === "insecure";
|
|
103
|
+
const targetUrl = isUnix
|
|
104
|
+
? "http://localhost"
|
|
105
|
+
: rawEndpoint.replace(/^tcp:/, isInsecure ? "http://" : "https://");
|
|
106
|
+
let rootCerts = null;
|
|
107
|
+
let clientKey = null;
|
|
108
|
+
let clientCert = null;
|
|
109
|
+
if (!isInsecure && options.tlsCaPath) {
|
|
110
|
+
rootCerts = fs.readFileSync(options.tlsCaPath);
|
|
111
|
+
}
|
|
112
|
+
if (options.tlsClientCertPath && options.tlsClientKeyPath) {
|
|
113
|
+
clientCert = fs.readFileSync(options.tlsClientCertPath);
|
|
114
|
+
clientKey = fs.readFileSync(options.tlsClientKeyPath);
|
|
115
|
+
}
|
|
116
|
+
const rpcMutex = createRpcMutex();
|
|
117
|
+
const self = this;
|
|
118
|
+
const authInterceptor = createAuthInterceptor({
|
|
119
|
+
secret: this.secret,
|
|
120
|
+
get nonceHex() { return self.nonceHex; },
|
|
121
|
+
set nonceHex(v) { self.nonceHex = v; },
|
|
122
|
+
bootstrap: () => self.bootstrapHandshake(),
|
|
123
|
+
rpcMutex,
|
|
124
|
+
});
|
|
125
|
+
const transport = createGrpcTransport({
|
|
126
|
+
baseUrl: targetUrl,
|
|
127
|
+
httpVersion: "2",
|
|
128
|
+
nodeOptions: isUnix
|
|
129
|
+
? { createConnection: () => net.connect(socketPath) }
|
|
130
|
+
: {
|
|
131
|
+
...(rootCerts ? { ca: rootCerts } : {}),
|
|
132
|
+
...(clientKey ? { key: clientKey } : {}),
|
|
133
|
+
...(clientCert ? { cert: clientCert } : {}),
|
|
134
|
+
...(isInsecure ? { rejectUnauthorized: false } : {}),
|
|
135
|
+
},
|
|
136
|
+
defaultTimeoutMs: options.timeoutMs ?? 30000,
|
|
137
|
+
interceptors: [authInterceptor],
|
|
138
|
+
});
|
|
139
|
+
this.client = createPromiseClient(LibravDB, transport);
|
|
140
|
+
}
|
|
141
|
+
async bootstrapHandshake() {
|
|
142
|
+
this.guardOpen();
|
|
143
|
+
try {
|
|
144
|
+
await this.client.health({ service: "" }, {
|
|
145
|
+
onHeader: (headers) => {
|
|
146
|
+
const nonce = headers.get("x-libravdb-nonce");
|
|
147
|
+
if (nonce)
|
|
148
|
+
this.nonceHex = nonce;
|
|
149
|
+
},
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
catch (error) {
|
|
153
|
+
throw new Error(`LibraVDB: failed to handshake with daemon: ${error instanceof Error ? error.message : String(error)}`);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
guardOpen() {
|
|
157
|
+
if (this.closed) {
|
|
158
|
+
throw new Error("LibravDB client is closed");
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
// ── Session lifecycle ────────────────────────────────────────────
|
|
162
|
+
async health(req = {}) {
|
|
163
|
+
this.guardOpen();
|
|
164
|
+
return this.client.health(req);
|
|
165
|
+
}
|
|
166
|
+
async status(req = {}) {
|
|
167
|
+
this.guardOpen();
|
|
168
|
+
return this.client.status(req);
|
|
169
|
+
}
|
|
170
|
+
async flush(req = {}) {
|
|
171
|
+
this.guardOpen();
|
|
172
|
+
return this.client.flush(req);
|
|
173
|
+
}
|
|
174
|
+
async sessionLifecycleHint(req) {
|
|
175
|
+
this.guardOpen();
|
|
176
|
+
return this.client.sessionLifecycleHint(req);
|
|
177
|
+
}
|
|
178
|
+
async listLifecycleJournal(req) {
|
|
179
|
+
this.guardOpen();
|
|
180
|
+
return this.client.listLifecycleJournal(req);
|
|
181
|
+
}
|
|
182
|
+
// ── Ingest ───────────────────────────────────────────────────────
|
|
183
|
+
async ingestMarkdownDocument(req) {
|
|
184
|
+
this.guardOpen();
|
|
185
|
+
return this.client.ingestMarkdownDocument(req);
|
|
186
|
+
}
|
|
187
|
+
async promoteDreamEntries(req) {
|
|
188
|
+
this.guardOpen();
|
|
189
|
+
return this.client.promoteDreamEntries(req);
|
|
190
|
+
}
|
|
191
|
+
async reindexAuthoredDocument(req) {
|
|
192
|
+
this.guardOpen();
|
|
193
|
+
return this.client.reindexAuthoredDocument(req);
|
|
194
|
+
}
|
|
195
|
+
async deleteAuthoredDocument(req) {
|
|
196
|
+
this.guardOpen();
|
|
197
|
+
return this.client.deleteAuthoredDocument(req);
|
|
198
|
+
}
|
|
199
|
+
async markMemorySuperseded(req) {
|
|
200
|
+
this.guardOpen();
|
|
201
|
+
return this.client.markMemorySuperseded(req);
|
|
202
|
+
}
|
|
203
|
+
// ── Search / query ───────────────────────────────────────────────
|
|
204
|
+
async searchText(req) {
|
|
205
|
+
this.guardOpen();
|
|
206
|
+
return this.client.searchText(req);
|
|
207
|
+
}
|
|
208
|
+
async searchTextCollections(req) {
|
|
209
|
+
this.guardOpen();
|
|
210
|
+
return this.client.searchTextCollections(req);
|
|
211
|
+
}
|
|
212
|
+
async listCollection(req) {
|
|
213
|
+
this.guardOpen();
|
|
214
|
+
return this.client.listCollection(req);
|
|
215
|
+
}
|
|
216
|
+
// ── Memory ───────────────────────────────────────────────────────
|
|
217
|
+
async exportMemory(req) {
|
|
218
|
+
this.guardOpen();
|
|
219
|
+
return this.client.exportMemory(req);
|
|
220
|
+
}
|
|
221
|
+
async flushNamespace(req) {
|
|
222
|
+
this.guardOpen();
|
|
223
|
+
return this.client.flushNamespace(req);
|
|
224
|
+
}
|
|
225
|
+
// ── Index ────────────────────────────────────────────────────────
|
|
226
|
+
async rebuildIndex(req, opts) {
|
|
227
|
+
this.guardOpen();
|
|
228
|
+
return this.client.rebuildIndex(req, opts);
|
|
229
|
+
}
|
|
230
|
+
// ── Kernel ───────────────────────────────────────────────────────
|
|
231
|
+
async bootstrapSessionKernel(req) {
|
|
232
|
+
this.guardOpen();
|
|
233
|
+
return this.client.bootstrapSessionKernel(req);
|
|
234
|
+
}
|
|
235
|
+
async ingestMessageKernel(req) {
|
|
236
|
+
this.guardOpen();
|
|
237
|
+
return this.client.ingestMessageKernel(req);
|
|
238
|
+
}
|
|
239
|
+
async afterTurnKernel(req) {
|
|
240
|
+
this.guardOpen();
|
|
241
|
+
return this.client.afterTurnKernel(req);
|
|
242
|
+
}
|
|
243
|
+
async assembleContextInternal(req) {
|
|
244
|
+
this.guardOpen();
|
|
245
|
+
return this.client.assembleContextInternal(req);
|
|
246
|
+
}
|
|
247
|
+
async compactSession(req) {
|
|
248
|
+
this.guardOpen();
|
|
249
|
+
return this.client.compactSession(req);
|
|
250
|
+
}
|
|
251
|
+
async rankCandidates(req) {
|
|
252
|
+
this.guardOpen();
|
|
253
|
+
return this.client.rankCandidates(req);
|
|
254
|
+
}
|
|
255
|
+
close() {
|
|
256
|
+
this.closed = true;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
function resolveCredentialMode(endpoint, tlsMode) {
|
|
260
|
+
if (tlsMode === "tls")
|
|
261
|
+
return "tls";
|
|
262
|
+
if (tlsMode === "insecure")
|
|
263
|
+
return "insecure";
|
|
264
|
+
const target = endpoint.startsWith("tcp:") ? endpoint.slice(4) : endpoint;
|
|
265
|
+
if (target.startsWith("unix:"))
|
|
266
|
+
return "insecure";
|
|
267
|
+
const host = extractHost(target);
|
|
268
|
+
const normalized = host.toLowerCase();
|
|
269
|
+
return normalized === "localhost" || normalized === "127.0.0.1" || normalized === "::1"
|
|
270
|
+
? "insecure"
|
|
271
|
+
: "tls";
|
|
272
|
+
}
|
|
273
|
+
function extractHost(target) {
|
|
274
|
+
const withoutDns = target.startsWith("dns:///") ? target.slice("dns:///".length) : target;
|
|
275
|
+
if (withoutDns.startsWith("[")) {
|
|
276
|
+
const close = withoutDns.indexOf("]");
|
|
277
|
+
return close > 0 ? withoutDns.slice(1, close) : withoutDns;
|
|
278
|
+
}
|
|
279
|
+
const sep = withoutDns.lastIndexOf(":");
|
|
280
|
+
return sep > 0 ? withoutDns.slice(0, sep) : withoutDns;
|
|
281
|
+
}
|
|
282
|
+
function loadSecretFromEnv() {
|
|
283
|
+
const secret = process.env.LIBRAVDB_AUTH_SECRET;
|
|
284
|
+
if (secret)
|
|
285
|
+
return secret;
|
|
286
|
+
const secretPath = process.env.LIBRAVDB_AUTH_SECRET_FILE;
|
|
287
|
+
if (secretPath) {
|
|
288
|
+
try {
|
|
289
|
+
return fs.readFileSync(secretPath, "utf8").trim();
|
|
290
|
+
}
|
|
291
|
+
catch {
|
|
292
|
+
return undefined;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
return undefined;
|
|
296
|
+
}
|
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
import type { LoggerLike, PluginConfig } from "./types.js";
|
|
2
|
+
import type { ClientGetter } from "./plugin-runtime.js";
|
|
2
3
|
type Disposable = {
|
|
3
4
|
close(): void;
|
|
4
5
|
};
|
|
5
|
-
interface RpcLike {
|
|
6
|
-
call<T>(method: string, params: unknown): Promise<T>;
|
|
7
|
-
}
|
|
8
|
-
type RpcGetterLike = () => Promise<RpcLike>;
|
|
9
6
|
interface FsDirentLike {
|
|
10
7
|
name: string;
|
|
11
8
|
isDirectory(): boolean;
|
|
@@ -47,5 +44,5 @@ export interface MarkdownIngestionSnapshot {
|
|
|
47
44
|
size: number;
|
|
48
45
|
mtimeMs: number;
|
|
49
46
|
}
|
|
50
|
-
export declare function createMarkdownIngestionHandle(cfg: PluginConfig,
|
|
47
|
+
export declare function createMarkdownIngestionHandle(cfg: PluginConfig, getClient: ClientGetter, logger?: LoggerLike, fsApi?: FsApi): MarkdownIngestionHandle;
|
|
51
48
|
export {};
|
package/dist/markdown-ingest.js
CHANGED
|
@@ -9,7 +9,7 @@ const DEFAULT_TOKENIZER_ID = "markdown-ingest:v1";
|
|
|
9
9
|
const MARKDOWN_INGEST_VERSION = 3;
|
|
10
10
|
const HASH_BACKEND = "wasm-fnv1a64";
|
|
11
11
|
const STREAM_CHUNK_BYTES = 64 * 1024;
|
|
12
|
-
export function createMarkdownIngestionHandle(cfg,
|
|
12
|
+
export function createMarkdownIngestionHandle(cfg, getClient, logger = console, fsApi = createRealFsApi()) {
|
|
13
13
|
const adapters = [];
|
|
14
14
|
const genericRoots = normalizeMarkdownRoots(cfg.markdownIngestionRoots);
|
|
15
15
|
if (isMarkdownIngestionEnabled(cfg, genericRoots)) {
|
|
@@ -21,7 +21,7 @@ export function createMarkdownIngestionHandle(cfg, getRpc, logger = console, fsA
|
|
|
21
21
|
snapshotPath: resolveMarkdownSnapshotPath("generic", cfg.markdownIngestionSnapshotPath),
|
|
22
22
|
priorityMode: cfg.markdownIngestionPriorityMode,
|
|
23
23
|
maxTokensPerFile: cfg.markdownIngestionMaxTokensPerFile,
|
|
24
|
-
},
|
|
24
|
+
}, getClient, logger, fsApi));
|
|
25
25
|
}
|
|
26
26
|
const obsidianRoots = normalizeMarkdownRoots(cfg.markdownIngestionObsidianRoots);
|
|
27
27
|
if (cfg.markdownIngestionObsidianEnabled === true && obsidianRoots.length > 0) {
|
|
@@ -33,7 +33,7 @@ export function createMarkdownIngestionHandle(cfg, getRpc, logger = console, fsA
|
|
|
33
33
|
snapshotPath: resolveMarkdownSnapshotPath("obsidian", cfg.markdownIngestionObsidianSnapshotPath),
|
|
34
34
|
priorityMode: cfg.markdownIngestionPriorityMode,
|
|
35
35
|
maxTokensPerFile: cfg.markdownIngestionMaxTokensPerFile,
|
|
36
|
-
},
|
|
36
|
+
}, getClient, logger, fsApi));
|
|
37
37
|
}
|
|
38
38
|
if (adapters.length === 0) {
|
|
39
39
|
return {
|
|
@@ -78,7 +78,7 @@ class DirectoryMarkdownSourceAdapter {
|
|
|
78
78
|
excludePatterns;
|
|
79
79
|
debounceMs;
|
|
80
80
|
fsApi;
|
|
81
|
-
|
|
81
|
+
getClient;
|
|
82
82
|
logger;
|
|
83
83
|
snapshotPath;
|
|
84
84
|
priorityMode;
|
|
@@ -104,14 +104,14 @@ class DirectoryMarkdownSourceAdapter {
|
|
|
104
104
|
lastWalCapacity = 0;
|
|
105
105
|
snapshotLoaded = false;
|
|
106
106
|
snapshotDirty = false;
|
|
107
|
-
constructor(kind, config,
|
|
107
|
+
constructor(kind, config, getClient, logger, fsApi) {
|
|
108
108
|
this.kind = kind;
|
|
109
109
|
this.roots = config.roots;
|
|
110
110
|
this.includePatterns = config.include?.length ? config.include : [];
|
|
111
111
|
this.excludePatterns = config.exclude?.length ? config.exclude : [];
|
|
112
112
|
this.debounceMs = config.debounceMs ?? DEFAULT_DEBOUNCE_MS;
|
|
113
113
|
this.fsApi = fsApi;
|
|
114
|
-
this.
|
|
114
|
+
this.getClient = getClient;
|
|
115
115
|
this.logger = logger;
|
|
116
116
|
this.snapshotPath = config.snapshotPath ?? resolveMarkdownSnapshotPath(kind);
|
|
117
117
|
this.priorityMode = config.priorityMode ?? "mtime";
|
|
@@ -536,8 +536,40 @@ class DirectoryMarkdownSourceAdapter {
|
|
|
536
536
|
}
|
|
537
537
|
async getIngestQueue() {
|
|
538
538
|
if (!this.ingestQueue) {
|
|
539
|
-
const
|
|
540
|
-
this.ingestQueue = new IngestQueue(
|
|
539
|
+
const client = await this.getClient();
|
|
540
|
+
this.ingestQueue = new IngestQueue((params) => client.ingestMarkdownDocument({
|
|
541
|
+
sourceDoc: params.sourceDoc,
|
|
542
|
+
text: params.text,
|
|
543
|
+
tokenizerId: params.tokenizerId,
|
|
544
|
+
coreDoc: params.coreDoc,
|
|
545
|
+
mode: params.mode,
|
|
546
|
+
sourceMeta: params.sourceMeta ? {
|
|
547
|
+
sourceRoot: params.sourceMeta.sourceRoot,
|
|
548
|
+
sourcePath: params.sourceMeta.sourcePath,
|
|
549
|
+
sourceKind: params.sourceMeta.sourceKind,
|
|
550
|
+
fileHash: params.sourceMeta.fileHash,
|
|
551
|
+
sourceSize: BigInt(params.sourceMeta.sourceSize),
|
|
552
|
+
sourceMtimeMs: BigInt(Math.trunc(params.sourceMeta.sourceMtimeMs)),
|
|
553
|
+
sourceCtimeMs: BigInt(Math.trunc(params.sourceMeta.sourceCtimeMs)),
|
|
554
|
+
ingestVersion: params.sourceMeta.ingestVersion,
|
|
555
|
+
hashBackend: params.sourceMeta.hashBackend,
|
|
556
|
+
} : undefined,
|
|
557
|
+
}).then((r) => ({
|
|
558
|
+
ok: r.ok,
|
|
559
|
+
feedback: r.feedback ? {
|
|
560
|
+
queueDepth: r.feedback.queueDepth,
|
|
561
|
+
queueCapacity: r.feedback.queueCapacity,
|
|
562
|
+
acceptMore: r.feedback.acceptMore,
|
|
563
|
+
retryAfterMs: r.feedback.retryAfterMs,
|
|
564
|
+
processingTimeUs: Number(r.feedback.processingTimeUs),
|
|
565
|
+
nodesAccepted: r.feedback.nodesAccepted,
|
|
566
|
+
nodesRejected: r.feedback.nodesRejected,
|
|
567
|
+
tokensIngested: r.feedback.tokensIngested,
|
|
568
|
+
tokenBurstLimit: r.feedback.tokenBurstLimit,
|
|
569
|
+
walDepth: r.feedback.walDepth,
|
|
570
|
+
walCapacity: r.feedback.walCapacity,
|
|
571
|
+
} : undefined,
|
|
572
|
+
})), (params) => client.deleteAuthoredDocument(params).then(() => undefined), this.logger, {
|
|
541
573
|
onChunkFeedback: (feedback) => this.applyIngestFeedback(feedback),
|
|
542
574
|
});
|
|
543
575
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { MemoryPromptSectionBuilder } from "openclaw/plugin-sdk/plugin-entry";
|
|
2
2
|
import type { PluginConfig } from "./types.js";
|
|
3
|
-
import type {
|
|
4
|
-
export declare function buildMemoryPromptSection(
|
|
3
|
+
import type { ClientGetter } from "./plugin-runtime.js";
|
|
4
|
+
export declare function buildMemoryPromptSection(_getClient: ClientGetter, _cfg: PluginConfig): MemoryPromptSectionBuilder;
|
package/dist/memory-provider.js
CHANGED
|
@@ -4,7 +4,7 @@ const MEMORY_PROMPT_HEADER = [
|
|
|
4
4
|
"in context via the context-engine assembler when available and relevant.",
|
|
5
5
|
"",
|
|
6
6
|
];
|
|
7
|
-
export function buildMemoryPromptSection(
|
|
7
|
+
export function buildMemoryPromptSection(_getClient, _cfg) {
|
|
8
8
|
return function memoryPromptSection({ availableTools: _availableTools, citationsMode: _citationsMode, }) {
|
|
9
9
|
// OpenClaw builds the memory prompt section synchronously for embedded runs.
|
|
10
10
|
// Actual retrieval and ranking happen in the context engine during assemble().
|
package/dist/memory-runtime.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ClientGetter } from "./plugin-runtime.js";
|
|
2
2
|
import type { PluginConfig } from "./types.js";
|
|
3
3
|
type MemorySearchParams = {
|
|
4
4
|
query?: string;
|
|
@@ -30,7 +30,7 @@ type MemoryRuntimeStatus = {
|
|
|
30
30
|
abstractiveReady?: boolean;
|
|
31
31
|
embeddingProfile?: string;
|
|
32
32
|
};
|
|
33
|
-
export declare function buildMemoryRuntimeBridge(
|
|
33
|
+
export declare function buildMemoryRuntimeBridge(getClient: ClientGetter, cfg: PluginConfig): {
|
|
34
34
|
getMemorySearchManager(params?: {
|
|
35
35
|
agentId?: string;
|
|
36
36
|
purpose?: string;
|
|
@@ -53,37 +53,8 @@ export declare function buildMemoryRuntimeBridge(getRpc: RpcGetter, cfg: PluginC
|
|
|
53
53
|
id: string;
|
|
54
54
|
score: number;
|
|
55
55
|
text: string;
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
sessionId?: string;
|
|
59
|
-
userId?: string;
|
|
60
|
-
role?: string;
|
|
61
|
-
source_doc?: string;
|
|
62
|
-
node_kind?: string;
|
|
63
|
-
ordinal?: number;
|
|
64
|
-
position?: number;
|
|
65
|
-
tier?: number;
|
|
66
|
-
authored?: boolean;
|
|
67
|
-
authority?: number;
|
|
68
|
-
access_count?: number;
|
|
69
|
-
collection?: string;
|
|
70
|
-
hop_targets?: string[] | string;
|
|
71
|
-
token_estimate?: number;
|
|
72
|
-
continuity_tail?: boolean;
|
|
73
|
-
continuity_base?: boolean;
|
|
74
|
-
continuity_bundle_id?: string;
|
|
75
|
-
elevated_guidance?: boolean;
|
|
76
|
-
source_turn_id?: string;
|
|
77
|
-
source_turn_ts?: number;
|
|
78
|
-
provenance_class?: string;
|
|
79
|
-
stability_weight?: number;
|
|
80
|
-
expanded_from_summary?: boolean;
|
|
81
|
-
parent_summary_id?: string;
|
|
82
|
-
expansion_depth?: number;
|
|
83
|
-
cascade_tier?: number;
|
|
84
|
-
[key: string]: unknown;
|
|
85
|
-
};
|
|
86
|
-
finalScore?: number;
|
|
56
|
+
metadataJson: Uint8Array<ArrayBuffer>;
|
|
57
|
+
version: bigint;
|
|
87
58
|
}[];
|
|
88
59
|
error?: undefined;
|
|
89
60
|
}>;
|