kongbrain 0.1.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.
@@ -0,0 +1,77 @@
1
+ import { existsSync } from "node:fs";
2
+ import type { EmbeddingConfig } from "./config.js";
3
+ import { swallow } from "./errors.js";
4
+
5
+ // Lazy-import node-llama-cpp to avoid top-level await issues with jiti.
6
+ // The actual import happens inside initialize() at runtime.
7
+ type LlamaEmbeddingContext = import("node-llama-cpp").LlamaEmbeddingContext;
8
+ type LlamaModel = import("node-llama-cpp").LlamaModel;
9
+
10
+ export class EmbeddingService {
11
+ private model: LlamaModel | null = null;
12
+ private ctx: LlamaEmbeddingContext | null = null;
13
+ private ready = false;
14
+ private embedCallCount = 0;
15
+
16
+ constructor(private readonly config: EmbeddingConfig) {}
17
+
18
+ async initialize(): Promise<void> {
19
+ if (!existsSync(this.config.modelPath)) {
20
+ throw new Error(
21
+ `Embedding model not found at: ${this.config.modelPath}\n Download BGE-M3 GGUF or set EMBED_MODEL_PATH`,
22
+ );
23
+ }
24
+ const { getLlama, LlamaLogLevel } = await import("node-llama-cpp");
25
+ const llama = await getLlama({
26
+ logLevel: LlamaLogLevel.error,
27
+ logger: (level, message) => {
28
+ if (message.includes("missing newline token")) return;
29
+ if (level === LlamaLogLevel.error) console.error(`[llama] ${message}`);
30
+ else if (level === LlamaLogLevel.warn) console.warn(`[llama] ${message}`);
31
+ },
32
+ });
33
+ this.model = await llama.loadModel({ modelPath: this.config.modelPath });
34
+ this.ctx = await this.model.createEmbeddingContext();
35
+ this.ready = true;
36
+ }
37
+
38
+ async embed(text: string): Promise<number[]> {
39
+ if (!this.ready || !this.ctx) throw new Error("Embeddings not initialized");
40
+ this.embedCallCount++;
41
+ const result = await this.ctx.getEmbeddingFor(text);
42
+ return Array.from(result.vector);
43
+ }
44
+
45
+ async embedBatch(texts: string[]): Promise<number[][]> {
46
+ if (texts.length === 0) return [];
47
+ const results: number[][] = [];
48
+ for (const text of texts) {
49
+ results.push(await this.embed(text));
50
+ }
51
+ return results;
52
+ }
53
+
54
+ isAvailable(): boolean {
55
+ return this.ready;
56
+ }
57
+
58
+ drainEmbedCallCount(): number {
59
+ const count = this.embedCallCount;
60
+ this.embedCallCount = 0;
61
+ return count;
62
+ }
63
+
64
+ getEmbedCallCount(): number {
65
+ return this.embedCallCount;
66
+ }
67
+
68
+ async dispose(): Promise<void> {
69
+ try {
70
+ await this.ctx?.dispose();
71
+ await this.model?.dispose();
72
+ this.ready = false;
73
+ } catch (e) {
74
+ swallow("embeddings:dispose", e);
75
+ }
76
+ }
77
+ }
package/src/errors.ts ADDED
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Lightweight error swallowing with severity levels.
3
+ *
4
+ * - swallow(ctx, e) — SILENT: expected degradation (embeddings offline, non-critical telemetry).
5
+ * Only visible with KONGBRAIN_DEBUG=1.
6
+ * - swallow.warn(ctx, e) — WARN: unexpected but recoverable (DB query failure, compaction failure).
7
+ * Always logged to stderr.
8
+ * - swallow.error(ctx, e) — ERROR: something is genuinely broken (cleanup failure, schema failure).
9
+ * Always logged to stderr with stack trace.
10
+ */
11
+
12
+ const DEBUG = process.env.KONGBRAIN_DEBUG === "1";
13
+
14
+ /**
15
+ * Swallow an error silently. Only visible with KONGBRAIN_DEBUG=1.
16
+ * Use for expected degradation (embeddings down, non-critical graph edges).
17
+ */
18
+ function swallow(context: string, err?: unknown): void {
19
+ if (!DEBUG) return;
20
+ const msg = err instanceof Error ? err.message : String(err ?? "unknown");
21
+ console.debug(`[swallow] ${context}: ${msg}`);
22
+ }
23
+
24
+ /**
25
+ * Swallow an error but log a warning. Always visible.
26
+ * Use for unexpected-but-recoverable issues (DB failures, compaction failures).
27
+ */
28
+ swallow.warn = function swallowWarn(context: string, err?: unknown): void {
29
+ const msg = err instanceof Error ? err.message : String(err ?? "unknown");
30
+ console.warn(`[warn] ${context}: ${msg}`);
31
+ };
32
+
33
+ /**
34
+ * Swallow an error but log an error. Always visible, includes stack.
35
+ * Use for genuinely broken things (cleanup failure, schema failure).
36
+ */
37
+ swallow.error = function swallowError(context: string, err?: unknown): void {
38
+ const msg = err instanceof Error ? err.message : String(err ?? "unknown");
39
+ const stack = err instanceof Error ? `\n${err.stack}` : "";
40
+ console.error(`[ERROR] ${context}: ${msg}${stack}`);
41
+ };
42
+
43
+ export { swallow };