@thelapyae/geniclaw 1.1.10 → 1.2.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/README.md CHANGED
@@ -1,14 +1,22 @@
1
1
  # 🦁 GeniClaw - Your AI Terminal Assistant
2
2
 
3
- **GeniClaw** is a powerful, local-first AI assistant manager that connects **Google Gemini** to your workflow. It runs as a background service (daemon) on your machine, managing conversation history, project sessions, and token usage efficiently.
4
-
5
- ## 🚀 Features
6
-
7
- - **🧠 Multi-Model Support**: Switch between `gemini-2.5-flash`, `pro`, and other models instantly.
8
- - **📂 Session Management**: Create separate "folders" (sessions) for different projects or topics. Each session has its own isolated memory.
9
- - **💾 Smart Memory**: Automatically manages conversation context. It keeps recent history while pruning older messages to stay within token limits (default ~100k tokens), enabling long-term usage without crashing.
10
- - **🖥️ Terminal UI (TUI)**: An interactive command-line interface to manage everything.
11
- - **⚡ Queue-Based**: Robust message processing ensures no data is lost, even if you are offline.
3
+ **GeniClaw** is a powerful, local-first AI assistant manager that connects multiple AI providers (Gemini, OpenAI, Claude, Groq, DeepSeek, Grok) to your workflow. It runs as a background service (daemon) on your machine, managing conversation history, project sessions, and token usage efficiently.
4
+
5
+ ## 🚀 Key Features
6
+
7
+ - **🧠 Multi-Provider Support**:
8
+ - **Google Gemini** (1.5 Flash/Pro, 2.0 Flash)
9
+ - **OpenAI** (GPT-4o, GPT-3.5)
10
+ - **Anthropic** (Claude 3.5 Sonnet, Opus)
11
+ - **Groq** (Llama 3, Mixtral - Ultra Fast)
12
+ - **DeepSeek** (Coder, Chat)
13
+ - **xAI** (Grok Beta)
14
+ - **🔎 Web Search**: Integrated **Brave Search** allows the AI to Google things for you in real-time.
15
+ - **🔀 Task Routing**: Assign different models to different tasks! (e.g., Use Groq for fast Chat, Gemini for heartbeat/cron jobs).
16
+ - **📂 Session Management**: Create separate "folders" (sessions) for different projects.
17
+ - **💾 Smart Memory**: Automatically manages conversation context and prunes old messages to stay within token limits.
18
+ - **🖥️ Terminal UI (TUI)**: A beautiful interactive interface to manage keys, models, and sessions.
19
+ - **⚡ Queue-Based**: Robust message processing ensures no data is lost.
12
20
 
13
21
  ---
14
22
 
@@ -17,20 +25,23 @@
17
25
  ### Prerequisites
18
26
 
19
27
  - **Node.js** (v18 or higher)
