@xdarkicex/openclaw-memory-libravdb 1.5.4 → 1.6.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/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 +25344 -29086
- package/dist/ingest-queue.d.ts +26 -3
- package/dist/ingest-queue.js +44 -23
- package/dist/libravdb-client.d.ts +59 -0
- package/dist/libravdb-client.js +296 -0
- package/dist/markdown-ingest.d.ts +10 -5
- package/dist/markdown-ingest.js +264 -32
- 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 +3 -21
- package/openclaw.plugin.json +15 -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/grpc-client.js
DELETED
|
@@ -1,188 +0,0 @@
|
|
|
1
|
-
import { createHmac } from "node:crypto";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import { fileURLToPath } from "node:url";
|
|
4
|
-
import fs from "node:fs";
|
|
5
|
-
import * as grpc from "@grpc/grpc-js";
|
|
6
|
-
import * as protoLoader from "@grpc/proto-loader";
|
|
7
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
8
|
-
// The proto file is expected to be copied to dist/proto/ at build time.
|
|
9
|
-
// In source, it's at api/proto/.
|
|
10
|
-
const PROTO_PATH = path.resolve(__dirname, "./proto/intelligence_kernel/v1/kernel.proto");
|
|
11
|
-
export function resolveGrpcTarget(endpoint) {
|
|
12
|
-
return endpoint.startsWith("tcp:") ? endpoint.substring(4) : endpoint;
|
|
13
|
-
}
|
|
14
|
-
/**
|
|
15
|
-
* Selects gRPC credential mode based on endpoint address class.
|
|
16
|
-
*
|
|
17
|
-
* - Unix socket endpoints → plaintext (local-only transport)
|
|
18
|
-
* - Loopback addresses (localhost, 127.0.0.1, ::1) → plaintext
|
|
19
|
-
* - All other TCP and DNS targets → TLS
|
|
20
|
-
*
|
|
21
|
-
* resolveGrpcCredentials uses this classification to return the
|
|
22
|
-
* appropriate grpc.ChannelCredentials. Pass tlsCaPath to load a
|
|
23
|
-
* custom CA certificate PEM file for self-signed or private CA
|
|
24
|
-
* deployments. Omit tlsCaPath for publicly trusted certificates
|
|
25
|
-
* (Let's Encrypt, cert-manager) — the system CA pool is used.
|
|
26
|
-
*/
|
|
27
|
-
export function resolveGrpcCredentialMode(endpoint, tlsMode) {
|
|
28
|
-
if (tlsMode === "tls")
|
|
29
|
-
return "tls";
|
|
30
|
-
if (tlsMode === "insecure")
|
|
31
|
-
return "insecure";
|
|
32
|
-
// "auto" or undefined — address-based heuristic
|
|
33
|
-
const target = resolveGrpcTarget(endpoint).trim();
|
|
34
|
-
if (target.startsWith("unix:"))
|
|
35
|
-
return "insecure";
|
|
36
|
-
const host = extractGrpcHost(target);
|
|
37
|
-
return isLoopbackHost(host) ? "insecure" : "tls";
|
|
38
|
-
}
|
|
39
|
-
export function resolveGrpcCredentials(endpoint, tlsCaPath, tlsMode, tlsClientCertPath, tlsClientKeyPath) {
|
|
40
|
-
if (resolveGrpcCredentialMode(endpoint, tlsMode) === "insecure") {
|
|
41
|
-
return grpc.credentials.createInsecure();
|
|
42
|
-
}
|
|
43
|
-
// tlsMode is "tls" or "auto"/undefined resolved to "tls"
|
|
44
|
-
let rootCerts = null;
|
|
45
|
-
if (tlsCaPath) {
|
|
46
|
-
try {
|
|
47
|
-
rootCerts = fs.readFileSync(tlsCaPath);
|
|
48
|
-
}
|
|
49
|
-
catch (err) {
|
|
50
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
51
|
-
throw new Error(`LibraVDB: failed to load TLS CA certificate from "${tlsCaPath}": ${msg}`);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
// Client certificate and key must both be present or both absent
|
|
55
|
-
const hasCert = tlsClientCertPath !== undefined;
|
|
56
|
-
const hasKey = tlsClientKeyPath !== undefined;
|
|
57
|
-
if (hasCert !== hasKey) {
|
|
58
|
-
throw new Error("LibraVDB: grpcEndpointTlsClientCert and grpcEndpointTlsClientKey " +
|
|
59
|
-
"must both be set or both be omitted");
|
|
60
|
-
}
|
|
61
|
-
let clientKey = null;
|
|
62
|
-
let clientCert = null;
|
|
63
|
-
if (tlsClientCertPath && tlsClientKeyPath) {
|
|
64
|
-
try {
|
|
65
|
-
clientCert = fs.readFileSync(tlsClientCertPath);
|
|
66
|
-
}
|
|
67
|
-
catch (err) {
|
|
68
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
69
|
-
throw new Error(`LibraVDB: failed to load TLS client certificate from "${tlsClientCertPath}": ${msg}`);
|
|
70
|
-
}
|
|
71
|
-
try {
|
|
72
|
-
clientKey = fs.readFileSync(tlsClientKeyPath);
|
|
73
|
-
}
|
|
74
|
-
catch (err) {
|
|
75
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
76
|
-
throw new Error(`LibraVDB: failed to load TLS client key from "${tlsClientKeyPath}": ${msg}`);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
return grpc.credentials.createSsl(rootCerts, clientKey, clientCert);
|
|
80
|
-
}
|
|
81
|
-
function extractGrpcHost(target) {
|
|
82
|
-
const withoutDnsPrefix = target.startsWith("dns:///") ? target.slice("dns:///".length) : target;
|
|
83
|
-
if (withoutDnsPrefix.startsWith("[")) {
|
|
84
|
-
const closeBracket = withoutDnsPrefix.indexOf("]");
|
|
85
|
-
return closeBracket > 0 ? withoutDnsPrefix.slice(1, closeBracket) : withoutDnsPrefix;
|
|
86
|
-
}
|
|
87
|
-
const portSeparator = withoutDnsPrefix.lastIndexOf(":");
|
|
88
|
-
return portSeparator > 0 ? withoutDnsPrefix.slice(0, portSeparator) : withoutDnsPrefix;
|
|
89
|
-
}
|
|
90
|
-
function isLoopbackHost(host) {
|
|
91
|
-
const normalized = host.toLowerCase();
|
|
92
|
-
return normalized === "localhost" || normalized === "127.0.0.1" || normalized === "::1";
|
|
93
|
-
}
|
|
94
|
-
export class GrpcKernelClient {
|
|
95
|
-
client;
|
|
96
|
-
secret;
|
|
97
|
-
timeoutMs;
|
|
98
|
-
nonceHex;
|
|
99
|
-
constructor(options) {
|
|
100
|
-
this.secret = options.secret;
|
|
101
|
-
this.timeoutMs = options.timeoutMs ?? 30000;
|
|
102
|
-
const packageDefinition = protoLoader.loadSync(PROTO_PATH, {
|
|
103
|
-
keepCase: true,
|
|
104
|
-
longs: String,
|
|
105
|
-
enums: String,
|
|
106
|
-
defaults: true,
|
|
107
|
-
oneofs: true,
|
|
108
|
-
});
|
|
109
|
-
const protoDescriptor = grpc.loadPackageDefinition(packageDefinition);
|
|
110
|
-
const kernelService = protoDescriptor.intelligence_kernel.v1.IntelligenceKernel;
|
|
111
|
-
const target = resolveGrpcTarget(options.endpoint);
|
|
112
|
-
this.client = new kernelService(target, resolveGrpcCredentials(options.endpoint, options.tlsCaPath, options.tlsMode, options.tlsClientCertPath, options.tlsClientKeyPath));
|
|
113
|
-
}
|
|
114
|
-
getMetadata(signed = true) {
|
|
115
|
-
const md = new grpc.Metadata();
|
|
116
|
-
if (this.secret && signed) {
|
|
117
|
-
if (!this.nonceHex) {
|
|
118
|
-
throw new Error("call initializeSession before authenticated RPCs");
|
|
119
|
-
}
|
|
120
|
-
// Challenge-response: HMAC(secret, nonce) — the secret is the HMAC key,
|
|
121
|
-
// the server-issued nonce is the message. The previous implementation
|
|
122
|
-
// swapped these, computing HMAC(nonce, secret), which is cryptographically
|
|
123
|
-
// incorrect: the nonce is sent in the clear and must not be used as the key.
|
|
124
|
-
const hmac = createHmac("sha256", this.secret);
|
|
125
|
-
hmac.update(this.nonceHex);
|
|
126
|
-
const signature = hmac.digest("hex");
|
|
127
|
-
md.add("x-libravdb-auth", signature);
|
|
128
|
-
}
|
|
129
|
-
return md;
|
|
130
|
-
}
|
|
131
|
-
call(method, req, signed = true) {
|
|
132
|
-
return new Promise((resolve, reject) => {
|
|
133
|
-
const deadline = new Date(Date.now() + this.timeoutMs);
|
|
134
|
-
this.client[method](req, this.getMetadata(signed), { deadline }, (err, resp) => {
|
|
135
|
-
if (err) {
|
|
136
|
-
reject(err);
|
|
137
|
-
}
|
|
138
|
-
else {
|
|
139
|
-
resolve(resp);
|
|
140
|
-
}
|
|
141
|
-
});
|
|
142
|
-
});
|
|
143
|
-
}
|
|
144
|
-
async initializeSession(req) {
|
|
145
|
-
return new Promise((resolve, reject) => {
|
|
146
|
-
const deadline = new Date(Date.now() + this.timeoutMs);
|
|
147
|
-
this.client.InitializeSession(req, this.getMetadata(false), { deadline }, (err, resp) => {
|
|
148
|
-
if (err) {
|
|
149
|
-
reject(err);
|
|
150
|
-
return;
|
|
151
|
-
}
|
|
152
|
-
const nonce = resp?.server_metadata?.nonce;
|
|
153
|
-
if (this.secret && (typeof nonce !== "string" || nonce.length === 0)) {
|
|
154
|
-
reject(new Error("InitializeSession response missing auth nonce"));
|
|
155
|
-
return;
|
|
156
|
-
}
|
|
157
|
-
if (typeof nonce === "string" && nonce.length > 0) {
|
|
158
|
-
this.nonceHex = nonce;
|
|
159
|
-
}
|
|
160
|
-
resolve(resp);
|
|
161
|
-
});
|
|
162
|
-
});
|
|
163
|
-
}
|
|
164
|
-
async assembleContext(req) {
|
|
165
|
-
return this.call("AssembleContext", req);
|
|
166
|
-
}
|
|
167
|
-
async rankCandidates(req) {
|
|
168
|
-
return this.call("RankCandidates", req);
|
|
169
|
-
}
|
|
170
|
-
async ingestMessage(req) {
|
|
171
|
-
return this.call("IngestMessage", req);
|
|
172
|
-
}
|
|
173
|
-
async afterTurn(req) {
|
|
174
|
-
return this.call("AfterTurn", req);
|
|
175
|
-
}
|
|
176
|
-
async bootstrapSession(req) {
|
|
177
|
-
return this.call("BootstrapSession", req);
|
|
178
|
-
}
|
|
179
|
-
async compactSession(req) {
|
|
180
|
-
return this.call("CompactSession", req);
|
|
181
|
-
}
|
|
182
|
-
async getStatus(req = {}) {
|
|
183
|
-
return this.call("GetStatus", req);
|
|
184
|
-
}
|
|
185
|
-
close() {
|
|
186
|
-
this.client.close();
|
|
187
|
-
}
|
|
188
|
-
}
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import { AfterTurnKernelRequest, AfterTurnKernelResponse, AssembleContextInternalRequest, AssembleContextInternalResponse, BootstrapSessionKernelRequest, BootstrapSessionKernelResponse, CompactSessionRequest, CompactSessionResponse, DeleteAuthoredDocumentResponse, DreamPromotionResponse, ExportMemoryResponse, FlushNamespaceResponse, FlushResponse, HealthResponse, IngestMarkdownDocumentResponse, IngestMessageKernelRequest, IngestMessageKernelResponse, MemoryStatusResponse, RankCandidatesRequest, RankCandidatesResponse, RebuildIndexRequest, RebuildIndexResponse, SearchTextResponse, SessionLifecycleHintResponse } from "@xdarkicex/libravdb-contracts";
|
|
2
|
-
import type { LifecycleHint } from "./plugin-runtime.js";
|
|
3
|
-
export type RpcMethodCodec<Params = unknown, Result = unknown> = {
|
|
4
|
-
encodeParams(params: Params): Uint8Array;
|
|
5
|
-
decodeResult(bytes: Uint8Array): Result;
|
|
6
|
-
};
|
|
7
|
-
export type RpcMethodName = keyof typeof rpcProtobufCodecs;
|
|
8
|
-
export declare const rpcProtobufCodecs: {
|
|
9
|
-
health: RpcMethodCodec<Record<string, never>, HealthResponse>;
|
|
10
|
-
status: RpcMethodCodec<Record<string, never>, MemoryStatusResponse>;
|
|
11
|
-
flush: RpcMethodCodec<Record<string, never>, FlushResponse>;
|
|
12
|
-
session_lifecycle_hint: RpcMethodCodec<LifecycleHint, SessionLifecycleHintResponse>;
|
|
13
|
-
search_text: RpcMethodCodec<{
|
|
14
|
-
collection: string;
|
|
15
|
-
text: string;
|
|
16
|
-
k?: number;
|
|
17
|
-
excludeIds?: string[];
|
|
18
|
-
}, SearchTextResponse>;
|
|
19
|
-
search_text_collections: RpcMethodCodec<{
|
|
20
|
-
collections: string[];
|
|
21
|
-
text: string;
|
|
22
|
-
k?: number;
|
|
23
|
-
excludeByCollection?: Record<string, unknown>;
|
|
24
|
-
}, SearchTextResponse>;
|
|
25
|
-
list_collection: RpcMethodCodec<{
|
|
26
|
-
collection: string;
|
|
27
|
-
}, SearchTextResponse>;
|
|
28
|
-
list_lifecycle_journal: RpcMethodCodec<{
|
|
29
|
-
sessionId?: string;
|
|
30
|
-
limit?: number;
|
|
31
|
-
}, SearchTextResponse>;
|
|
32
|
-
export_memory: RpcMethodCodec<{
|
|
33
|
-
userId?: string;
|
|
34
|
-
namespace?: string;
|
|
35
|
-
}, ExportMemoryResponse>;
|
|
36
|
-
flush_namespace: RpcMethodCodec<{
|
|
37
|
-
userId?: string;
|
|
38
|
-
namespace?: string;
|
|
39
|
-
}, FlushNamespaceResponse>;
|
|
40
|
-
promote_dream_entries: RpcMethodCodec<{
|
|
41
|
-
userId: string;
|
|
42
|
-
sourceDoc: string;
|
|
43
|
-
sourceRoot?: string;
|
|
44
|
-
sourcePath?: string;
|
|
45
|
-
sourceKind?: string;
|
|
46
|
-
fileHash?: string;
|
|
47
|
-
sourceSize?: number;
|
|
48
|
-
sourceMtimeMs?: number;
|
|
49
|
-
ingestVersion?: number;
|
|
50
|
-
hashBackend?: string;
|
|
51
|
-
entries?: Array<Record<string, unknown>>;
|
|
52
|
-
}, DreamPromotionResponse>;
|
|
53
|
-
ingest_markdown_document: RpcMethodCodec<{
|
|
54
|
-
sourceDoc: string;
|
|
55
|
-
text: string;
|
|
56
|
-
tokenizerId?: string;
|
|
57
|
-
coreDoc?: boolean;
|
|
58
|
-
sourceMeta?: Record<string, unknown>;
|
|
59
|
-
}, IngestMarkdownDocumentResponse>;
|
|
60
|
-
delete_authored_document: RpcMethodCodec<{
|
|
61
|
-
sourceDoc: string;
|
|
62
|
-
}, DeleteAuthoredDocumentResponse>;
|
|
63
|
-
bootstrap_session_kernel: RpcMethodCodec<BootstrapSessionKernelRequest, BootstrapSessionKernelResponse>;
|
|
64
|
-
ingest_message_kernel: RpcMethodCodec<IngestMessageKernelRequest, IngestMessageKernelResponse>;
|
|
65
|
-
after_turn_kernel: RpcMethodCodec<AfterTurnKernelRequest, AfterTurnKernelResponse>;
|
|
66
|
-
assemble_context_internal: RpcMethodCodec<AssembleContextInternalRequest, AssembleContextInternalResponse>;
|
|
67
|
-
compact_session: RpcMethodCodec<CompactSessionRequest, CompactSessionResponse>;
|
|
68
|
-
rank_candidates: RpcMethodCodec<RankCandidatesRequest, RankCandidatesResponse>;
|
|
69
|
-
rebuild_index: RpcMethodCodec<RebuildIndexRequest, RebuildIndexResponse>;
|
|
70
|
-
};
|
|
71
|
-
export declare function getRpcMethodCodec(method: string): RpcMethodCodec<any, any> | undefined;
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
import { AfterTurnKernelRequest, AfterTurnKernelResponse, AssembleContextInternalRequest, AssembleContextInternalResponse, BootstrapSessionKernelRequest, BootstrapSessionKernelResponse, CompactSessionRequest, CompactSessionResponse, DeleteAuthoredDocumentRequest, DeleteAuthoredDocumentResponse, DreamPromotionResponse, ExportMemoryRequest, ExportMemoryResponse, FlushNamespaceRequest, FlushNamespaceResponse, FlushResponse, HealthResponse, IngestMarkdownDocumentRequest, IngestMarkdownDocumentResponse, IngestMessageKernelRequest, IngestMessageKernelResponse, ListCollectionRequest, ListLifecycleJournalRequest, MemoryStatusResponse, PromoteDreamEntriesRequest, RankCandidatesRequest, RankCandidatesResponse, RebuildIndexRequest, RebuildIndexResponse, SearchTextCollectionsRequest, SearchTextRequest, SearchTextResponse, SessionLifecycleHintRequest, SessionLifecycleHintResponse, StringList, } from "@xdarkicex/libravdb-contracts";
|
|
2
|
-
function encodeMessage(schema, init) {
|
|
3
|
-
return new schema(init).toBinary();
|
|
4
|
-
}
|
|
5
|
-
function decodeProtobufResult(schema, bytes) {
|
|
6
|
-
return new schema().fromBinary(bytes).toJson();
|
|
7
|
-
}
|
|
8
|
-
function emptyBytes() {
|
|
9
|
-
return new Uint8Array(0);
|
|
10
|
-
}
|
|
11
|
-
function normalizeSearchTextResponse(bytes) {
|
|
12
|
-
const response = decodeProtobufResult(SearchTextResponse, bytes);
|
|
13
|
-
if (!Array.isArray(response.results)) {
|
|
14
|
-
response.results = [];
|
|
15
|
-
}
|
|
16
|
-
for (const item of response.results) {
|
|
17
|
-
if (!item || typeof item !== "object" || Array.isArray(item)) {
|
|
18
|
-
continue;
|
|
19
|
-
}
|
|
20
|
-
if (!item.metadata || typeof item.metadata !== "object" || Array.isArray(item.metadata)) {
|
|
21
|
-
item.metadata = {};
|
|
22
|
-
}
|
|
23
|
-
if (typeof item.text !== "string") {
|
|
24
|
-
item.text = "";
|
|
25
|
-
}
|
|
26
|
-
if (typeof item.score !== "number" || !Number.isFinite(item.score)) {
|
|
27
|
-
item.score = 0;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
return response;
|
|
31
|
-
}
|
|
32
|
-
function normalizeAssembleContextInternalResponse(bytes) {
|
|
33
|
-
const response = decodeProtobufResult(AssembleContextInternalResponse, bytes);
|
|
34
|
-
if (!Array.isArray(response.messages)) {
|
|
35
|
-
response.messages = [];
|
|
36
|
-
}
|
|
37
|
-
return response;
|
|
38
|
-
}
|
|
39
|
-
function normalizeExcludeByCollection(value) {
|
|
40
|
-
const normalized = {};
|
|
41
|
-
if (!value) {
|
|
42
|
-
return normalized;
|
|
43
|
-
}
|
|
44
|
-
for (const [collection, raw] of Object.entries(value)) {
|
|
45
|
-
if (raw instanceof StringList) {
|
|
46
|
-
normalized[collection] = raw;
|
|
47
|
-
continue;
|
|
48
|
-
}
|
|
49
|
-
const values = Array.isArray(raw)
|
|
50
|
-
? raw
|
|
51
|
-
: raw && typeof raw === "object" && Array.isArray(raw.values)
|
|
52
|
-
? (raw.values)
|
|
53
|
-
: [];
|
|
54
|
-
normalized[collection] = new StringList({ values });
|
|
55
|
-
}
|
|
56
|
-
return normalized;
|
|
57
|
-
}
|
|
58
|
-
function codec(encodeParams, decodeResult) {
|
|
59
|
-
return { encodeParams, decodeResult };
|
|
60
|
-
}
|
|
61
|
-
const encodeEmpty = () => emptyBytes();
|
|
62
|
-
export const rpcProtobufCodecs = {
|
|
63
|
-
health: codec(encodeEmpty, (bytes) => decodeProtobufResult(HealthResponse, bytes)),
|
|
64
|
-
status: codec(encodeEmpty, (bytes) => decodeProtobufResult(MemoryStatusResponse, bytes)),
|
|
65
|
-
flush: codec(encodeEmpty, (bytes) => decodeProtobufResult(FlushResponse, bytes)),
|
|
66
|
-
session_lifecycle_hint: codec((params) => encodeMessage(SessionLifecycleHintRequest, params), (bytes) => decodeProtobufResult(SessionLifecycleHintResponse, bytes)),
|
|
67
|
-
search_text: codec((params) => encodeMessage(SearchTextRequest, params), normalizeSearchTextResponse),
|
|
68
|
-
search_text_collections: codec((params) => encodeMessage(SearchTextCollectionsRequest, {
|
|
69
|
-
collections: params.collections,
|
|
70
|
-
text: params.text,
|
|
71
|
-
k: params.k ?? 0,
|
|
72
|
-
excludeByCollection: normalizeExcludeByCollection(params.excludeByCollection),
|
|
73
|
-
}), normalizeSearchTextResponse),
|
|
74
|
-
list_collection: codec((params) => encodeMessage(ListCollectionRequest, params), normalizeSearchTextResponse),
|
|
75
|
-
list_lifecycle_journal: codec((params) => encodeMessage(ListLifecycleJournalRequest, params), normalizeSearchTextResponse),
|
|
76
|
-
export_memory: codec((params) => encodeMessage(ExportMemoryRequest, params), (bytes) => decodeProtobufResult(ExportMemoryResponse, bytes)),
|
|
77
|
-
flush_namespace: codec((params) => encodeMessage(FlushNamespaceRequest, params), (bytes) => decodeProtobufResult(FlushNamespaceResponse, bytes)),
|
|
78
|
-
promote_dream_entries: codec((params) => encodeMessage(PromoteDreamEntriesRequest, params), (bytes) => decodeProtobufResult(DreamPromotionResponse, bytes)),
|
|
79
|
-
ingest_markdown_document: codec((params) => encodeMessage(IngestMarkdownDocumentRequest, params), (bytes) => decodeProtobufResult(IngestMarkdownDocumentResponse, bytes)),
|
|
80
|
-
delete_authored_document: codec((params) => encodeMessage(DeleteAuthoredDocumentRequest, params), (bytes) => decodeProtobufResult(DeleteAuthoredDocumentResponse, bytes)),
|
|
81
|
-
bootstrap_session_kernel: codec((params) => encodeMessage(BootstrapSessionKernelRequest, params), (bytes) => decodeProtobufResult(BootstrapSessionKernelResponse, bytes)),
|
|
82
|
-
ingest_message_kernel: codec((params) => encodeMessage(IngestMessageKernelRequest, params), (bytes) => decodeProtobufResult(IngestMessageKernelResponse, bytes)),
|
|
83
|
-
after_turn_kernel: codec((params) => encodeMessage(AfterTurnKernelRequest, params), (bytes) => decodeProtobufResult(AfterTurnKernelResponse, bytes)),
|
|
84
|
-
assemble_context_internal: codec((params) => encodeMessage(AssembleContextInternalRequest, params), normalizeAssembleContextInternalResponse),
|
|
85
|
-
compact_session: codec((params) => encodeMessage(CompactSessionRequest, params), (bytes) => decodeProtobufResult(CompactSessionResponse, bytes)),
|
|
86
|
-
rank_candidates: codec((params) => encodeMessage(RankCandidatesRequest, params), (bytes) => decodeProtobufResult(RankCandidatesResponse, bytes)),
|
|
87
|
-
rebuild_index: codec((params) => encodeMessage(RebuildIndexRequest, params), (bytes) => decodeProtobufResult(RebuildIndexResponse, bytes)),
|
|
88
|
-
};
|
|
89
|
-
export function getRpcMethodCodec(method) {
|
|
90
|
-
return rpcProtobufCodecs[method];
|
|
91
|
-
}
|
package/dist/rpc.d.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import type { RpcCallOptions, SidecarSocket } from "./types.js";
|
|
2
|
-
export declare class RpcClient {
|
|
3
|
-
private readonly socket;
|
|
4
|
-
private readonly options;
|
|
5
|
-
private seq;
|
|
6
|
-
private readonly pending;
|
|
7
|
-
private rxBuf;
|
|
8
|
-
private sentMagic;
|
|
9
|
-
constructor(socket: SidecarSocket, options: RpcCallOptions);
|
|
10
|
-
call<T>(method: string, params: unknown, callOptions?: Partial<RpcCallOptions>): Promise<T>;
|
|
11
|
-
private waitForReconnect;
|
|
12
|
-
private handleData;
|
|
13
|
-
private dispatchMessage;
|
|
14
|
-
private rejectAll;
|
|
15
|
-
}
|
package/dist/rpc.js
DELETED
|
@@ -1,203 +0,0 @@
|
|
|
1
|
-
import { RpcRequest, RpcResponse } from "@xdarkicex/libravdb-contracts";
|
|
2
|
-
import { getRpcMethodCodec } from "./rpc-protobuf-codecs.js";
|
|
3
|
-
export class RpcClient {
|
|
4
|
-
socket;
|
|
5
|
-
options;
|
|
6
|
-
seq = 0n;
|
|
7
|
-
pending = new Map();
|
|
8
|
-
rxBuf = Buffer.alloc(0);
|
|
9
|
-
sentMagic = false;
|
|
10
|
-
constructor(socket, options) {
|
|
11
|
-
this.socket = socket;
|
|
12
|
-
this.options = options;
|
|
13
|
-
// Remove socket.setEncoding("utf8"); completely. The socket must stay binary.
|
|
14
|
-
socket.on("data", (chunk) => this.handleData(chunk));
|
|
15
|
-
socket.on("close", () => {
|
|
16
|
-
this.sentMagic = false; // Force magic byte on next reconnect
|
|
17
|
-
this.rejectAll(new Error("Socket closed"));
|
|
18
|
-
});
|
|
19
|
-
socket.on("error", (error) => this.rejectAll(error));
|
|
20
|
-
}
|
|
21
|
-
async call(method, params, callOptions = {}) {
|
|
22
|
-
const codec = getRpcMethodCodec(method);
|
|
23
|
-
if (!codec) {
|
|
24
|
-
throw new Error(`Unsupported LibraVDB RPC method for protobuf transport: ${method}`);
|
|
25
|
-
}
|
|
26
|
-
return await new Promise((resolve, reject) => {
|
|
27
|
-
const id = ++this.seq;
|
|
28
|
-
const timeoutMs = callOptions.timeoutMs ?? this.options.timeoutMs;
|
|
29
|
-
const deadline = Date.now() + timeoutMs;
|
|
30
|
-
const timer = setTimeout(() => {
|
|
31
|
-
this.pending.delete(id);
|
|
32
|
-
reject(new Error(`RPC timeout: ${method} (${timeoutMs}ms)`));
|
|
33
|
-
}, timeoutMs);
|
|
34
|
-
this.pending.set(id, { resolve, reject, timer, decodeResult: codec.decodeResult });
|
|
35
|
-
const buildFrame = () => {
|
|
36
|
-
const envelope = new RpcRequest({
|
|
37
|
-
id,
|
|
38
|
-
method,
|
|
39
|
-
params: codec.encodeParams(params),
|
|
40
|
-
});
|
|
41
|
-
const payload = Buffer.from(envelope.toBinary());
|
|
42
|
-
const header = Buffer.alloc(4);
|
|
43
|
-
header.writeUInt32BE(payload.byteLength, 0);
|
|
44
|
-
const chunks = [];
|
|
45
|
-
const includesMagic = !this.sentMagic;
|
|
46
|
-
if (includesMagic) {
|
|
47
|
-
chunks.push(Buffer.from([0x02]));
|
|
48
|
-
}
|
|
49
|
-
chunks.push(header, payload);
|
|
50
|
-
return { frame: Buffer.concat(chunks), includesMagic };
|
|
51
|
-
};
|
|
52
|
-
const send = (allowReconnectRetry) => {
|
|
53
|
-
if (!this.pending.has(id)) {
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
|
-
const { frame, includesMagic } = buildFrame();
|
|
57
|
-
try {
|
|
58
|
-
this.socket.write(frame);
|
|
59
|
-
if (includesMagic) {
|
|
60
|
-
this.sentMagic = true;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
catch (error) {
|
|
64
|
-
if (allowReconnectRetry && isReconnectableSocketGap(error)) {
|
|
65
|
-
this.sentMagic = false;
|
|
66
|
-
const remainingMs = Math.max(0, deadline - Date.now());
|
|
67
|
-
if (remainingMs <= 0) {
|
|
68
|
-
if (!this.pending.has(id)) {
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
clearTimeout(timer);
|
|
72
|
-
this.pending.delete(id);
|
|
73
|
-
reject(new Error(`RPC timeout: ${method} (${timeoutMs}ms)`));
|
|
74
|
-
return;
|
|
75
|
-
}
|
|
76
|
-
void this.waitForReconnect(remainingMs)
|
|
77
|
-
.then(() => {
|
|
78
|
-
if (!this.pending.has(id)) {
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
send(false);
|
|
82
|
-
})
|
|
83
|
-
.catch((reconnectError) => {
|
|
84
|
-
if (!this.pending.has(id)) {
|
|
85
|
-
return;
|
|
86
|
-
}
|
|
87
|
-
clearTimeout(timer);
|
|
88
|
-
this.pending.delete(id);
|
|
89
|
-
const error = reconnectError instanceof Error
|
|
90
|
-
? reconnectError
|
|
91
|
-
: new Error(String(reconnectError));
|
|
92
|
-
reject(/^Sidecar reconnect timed out/.test(error.message)
|
|
93
|
-
? new Error(`RPC timeout: ${method} (${timeoutMs}ms)`)
|
|
94
|
-
: error);
|
|
95
|
-
});
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
clearTimeout(timer);
|
|
99
|
-
this.pending.delete(id);
|
|
100
|
-
reject(error instanceof Error ? error : new Error(String(error)));
|
|
101
|
-
}
|
|
102
|
-
};
|
|
103
|
-
send(true);
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
async waitForReconnect(timeoutMs) {
|
|
107
|
-
await new Promise((resolve, reject) => {
|
|
108
|
-
let settled = false;
|
|
109
|
-
const onConnect = () => {
|
|
110
|
-
if (settled)
|
|
111
|
-
return;
|
|
112
|
-
settled = true;
|
|
113
|
-
clearTimeout(timer);
|
|
114
|
-
this.socket.off("error", onError);
|
|
115
|
-
resolve();
|
|
116
|
-
};
|
|
117
|
-
const onError = (error) => {
|
|
118
|
-
if (settled)
|
|
119
|
-
return;
|
|
120
|
-
settled = true;
|
|
121
|
-
clearTimeout(timer);
|
|
122
|
-
this.socket.off("connect", onConnect);
|
|
123
|
-
reject(error);
|
|
124
|
-
};
|
|
125
|
-
const timer = setTimeout(() => {
|
|
126
|
-
if (settled)
|
|
127
|
-
return;
|
|
128
|
-
settled = true;
|
|
129
|
-
this.socket.off("connect", onConnect);
|
|
130
|
-
this.socket.off("error", onError);
|
|
131
|
-
reject(new Error(`Sidecar reconnect timed out (${timeoutMs}ms)`));
|
|
132
|
-
}, timeoutMs);
|
|
133
|
-
this.socket.once("connect", onConnect);
|
|
134
|
-
this.socket.once("error", onError);
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
|
-
handleData(chunk) {
|
|
138
|
-
if (chunk.byteLength > 64 << 20) {
|
|
139
|
-
this.socket.destroy();
|
|
140
|
-
return;
|
|
141
|
-
}
|
|
142
|
-
this.rxBuf = Buffer.concat([this.rxBuf, chunk]);
|
|
143
|
-
while (this.rxBuf.byteLength >= 4) {
|
|
144
|
-
const payloadLength = this.rxBuf.readUInt32BE(0);
|
|
145
|
-
if (payloadLength > 64 << 20) {
|
|
146
|
-
this.socket.destroy();
|
|
147
|
-
return;
|
|
148
|
-
}
|
|
149
|
-
const frameSize = 4 + payloadLength;
|
|
150
|
-
// Wait for the full frame to arrive
|
|
151
|
-
if (this.rxBuf.byteLength < frameSize) {
|
|
152
|
-
break;
|
|
153
|
-
}
|
|
154
|
-
const payload = this.rxBuf.subarray(4, frameSize);
|
|
155
|
-
this.rxBuf = this.rxBuf.subarray(frameSize);
|
|
156
|
-
this.dispatchMessage(payload);
|
|
157
|
-
}
|
|
158
|
-
// Compaction guard: release large backing allocations if the remainder is tiny
|
|
159
|
-
if (this.rxBuf.buffer.byteLength > 65536 &&
|
|
160
|
-
this.rxBuf.byteLength < this.rxBuf.buffer.byteLength >>> 2) {
|
|
161
|
-
this.rxBuf = Buffer.from(this.rxBuf);
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
dispatchMessage(payload) {
|
|
165
|
-
try {
|
|
166
|
-
const msg = RpcResponse.fromBinary(payload);
|
|
167
|
-
if (typeof msg.id !== "bigint") {
|
|
168
|
-
this.socket.destroy(new Error("Protocol violation: expected bigint message id"));
|
|
169
|
-
return;
|
|
170
|
-
}
|
|
171
|
-
const pending = this.pending.get(msg.id);
|
|
172
|
-
if (!pending) {
|
|
173
|
-
return;
|
|
174
|
-
}
|
|
175
|
-
clearTimeout(pending.timer);
|
|
176
|
-
this.pending.delete(msg.id);
|
|
177
|
-
if (msg.error) {
|
|
178
|
-
const message = msg.error.message?.trim() || `RPC error ${msg.error.code}`;
|
|
179
|
-
pending.reject(new Error(msg.error.code ? `${message} (${msg.error.code})` : message));
|
|
180
|
-
return;
|
|
181
|
-
}
|
|
182
|
-
try {
|
|
183
|
-
pending.resolve(pending.decodeResult(msg.result));
|
|
184
|
-
}
|
|
185
|
-
catch (error) {
|
|
186
|
-
pending.reject(error instanceof Error ? error : new Error(String(error)));
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
catch {
|
|
190
|
-
// Ignore malformed frames
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
rejectAll(error) {
|
|
194
|
-
for (const [id, pending] of this.pending.entries()) {
|
|
195
|
-
clearTimeout(pending.timer);
|
|
196
|
-
this.pending.delete(id);
|
|
197
|
-
pending.reject(error);
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
function isReconnectableSocketGap(error) {
|
|
202
|
-
return error instanceof Error && /Sidecar socket unavailable/i.test(error.message);
|
|
203
|
-
}
|
package/dist/sidecar.d.ts
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import type { LoggerLike, PluginConfig, SidecarHandle, SidecarSocket } from "./types.js";
|
|
2
|
-
type CloseHandler = () => void;
|
|
3
|
-
type DataHandler = (chunk: Buffer) => void;
|
|
4
|
-
type ErrorHandler = (error: Error) => void;
|
|
5
|
-
export interface SidecarRuntime {
|
|
6
|
-
resolveEndpoint(cfg: PluginConfig): string | Promise<string>;
|
|
7
|
-
createSocket(endpoint: string): SidecarSocket;
|
|
8
|
-
scheduleRestart(delayMs: number, restart: () => void): void;
|
|
9
|
-
stabilityWindowMs?: number;
|
|
10
|
-
}
|
|
11
|
-
declare class PlaceholderSocket implements SidecarSocket {
|
|
12
|
-
private readonly onData;
|
|
13
|
-
private readonly onClose;
|
|
14
|
-
private readonly onError;
|
|
15
|
-
private readonly connectOnce;
|
|
16
|
-
private readonly errorOnce;
|
|
17
|
-
constructor();
|
|
18
|
-
setEncoding(_encoding: string): void;
|
|
19
|
-
on(event: "data" | "close" | "error", handler: DataHandler | CloseHandler | ErrorHandler): void;
|
|
20
|
-
once(event: "connect" | "error", handler: CloseHandler | ErrorHandler): void;
|
|
21
|
-
off(event: "connect" | "error", handler: CloseHandler | ErrorHandler): void;
|
|
22
|
-
write(chunk: Buffer | string): void;
|
|
23
|
-
destroy(): void;
|
|
24
|
-
private emitError;
|
|
25
|
-
}
|
|
26
|
-
export declare function startSidecar(cfg: PluginConfig, logger?: LoggerLike, runtime?: SidecarRuntime): Promise<SidecarHandle>;
|
|
27
|
-
export declare function computeBackoffMs(retries: number): number;
|
|
28
|
-
export declare function computeStartupConnectRetryDelay(attempt: number, waitedMs?: number): number;
|
|
29
|
-
export declare function isTcpEndpoint(endpoint: string): boolean;
|
|
30
|
-
export declare function parseTcpEndpoint(endpoint: string): {
|
|
31
|
-
host: string;
|
|
32
|
-
port: number;
|
|
33
|
-
} | null;
|
|
34
|
-
export declare function resolveEndpoint(cfg: PluginConfig): string;
|
|
35
|
-
export declare function resolveConfiguredEndpoint(cfg: PluginConfig): string;
|
|
36
|
-
export declare function daemonProvisioningHint(): string;
|
|
37
|
-
export declare function defaultEndpoint(platform?: NodeJS.Platform, homeDir?: string, pathExists?: (path: string) => boolean): string;
|
|
38
|
-
export declare function buildSidecarEnv(cfg: PluginConfig): Record<string, string>;
|
|
39
|
-
export { PlaceholderSocket };
|
|
40
|
-
export declare function probeSidecarEndpoint(cfg: PluginConfig): Promise<string | null>;
|