@reepoe/plugin 1.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.
package/README.md ADDED
@@ -0,0 +1,223 @@
1
+ # @reepoe/plugin
2
+
3
+ > **ReePoe AI Code Manager** - Install in any codebase for instant AI agent integration
4
+
5
+ Transform your codebase into an AI-optimized workspace in 30 seconds. ReePoe provides intelligent context management, token optimization, and seamless AI agent integration.
6
+
7
+ ## šŸš€ Quick Start
8
+
9
+ ```bash
10
+ # Install globally
11
+ npm install -g @reepoe/plugin
12
+
13
+ # Navigate to your project
14
+ cd /path/to/your/project
15
+
16
+ # Start ReePoe
17
+ reepoe-start
18
+
19
+ # Query your codebase
20
+ reepoe query "what does this codebase do?"
21
+ ```
22
+
23
+ That's it! ReePoe automatically:
24
+ - āœ… Detects your project type (Node.js, Python, Go, etc.)
25
+ - āœ… Scans your codebase
26
+ - āœ… Starts API server
27
+ - āœ… Optimizes context for AI agents
28
+
29
+ ## šŸ“¦ What's Included
30
+
31
+ - **Multi-Language Support** - JavaScript, TypeScript, Python, Go, Rust, Java, and more
32
+ - **Smart Context** - Intelligent code analysis and context optimization
33
+ - **MiniRAG** - Pattern-based instant responses
34
+ - **Token Optimization** - 90%+ token reduction
35
+ - **API Server** - RESTful API for AI agent integration
36
+ - **Dashboard** - Real-time metrics and analytics
37
+
38
+ ## šŸ› ļø Commands
39
+
40
+ ### Server Management
41
+ ```bash
42
+ reepoe-start # Start ReePoe server in background
43
+ reepoe-stop # Stop ReePoe server
44
+ reepoe-status # Check server status and health
45
+ ```
46
+
47
+ ### Queries
48
+ ```bash
49
+ reepoe query "show me all API endpoints"
50
+ reepoe query "find all test files"
51
+ reepoe query "explain the authentication system"
52
+ reepoe query "what's the project structure?"
53
+ ```
54
+
55
+ ## šŸ“” API Endpoints
56
+
57
+ Once started, ReePoe exposes:
58
+
59
+ ```
60
+ GET /health - Health check
61
+ GET /describe - Full capability description
62
+ POST /query - Natural language queries
63
+ GET /metrics - Performance analytics
64
+ GET /token-analytics - Token usage details
65
+ ```
66
+
67
+ ## šŸŽÆ Use Cases
68
+
69
+ ### For AI Agents
70
+ ```javascript
71
+ // Claude, ChatGPT, or custom agents can query ReePoe
72
+ const response = await fetch('http://localhost:8000/query', {
73
+ method: 'POST',
74
+ headers: { 'Content-Type': 'application/json' },
75
+ body: JSON.stringify({
76
+ instruction: 'analyze this codebase architecture'
77
+ })
78
+ });
79
+ ```
80
+
81
+ ### For Developers
82
+ ```bash
83
+ # Quick codebase insights
84
+ reepoe query "what external APIs are used?"
85
+ reepoe query "show me database models"
86
+ reepoe query "find security-related code"
87
+ ```
88
+
89
+ ### For Code Reviews
90
+ ```bash
91
+ # Automated analysis
92
+ reepoe query "find all TODO comments"
93
+ reepoe query "show me recent changes to auth system"
94
+ reepoe query "what tests exist for the API?"
95
+ ```
96
+
97
+ ## šŸ”§ Configuration
98
+
99
+ ReePoe auto-configures on first start, but you can customize:
100
+
101
+ ```json
102
+ // reepoe.config.json (auto-generated)
103
+ {
104
+ "project": {
105
+ "name": "my-awesome-app",
106
+ "type": "javascript",
107
+ "framework": "Express"
108
+ },
109
+ "api": {
110
+ "port": 8000,
111
+ "host": "127.0.0.1"
112
+ },
113
+ "mini_rag": {
114
+ "enabled": true,
115
+ "cta_whitelist": ["run_tests", "search_symbols"]
116
+ }
117
+ }
118
+ ```
119
+
120
+ ## šŸ“Š Supported Languages
121
+
122
+ | Language | Support Level | Symbol Extraction |
123
+ |----------|---------------|-------------------|
124
+ | JavaScript/TypeScript | āœ… Full | Functions, Classes, Interfaces, Types |
125
+ | Python | āœ… Full | Functions, Classes, Methods, Decorators |
126
+ | Go | āœ… Full | Functions, Structs, Interfaces, Methods |
127
+ | Rust | āš ļø Generic | Functions, Structs, Traits |
128
+ | Java | āš ļø Generic | Classes, Methods, Interfaces |
129
+ | C/C++ | āš ļø Generic | Functions, Classes, Structs |
130
+
131
+ ## šŸ—ļø Architecture
132
+
133
+ ```
134
+ ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā” ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā” ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
135
+ │ AI Agents │────│ ReePoe API │────│ LLM Providers │
136
+ │ (Claude, GPT) │ │ │ │ (OpenRouter) │
137
+ ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜ ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜ ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜
138
+ │
139
+ ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā–¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
140
+ │ Your Codebase │
141
+ │ (Any Language)│
142
+ ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜
143
+ ```
144
+
145
+ ## šŸ’” Features
146
+
147
+ ### Intelligent Context Management
148
+ - Automatic codebase indexing
149
+ - Symbol-level navigation
150
+ - Context slicing and optimization
151
+ - Reference-based loading
152
+
153
+ ### Token Optimization
154
+ - 90%+ token reduction
155
+ - Smart context compression
156
+ - Pattern-based caching (MiniRAG)
157
+ - Real-time usage tracking
158
+
159
+ ### AI Agent Integration
160
+ - Standard REST API
161
+ - MCP (Model Context Protocol) support
162
+ - Auto-discovery via `/describe`
163
+ - Comprehensive onboarding
164
+
165
+ ## šŸ› Troubleshooting
166
+
167
+ ### Server won't start
168
+ ```bash
169
+ # Check status
170
+ reepoe-status
171
+
172
+ # Check if port is in use
173
+ lsof -i :8000
174
+
175
+ # Try different port
176
+ # Edit reepoe.config.json and change api.port
177
+ ```
178
+
179
+ ### Binary permissions (Unix/Linux)
180
+ ```bash
181
+ chmod +x ~/.npm-global/lib/node_modules/@reepoe/plugin/binaries/reepoe-*
182
+ ```
183
+
184
+ ### Reset configuration
185
+ ```bash
186
+ rm reepoe.config.json
187
+ reepoe-start # Will regenerate
188
+ ```
189
+
190
+ ## šŸ“ Requirements
191
+
192
+ - **Node.js** 16.0.0 or higher
193
+ - **Operating Systems:** macOS, Linux, Windows
194
+ - **Architecture:** x64, arm64
195
+
196
+ ## šŸ”’ Security
197
+
198
+ - Runs locally on your machine
199
+ - No data sent to external servers (except configured LLM APIs)
200
+ - Closed-source binary distribution
201
+ - Whitelist-based CTA execution
202
+
203
+ ## šŸ“ˆ Performance
204
+
205
+ - **Install time:** < 60 seconds
206
+ - **Startup time:** < 3 seconds
207
+ - **Query latency:** < 2 seconds
208
+ - **Memory usage:** < 500MB
209
+
210
+ ## šŸ†˜ Support
211
+
212
+ - **Documentation:** https://reepoe.com/docs
213
+ - **Issues:** https://github.com/MarcAndre72/ReePoe/issues
214
+ - **API Reference:** http://localhost:8000/describe (after starting)
215
+
216
+ ## šŸ“„ License
217
+
218
+ Proprietary - See LICENSE file for details
219
+
220
+ ---
221
+
222
+ **ReePoe** - Making AI agents smarter, one codebase at a time šŸš€
223
+
package/bin/admin.js ADDED
@@ -0,0 +1,286 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * ReePoe Admin CLI - Administrative tools
4
+ */
5
+
6
+ const ActivationClient = require('../lib/activation-client');
7
+ const readline = require('readline');
8
+ const fs = require('fs');
9
+
10
+ const client = new ActivationClient();
11
+
12
+ async function promptInput(question) {
13
+ const rl = readline.createInterface({
14
+ input: process.stdin,
15
+ output: process.stdout
16
+ });
17
+
18
+ return new Promise((resolve) => {
19
+ rl.question(question, (answer) => {
20
+ rl.close();
21
+ resolve(answer.trim());
22
+ });
23
+ });
24
+ }
25
+
26
+ async function adminLogin() {
27
+ console.log('\n╔═══════════════════════════════════════════════════════════════╗');
28
+ console.log('ā•‘ šŸ” ReePoe Admin Login ā•‘');
29
+ console.log('ā•šā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•\n');
30
+
31
+ const email = await promptInput('šŸ“§ Admin Email: ');
32
+ const adminCode = await promptInput('šŸ”‘ Admin Code: ');
33
+
34
+ console.log('\nā³ Authenticating...\n');
35
+
36
+ try {
37
+ const result = await client.adminLogin(email, adminCode);
38
+
39
+ if (result.success) {
40
+ console.log('āœ… Admin access granted!');
41
+ console.log(` Token valid for: 1 hour`);
42
+ console.log(` Permissions: Full admin access\n`);
43
+ console.log('Commands available:');
44
+ console.log(' reepoe admin users list');
45
+ console.log(' reepoe admin codes generate');
46
+ console.log(' reepoe admin metrics\n');
47
+ } else {
48
+ console.log(`āŒ Login failed: ${result.message || 'Invalid credentials'}\n`);
49
+ process.exit(1);
50
+ }
51
+ } catch (error) {
52
+ console.error(`āŒ Login error: ${error.message}\n`);
53
+ process.exit(1);
54
+ }
55
+ }
56
+
57
+ async function listUsers(options = {}) {
58
+ try {
59
+ const result = await client.adminListUsers(options.status, options.limit || 50);
60
+
61
+ console.log('\n╔═══════════════════════════════════════════════════════════════╗');
62
+ console.log(`ā•‘ šŸ‘„ Users (${result.total} total)${' '.repeat(47 - result.total.toString().length)}ā•‘`);
63
+ console.log('ā•šā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•\n');
64
+
65
+ if (result.users.length === 0) {
66
+ console.log('No users found.\n');
67
+ return;
68
+ }
69
+
70
+ // Table header
71
+ console.log('Email Status Queries Tokens Saved Expires');
72
+ console.log('─────────────────────────────────────────────────────────────────');
73
+
74
+ for (const user of result.users) {
75
+ const email = user.email.substring(0, 25).padEnd(26);
76
+ const status = user.status.padEnd(9);
77
+ const queries = String(user.total_queries || 0).padStart(7);
78
+ const tokens = String(user.total_tokens_saved || 0).padStart(13);
79
+
80
+ let expires = ' - ';
81
+ if (user.expires_at) {
82
+ const expDate = new Date(user.expires_at);
83
+ const days = Math.ceil((expDate - new Date()) / (1000 * 60 * 60 * 24));
84
+ expires = `${days}d`.padStart(8);
85
+ }
86
+
87
+ console.log(`${email}${status}${queries} ${tokens}${expires}`);
88
+ }
89
+
90
+ console.log('\nšŸ’” Commands:');
91
+ console.log(' reepoe admin users extend <email> +30d');
92
+ console.log(' reepoe admin users revoke <email>\n');
93
+
94
+ } catch (error) {
95
+ console.error(`\nāŒ Failed to list users: ${error.message}\n`);
96
+ process.exit(1);
97
+ }
98
+ }
99
+
100
+ async function generateCodes(count, options = {}) {
101
+ try {
102
+ const codeType = options.type || 'ALPHA';
103
+ const notes = options.notes;
104
+ const adminEmail = 'admin'; // TODO: Get from admin session
105
+
106
+ console.log('\n╔═══════════════════════════════════════════════════════════════╗');
107
+ console.log('ā•‘ šŸ”‘ Generating Activation Codes ā•‘');
108
+ console.log('ā•šā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•\n');
109
+
110
+ console.log(`Type: ${codeType}`);
111
+ console.log(`Count: ${count}`);
112
+ console.log(`Expires: 30 days from now\n`);
113
+
114
+ console.log('ā³ Generating...\n');
115
+
116
+ const result = await client.adminGenerateCodes(count, codeType, adminEmail, notes);
117
+
118
+ if (result.success) {
119
+ console.log(`āœ… Generated ${result.count} codes!\n`);
120
+
121
+ console.log('Codes:');
122
+ result.codes.forEach((code, i) => {
123
+ console.log(` ${i + 1}. ${code}`);
124
+ });
125
+
126
+ // Save to file
127
+ const filename = `alpha_codes_${Date.now()}.txt`;
128
+ fs.writeFileSync(filename, result.codes.join('\n'));
129
+
130
+ console.log(`\nšŸ“„ Saved to: ${filename}`);
131
+ console.log(`\nšŸ’” Share these codes with alpha testers!\n`);
132
+ } else {
133
+ console.log(`āŒ Failed to generate codes\n`);
134
+ }
135
+
136
+ } catch (error) {
137
+ console.error(`\nāŒ Code generation failed: ${error.message}\n`);
138
+ process.exit(1);
139
+ }
140
+ }
141
+
142
+ async function extendUser(email, days) {
143
+ try {
144
+ const adminEmail = 'admin'; // TODO: Get from admin session
145
+
146
+ console.log(`\nā³ Extending ${email} by ${days} days...\n`);
147
+
148
+ const result = await client.adminExtendUser(email, days, adminEmail);
149
+
150
+ if (result.success) {
151
+ console.log(`āœ… ${result.message}`);
152
+ console.log(` New expiration: ${new Date(result.new_expires_at).toLocaleDateString()}\n`);
153
+ } else {
154
+ console.log(`āŒ Extension failed: ${result.error}\n`);
155
+ }
156
+
157
+ } catch (error) {
158
+ console.error(`\nāŒ Extension error: ${error.message}\n`);
159
+ process.exit(1);
160
+ }
161
+ }
162
+
163
+ // Parse command line arguments
164
+ const args = process.argv.slice(2);
165
+ const command = args[0];
166
+ const subcommand = args[1];
167
+
168
+ async function showUserMetrics(email) {
169
+ const axios = require('axios');
170
+
171
+ try {
172
+ console.log(`\nšŸ“Š Loading metrics for ${email}...\n`);
173
+
174
+ // Get aggregate metrics (same as dashboard)
175
+ const API_URL = process.env.REEPOE_API_URL || 'http://localhost:8000';
176
+ const res = await axios.get(`${API_URL}/metrics`);
177
+ const data = res.data;
178
+
179
+ console.log('╔═══════════════════════════════════════════════════════════════╗');
180
+ console.log(`ā•‘ šŸ“Š User Metrics - ${email.substring(0, 42).padEnd(42)}ā•‘`);
181
+ console.log('ā•šā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•\n');
182
+
183
+ console.log('ALL TIME (Aggregate):');
184
+ console.log('─────────────────────────────────────────────────────');
185
+ console.log(` Total Queries: ${data.lifetime?.total_queries || 0}`);
186
+ console.log(` Tokens Saved: ${(data.lifetime?.tokens_saved || 0).toLocaleString()}`);
187
+ console.log(` MiniRAG Hits: ${data.lifetime?.mini_rag_hits || 0}`);
188
+ console.log(` Cache Hit Rate: ${((data.performance?.cache_hit_rate || 0) * 100).toFixed(1)}%`);
189
+ console.log('\nšŸ’” Note: Showing aggregate metrics (per-user tracking in Phase 3C)\n');
190
+
191
+ } catch (error) {
192
+ console.error(`\nāŒ Failed to load metrics: ${error.message}\n`);
193
+ process.exit(1);
194
+ }
195
+ }
196
+
197
+ async function showAggregateMetrics() {
198
+ const axios = require('axios');
199
+
200
+ try {
201
+ console.log('\nšŸ“Š Loading aggregate metrics...\n');
202
+
203
+ // Get users and metrics
204
+ const users = await client.adminListUsers();
205
+ const API_URL = process.env.REEPOE_API_URL || 'http://localhost:8000';
206
+ const res = await axios.get(`${API_URL}/metrics`);
207
+ const data = res.data;
208
+
209
+ console.log('╔═══════════════════════════════════════════════════════════════╗');
210
+ console.log('ā•‘ šŸ“Š ReePoe Admin Dashboard - Aggregate Metrics ā•‘');
211
+ console.log('ā•šā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•\n');
212
+
213
+ console.log('USERS');
214
+ console.log('─────────────────────────────────────────────────────');
215
+ const activeUsers = users.users.filter(u => u.status === 'active').length;
216
+ const waitlistUsers = users.users.filter(u => u.status === 'waitlist').length;
217
+ console.log(` Total: ${users.total || 0}`);
218
+ console.log(` Active: ${activeUsers}`);
219
+ console.log(` Waitlist: ${waitlistUsers}`);
220
+
221
+ console.log('\nUSAGE (ALL USERS)');
222
+ console.log('─────────────────────────────────────────────────────');
223
+ console.log(` Total Queries: ${data.lifetime?.total_queries || 0}`);
224
+ console.log(` Tokens Saved: ${(data.lifetime?.tokens_saved || 0).toLocaleString()}`);
225
+ console.log(` MiniRAG Hits: ${data.lifetime?.mini_rag_hits || 0}`);
226
+ console.log(` Cache Hit Rate: ${((data.performance?.cache_hit_rate || 0) * 100).toFixed(1)}%`);
227
+
228
+ console.log('\nPERFORMANCE');
229
+ console.log('─────────────────────────────────────────────────────');
230
+ console.log(` Token Savings Rate: ${((data.performance?.token_savings_rate || 0) * 100).toFixed(1)}%`);
231
+ console.log(` Avg Response Time: ${(data.performance?.avg_response_time_ms || 0).toFixed(0)}ms`);
232
+
233
+ console.log('\n🌐 Dashboard: https://reepoe.com\n');
234
+
235
+ } catch (error) {
236
+ console.error(`\nāŒ Failed to load metrics: ${error.message}\n`);
237
+ process.exit(1);
238
+ }
239
+ }
240
+
241
+ async function main() {
242
+ if (command === 'login') {
243
+ await adminLogin();
244
+ } else if (command === 'users') {
245
+ if (subcommand === 'list') {
246
+ await listUsers({ status: args[2] });
247
+ } else if (subcommand === 'extend' && args[2]) {
248
+ const email = args[2];
249
+ const days = parseInt(args[3]) || 30;
250
+ await extendUser(email, days);
251
+ } else if (subcommand === 'metrics' && args[2]) {
252
+ const email = args[2];
253
+ await showUserMetrics(email);
254
+ } else {
255
+ console.log('\nUsage:');
256
+ console.log(' reepoe admin users list [status]');
257
+ console.log(' reepoe admin users extend <email> <days>');
258
+ console.log(' reepoe admin users metrics <email>\n');
259
+ }
260
+ } else if (command === 'codes') {
261
+ if (subcommand === 'generate' && args[2]) {
262
+ const count = parseInt(args[2]);
263
+ await generateCodes(count);
264
+ } else {
265
+ console.log('\nUsage:');
266
+ console.log(' reepoe admin codes generate <count>\n');
267
+ }
268
+ } else if (command === 'metrics') {
269
+ await showAggregateMetrics();
270
+ } else {
271
+ console.log('\n╔═══════════════════════════════════════════════════════════════╗');
272
+ console.log('ā•‘ šŸ” ReePoe Admin CLI ā•‘');
273
+ console.log('ā•šā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•\n');
274
+ console.log('Commands:');
275
+ console.log(' reepoe admin login');
276
+ console.log(' reepoe admin users list');
277
+ console.log(' reepoe admin users extend <email> <days>');
278
+ console.log(' reepoe admin codes generate <count>\n');
279
+ }
280
+ }
281
+
282
+ main().catch(error => {
283
+ console.error(`āŒ Error: ${error.message}`);
284
+ process.exit(1);
285
+ });
286
+
@@ -0,0 +1,69 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * ReePoe Extension Request - User requests access extension
4
+ */
5
+
6
+ const ActivationClient = require('../lib/activation-client');
7
+ const readline = require('readline');
8
+
9
+ async function requestExtension() {
10
+ const client = new ActivationClient();
11
+
12
+ // Load activation
13
+ const activation = client.loadActivation();
14
+
15
+ if (!activation) {
16
+ console.log('\nāŒ No activation found');
17
+ console.log(' Please activate ReePoe first: reepoe-start\n');
18
+ process.exit(1);
19
+ }
20
+
21
+ console.log('\n╔═══════════════════════════════════════════════════════════════╗');
22
+ console.log('ā•‘ šŸ“§ Request Access Extension ā•‘');
23
+ console.log('ā•šā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•\n');
24
+
25
+ console.log(`Your current access expires:`);
26
+ if (activation.expires_at) {
27
+ const expiresDate = new Date(activation.expires_at);
28
+ const daysRemaining = Math.ceil((expiresDate - new Date()) / (1000 * 60 * 60 * 24));
29
+ console.log(` ${expiresDate.toLocaleDateString()} (${daysRemaining} days remaining)\n`);
30
+ } else {
31
+ console.log(' Lifetime access\n');
32
+ }
33
+
34
+ const rl = readline.createInterface({
35
+ input: process.stdin,
36
+ output: process.stdout
37
+ });
38
+
39
+ const reason = await new Promise((resolve) => {
40
+ rl.question('šŸ’¬ Reason for extension (optional): ', (answer) => {
41
+ rl.close();
42
+ resolve(answer.trim());
43
+ });
44
+ });
45
+
46
+ console.log('\nā³ Sending extension request...\n');
47
+
48
+ try {
49
+ const result = await client.requestExtension(activation.email, reason || 'Standard extension request');
50
+
51
+ if (result.success) {
52
+ console.log('╔═══════════════════════════════════════════════════════════════╗');
53
+ console.log('ā•‘ āœ… Extension Request Sent! ā•‘');
54
+ console.log('ā•šā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•\n');
55
+ console.log('Your request has been sent to the admin team.');
56
+ console.log('You\'ll be notified when it\'s reviewed.\n');
57
+ console.log('šŸ’” Typically reviewed within 24-48 hours.\n');
58
+ } else {
59
+ console.log(`āŒ Request failed: ${result.message}\n`);
60
+ }
61
+
62
+ } catch (error) {
63
+ console.error(`\nāŒ Error: ${error.message}\n`);
64
+ process.exit(1);
65
+ }
66
+ }
67
+
68
+ requestExtension();
69
+
package/bin/metrics.js ADDED
@@ -0,0 +1,89 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * ReePoe Metrics - Display user's personal statistics
4
+ */
5
+
6
+ const ActivationClient = require('../lib/activation-client');
7
+ const fs = require('fs');
8
+ const path = require('path');
9
+ const os = require('os');
10
+
11
+ async function showMetrics() {
12
+ const axios = require('axios');
13
+ const client = new ActivationClient();
14
+
15
+ // Load activation to get email
16
+ const activation = client.loadActivation();
17
+
18
+ if (!activation) {
19
+ console.log('\nāŒ No activation found');
20
+ console.log(' Please activate ReePoe first: reepoe-start\n');
21
+ process.exit(1);
22
+ }
23
+
24
+ console.log('\nšŸ“Š Loading your ReePoe metrics...\n');
25
+
26
+ try {
27
+ // Use per-user metrics endpoint (NOT aggregate)
28
+ const API_URL = process.env.REEPOE_API_URL || 'http://localhost:8000';
29
+ const res = await axios.get(`${API_URL}/api/metrics/user/${activation.email}`);
30
+ const data = res.data;
31
+
32
+ // Per-user endpoint returns the correct structure already
33
+ const metrics = {
34
+ metrics: data.metrics, // Already has today, week, alltime
35
+ account: data.account // Already has activated_at, expires_at, status
36
+ };
37
+
38
+ console.log('╔═══════════════════════════════════════════════════════════════╗');
39
+ console.log(`ā•‘ šŸ“Š ReePoe Metrics - ${activation.email.padEnd(39)}ā•‘`);
40
+ console.log('ā•šā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•\n');
41
+
42
+ console.log('TODAY');
43
+ console.log('─────────────────────────────────────────────────────');
44
+ console.log(` Queries: ${metrics.metrics.today.queries || 0}`);
45
+ console.log(` Tokens Saved: ${(metrics.metrics.today.tokens_saved || 0).toLocaleString()}`);
46
+ console.log(` Cost Saved: $${(metrics.metrics.today.cost_saved || 0).toFixed(2)}`);
47
+
48
+ console.log('\nTHIS WEEK');
49
+ console.log('─────────────────────────────────────────────────────');
50
+ console.log(` Queries: ${metrics.metrics.week.queries || 0}`);
51
+ console.log(` Tokens Saved: ${(metrics.metrics.week.tokens_saved || 0).toLocaleString()}`);
52
+ console.log(` Cost Saved: $${(metrics.metrics.week.cost_saved || 0).toFixed(2)}`);
53
+
54
+ console.log('\nALL TIME');
55
+ console.log('─────────────────────────────────────────────────────');
56
+ console.log(` Queries: ${metrics.metrics.alltime.queries || 0}`);
57
+ console.log(` Tokens Saved: ${(metrics.metrics.alltime.tokens_saved || 0).toLocaleString()}`);
58
+ console.log(` Cost Saved: $${(metrics.metrics.alltime.cost_saved || 0).toFixed(2)}`);
59
+ console.log(` Patterns Learned: ${metrics.metrics.alltime.patterns_learned || 0}`);
60
+ console.log(` Patterns Active: ${metrics.metrics.alltime.patterns_active || 0}`);
61
+
62
+ console.log('\nACCOUNT INFO');
63
+ console.log('─────────────────────────────────────────────────────');
64
+ console.log(` Status: āœ… ${metrics.account.status}`);
65
+
66
+ if (metrics.account.expires_at) {
67
+ const expiresDate = new Date(metrics.account.expires_at);
68
+ const daysRemaining = Math.ceil((expiresDate - new Date()) / (1000 * 60 * 60 * 24));
69
+ console.log(` Expires: ${expiresDate.toLocaleDateString()}`);
70
+ console.log(` Days Remaining: ${daysRemaining}`);
71
+ }
72
+
73
+ console.log('\nšŸ’” Your Impact:');
74
+ console.log(` You've saved ${metrics.metrics.alltime.tokens_saved.toLocaleString()} tokens!`);
75
+ if (metrics.metrics.alltime.patterns_active > 0) {
76
+ console.log(` ${metrics.metrics.alltime.patterns_active} query types are now instant (0 tokens)\n`);
77
+ }
78
+
79
+ } catch (error) {
80
+ console.error(`\nāŒ Failed to load metrics: ${error.message}\n`);
81
+ process.exit(1);
82
+ }
83
+ }
84
+
85
+ showMetrics().catch(error => {
86
+ console.error(`āŒ Error: ${error.message}`);
87
+ process.exit(1);
88
+ });
89
+