20
- - **Google Gemini API Key**: Get one for free at [aistudio.google.com](https://aistudio.google.com/).
21
- - **Telegram Bot Token** (Optional, for chatting via Telegram): Get one from [@BotFather](https://t.me/botfather).
28
+ - **API Keys**: You need at least one API key from a supported provider:
29
+ - [Google AI Studio](https://aistudio.google.com/)
30
+ - [OpenAI](https://platform.openai.com/)
31
+ - [Anthropic](https://console.anthropic.com/)
32
+ - [Groq](https://console.groq.com/)
33
+ - [DeepSeek](https://platform.deepseek.com/)
34
+ - [Brave Search](https://brave.com/search/api/) (Optional, for Web Search)
35
+ - **Telegram Bot Token** (Optional, for chatting via Telegram).
22
36
 
23
37
  ### Installation
24
38
 
25
39
  1. **Install via NPM**:
26
- ```bash
27
40
  ```bash
28
41
  npm install -g @thelapyae/geniclaw
29
42
  ```
30
- *Note: The `-g` flag installs it globally so you can run `geniclaw` from anywhere.*
31
43
 
32
44
  2. **Run Setup**:
33
- This will guide you through entering your API keys.
34
45
  ```bash
35
46
  geniclaw setup
36
47
  ```
@@ -42,87 +53,52 @@
42
53
  GeniClaw is managed entirely through its **Interactive TUI**.
43
54
 
44
55
  ### 1. Start the TUI
45
- Run the following command in your terminal:
46
56
  ```bash
47
- ./bin/geniclaw.js
48
- # Or if you linked it:
49
57
  geniclaw
50
58
  ```
51
59
 
52
60
  ### 2. Main Menu Options
53
- - **Start Daemon**: Launches the background process (Queue Processor & Telegram Bot).
54
- - **Stop Daemon**: Stops all background processes.
55
- - **Check Status**: Shows if the daemon is running and recent activity.
56
- - **📂 Manage Sessions**: Create or switch between different conversation contexts.
57
- - **🧠 Change Gemini Model**: Select the AI model you want to use.
58
- - **View Logs**: Inspect what's happening under the hood.
61
+ - **🤖 Select AI Provider & Model**: Choose which brain you want to use (Gemini, GPT-4, Claude, etc.).
62
+ - **🔑 Manage API Keys**: Enter keys for different providers.
63
+ - **🔀 Task Routing**: Configure which provider handles Chat vs. Background Tasks.
64
+ - **🔎 Web Search Config**: Set your Brave Search API key to enable internet access.
65
+ - **Start/Stop Daemon**: Control the background process.
59
66
 
60
67
  ### 3. Chatting
61
- Once the daemon is running (`Start Daemon`), you can interact with it via:
62
- - **Telegram**: If configured, just chat with your bot.
63
- - **CLI (Manual)**: You can send a one-off message from the terminal:
64
- ```bash
65
- ./geniclaw.sh send "Hello Gemini, how are you?"
66
- ```
67
-
68
- ---
69
-
70
- ## 📂 Session Management (Folders)
71
-
72
- GeniClaw allows you to organize multiple conversations.
73
-
74
- 1. Open the TUI: `geniclaw`
75
- 2. Select **Manage Sessions**.
76
- 3. **Create New Session**: Name it (e.g., `coding-project`, `personal-notes`).
77
- 4. **Switch Session**: Select it to make it active.
78
-
79
- **How it works**:
80
- - When you switch to `coding-project`, GeniClaw creates a folder at `~/.geniclaw/sessions/coding-project/`.
81
- - All history and memory for that conversation are stored there.
82
- - Switching back to `default` restores your previous context instantly.
83
-
84
- ---
85
-
86
- ## ⚙️ Memory & Token Management
87
-
88
- To support **Long Term Usage**, GeniClaw monitors your token usage.
68
+ - **Telegram**: Chat with your bot.
69
+ - **CLI**: `geniclaw send "Hello!"`
89
70
 
90
- - **Automatic Pruning**: If a conversation exceeds the safe limit (default ~100k tokens), GeniClaw removes the oldest messages to make room for new ones. This prevents "Context Length Exceeded" errors.
91
- - **Check Usage**:
92
- - Type `/stats` in the chat to see current token usage.
93
- - **Reset**:
94
- - Type `/reset` or use the **Reset** command in TUI to clear the current session's memory.
71
+ ### web Search
72
+ Just ask:
73
+ - "Search for the latest heavy metal news"
74
+ - "Google the price of Bitcoin"
75
+ - "/search Who won the super bowl?"
95
76
 
96
77
  ---
97
78
 
98
- ## 🏗️ Architecture & Storage
79
+ ## 🔒 Safety & Technology
99
80
 
100
- ### Where are my files?
101
- By default, GeniClaw stores everything locally in your home directory:
102
- `~/.geniclaw/`
81
+ GeniClaw creates a secure, local-first environment for your AI interactions.
103
82
 
104
- - `config.json`: Your settings (API keys, active session).
105
- - `sessions/`: Folders containing history files for each session.
106
- - `queue/`: Temporary files for messages being processed.
107
- - `logs/`: Log files for debugging.
83
+ ### Technology Stack
84
+ - **Runtime**: Node.js & TypeScript.
85
+ - **State Management**: Local JSON files (No external database required).
86
+ - **API Integration**: Uses official SDKs (Google Generative AI) and standard REST APIs (OpenAI-compatible) via `node-fetch`.
87
+ - **Background Service**: A lightweight daemon process manages the message queue.
108
88
 
109
- ### How it works
110
- 1. **Input**: You send a message (Telegram/CLI).
111
- 2. **Queue**: The message is written to `queue/incoming/`.
112
- 3. **Processor**: The `queue-processor` picks it up.
113
- - It loads the **Active Session** history.
114
- - It checks **Token Limits**.
115
- - It sends context + message to **Gemini API**.
116
- 4. **Response**: Gemini's reply is saved to history and written to `queue/outgoing/`.
117
- 5. **Output**: The interface (Telegram/CLI) sends the reply back to you.
89
+ ### Why is it Safe?
90
+ 1. **Local Data**: All conversation history, sessions, and logs are stored **locally on your machine** in `~/.geniclaw/`. Your data never leaves your computer except to go directly to the AI provider.
91
+ 2. **Direct Connection**: GeniClaw connects **directly** to the AI APIs (Google, OpenAI, etc.). There is no "middleman" server collecting your data.
92
+ 3. **Open Source**: The code is transparent. You can inspect exactly how your keys and data are used.
93
+ 4. **Key Security**: API keys are stored in a local config file (`config.json`) on your machine.
118
94
 
119
95
  ---
120
96
 
121
- ## ⚠️ Things to Take Care Of
97
+ ## ⚠️ Important Notes
122
98
 
123
- 1. **API Costs**: While many Gemini models have a free tier, heavy usage (especially with large contexts) might incur costs if you are on a paid plan. Use `/stats` to monitor usage.
124
- 2. **Daemon**: The background process must be running to reply. If it stops, just run **Start Daemon** again.
125
- 3. **Privacy**: Your history is stored **locally** in plain text JSON files in `~/.geniclaw`. Keep your computer secure.
99
+ 1. **API Costs**: Using commercial APIs (OpenAI, Anthropic) is not free. Costs depend on your usage. Groq and Gemini (Free Tier) offer free options.
100
+ 2. **Privacy**: While GeniClaw is local, the AI Providers (Google, OpenAI, etc.) have their own data policies.
101
+ 3. **Daemon**: The background process must be running for GeniClaw to reply.
126
102
 
127
103
  ---
128
104
 
package/bin/geniclaw.js CHANGED
@@ -111,10 +111,13 @@ async function showMenu() {
111
111
 
112
112
  // Show current status summary
113
113
  try {
114
- console.log(`Current Model: ${config.geminiModel || 'Default'}`);
115
- console.log(`Active Session: 📂 ${activeSession}`);
116
- console.log(`Active Skill: 🧠 ${activeSkill}`);
117
- if (config.geminiApiUrl) console.log(`API URL: 🔌 ${config.geminiApiUrl}`);
114
+ console.log(`Active Provider: ${config.activeProvider || 'gemini'} (${config.activeProvider === 'gemini' ? config.geminiModel : (config[config.activeProvider + 'Model'] || 'Default')})`);
115
+ console.log(`Active Session: 📂 ${activeSession}`);
116
+ console.log(`Active Skill: 🧠 ${activeSkill}`);
117
+ if (config.providerRouting && (config.providerRouting.chat !== config.activeProvider)) {
118
+ console.log(`Routing: 🔀 Custom`);
119
+ }
120
+ if (config.geminiApiUrl) console.log(`API URL: 🔌 ${config.geminiApiUrl}`);
118
121
  } catch (e) {}
119
122
  console.log('');
120
123
 
@@ -127,13 +130,16 @@ async function showMenu() {
127
130
  { name: 'Start Daemon', value: 'start' },
128
131
  { name: 'Stop Daemon', value: 'stop' },
129
132
  { name: 'Restart Daemon', value: 'restart' },
130
- { name: 'Check Status', value: 'status' },
131
133
  { name: 'View Logs', value: 'logs' },
132
134
  new inquirer.Separator(),
133
- { name: '📂 Manage Sessions', value: 'sessions' },
135
+ { name: '🤖 Select AI Provider & Model', value: 'provider' },
136
+ { name: '🔑 Manage API Keys', value: 'keys' },
137
+ { name: '🔀 Task Routing (Chat/Heartbeat/Cron)', value: 'routing' },
138
+ { name: '🔎 Web Search Config', value: 'search' },
134
139
  { name: '🧠 Manage Skills', value: 'skills' },
135
- { name: '🤖 Change Gemini Model', value: 'model' },
136
- { name: '🔌 Change API Base URL', value: 'apiUrl' },
140
+ { name: '📂 Manage Sessions', value: 'sessions' },
141
+ { name: '🔌 Change API Base URL (Gemini/Proxy)', value: 'apiUrl' },
142
+ { name: '🔑 Set Gateway/Proxy Key', value: 'gatewayKey' },
137
143
  new inquirer.Separator(),
138
144
  { name: '✨ Update GeniClaw', value: 'update' },
139
145
  { name: 'Run Setup Wizard', value: 'setup' },
@@ -157,18 +163,39 @@ async function showMenu() {
157
163
  return showMenu();
158
164
  }
159
165
 
160
- if (action === 'model') {
161
- await changeModel();
166
+ if (action === 'provider') {
167
+ await selectProviderAndModel();
162
168
  await promptContinue();
163
169
  return showMenu();
164
170
  }
165
171
 
172
+ if (action === 'keys') {
173
+ await manageApiKeys();
174
+ return showMenu();
175
+ }
176
+
177
+ if (action === 'routing') {
178
+ await manageTaskRouting();
179
+ return showMenu();
180
+ }
181
+
182
+ if (action === 'search') {
183
+ await configureWebSearch();
184
+ return showMenu();
185
+ }
186
+
166
187
  if (action === 'apiUrl') {
167
188
  await changeApiUrl();
168
189
  await promptContinue();
169
190
  return showMenu();
170
191
  }
171
192
 
193
+ if (action === 'gatewayKey') {
194
+ await changeGatewayKey();
195
+ await promptContinue();
196
+ return showMenu();
197
+ }
198
+
172
199
  if (action === 'sessions') {
173
200
  await manageSessions();
174
201
  return showMenu();
@@ -200,25 +227,72 @@ async function promptContinue() {
200
227
  ]);
201
228
  }
202
229
 
203
- async function changeModel() {
230
+ async function selectProviderAndModel() {
204
231
  const config = loadConfig();
205
- const currentModel = config.geminiModel || 'gemini-2.5-flash';
232
+ const currentProvider = config.activeProvider || 'gemini';
233
+
234
+ const { provider } = await inquirer.prompt([
235
+ {
236
+ type: 'list',
237
+ name: 'provider',
238
+ message: 'Select Active AI Provider:',
239
+ default: currentProvider,
240
+ choices: [
241
+ { name: 'Google Gemini', value: 'gemini' },
242
+ { name: 'OpenAI (GPT-4)', value: 'openai' },
243
+ { name: 'Anthropic (Claude)', value: 'anthropic' },
244
+ { name: 'Groq (Llama 3)', value: 'groq' },
245
+ { name: 'Deepseek', value: 'deepseek' },
246
+ { name: 'xAI (Grok)', value: 'grok' }
247
+ ]
248
+ }
249
+ ]);
250
+
251
+ config.activeProvider = provider;
252
+ saveConfig(config);
253
+ console.log(`✅ Active Provider set to: ${provider}`);
254
+
255
+ // Now configure model for this provider
256
+ let currentModel = 'default';
257
+ let choices = [];
258
+
259
+ switch (provider) {
260
+ case 'gemini':
261
+ currentModel = config.geminiModel || 'gemini-2.5-flash';
262
+ choices = ['gemini-2.5-flash', 'gemini-flash-lite-latest', 'gemini-2.5-pro', 'gemini-3-flash-preview', 'gemini-3-pro-preview'];
263
+ break;
264
+ case 'openai':
265
+ currentModel = config.openaiModel || 'gpt-4o';
266
+ choices = ['gpt-4o', 'gpt-4-turbo', 'gpt-3.5-turbo'];
267
+ break;
268
+ case 'anthropic':
269
+ currentModel = config.anthropicModel || 'claude-3-5-sonnet-20240620';
270
+ choices = ['claude-3-5-sonnet-20240620', 'claude-3-opus-20240229', 'claude-3-haiku-20240307'];
271
+ break;
272
+ case 'groq':
273
+ currentModel = config.groqModel || 'llama3-70b-8192';
274
+ choices = ['llama3-70b-8192', 'llama3-8b-8192', 'mixtral-8x7b-32768', 'gemma-7b-it'];
275
+ break;
276
+ case 'deepseek':
277
+ currentModel = config.deepseekModel || 'deepseek-chat';
278
+ choices = ['deepseek-chat', 'deepseek-coder'];
279
+ break;
280
+ case 'grok':
281
+ currentModel = config.grokModel || 'grok-beta';
282
+ choices = ['grok-beta'];
283
+ break;
284
+ }
285
+
286
+ choices.push(new inquirer.Separator());
287
+ choices.push({ name: 'Custom (Enter manually)', value: 'custom' });
206
288
 
207
289
  const { model } = await inquirer.prompt([
208
290
  {
209
291
  type: 'list',
210
292
  name: 'model',
211
- message: 'Select Gemini Model:',
293
+ message: `Select Model for ${provider}:`,
212
294
  default: currentModel,
213
- choices: [
214
- 'gemini-2.5-flash',
215
- 'gemini-flash-lite-latest',
216
- 'gemini-2.5-pro',
217
- 'gemini-3-flash-preview',
218
- 'gemini-3-pro-preview',
219
- new inquirer.Separator(),
220
- { name: 'Custom (Enter manually)', value: 'custom' }
221
- ]
295
+ choices: choices
222
296
  }
223
297
  ]);
224
298
 
@@ -235,10 +309,152 @@ async function changeModel() {
235
309
  selectedModel = customModel;
236
310
  }
237
311
 
238
- config.geminiModel = selectedModel;
312
+ // Save model to correct config field
313
+ config[`${provider}Model`] = selectedModel;
314
+ saveConfig(config);
315
+ console.log(`✅ Model for ${provider} updated to: ${selectedModel}`);
316
+
317
+ // Check if key is set
318
+ const keyField = `${provider}ApiKey`;
319
+ if (!config[keyField] && !process.env[keyField.toUpperCase().replace(/([A-Z])/g, '_$1').toUpperCase()]) {
320
+ console.log(`⚠️ Warning: API Key for ${provider} is not set.`);
321
+ const { setKey } = await inquirer.prompt([{ type: 'confirm', name: 'setKey', message: 'Set API Key now?', default: true }]);
322
+ if (setKey) await manageApiKeys(provider);
323
+ }
324
+ }
325
+
326
+ async function manageApiKeys(targetProvider = null) {
327
+ const config = loadConfig();
328
+
329
+ let provider = targetProvider;
330
+ if (!provider) {
331
+ const result = await inquirer.prompt([
332
+ {
333
+ type: 'list',
334
+ name: 'provider',
335
+ message: 'Select Provider to manage key:',
336
+ choices: [
337
+ { name: 'Google Gemini', value: 'gemini' },
338
+ { name: 'OpenAI', value: 'openai' },
339
+ { name: 'Anthropic', value: 'anthropic' },
340
+ { name: 'Groq', value: 'groq' },
341
+ { name: 'Deepseek', value: 'deepseek' },
342
+ { name: 'xAI (Grok)', value: 'grok' },
343
+ { name: 'Brave Search', value: 'brave' },
344
+ { name: 'Back', value: 'back' }
345
+ ]
346
+ }
347
+ ]);
348
+ if (result.provider === 'back') return;
349
+ provider = result.provider;
350
+ }
351
+
352
+ const keyField = `${provider}ApiKey`;
353
+ const currentKey = config[keyField] ? '********' : 'Not Set';
354
+
355
+ const { key } = await inquirer.prompt([
356
+ {
357
+ type: 'password',
358
+ name: 'key',
359
+ message: `Enter API Key for ${provider} (Current: ${currentKey}):`,
360
+ suffix: '\n(Leave empty to keep current)',
361
+ mask: '*'
362
+ }
363
+ ]);
364
+
365
+ if (key && key.trim() !== '') {
366
+ config[keyField] = key.trim();
367
+ saveConfig(config);
368
+ console.log(`✅ API Key for ${provider} updated.`);
369
+ } else {
370
+ console.log('No change.');
371
+ }
372
+
373
+ if (!targetProvider) await promptContinue();
374
+ }
375
+
376
+ async function manageTaskRouting() {
377
+ const config = loadConfig();
378
+ const routing = config.providerRouting || { chat: 'gemini', heartbeat: 'gemini', cron: 'gemini' };
379
+
380
+ const { task } = await inquirer.prompt([
381
+ {
382
+ type: 'list',
383
+ name: 'task',
384
+ message: 'Select Task to Route:',
385
+ choices: [
386
+ { name: `Chat (Current: ${routing.chat || 'default'})`, value: 'chat' },
387
+ { name: `Heartbeat (Current: ${routing.heartbeat || 'default'})`, value: 'heartbeat' },
388
+ { name: `Cron Jobs (Current: ${routing.cron || 'default'})`, value: 'cron' },
389
+ { name: 'Back', value: 'back' }
390
+ ]
391
+ }
392
+ ]);
393
+
394
+ if (task === 'back') return;
395
+
396
+ const { provider } = await inquirer.prompt([
397
+ {
398
+ type: 'list',
399
+ name: 'provider',
400
+ message: `Select Provider for ${task}:`,
401
+ choices: [
402
+ { name: 'Use Active Provider (Default)', value: null },
403
+ new inquirer.Separator(),
404
+ { name: 'Google Gemini', value: 'gemini' },
405
+ { name: 'OpenAI', value: 'openai' },
406
+ { name: 'Anthropic', value: 'anthropic' },
407
+ { name: 'Groq', value: 'groq' },
408
+ { name: 'Deepseek', value: 'deepseek' },
409
+ { name: 'xAI (Grok)', value: 'grok' }
410
+ ]
411
+ }
412
+ ]);
413
+
414
+ if (provider) {
415
+ routing[task] = provider;
416
+ } else {
417
+ delete routing[task];
418
+ }
419
+
420
+ config.providerRouting = routing;
239
421
  saveConfig(config);
240
- console.log(`✅ Model updated to: ${selectedModel}`);
241
- console.log('Note: You may need to restart the daemon for changes to take effect.');
422
+ console.log(`✅ Routing updated.`);
423
+
424
+ return manageTaskRouting();
425
+ }
426
+
427
+ async function configureWebSearch() {
428
+ const config = loadConfig();
429
+ const currentKey = config.braveApiKey ? '********' : 'Not Set';
430
+
431
+ console.log('configured Web Search uses Brave Search API.');
432
+ console.log('Get a free key at: https://brave.com/search/api/');
433
+
434
+ const { key } = await inquirer.prompt([
435
+ {
436
+ type: 'password',
437
+ name: 'key',
438
+ message: `Enter Brave Search API Key (Current: ${currentKey}):`,
439
+ suffix: '\n(Leave empty to remove/keep)',
440
+ mask: '*'
441
+ }
442
+ ]);
443
+
444
+ if (key && key.trim() !== '') {
445
+ config.braveApiKey = key.trim();
446
+ saveConfig(config);
447
+ console.log('✅ Brave API Key set.');
448
+ } else if (config.braveApiKey && key === '') {
449
+ const { remove } = await inquirer.prompt([{ type: 'confirm', name: 'remove', message: 'Remove existing key?', default: false}]);
450
+ if (remove) {
451
+ delete config.braveApiKey;
452
+ saveConfig(config);
453
+ console.log('✅ Brave API Key removed.');
454
+ }
455
+ }
456
+
457
+ await promptContinue();
242
458
  }
243
459
 
244
460
  async function changeApiUrl() {
@@ -269,6 +485,31 @@ async function changeApiUrl() {
269
485
  console.log('Note: Restart daemon to apply changes.');
270
486
  }
271
487
 
488
+ async function changeGatewayKey() {
489
+ const config = loadConfig();
490
+ const currentKey = config.geminiGatewayKey ? '********' : 'Not Set';
491
+
492
+ const { key } = await inquirer.prompt([
493
+ {
494
+ type: 'password',
495
+ name: 'key',
496
+ message: `Enter Gateway API Key (Current: ${currentKey}):`,
497
+ suffix: '\n(Leave empty to remove key)',
498
+ mask: '*'
499
+ }
500
+ ]);
501
+
502
+ if (!key || key.trim() === '') {
503
+ delete config.geminiGatewayKey;
504
+ console.log('✅ Gateway Key removed.');
505
+ } else {
506
+ config.geminiGatewayKey = key.trim();
507
+ console.log('✅ Gateway Key updated.');
508
+ }
509
+ saveConfig(config);
510
+ console.log('Note: Restart daemon to apply changes.');
511
+ }
512
+
272
513
  async function manageSessions() {
273
514
  const config = loadConfig();
274
515
  const activeSession = config.activeSession || 'default';
@@ -6,11 +6,29 @@ export interface AppConfig {
6
6
  telegramBotToken?: string;
7
7
  telegramAllowedUserId?: string;
8
8
  geminiApiUrl?: string;
9
+ geminiGatewayKey?: string;
9
10
  activeSession: string;
10
11
  activeSkill?: string;
11
12
  userName?: string;
12
13
  botName?: string;
13
14
  botPurpose?: string;
15
+ activeProvider?: 'gemini' | 'openai' | 'anthropic' | 'groq' | 'deepseek' | 'grok';
16
+ providerRouting?: {
17
+ chat?: string;
18
+ heartbeat?: string;
19
+ cron?: string;
20
+ };
21
+ openaiModel?: string;
22
+ anthropicModel?: string;
23
+ groqModel?: string;
24
+ deepseekModel?: string;
25
+ grokModel?: string;
26
+ openaiApiKey?: string;
27
+ anthropicApiKey?: string;
28
+ groqApiKey?: string;
29
+ deepseekApiKey?: string;
30
+ grokApiKey?: string;
31
+ braveApiKey?: string;
14
32
  onboardingState: 'INIT' | 'AWAITING_NAME' | 'AWAITING_BOT_NAME' | 'AWAITING_PURPOSE' | 'READY';
15
33
  }
16
34
  export declare class ConfigManager {
@@ -1 +1 @@
1
- {"version":3,"file":"config-manager.d.ts","sourceRoot":"","sources":["../src/config-manager.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,iBAAiB,QAAiH,CAAC;AAChJ,eAAO,MAAM,WAAW,QAA8C,CAAC;AAGvE,MAAM,WAAW,SAAS;IAEtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAE/B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,GAAG,eAAe,GAAG,mBAAmB,GAAG,kBAAkB,GAAG,OAAO,CAAC;CAClG;AAED,qBAAa,aAAa;IACtB,OAAO,CAAC,MAAM,CAAC,YAAY,CAA0B;IAErD,MAAM,CAAC,IAAI,IAAI,SAAS;IAsBxB,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI;IAcpC,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,IAAI;CAKnD"}
1
+ {"version":3,"file":"config-manager.d.ts","sourceRoot":"","sources":["../src/config-manager.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,iBAAiB,QAAiH,CAAC;AAChJ,eAAO,MAAM,WAAW,QAA8C,CAAC;AAGvE,MAAM,WAAW,SAAS;IAEtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAE/B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,WAAW,GAAG,MAAM,GAAG,UAAU,GAAG,MAAM,CAAC;IAClF,eAAe,CAAC,EAAE;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,IAAI,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;IAGF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IAGnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,eAAe,EAAE,MAAM,GAAG,eAAe,GAAG,mBAAmB,GAAG,kBAAkB,GAAG,OAAO,CAAC;CAClG;AAED,qBAAa,aAAa;IACtB,OAAO,CAAC,MAAM,CAAC,YAAY,CAA0B;IAErD,MAAM,CAAC,IAAI,IAAI,SAAS;IAmCxB,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI;IAcpC,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,IAAI;CAKnD"}
@@ -31,7 +31,20 @@ class ConfigManager {
31
31
  onboardingState: 'INIT',
32
32
  geminiModel: process.env.GEMINI_MODEL || 'gemini-1.5-flash',
33
33
  geminiApiUrl: process.env.GEMINI_API_URL || undefined,
34
- activeSession: 'default'
34
+ geminiGatewayKey: process.env.GEMINI_GATEWAY_KEY || undefined,
35
+ activeSession: 'default',
36
+ activeProvider: 'gemini',
37
+ providerRouting: {
38
+ chat: 'gemini',
39
+ heartbeat: 'gemini',
40
+ cron: 'gemini'
41
+ },
42
+ // Default Models
43
+ openaiModel: 'gpt-4o',
44
+ anthropicModel: 'claude-3-5-sonnet-20240620',
45
+ groqModel: 'llama3-70b-8192',
46
+ deepseekModel: 'deepseek-chat',
47
+ grokModel: 'grok-beta'
35
48
  };
36
49
  }
37
50
  static save(config) {
@@ -1 +1 @@
1
- {"version":3,"file":"config-manager.js","sourceRoot":"","sources":["../src/config-manager.ts"],"names":[],"mappings":";;;;;;AAAA,4CAAoB;AACpB,gDAAwB;AACxB,4CAAoB;AAEpB,eAAe;AACf,MAAM,SAAS,GAAG,cAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,WAAW,CAAC,CAAC;AAC3C,QAAA,iBAAiB,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,cAAI,CAAC,IAAI,CAAC,YAAE,CAAC,OAAO,EAAE,EAAE,WAAW,CAAC,CAAC,CAAC;AACnI,QAAA,WAAW,GAAG,cAAI,CAAC,IAAI,CAAC,yBAAiB,EAAE,aAAa,CAAC,CAAC;AAmBvE,MAAa,aAAa;IACd,MAAM,CAAC,YAAY,GAAqB,IAAI,CAAC;IAErD,MAAM,CAAC,IAAI;QACP,IAAI,IAAI,CAAC,YAAY;YAAE,OAAO,IAAI,CAAC,YAAY,CAAC;QAEhD,IAAI,YAAE,CAAC,UAAU,CAAC,mBAAW,CAAC,EAAE,CAAC;YAC7B,IAAI,CAAC;gBACD,MAAM,IAAI,GAAG,YAAE,CAAC,YAAY,CAAC,mBAAW,EAAE,MAAM,CAAC,CAAC;gBAClD,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBACrC,OAAO,IAAI,CAAC,YAAa,CAAC;YAC9B,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACT,OAAO,CAAC,KAAK,CAAC,0BAA2B,CAAW,CAAC,OAAO,EAAE,CAAC,CAAC;YACpE,CAAC;QACL,CAAC;QAED,iBAAiB;QACjB,OAAO;YACH,eAAe,EAAE,MAAM;YACvB,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,kBAAkB;YAC3D,YAAY,EAAE,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,SAAS;YACrD,aAAa,EAAE,SAAS;SAC3B,CAAC;IACN,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,MAAiB;QACzB,IAAI,CAAC;YACD,0BAA0B;YAC1B,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,yBAAiB,CAAC,EAAE,CAAC;gBACpC,YAAE,CAAC,SAAS,CAAC,yBAAiB,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YACzD,CAAC;YAED,YAAE,CAAC,aAAa,CAAC,mBAAW,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YAC/D,IAAI,CAAC,YAAY,GAAG,MAAM,CAAC;QAC/B,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACT,OAAO,CAAC,KAAK,CAAC,0BAA2B,CAAW,CAAC,OAAO,EAAE,CAAC,CAAC;QACpE,CAAC;IACL,CAAC;IAED,MAAM,CAAC,MAAM,CAAC,OAA2B;QACrC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5B,MAAM,OAAO,GAAG,EAAE,GAAG,OAAO,EAAE,GAAG,OAAO,EAAE,CAAC;QAC3C,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACvB,CAAC;;AA3CL,sCA4CC"}
1
+ {"version":3,"file":"config-manager.js","sourceRoot":"","sources":["../src/config-manager.ts"],"names":[],"mappings":";;;;;;AAAA,4CAAoB;AACpB,gDAAwB;AACxB,4CAAoB;AAEpB,eAAe;AACf,MAAM,SAAS,GAAG,cAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,WAAW,CAAC,CAAC;AAC3C,QAAA,iBAAiB,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,cAAI,CAAC,IAAI,CAAC,YAAE,CAAC,OAAO,EAAE,EAAE,WAAW,CAAC,CAAC,CAAC;AACnI,QAAA,WAAW,GAAG,cAAI,CAAC,IAAI,CAAC,yBAAiB,EAAE,aAAa,CAAC,CAAC;AA0CvE,MAAa,aAAa;IACd,MAAM,CAAC,YAAY,GAAqB,IAAI,CAAC;IAErD,MAAM,CAAC,IAAI;QACP,IAAI,IAAI,CAAC,YAAY;YAAE,OAAO,IAAI,CAAC,YAAY,CAAC;QAEhD,IAAI,YAAE,CAAC,UAAU,CAAC,mBAAW,CAAC,EAAE,CAAC;YAC7B,IAAI,CAAC;gBACD,MAAM,IAAI,GAAG,YAAE,CAAC,YAAY,CAAC,mBAAW,EAAE,MAAM,CAAC,CAAC;gBAClD,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBACrC,OAAO,IAAI,CAAC,YAAa,CAAC;YAC9B,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACT,OAAO,CAAC,KAAK,CAAC,0BAA2B,CAAW,CAAC,OAAO,EAAE,CAAC,CAAC;YACpE,CAAC;QACL,CAAC;QAED,iBAAiB;QACjB,OAAO;YACH,eAAe,EAAE,MAAM;YACvB,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,kBAAkB;YAC3D,YAAY,EAAE,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,SAAS;YACrD,gBAAgB,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,SAAS;YAC7D,aAAa,EAAE,SAAS;YACxB,cAAc,EAAE,QAAQ;YACxB,eAAe,EAAE;gBACb,IAAI,EAAE,QAAQ;gBACd,SAAS,EAAE,QAAQ;gBACnB,IAAI,EAAE,QAAQ;aACjB;YACD,iBAAiB;YACjB,WAAW,EAAE,QAAQ;YACrB,cAAc,EAAE,4BAA4B;YAC5C,SAAS,EAAE,iBAAiB;YAC5B,aAAa,EAAE,eAAe;YAC9B,SAAS,EAAE,WAAW;SACzB,CAAC;IACN,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,MAAiB;QACzB,IAAI,CAAC;YACD,0BAA0B;YAC1B,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,yBAAiB,CAAC,EAAE,CAAC;gBACpC,YAAE,CAAC,SAAS,CAAC,yBAAiB,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YACzD,CAAC;YAED,YAAE,CAAC,aAAa,CAAC,mBAAW,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YAC/D,IAAI,CAAC,YAAY,GAAG,MAAM,CAAC;QAC/B,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACT,OAAO,CAAC,KAAK,CAAC,0BAA2B,CAAW,CAAC,OAAO,EAAE,CAAC,CAAC;QACpE,CAAC;IACL,CAAC;IAED,MAAM,CAAC,MAAM,CAAC,OAA2B;QACrC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5B,MAAM,OAAO,GAAG,EAAE,GAAG,OAAO,EAAE,GAAG,OAAO,EAAE,CAAC;QAC3C,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACvB,CAAC;;AAxDL,sCAyDC"}
@@ -0,0 +1,19 @@
1
+ import { LLMProvider } from './types';
2
+ import { AppConfig } from '../config-manager';
3
+ export declare class AnthropicProvider implements LLMProvider {
4
+ private config;
5
+ constructor(config: AppConfig);
6
+ generateResponse(message: string, history: {
7
+ role: 'user' | 'model';
8
+ parts: {
9
+ text: string;
10
+ }[];
11
+ }[], systemInstruction?: string): Promise<string>;
12
+ countTokens(message: string, history: {
13
+ role: 'user' | 'model';
14
+ parts: {
15
+ text: string;
16
+ }[];
17
+ }[]): Promise<number>;
18
+ }
19
+ //# sourceMappingURL=anthropic.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anthropic.d.ts","sourceRoot":"","sources":["../../src/providers/anthropic.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAE9C,qBAAa,iBAAkB,YAAW,WAAW;IACjD,OAAO,CAAC,MAAM,CAAY;gBAEd,MAAM,EAAE,SAAS;IAIvB,gBAAgB,CAClB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;QAAC,KAAK,EAAE;YAAE,IAAI,EAAE,MAAM,CAAA;SAAE,EAAE,CAAA;KAAE,EAAE,EAChE,iBAAiB,CAAC,EAAE,MAAM,GAC3B,OAAO,CAAC,MAAM,CAAC;IA+CZ,WAAW,CACb,OAAO,EAAE,MAAM,EACf,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;QAAC,KAAK,EAAE;YAAE,IAAI,EAAE,MAAM,CAAA;SAAE,EAAE,CAAA;KAAE,EAAE,GACjE,OAAO,CAAC,MAAM,CAAC;CAQrB"}