@thelapyae/geniclaw 1.1.11 → 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,11 +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}`);
118
- if (config.geminiGatewayKey) console.log(`Gateway Key: 🔑 Set`);
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}`);
119
121
  } catch (e) {}
120
122
  console.log('');
121
123
 
@@ -128,13 +130,15 @@ async function showMenu() {
128
130
  { name: 'Start Daemon', value: 'start' },
129
131
  { name: 'Stop Daemon', value: 'stop' },
130
132
  { name: 'Restart Daemon', value: 'restart' },
131
- { name: 'Check Status', value: 'status' },
132
133
  { name: 'View Logs', value: 'logs' },
133
134
  new inquirer.Separator(),
134
- { 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' },
135
139
  { name: '🧠 Manage Skills', value: 'skills' },
136
- { name: '🤖 Change Gemini Model', value: 'model' },
137
- { name: '🔌 Change API Base URL', value: 'apiUrl' },
140
+ { name: '📂 Manage Sessions', value: 'sessions' },
141
+ { name: '🔌 Change API Base URL (Gemini/Proxy)', value: 'apiUrl' },
138
142
  { name: '🔑 Set Gateway/Proxy Key', value: 'gatewayKey' },
139
143
  new inquirer.Separator(),
140
144
  { name: '✨ Update GeniClaw', value: 'update' },
@@ -159,12 +163,27 @@ async function showMenu() {
159
163
  return showMenu();
160
164
  }
161
165
 
162
- if (action === 'model') {
163
- await changeModel();
166
+ if (action === 'provider') {
167
+ await selectProviderAndModel();
164
168
  await promptContinue();
165
169
  return showMenu();
166
170
  }
167
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
+
168
187
  if (action === 'apiUrl') {
169
188
  await changeApiUrl();
170
189
  await promptContinue();
@@ -208,25 +227,72 @@ async function promptContinue() {
208
227
  ]);
209
228
  }
210
229
 
211
- async function changeModel() {
230
+ async function selectProviderAndModel() {
212
231
  const config = loadConfig();
213
- 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' });
214
288
 
215
289
  const { model } = await inquirer.prompt([
216
290
  {
217
291
  type: 'list',
218
292
  name: 'model',
219
- message: 'Select Gemini Model:',
293
+ message: `Select Model for ${provider}:`,
220
294
  default: currentModel,
221
- choices: [
222
- 'gemini-2.5-flash',
223
- 'gemini-flash-lite-latest',
224
- 'gemini-2.5-pro',
225
- 'gemini-3-flash-preview',
226
- 'gemini-3-pro-preview',
227
- new inquirer.Separator(),
228
- { name: 'Custom (Enter manually)', value: 'custom' }
229
- ]
295
+ choices: choices
230
296
  }
231
297
  ]);
232
298
 
@@ -243,10 +309,152 @@ async function changeModel() {
243
309
  selectedModel = customModel;
244
310
  }
245
311
 
246
- 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;
247
421
  saveConfig(config);
248
- console.log(`✅ Model updated to: ${selectedModel}`);
249
- 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();
250
458
  }
251
459
 
252
460
  async function changeApiUrl() {
@@ -12,6 +12,23 @@ export interface AppConfig {
12
12
  userName?: string;
13
13
  botName?: string;
14
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;
15
32
  onboardingState: 'INIT' | 'AWAITING_NAME' | 'AWAITING_BOT_NAME' | 'AWAITING_PURPOSE' | 'READY';
16
33
  }
17
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,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,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;IAuBxB,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"}
@@ -32,7 +32,19 @@ class ConfigManager {
32
32
  geminiModel: process.env.GEMINI_MODEL || 'gemini-1.5-flash',
33
33
  geminiApiUrl: process.env.GEMINI_API_URL || undefined,
34
34
  geminiGatewayKey: process.env.GEMINI_GATEWAY_KEY || undefined,
35
- activeSession: 'default'
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'
36
48
  };
37
49
  }
38
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;AAoBvE,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;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;;AA5CL,sCA6CC"}
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"}
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AnthropicProvider = void 0;
4
+ class AnthropicProvider {
5
+ config;
6
+ constructor(config) {
7
+ this.config = config;
8
+ }
9
+ async generateResponse(message, history, systemInstruction) {
10
+ const apiKey = this.config.anthropicApiKey || process.env.ANTHROPIC_API_KEY;
11
+ if (!apiKey) {
12
+ throw new Error("Anthropic API Key not found.");
13
+ }
14
+ const messages = [];
15
+ // History
16
+ for (const item of history) {
17
+ messages.push({
18
+ role: item.role === 'model' ? 'assistant' : 'user',
19
+ content: item.parts[0].text
20
+ });
21
+ }
22
+ // Current Message
23
+ messages.push({ role: 'user', content: message });
24
+ try {
25
+ const response = await fetch('https://api.anthropic.com/v1/messages', {
26
+ method: 'POST',
27
+ headers: {
28
+ 'Content-Type': 'application/json',
29
+ 'x-api-key': apiKey,
30
+ 'anthropic-version': '2023-06-01'
31
+ },
32
+ body: JSON.stringify({
33
+ model: this.config.anthropicModel || 'claude-3-5-sonnet-20240620',
34
+ max_tokens: 4096,
35
+ system: systemInstruction,
36
+ messages: messages
37
+ })
38
+ });
39
+ if (!response.ok) {
40
+ const errorText = await response.text();
41
+ throw new Error(`Anthropic Error (${response.status}): ${errorText}`);
42
+ }
43
+ const data = await response.json();
44
+ return data.content[0].text;
45
+ }
46
+ catch (error) {
47
+ throw new Error(`Anthropic Error: ${error.message}`);
48
+ }
49
+ }
50
+ async countTokens(message, history) {
51
+ // Rough estimation: 4 chars = 1 token
52
+ let text = message;
53
+ for (const item of history) {
54
+ text += item.parts[0].text;
55
+ }
56
+ return Math.ceil(text.length / 4);
57
+ }
58
+ }
59
+ exports.AnthropicProvider = AnthropicProvider;
60
+ //# sourceMappingURL=anthropic.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anthropic.js","sourceRoot":"","sources":["../../src/providers/anthropic.ts"],"names":[],"mappings":";;;AAIA,MAAa,iBAAiB;IAClB,MAAM,CAAY;IAE1B,YAAY,MAAiB;QACzB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,gBAAgB,CAClB,OAAe,EACf,OAAgE,EAChE,iBAA0B;QAE1B,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,eAAe,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;QAC5E,IAAI,CAAC,MAAM,EAAE,CAAC;YACV,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;QACpD,CAAC;QAED,MAAM,QAAQ,GAAG,EAAE,CAAC;QAEpB,UAAU;QACV,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;YACzB,QAAQ,CAAC,IAAI,CAAC;gBACV,IAAI,EAAE,IAAI,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM;gBAClD,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI;aAC9B,CAAC,CAAC;QACP,CAAC;QAED,kBAAkB;QAClB,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;QAElD,IAAI,CAAC;YACD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,uCAAuC,EAAE;gBAClE,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACL,cAAc,EAAE,kBAAkB;oBAClC,WAAW,EAAE,MAAM;oBACnB,mBAAmB,EAAE,YAAY;iBACpC;gBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;oBACjB,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,cAAc,IAAI,4BAA4B;oBACjE,UAAU,EAAE,IAAI;oBAChB,MAAM,EAAE,iBAAiB;oBACzB,QAAQ,EAAE,QAAQ;iBACrB,CAAC;aACL,CAAC,CAAC;YAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACf,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;gBACxC,MAAM,IAAI,KAAK,CAAC,oBAAoB,QAAQ,CAAC,MAAM,MAAM,SAAS,EAAE,CAAC,CAAC;YAC1E,CAAC;YAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAS,CAAC;YAC1C,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAChC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,oBAAqB,KAAe,CAAC,OAAO,EAAE,CAAC,CAAC;QACpE,CAAC;IACL,CAAC;IAED,KAAK,CAAC,WAAW,CACb,OAAe,EACf,OAAgE;QAEhE,sCAAsC;QACtC,IAAI,IAAI,GAAG,OAAO,CAAC;QACnB,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;YACzB,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAC/B,CAAC;QACD,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACtC,CAAC;CACJ;AArED,8CAqEC"}