bikky 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.
Files changed (124) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +323 -0
  3. package/bin/bikky.js +6 -0
  4. package/dist/cli.d.ts +12 -0
  5. package/dist/cli.d.ts.map +1 -0
  6. package/dist/cli.js +51 -0
  7. package/dist/cli.js.map +1 -0
  8. package/dist/config.d.ts +59 -0
  9. package/dist/config.d.ts.map +1 -0
  10. package/dist/config.js +141 -0
  11. package/dist/config.js.map +1 -0
  12. package/dist/config.test.d.ts +8 -0
  13. package/dist/config.test.d.ts.map +1 -0
  14. package/dist/config.test.js +449 -0
  15. package/dist/config.test.js.map +1 -0
  16. package/dist/daemon/consolidation.d.ts +60 -0
  17. package/dist/daemon/consolidation.d.ts.map +1 -0
  18. package/dist/daemon/consolidation.js +448 -0
  19. package/dist/daemon/consolidation.js.map +1 -0
  20. package/dist/daemon/extraction.d.ts +17 -0
  21. package/dist/daemon/extraction.d.ts.map +1 -0
  22. package/dist/daemon/extraction.js +465 -0
  23. package/dist/daemon/extraction.js.map +1 -0
  24. package/dist/daemon/index.d.ts +3 -0
  25. package/dist/daemon/index.d.ts.map +1 -0
  26. package/dist/daemon/index.js +3 -0
  27. package/dist/daemon/index.js.map +1 -0
  28. package/dist/daemon/loop.d.ts +3 -0
  29. package/dist/daemon/loop.d.ts.map +1 -0
  30. package/dist/daemon/loop.js +93 -0
  31. package/dist/daemon/loop.js.map +1 -0
  32. package/dist/daemon/qdrant.d.ts +103 -0
  33. package/dist/daemon/qdrant.d.ts.map +1 -0
  34. package/dist/daemon/qdrant.js +273 -0
  35. package/dist/daemon/qdrant.js.map +1 -0
  36. package/dist/daemon/qdrant.test.d.ts +8 -0
  37. package/dist/daemon/qdrant.test.d.ts.map +1 -0
  38. package/dist/daemon/qdrant.test.js +209 -0
  39. package/dist/daemon/qdrant.test.js.map +1 -0
  40. package/dist/daemon/relations.d.ts +54 -0
  41. package/dist/daemon/relations.d.ts.map +1 -0
  42. package/dist/daemon/relations.js +290 -0
  43. package/dist/daemon/relations.js.map +1 -0
  44. package/dist/daemon/staleness.d.ts +24 -0
  45. package/dist/daemon/staleness.d.ts.map +1 -0
  46. package/dist/daemon/staleness.js +63 -0
  47. package/dist/daemon/staleness.js.map +1 -0
  48. package/dist/daemon/watcher.d.ts +11 -0
  49. package/dist/daemon/watcher.d.ts.map +1 -0
  50. package/dist/daemon/watcher.js +38 -0
  51. package/dist/daemon/watcher.js.map +1 -0
  52. package/dist/daemon/watcher.test.d.ts +8 -0
  53. package/dist/daemon/watcher.test.d.ts.map +1 -0
  54. package/dist/daemon/watcher.test.js +214 -0
  55. package/dist/daemon/watcher.test.js.map +1 -0
  56. package/dist/install.d.ts +5 -0
  57. package/dist/install.d.ts.map +1 -0
  58. package/dist/install.js +49 -0
  59. package/dist/install.js.map +1 -0
  60. package/dist/install.test.d.ts +9 -0
  61. package/dist/install.test.d.ts.map +1 -0
  62. package/dist/install.test.js +126 -0
  63. package/dist/install.test.js.map +1 -0
  64. package/dist/llm/embedding.d.ts +13 -0
  65. package/dist/llm/embedding.d.ts.map +1 -0
  66. package/dist/llm/embedding.js +127 -0
  67. package/dist/llm/embedding.js.map +1 -0
  68. package/dist/llm/embedding.test.d.ts +8 -0
  69. package/dist/llm/embedding.test.d.ts.map +1 -0
  70. package/dist/llm/embedding.test.js +117 -0
  71. package/dist/llm/embedding.test.js.map +1 -0
  72. package/dist/llm/index.d.ts +4 -0
  73. package/dist/llm/index.d.ts.map +1 -0
  74. package/dist/llm/index.js +3 -0
  75. package/dist/llm/index.js.map +1 -0
  76. package/dist/llm/inference.d.ts +12 -0
  77. package/dist/llm/inference.d.ts.map +1 -0
  78. package/dist/llm/inference.js +146 -0
  79. package/dist/llm/inference.js.map +1 -0
  80. package/dist/llm/inference.test.d.ts +8 -0
  81. package/dist/llm/inference.test.d.ts.map +1 -0
  82. package/dist/llm/inference.test.js +117 -0
  83. package/dist/llm/inference.test.js.map +1 -0
  84. package/dist/llm/types.d.ts +41 -0
  85. package/dist/llm/types.d.ts.map +1 -0
  86. package/dist/llm/types.js +5 -0
  87. package/dist/llm/types.js.map +1 -0
  88. package/dist/logger.d.ts +13 -0
  89. package/dist/logger.d.ts.map +1 -0
  90. package/dist/logger.js +41 -0
  91. package/dist/logger.js.map +1 -0
  92. package/dist/mcp/api.d.ts +30 -0
  93. package/dist/mcp/api.d.ts.map +1 -0
  94. package/dist/mcp/api.js +150 -0
  95. package/dist/mcp/api.js.map +1 -0
  96. package/dist/mcp/helpers.d.ts +35 -0
  97. package/dist/mcp/helpers.d.ts.map +1 -0
  98. package/dist/mcp/helpers.js +152 -0
  99. package/dist/mcp/helpers.js.map +1 -0
  100. package/dist/mcp/helpers.test.d.ts +5 -0
  101. package/dist/mcp/helpers.test.d.ts.map +1 -0
  102. package/dist/mcp/helpers.test.js +487 -0
  103. package/dist/mcp/helpers.test.js.map +1 -0
  104. package/dist/mcp/index.d.ts +9 -0
  105. package/dist/mcp/index.d.ts.map +1 -0
  106. package/dist/mcp/index.js +67 -0
  107. package/dist/mcp/index.js.map +1 -0
  108. package/dist/mcp/taxonomy.d.ts +38 -0
  109. package/dist/mcp/taxonomy.d.ts.map +1 -0
  110. package/dist/mcp/taxonomy.js +223 -0
  111. package/dist/mcp/taxonomy.js.map +1 -0
  112. package/dist/mcp/taxonomy.test.d.ts +5 -0
  113. package/dist/mcp/taxonomy.test.d.ts.map +1 -0
  114. package/dist/mcp/taxonomy.test.js +341 -0
  115. package/dist/mcp/taxonomy.test.js.map +1 -0
  116. package/dist/mcp/tools.d.ts +6 -0
  117. package/dist/mcp/tools.d.ts.map +1 -0
  118. package/dist/mcp/tools.js +958 -0
  119. package/dist/mcp/tools.js.map +1 -0
  120. package/dist/mcp/types.d.ts +118 -0
  121. package/dist/mcp/types.d.ts.map +1 -0
  122. package/dist/mcp/types.js +5 -0
  123. package/dist/mcp/types.js.map +1 -0
  124. package/package.json +56 -0
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Qdrant client for the bikky daemon — direct HTTP access to Qdrant Cloud.
3
+ * Embedding is handled by ../llm/embedding.ts (config-driven provider abstraction).
4
+ *
5
+ * Credentials: config file (~/.bikky/config.json) → env vars.
6
+ */
7
+ import { embed } from "../llm/index.js";
8
+ import type { EmbeddingProviderConfig } from "../llm/index.js";
9
+ export type LogFn = (level: string, ...args: unknown[]) => void;
10
+ export interface QdrantPayload {
11
+ content: string;
12
+ category: string;
13
+ domain: string;
14
+ kind: string;
15
+ entities: string[];
16
+ source: string;
17
+ confidence: number;
18
+ importance: number;
19
+ content_hash: string;
20
+ reinforcement_count: number;
21
+ last_reinforced_at: string;
22
+ superseded_by: string | null;
23
+ superseded_at: string | null;
24
+ created_at: string;
25
+ updated_at: string;
26
+ metadata: Record<string, string>;
27
+ from_entity?: string;
28
+ relation_type?: string;
29
+ to_entity?: string;
30
+ }
31
+ export interface StoreFact {
32
+ content: string;
33
+ category: string;
34
+ domain?: string;
35
+ kind?: string;
36
+ entities: string[];
37
+ source?: string;
38
+ confidence?: number;
39
+ importance?: number;
40
+ content_hash: string;
41
+ metadata?: Record<string, string>;
42
+ relation?: {
43
+ from: string;
44
+ type: string;
45
+ to: string;
46
+ } | null;
47
+ }
48
+ export interface QdrantSearchResult {
49
+ id: string;
50
+ score: number;
51
+ content: string;
52
+ category: string;
53
+ entities: string[];
54
+ confidence: number;
55
+ last_reinforced_at: string;
56
+ created_at: string;
57
+ }
58
+ export interface QdrantScrollResult {
59
+ id: string;
60
+ content: string;
61
+ category: string;
62
+ entities: string[];
63
+ confidence: number;
64
+ last_reinforced_at: string;
65
+ created_at: string;
66
+ }
67
+ export interface QdrantSearchFilters {
68
+ category?: string;
69
+ entity?: string;
70
+ since?: string;
71
+ domain?: string;
72
+ source?: string;
73
+ }
74
+ export interface QdrantScrollFilters {
75
+ categories?: string[];
76
+ olderThan?: string;
77
+ domain?: string;
78
+ }
79
+ export type DedupAction = "insert" | "skip" | "supersede";
80
+ export interface DedupResult {
81
+ action: DedupAction;
82
+ existingId?: string;
83
+ existingCount?: number;
84
+ score?: number;
85
+ }
86
+ export interface DedupThresholds {
87
+ exactThreshold?: number;
88
+ supersedeThreshold?: number;
89
+ }
90
+ declare let collection: string;
91
+ declare const setLogger: (fn: LogFn) => void;
92
+ declare const setEmbeddingConfig: (overrides?: Partial<EmbeddingProviderConfig>) => void;
93
+ declare const init: () => boolean;
94
+ declare const isReady: () => boolean;
95
+ declare const qdrantRequest: (method: string, urlPath: string, body?: unknown) => Promise<Record<string, unknown>>;
96
+ declare const searchFacts: (query: string, filters?: QdrantSearchFilters, limit?: number) => Promise<QdrantSearchResult[]>;
97
+ declare const scrollFacts: (filters?: QdrantScrollFilters, limit?: number) => Promise<QdrantScrollResult[]>;
98
+ declare const storeFact: (fact: StoreFact) => Promise<string>;
99
+ declare const supersedeFact: (oldFactId: string, newFactId: string) => Promise<void>;
100
+ declare const reinforceFact: (factId: string, currentCount: number) => Promise<void>;
101
+ declare const dedupCheck: (content: string, contentHashVal: string, { exactThreshold, supersedeThreshold }?: DedupThresholds) => Promise<DedupResult>;
102
+ export { init, isReady, setLogger, setEmbeddingConfig, qdrantRequest, embed, searchFacts, scrollFacts, storeFact, supersedeFact, reinforceFact, dedupCheck, collection, };
103
+ //# sourceMappingURL=qdrant.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"qdrant.d.ts","sourceRoot":"","sources":["../../src/daemon/qdrant.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,273 @@
1
+ /**
2
+ * Qdrant client for the bikky daemon — direct HTTP access to Qdrant Cloud.
3
+ * Embedding is handled by ../llm/embedding.ts (config-driven provider abstraction).
4
+ *
5
+ * Credentials: config file (~/.bikky/config.json) → env vars.
6
+ */
7
+ import { randomUUID } from "node:crypto";
8
+ import { loadConfig } from "../config.js";
9
+ import { embed, initEmbedding } from "../llm/index.js";
10
+ // ---------------------------------------------------------------------------
11
+ // State
12
+ // ---------------------------------------------------------------------------
13
+ let qdrantUrl = null;
14
+ let qdrantApiKey = null;
15
+ let collection = "bikky";
16
+ let logFn = () => { };
17
+ const setLogger = (fn) => { logFn = fn; };
18
+ const setEmbeddingConfig = (overrides) => {
19
+ if (overrides)
20
+ initEmbedding(overrides);
21
+ };
22
+ // ---------------------------------------------------------------------------
23
+ // Init — reads credentials from loadConfig()
24
+ // ---------------------------------------------------------------------------
25
+ const init = () => {
26
+ const cfg = loadConfig();
27
+ qdrantUrl = cfg.qdrant_url;
28
+ qdrantApiKey = cfg.qdrant_api_key;
29
+ collection = cfg.collection || "bikky";
30
+ if (qdrantUrl)
31
+ qdrantUrl = qdrantUrl.replace(/\/+$/, "");
32
+ // Initialize embedding provider from config
33
+ const embCfg = initEmbedding({
34
+ provider: cfg.embedding.provider,
35
+ baseUrl: cfg.embedding.base_url,
36
+ model: cfg.embedding.model,
37
+ dimensions: cfg.embedding.dimensions,
38
+ apiKey: cfg.embedding.api_key,
39
+ });
40
+ logFn("INFO", `Embedding provider: ${embCfg.provider}/${embCfg.model} (${embCfg.dimensions}d) @ ${embCfg.baseUrl}`);
41
+ const ready = !!(qdrantUrl && qdrantApiKey);
42
+ if (!ready) {
43
+ logFn("WARN", "Qdrant client: missing credentials (some memory features disabled)");
44
+ }
45
+ return ready;
46
+ };
47
+ const isReady = () => !!(qdrantUrl && qdrantApiKey);
48
+ // ---------------------------------------------------------------------------
49
+ // HTTP requests
50
+ // ---------------------------------------------------------------------------
51
+ const qdrantRequest = async (method, urlPath, body) => {
52
+ const url = `${qdrantUrl}${urlPath}`;
53
+ const opts = {
54
+ method,
55
+ headers: {
56
+ "Content-Type": "application/json",
57
+ "api-key": qdrantApiKey,
58
+ },
59
+ };
60
+ if (body)
61
+ opts.body = JSON.stringify(body);
62
+ const resp = await fetch(url, opts);
63
+ if (!resp.ok) {
64
+ const text = await resp.text().catch(() => "");
65
+ throw new Error(`Qdrant ${method} ${urlPath} failed (${resp.status}): ${text.slice(0, 200)}`);
66
+ }
67
+ return resp.json();
68
+ };
69
+ // ---------------------------------------------------------------------------
70
+ // Read methods
71
+ // ---------------------------------------------------------------------------
72
+ const searchFacts = async (query, filters = {}, limit = 10) => {
73
+ const vector = await embed(query);
74
+ const must = [
75
+ { is_null: { key: "superseded_by" } },
76
+ ];
77
+ if (filters.category) {
78
+ must.push({ key: "category", match: { value: filters.category } });
79
+ }
80
+ if (filters.entity) {
81
+ must.push({ key: "entities", match: { value: filters.entity } });
82
+ }
83
+ if (filters.since) {
84
+ must.push({ key: "created_at", range: { gte: filters.since } });
85
+ }
86
+ if (filters.domain) {
87
+ must.push({ key: "domain", match: { value: filters.domain } });
88
+ }
89
+ if (filters.source) {
90
+ must.push({ key: "source", match: { value: filters.source } });
91
+ }
92
+ const result = await qdrantRequest("POST", `/collections/${collection}/points/search`, {
93
+ vector,
94
+ filter: { must },
95
+ limit,
96
+ with_payload: true,
97
+ });
98
+ return (result.result || []).map((hit) => ({
99
+ id: hit.id,
100
+ score: hit.score,
101
+ content: hit.payload?.content ?? "",
102
+ category: hit.payload?.category ?? "",
103
+ entities: hit.payload?.entities || [],
104
+ confidence: hit.payload?.confidence ?? 0,
105
+ last_reinforced_at: hit.payload?.last_reinforced_at ?? "",
106
+ created_at: hit.payload?.created_at ?? "",
107
+ }));
108
+ };
109
+ const scrollFacts = async (filters = {}, limit = 10) => {
110
+ const must = [
111
+ { is_null: { key: "superseded_by" } },
112
+ ];
113
+ if (filters.categories && filters.categories.length > 0) {
114
+ must.push({
115
+ key: "category",
116
+ match: { any: filters.categories },
117
+ });
118
+ }
119
+ if (filters.olderThan) {
120
+ must.push({
121
+ key: "last_reinforced_at",
122
+ range: { lt: filters.olderThan },
123
+ });
124
+ }
125
+ if (filters.domain) {
126
+ must.push({ key: "domain", match: { value: filters.domain } });
127
+ }
128
+ const result = await qdrantRequest("POST", `/collections/${collection}/points/scroll`, {
129
+ filter: { must },
130
+ limit,
131
+ with_payload: true,
132
+ });
133
+ return (result.result?.points || []).map((pt) => ({
134
+ id: pt.id,
135
+ content: pt.payload?.content ?? "",
136
+ category: pt.payload?.category ?? "",
137
+ entities: pt.payload?.entities || [],
138
+ confidence: pt.payload?.confidence ?? 0,
139
+ last_reinforced_at: pt.payload?.last_reinforced_at ?? "",
140
+ created_at: pt.payload?.created_at ?? "",
141
+ }));
142
+ };
143
+ // ---------------------------------------------------------------------------
144
+ // Write methods
145
+ // ---------------------------------------------------------------------------
146
+ const storeFact = async (fact) => {
147
+ const vector = await embed(fact.content);
148
+ const now = new Date().toISOString();
149
+ const id = randomUUID();
150
+ const payload = {
151
+ content: fact.content,
152
+ category: fact.category,
153
+ domain: fact.domain || "work",
154
+ kind: fact.kind || "fact",
155
+ entities: fact.entities || [],
156
+ source: fact.source || "daemon",
157
+ confidence: fact.confidence ?? 0.7,
158
+ importance: fact.importance ?? 0.5,
159
+ content_hash: fact.content_hash,
160
+ reinforcement_count: 1,
161
+ last_reinforced_at: now,
162
+ superseded_by: null,
163
+ superseded_at: null,
164
+ created_at: now,
165
+ updated_at: now,
166
+ metadata: fact.metadata || {},
167
+ };
168
+ // Add relation fields if present
169
+ if (fact.relation) {
170
+ payload.from_entity = fact.relation.from;
171
+ payload.relation_type = fact.relation.type;
172
+ payload.to_entity = fact.relation.to;
173
+ }
174
+ await qdrantRequest("PUT", `/collections/${collection}/points`, {
175
+ points: [{ id, vector, payload }],
176
+ });
177
+ logFn("DEBUG", `Qdrant: stored fact ${id} [${fact.category}] ${fact.content.slice(0, 60)}`);
178
+ return id;
179
+ };
180
+ const supersedeFact = async (oldFactId, newFactId) => {
181
+ const now = new Date().toISOString();
182
+ await qdrantRequest("POST", `/collections/${collection}/points/payload`, {
183
+ payload: {
184
+ superseded_by: newFactId,
185
+ superseded_at: now,
186
+ updated_at: now,
187
+ },
188
+ points: [oldFactId],
189
+ });
190
+ logFn("DEBUG", `Qdrant: superseded fact ${oldFactId} → ${newFactId}`);
191
+ };
192
+ const reinforceFact = async (factId, currentCount) => {
193
+ const now = new Date().toISOString();
194
+ await qdrantRequest("POST", `/collections/${collection}/points/payload`, {
195
+ payload: {
196
+ reinforcement_count: (currentCount || 1) + 1,
197
+ last_reinforced_at: now,
198
+ updated_at: now,
199
+ },
200
+ points: [factId],
201
+ });
202
+ logFn("DEBUG", `Qdrant: reinforced fact ${factId}`);
203
+ };
204
+ const dedupCheck = async (content, contentHashVal, { exactThreshold = 0.92, supersedeThreshold = 0.80 } = {}) => {
205
+ // First: hash-based exact check (fast, no embedding)
206
+ try {
207
+ const hashResult = await qdrantRequest("POST", `/collections/${collection}/points/scroll`, {
208
+ filter: {
209
+ must: [
210
+ { key: "content_hash", match: { value: contentHashVal } },
211
+ { is_null: { key: "superseded_by" } },
212
+ ],
213
+ },
214
+ limit: 1,
215
+ with_payload: true,
216
+ });
217
+ const existing = hashResult.result?.points?.[0];
218
+ if (existing) {
219
+ return {
220
+ action: "skip",
221
+ existingId: existing.id,
222
+ existingCount: existing.payload?.reinforcement_count || 1,
223
+ score: 1.0,
224
+ };
225
+ }
226
+ }
227
+ catch (e) {
228
+ const msg = e instanceof Error ? e.message : String(e);
229
+ logFn("WARN", `Qdrant dedup hash check failed: ${msg}`);
230
+ }
231
+ // Second: vector similarity check
232
+ try {
233
+ const vector = await embed(content);
234
+ const searchResult = await qdrantRequest("POST", `/collections/${collection}/points/search`, {
235
+ vector,
236
+ filter: {
237
+ must: [{ is_null: { key: "superseded_by" } }],
238
+ },
239
+ limit: 1,
240
+ with_payload: true,
241
+ });
242
+ const top = searchResult.result?.[0];
243
+ if (!top)
244
+ return { action: "insert" };
245
+ if (top.score >= exactThreshold) {
246
+ return {
247
+ action: "skip",
248
+ existingId: top.id,
249
+ existingCount: top.payload?.reinforcement_count || 1,
250
+ score: top.score,
251
+ };
252
+ }
253
+ if (top.score >= supersedeThreshold) {
254
+ return {
255
+ action: "supersede",
256
+ existingId: top.id,
257
+ existingCount: top.payload?.reinforcement_count || 1,
258
+ score: top.score,
259
+ };
260
+ }
261
+ return { action: "insert" };
262
+ }
263
+ catch (e) {
264
+ const msg = e instanceof Error ? e.message : String(e);
265
+ logFn("WARN", `Qdrant dedup vector check failed: ${msg}`);
266
+ return { action: "insert" }; // fail open — better to duplicate than lose
267
+ }
268
+ };
269
+ // ---------------------------------------------------------------------------
270
+ // Exports
271
+ // ---------------------------------------------------------------------------
272
+ export { init, isReady, setLogger, setEmbeddingConfig, qdrantRequest, embed, searchFacts, scrollFacts, storeFact, supersedeFact, reinforceFact, dedupCheck, collection, };
273
+ //# sourceMappingURL=qdrant.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"qdrant.js","sourceRoot":"","sources":["../../src/daemon/qdrant.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Tests for the daemon Qdrant client — unit tests only.
3
+ *
4
+ * These test initialization and validation logic without making
5
+ * actual HTTP calls to Qdrant.
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=qdrant.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"qdrant.test.d.ts","sourceRoot":"","sources":["../../src/daemon/qdrant.test.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
@@ -0,0 +1,209 @@
1
+ /**
2
+ * Tests for the daemon Qdrant client — unit tests only.
3
+ *
4
+ * These test initialization and validation logic without making
5
+ * actual HTTP calls to Qdrant.
6
+ */
7
+ import { describe, it, before, after, beforeEach } from "node:test";
8
+ import assert from "node:assert/strict";
9
+ import fs from "node:fs";
10
+ import path from "node:path";
11
+ import os from "node:os";
12
+ import { resetConfig, saveConfig, CONFIG_DEFAULTS } from "../config.js";
13
+ import { init, isReady, setLogger, setEmbeddingConfig, } from "./qdrant.js";
14
+ // ---------------------------------------------------------------------------
15
+ // Setup
16
+ // ---------------------------------------------------------------------------
17
+ let savedConfig = null;
18
+ const configPath = path.join(os.homedir(), ".bikky", "config.json");
19
+ // Env vars that override config — must be cleared for null-credential tests
20
+ const QDRANT_ENV_KEYS = ["QDRANT_URL", "QDRANT_API_KEY"];
21
+ let savedQdrantEnv = {};
22
+ describe("daemon/qdrant", () => {
23
+ before(() => {
24
+ if (fs.existsSync(configPath)) {
25
+ savedConfig = fs.readFileSync(configPath, "utf-8");
26
+ }
27
+ // Save env vars
28
+ for (const key of QDRANT_ENV_KEYS) {
29
+ savedQdrantEnv[key] = process.env[key];
30
+ }
31
+ });
32
+ after(() => {
33
+ // Restore env vars
34
+ for (const key of QDRANT_ENV_KEYS) {
35
+ if (savedQdrantEnv[key] === undefined) {
36
+ delete process.env[key];
37
+ }
38
+ else {
39
+ process.env[key] = savedQdrantEnv[key];
40
+ }
41
+ }
42
+ // Restore config
43
+ if (savedConfig !== null) {
44
+ fs.writeFileSync(configPath, savedConfig);
45
+ }
46
+ resetConfig();
47
+ });
48
+ beforeEach(() => {
49
+ // Clear qdrant env vars so saveConfig controls the values
50
+ for (const key of QDRANT_ENV_KEYS) {
51
+ delete process.env[key];
52
+ }
53
+ resetConfig();
54
+ });
55
+ // Restore config after all tests in this file
56
+ // Note: this runs once since we only save the original once
57
+ // ── isReady ──────────────────────────────────────────────────────────────
58
+ describe("isReady", () => {
59
+ it("returns false before init when no credentials configured", () => {
60
+ // Set config with null qdrant credentials
61
+ saveConfig({
62
+ ...CONFIG_DEFAULTS,
63
+ qdrant_url: null,
64
+ qdrant_api_key: null,
65
+ });
66
+ resetConfig();
67
+ // isReady checks module-level state — after fresh module load it should be false
68
+ // since we haven't called init()
69
+ // Actually, isReady checks the module-level variables which may have been set by prior tests
70
+ // But init() with null credentials will set qdrantUrl to null, so isReady returns false
71
+ init();
72
+ assert.strictEqual(isReady(), false);
73
+ });
74
+ });
75
+ // ── init ─────────────────────────────────────────────────────────────────
76
+ describe("init", () => {
77
+ it("returns false when qdrant_url is null", () => {
78
+ saveConfig({
79
+ ...CONFIG_DEFAULTS,
80
+ qdrant_url: null,
81
+ qdrant_api_key: null,
82
+ });
83
+ resetConfig();
84
+ const ready = init();
85
+ assert.strictEqual(ready, false);
86
+ });
87
+ it("returns false when qdrant_api_key is null", () => {
88
+ saveConfig({
89
+ ...CONFIG_DEFAULTS,
90
+ qdrant_url: "https://my-qdrant.example.com:6333",
91
+ qdrant_api_key: null,
92
+ });
93
+ resetConfig();
94
+ const ready = init();
95
+ assert.strictEqual(ready, false);
96
+ });
97
+ it("returns true when both url and api_key are set", () => {
98
+ saveConfig({
99
+ ...CONFIG_DEFAULTS,
100
+ qdrant_url: "https://my-qdrant.example.com:6333",
101
+ qdrant_api_key: "test-api-key",
102
+ });
103
+ resetConfig();
104
+ const ready = init();
105
+ assert.strictEqual(ready, true);
106
+ });
107
+ it("isReady returns true after successful init", () => {
108
+ saveConfig({
109
+ ...CONFIG_DEFAULTS,
110
+ qdrant_url: "https://my-qdrant.example.com:6333",
111
+ qdrant_api_key: "test-api-key",
112
+ });
113
+ resetConfig();
114
+ init();
115
+ assert.strictEqual(isReady(), true);
116
+ });
117
+ it("isReady returns false after init with missing credentials", () => {
118
+ saveConfig({
119
+ ...CONFIG_DEFAULTS,
120
+ qdrant_url: null,
121
+ qdrant_api_key: null,
122
+ });
123
+ resetConfig();
124
+ init();
125
+ assert.strictEqual(isReady(), false);
126
+ });
127
+ });
128
+ // ── setLogger ────────────────────────────────────────────────────────────
129
+ describe("setLogger", () => {
130
+ it("does not throw when called with a function", () => {
131
+ assert.doesNotThrow(() => {
132
+ setLogger((level, ...args) => {
133
+ // noop logger
134
+ });
135
+ });
136
+ });
137
+ it("does not throw when called with noop", () => {
138
+ assert.doesNotThrow(() => {
139
+ setLogger(() => { });
140
+ });
141
+ });
142
+ });
143
+ // ── setEmbeddingConfig ───────────────────────────────────────────────────
144
+ describe("setEmbeddingConfig", () => {
145
+ it("does not throw when called with overrides", () => {
146
+ assert.doesNotThrow(() => {
147
+ setEmbeddingConfig({ provider: "ollama", model: "nomic-embed-text" });
148
+ });
149
+ });
150
+ it("does not throw when called with undefined", () => {
151
+ assert.doesNotThrow(() => {
152
+ setEmbeddingConfig(undefined);
153
+ });
154
+ });
155
+ it("does not throw when called with empty overrides", () => {
156
+ assert.doesNotThrow(() => {
157
+ setEmbeddingConfig({});
158
+ });
159
+ });
160
+ });
161
+ // ── StoreFact type shape ─────────────────────────────────────────────────
162
+ describe("StoreFact type", () => {
163
+ it("accepts minimal required fields", () => {
164
+ const fact = {
165
+ content: "test content",
166
+ category: "infrastructure",
167
+ entities: ["test"],
168
+ content_hash: "abc123",
169
+ };
170
+ assert.ok(fact.content);
171
+ assert.ok(fact.category);
172
+ assert.ok(Array.isArray(fact.entities));
173
+ assert.ok(fact.content_hash);
174
+ });
175
+ it("accepts all optional fields", () => {
176
+ const fact = {
177
+ content: "test content",
178
+ category: "decisions",
179
+ entities: ["redis", "cache"],
180
+ content_hash: "def456",
181
+ domain: "work",
182
+ kind: "fact",
183
+ source: "agent",
184
+ confidence: 0.9,
185
+ importance: 0.7,
186
+ metadata: { session_id: "abc" },
187
+ relation: { from: "redis", type: "uses", to: "cache" },
188
+ };
189
+ assert.strictEqual(fact.domain, "work");
190
+ assert.strictEqual(fact.kind, "fact");
191
+ assert.strictEqual(fact.source, "agent");
192
+ assert.strictEqual(fact.confidence, 0.9);
193
+ assert.strictEqual(fact.importance, 0.7);
194
+ assert.deepStrictEqual(fact.metadata, { session_id: "abc" });
195
+ assert.deepStrictEqual(fact.relation, { from: "redis", type: "uses", to: "cache" });
196
+ });
197
+ it("accepts null relation", () => {
198
+ const fact = {
199
+ content: "test",
200
+ category: "observation",
201
+ entities: [],
202
+ content_hash: "ghi789",
203
+ relation: null,
204
+ };
205
+ assert.strictEqual(fact.relation, null);
206
+ });
207
+ });
208
+ });
209
+ //# sourceMappingURL=qdrant.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"qdrant.test.js","sourceRoot":"","sources":["../../src/daemon/qdrant.test.ts"],"names":[],"mappings":"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"}