@bike4mind/cli 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,235 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ EmbeddingFactory,
4
+ computeCosineSimilarity,
5
+ getProviderFromModel,
6
+ getSettingsByNames,
7
+ obfuscateApiKey,
8
+ secureParameters
9
+ } from "./chunk-JVPB6BB5.js";
10
+ import {
11
+ ApiKeyType,
12
+ MementoTier,
13
+ isSupportedEmbeddingModel
14
+ } from "./chunk-MKO2KCCS.js";
15
+
16
+ // ../../b4m-core/packages/services/dist/src/apiKeyService/get.js
17
+ import { z } from "zod";
18
+ var getApiKeySchema = z.object({
19
+ type: z.nativeEnum(ApiKeyType),
20
+ nullIfMissing: z.boolean().optional(),
21
+ obfuscate: z.boolean().optional(),
22
+ demoKeyName: z.string().optional()
23
+ });
24
+ var getApiKey = async (userId, params, { db }) => {
25
+ const { type, obfuscate } = secureParameters(params, getApiKeySchema);
26
+ const apiKey = await db.apiKeys.findByUserIdAndType(userId, type);
27
+ if (apiKey && obfuscate) {
28
+ return {
29
+ ...apiKey,
30
+ apiKey: obfuscateApiKey(apiKey.apiKey)
31
+ };
32
+ }
33
+ return apiKey;
34
+ };
35
+ var getMultipleApiKeys = async (userId, types, { db }, options) => {
36
+ const apiKeys = await db.apiKeys.findByUserIdAndTypes(userId, types);
37
+ if (options?.obfuscate) {
38
+ return apiKeys.map((apiKey) => ({
39
+ ...apiKey,
40
+ apiKey: obfuscateApiKey(apiKey.apiKey)
41
+ }));
42
+ }
43
+ return apiKeys;
44
+ };
45
+
46
+ // ../../b4m-core/packages/services/dist/src/apiKeyService/getEffective.js
47
+ var DEMO_KEY_MAP = {
48
+ [ApiKeyType.openai]: "openaiDemoKey",
49
+ [ApiKeyType.anthropic]: "anthropicDemoKey",
50
+ [ApiKeyType.gemini]: "geminiDemoKey",
51
+ [ApiKeyType.xai]: "xaiApiKey",
52
+ [ApiKeyType.bfl]: "bflApiKey",
53
+ [ApiKeyType.voyageai]: "voyageApiKey"
54
+ };
55
+ var getSerperKey = async (adapters) => {
56
+ const { db } = adapters;
57
+ const settings = await db.adminSettings.findBySettingName("SerperKey");
58
+ return settings?.settingValue;
59
+ };
60
+ var getOpenWeatherKey = async (adapters) => {
61
+ const { db } = adapters;
62
+ const settings = await db.adminSettings.findBySettingName("OpenWeatherKey");
63
+ return settings?.settingValue;
64
+ };
65
+ var getEffectiveApiKey = async (userId, params, adapters) => {
66
+ const { db } = adapters;
67
+ const apiKey = await getApiKey(userId, params, adapters);
68
+ let key = apiKey?.apiKey;
69
+ if (!key) {
70
+ const demoKeyName = params.demoKeyName || DEMO_KEY_MAP[params.type];
71
+ if (demoKeyName) {
72
+ const settings = await db.adminSettings.findBySettingName(demoKeyName);
73
+ key = settings?.settingValue;
74
+ }
75
+ }
76
+ return key;
77
+ };
78
+ var getEffectiveLLMApiKeys = async (userId, adapters, options) => {
79
+ const { db } = adapters;
80
+ const logger = options?.logger;
81
+ const apiKeyFetchStartTime = Date.now();
82
+ const userApiKeys = await getMultipleApiKeys(userId, [ApiKeyType.openai, ApiKeyType.anthropic, ApiKeyType.gemini, ApiKeyType.bfl, ApiKeyType.xai, ApiKeyType.voyageai], adapters);
83
+ const userKeyMap = /* @__PURE__ */ new Map();
84
+ userApiKeys.forEach((key) => userKeyMap.set(key.type, key));
85
+ const openaiUserKey = userKeyMap.get(ApiKeyType.openai) || null;
86
+ const anthropicUserKey = userKeyMap.get(ApiKeyType.anthropic) || null;
87
+ const geminiUserKey = userKeyMap.get(ApiKeyType.gemini) || null;
88
+ const bflUserKey = userKeyMap.get(ApiKeyType.bfl) || null;
89
+ const xaiUserKey = userKeyMap.get(ApiKeyType.xai) || null;
90
+ const voyageaiUserKey = userKeyMap.get(ApiKeyType.voyageai) || null;
91
+ const adminSettingNames = [
92
+ "openaiDemoKey",
93
+ "anthropicDemoKey",
94
+ "geminiDemoKey",
95
+ "bflApiKey",
96
+ "xaiApiKey",
97
+ "voyageApiKey",
98
+ "ollamaBackend",
99
+ "EnableOllama"
100
+ ];
101
+ const adminSettingsStartTime = Date.now();
102
+ const adminSettings = await getSettingsByNames(adminSettingNames, { adminSettings: db.adminSettings }, { logger });
103
+ const openaiDemoKey = adminSettings["openaiDemoKey"];
104
+ const anthropicDemoKey = adminSettings["anthropicDemoKey"];
105
+ const geminiDemoKey = adminSettings["geminiDemoKey"];
106
+ const bflDemoKey = adminSettings["bflApiKey"];
107
+ const xaiDemoKey = adminSettings["xaiApiKey"];
108
+ const voyageaiDemoKey = adminSettings["voyageApiKey"];
109
+ const ollamaBackend = adminSettings["ollamaBackend"];
110
+ const enableOllama = adminSettings["EnableOllama"];
111
+ const adminSettingsTime = Date.now() - adminSettingsStartTime;
112
+ const totalTime = Date.now() - apiKeyFetchStartTime;
113
+ if (logger) {
114
+ logger.info(`\u{1F4E6} Cached admin settings fetch completed in ${adminSettingsTime}ms (total API key fetch: ${totalTime}ms)`);
115
+ }
116
+ const ollamaEnabled = enableOllama === "true" || enableOllama === true;
117
+ const keyOrExpired = (apiKey) => {
118
+ if (!apiKey)
119
+ return null;
120
+ if (apiKey.expiresAt && apiKey.expiresAt < /* @__PURE__ */ new Date())
121
+ return "expired";
122
+ return apiKey.apiKey;
123
+ };
124
+ return {
125
+ openai: keyOrExpired(openaiUserKey) || openaiDemoKey || null,
126
+ anthropic: keyOrExpired(anthropicUserKey) || anthropicDemoKey || null,
127
+ gemini: keyOrExpired(geminiUserKey) || geminiDemoKey || null,
128
+ bfl: keyOrExpired(bflUserKey) || bflDemoKey || null,
129
+ xai: keyOrExpired(xaiUserKey) || xaiDemoKey || null,
130
+ voyageai: keyOrExpired(voyageaiUserKey) || voyageaiDemoKey || null,
131
+ ollama: ollamaEnabled ? ollamaBackend || null : null
132
+ };
133
+ };
134
+
135
+ // ../../b4m-core/packages/services/dist/src/mementoService/getRelevantMementos.js
136
+ async function getRelevantMementos(userId, prompt, options = {}, adapters) {
137
+ const { topK = 5, minSimilarity = 0.7, tier = MementoTier.HOT, embeddingModel: providedEmbeddingModel, apiKeyTable: providedApiKeyTable, logger } = options;
138
+ logger?.updateMetadata({
139
+ promptLength: prompt.length
140
+ });
141
+ const apiKeyTable = providedApiKeyTable || await getEffectiveLLMApiKeys(userId, {
142
+ db: {
143
+ apiKeys: adapters.db.apiKeys,
144
+ adminSettings: adapters.db.adminSettings
145
+ }
146
+ }, { logger });
147
+ let embeddingModel = providedEmbeddingModel;
148
+ if (!embeddingModel) {
149
+ const defaultModel = await adapters.db.adminSettings.getSettingsValue("defaultEmbeddingModel");
150
+ if (!defaultModel || !isSupportedEmbeddingModel(defaultModel)) {
151
+ throw new Error("Default embedding model not configured. Please configure it in admin settings.");
152
+ }
153
+ embeddingModel = defaultModel;
154
+ }
155
+ logger?.debug?.("Using embedding model for memento retrieval:", embeddingModel);
156
+ const requiredProvider = getProviderFromModel(embeddingModel);
157
+ const embeddingConfig = {};
158
+ if (requiredProvider === "openai") {
159
+ if (!apiKeyTable?.openai) {
160
+ throw new Error("OpenAI API key is required for memento retrieval but not found.");
161
+ }
162
+ embeddingConfig.openaiApiKey = apiKeyTable.openai;
163
+ } else if (requiredProvider === "voyageai") {
164
+ if (!apiKeyTable?.voyageai) {
165
+ throw new Error("VoyageAI API key is required for memento retrieval but not found.");
166
+ }
167
+ embeddingConfig.voyageApiKey = apiKeyTable.voyageai;
168
+ }
169
+ const embeddingFactory = new EmbeddingFactory(embeddingConfig);
170
+ const embeddingService = embeddingFactory.createEmbeddingService(embeddingModel);
171
+ logger?.debug?.("Generating embedding for prompt:", prompt.substring(0, 100));
172
+ try {
173
+ const promptEmbedding = await embeddingService.generateEmbedding(prompt);
174
+ const mementos = await adapters.db.mementos.findByUserId(userId, {
175
+ tier: tier === "all" ? void 0 : tier,
176
+ select: "summary embedding weight tags fullContent lastAccessedAt"
177
+ });
178
+ logger?.debug?.(`Found ${mementos.length} mementos to search through (tier: ${tier})`);
179
+ if (mementos.length === 0) {
180
+ logger?.debug?.("No mementos found for user");
181
+ return [];
182
+ }
183
+ const mementosWithScores = mementos.reduce((acc, memento) => {
184
+ if (!memento.embedding || memento.embedding.length === 0) {
185
+ logger?.warn?.(`Memento ${memento.id} missing embedding, skipping`);
186
+ return acc;
187
+ }
188
+ const similarity = computeCosineSimilarity(promptEmbedding, memento.embedding);
189
+ if (similarity >= minSimilarity) {
190
+ acc.push({
191
+ memento,
192
+ similarity
193
+ });
194
+ }
195
+ return acc;
196
+ }, []);
197
+ const sortedMementos = mementosWithScores.sort((a, b) => b.similarity - a.similarity).slice(0, topK);
198
+ logger?.debug?.(`Returning ${sortedMementos.length} relevant mementos (min similarity: ${minSimilarity}, topK: ${topK})`);
199
+ if (sortedMementos.length > 0) {
200
+ logger?.debug?.(`Top memento similarity: ${sortedMementos[0].similarity.toFixed(3)} - "${sortedMementos[0].memento.summary}"`);
201
+ }
202
+ return sortedMementos;
203
+ } catch (error) {
204
+ logger?.warn?.("Error generating embedding for prompt, returning empty array:", error);
205
+ return [];
206
+ }
207
+ }
208
+
209
+ // ../../b4m-core/packages/services/dist/src/mementoService/findMostSimilarMemento.js
210
+ function findMostSimilarMemento(targetEmbedding, mementos) {
211
+ let highestSimilarity = 0;
212
+ let mostSimilarMemento = null;
213
+ for (const memento of mementos) {
214
+ if (!memento.embedding || memento.embedding.length === 0) {
215
+ continue;
216
+ }
217
+ const similarity = computeCosineSimilarity(targetEmbedding, memento.embedding);
218
+ if (similarity > highestSimilarity) {
219
+ highestSimilarity = similarity;
220
+ mostSimilarMemento = memento;
221
+ }
222
+ }
223
+ return {
224
+ memento: mostSimilarMemento,
225
+ similarity: highestSimilarity
226
+ };
227
+ }
228
+
229
+ export {
230
+ getSerperKey,
231
+ getOpenWeatherKey,
232
+ getEffectiveApiKey,
233
+ getRelevantMementos,
234
+ findMostSimilarMemento
235
+ };