@relayplane/proxy 0.2.0 → 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/dist/telemetry.js DELETED
@@ -1,315 +0,0 @@
1
- "use strict";
2
- /**
3
- * RelayPlane Proxy Telemetry
4
- *
5
- * Anonymized telemetry collection for improving model routing.
6
- *
7
- * What we collect (exact schema):
8
- * - device_id: anonymous random ID
9
- * - task_type: inferred from token patterns, NOT prompt content
10
- * - model: which model was used
11
- * - tokens_in/out: token counts
12
- * - latency_ms: response time
13
- * - success: whether request succeeded
14
- * - cost_usd: estimated cost
15
- *
16
- * What we NEVER collect:
17
- * - Prompts or responses
18
- * - File paths or contents
19
- * - Anything that could identify you or your project
20
- *
21
- * @packageDocumentation
22
- */
23
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
24
- if (k2 === undefined) k2 = k;
25
- var desc = Object.getOwnPropertyDescriptor(m, k);
26
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
27
- desc = { enumerable: true, get: function() { return m[k]; } };
28
- }
29
- Object.defineProperty(o, k2, desc);
30
- }) : (function(o, m, k, k2) {
31
- if (k2 === undefined) k2 = k;
32
- o[k2] = m[k];
33
- }));
34
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
35
- Object.defineProperty(o, "default", { enumerable: true, value: v });
36
- }) : function(o, v) {
37
- o["default"] = v;
38
- });
39
- var __importStar = (this && this.__importStar) || (function () {
40
- var ownKeys = function(o) {
41
- ownKeys = Object.getOwnPropertyNames || function (o) {
42
- var ar = [];
43
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
44
- return ar;
45
- };
46
- return ownKeys(o);
47
- };
48
- return function (mod) {
49
- if (mod && mod.__esModule) return mod;
50
- var result = {};
51
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
52
- __setModuleDefault(result, mod);
53
- return result;
54
- };
55
- })();
56
- Object.defineProperty(exports, "__esModule", { value: true });
57
- exports.inferTaskType = inferTaskType;
58
- exports.estimateCost = estimateCost;
59
- exports.setAuditMode = setAuditMode;
60
- exports.isAuditMode = isAuditMode;
61
- exports.setOfflineMode = setOfflineMode;
62
- exports.isOfflineMode = isOfflineMode;
63
- exports.getAuditBuffer = getAuditBuffer;
64
- exports.clearAuditBuffer = clearAuditBuffer;
65
- exports.recordTelemetry = recordTelemetry;
66
- exports.getLocalTelemetry = getLocalTelemetry;
67
- exports.getTelemetryStats = getTelemetryStats;
68
- exports.clearTelemetry = clearTelemetry;
69
- exports.getTelemetryPath = getTelemetryPath;
70
- exports.printTelemetryDisclosure = printTelemetryDisclosure;
71
- const fs = __importStar(require("fs"));
72
- const path = __importStar(require("path"));
73
- const config_js_1 = require("./config.js");
74
- /**
75
- * Local telemetry store using SQLite (via Ledger)
76
- */
77
- const TELEMETRY_FILE = path.join((0, config_js_1.getConfigDir)(), 'telemetry.jsonl');
78
- // In-memory buffer for audit mode
79
- let auditBuffer = [];
80
- let auditMode = false;
81
- let offlineMode = false;
82
- /**
83
- * Task type inference based on token patterns
84
- * This infers task type from request characteristics, NOT from prompt content
85
- */
86
- function inferTaskType(inputTokens, outputTokens, model, hasTools = false) {
87
- // Simple heuristics based on token patterns
88
- const ratio = outputTokens / Math.max(inputTokens, 1);
89
- if (hasTools) {
90
- return 'tool_use';
91
- }
92
- if (inputTokens > 10000) {
93
- return 'long_context';
94
- }
95
- if (ratio > 5) {
96
- return 'generation';
97
- }
98
- if (ratio < 0.3 && outputTokens < 100) {
99
- return 'classification';
100
- }
101
- if (inputTokens < 500 && outputTokens < 500) {
102
- return 'quick_task';
103
- }
104
- if (inputTokens > 2000 && outputTokens > 500) {
105
- return 'code_review';
106
- }
107
- if (outputTokens > 1000) {
108
- return 'content_generation';
109
- }
110
- return 'general';
111
- }
112
- /**
113
- * Estimate cost based on model and token counts
114
- * Pricing as of 2024 (USD per 1M tokens)
115
- */
116
- const MODEL_PRICING = {
117
- // Anthropic
118
- 'claude-opus-4-20250514': { input: 15.0, output: 75.0 },
119
- 'claude-sonnet-4-20250514': { input: 3.0, output: 15.0 },
120
- 'claude-3-5-sonnet-20241022': { input: 3.0, output: 15.0 },
121
- 'claude-3-5-sonnet-20240620': { input: 3.0, output: 15.0 },
122
- 'claude-3-5-haiku-20241022': { input: 0.8, output: 4.0 },
123
- 'claude-3-opus-20240229': { input: 15.0, output: 75.0 },
124
- 'claude-3-sonnet-20240229': { input: 3.0, output: 15.0 },
125
- 'claude-3-haiku-20240307': { input: 0.25, output: 1.25 },
126
- // OpenAI
127
- 'gpt-4o': { input: 2.5, output: 10.0 },
128
- 'gpt-4o-mini': { input: 0.15, output: 0.60 },
129
- 'gpt-4-turbo': { input: 10.0, output: 30.0 },
130
- 'gpt-4': { input: 30.0, output: 60.0 },
131
- 'gpt-3.5-turbo': { input: 0.5, output: 1.5 },
132
- // Default for unknown models
133
- 'default': { input: 1.0, output: 3.0 },
134
- };
135
- function estimateCost(model, inputTokens, outputTokens) {
136
- const pricing = MODEL_PRICING[model] || MODEL_PRICING['default'];
137
- const inputCost = (inputTokens / 1_000_000) * pricing.input;
138
- const outputCost = (outputTokens / 1_000_000) * pricing.output;
139
- return Math.round((inputCost + outputCost) * 10000) / 10000; // Round to 4 decimal places
140
- }
141
- /**
142
- * Set audit mode - shows telemetry payload before sending
143
- */
144
- function setAuditMode(enabled) {
145
- auditMode = enabled;
146
- }
147
- /**
148
- * Check if audit mode is enabled
149
- */
150
- function isAuditMode() {
151
- return auditMode;
152
- }
153
- /**
154
- * Set offline mode - disables all network calls except LLM
155
- */
156
- function setOfflineMode(enabled) {
157
- offlineMode = enabled;
158
- }
159
- /**
160
- * Check if offline mode is enabled
161
- */
162
- function isOfflineMode() {
163
- return offlineMode;
164
- }
165
- /**
166
- * Get pending audit events
167
- */
168
- function getAuditBuffer() {
169
- return [...auditBuffer];
170
- }
171
- /**
172
- * Clear audit buffer
173
- */
174
- function clearAuditBuffer() {
175
- auditBuffer = [];
176
- }
177
- /**
178
- * Record a telemetry event
179
- */
180
- function recordTelemetry(event) {
181
- if (!(0, config_js_1.isTelemetryEnabled)() && !auditMode) {
182
- return; // Telemetry disabled and not in audit mode
183
- }
184
- const fullEvent = {
185
- ...event,
186
- device_id: (0, config_js_1.getDeviceId)(),
187
- timestamp: new Date().toISOString(),
188
- };
189
- if (auditMode) {
190
- // In audit mode, buffer events and print them
191
- auditBuffer.push(fullEvent);
192
- console.log('\n📊 [TELEMETRY AUDIT] The following data would be collected:');
193
- console.log(JSON.stringify(fullEvent, null, 2));
194
- console.log('');
195
- return;
196
- }
197
- if (!(0, config_js_1.isTelemetryEnabled)()) {
198
- return;
199
- }
200
- // Store locally (append to JSONL file)
201
- try {
202
- const configDir = (0, config_js_1.getConfigDir)();
203
- if (!fs.existsSync(configDir)) {
204
- fs.mkdirSync(configDir, { recursive: true });
205
- }
206
- fs.appendFileSync(TELEMETRY_FILE, JSON.stringify(fullEvent) + '\n');
207
- }
208
- catch (err) {
209
- // Silently fail - telemetry should never break the proxy
210
- }
211
- }
212
- /**
213
- * Get local telemetry data
214
- */
215
- function getLocalTelemetry() {
216
- try {
217
- if (!fs.existsSync(TELEMETRY_FILE)) {
218
- return [];
219
- }
220
- const data = fs.readFileSync(TELEMETRY_FILE, 'utf-8');
221
- return data
222
- .split('\n')
223
- .filter(line => line.trim())
224
- .map(line => JSON.parse(line));
225
- }
226
- catch (err) {
227
- return [];
228
- }
229
- }
230
- /**
231
- * Get telemetry stats summary
232
- */
233
- function getTelemetryStats() {
234
- const events = getLocalTelemetry();
235
- const byModel = {};
236
- const byTaskType = {};
237
- let totalCost = 0;
238
- let successCount = 0;
239
- for (const event of events) {
240
- totalCost += event.cost_usd;
241
- if (event.success)
242
- successCount++;
243
- if (!byModel[event.model]) {
244
- byModel[event.model] = { count: 0, cost: 0 };
245
- }
246
- byModel[event.model].count++;
247
- byModel[event.model].cost += event.cost_usd;
248
- if (!byTaskType[event.task_type]) {
249
- byTaskType[event.task_type] = { count: 0, cost: 0 };
250
- }
251
- byTaskType[event.task_type].count++;
252
- byTaskType[event.task_type].cost += event.cost_usd;
253
- }
254
- return {
255
- totalEvents: events.length,
256
- totalCost: Math.round(totalCost * 100) / 100,
257
- byModel,
258
- byTaskType,
259
- successRate: events.length > 0 ? successCount / events.length : 0,
260
- };
261
- }
262
- /**
263
- * Clear all local telemetry data
264
- */
265
- function clearTelemetry() {
266
- try {
267
- if (fs.existsSync(TELEMETRY_FILE)) {
268
- fs.unlinkSync(TELEMETRY_FILE);
269
- }
270
- }
271
- catch (err) {
272
- // Silently fail
273
- }
274
- }
275
- /**
276
- * Get telemetry file path
277
- */
278
- function getTelemetryPath() {
279
- return TELEMETRY_FILE;
280
- }
281
- /**
282
- * Print telemetry disclosure message
283
- */
284
- function printTelemetryDisclosure() {
285
- console.log(`
286
- ╭─────────────────────────────────────────────────────────────────────╮
287
- │ 📊 TELEMETRY DISCLOSURE │
288
- ╰─────────────────────────────────────────────────────────────────────╯
289
-
290
- RelayPlane collects anonymous telemetry to improve model routing.
291
-
292
- What we collect:
293
- • Anonymous device ID (random, not fingerprintable)
294
- • Task type (inferred from token patterns, NOT your prompts)
295
- • Model used, token counts, latency, success/failure
296
- • Estimated cost
297
-
298
- What we NEVER collect:
299
- • Your prompts or model responses
300
- • File paths or contents
301
- • Anything that could identify you or your project
302
-
303
- How to verify:
304
- • Run with --audit to see exact payloads before they're sent
305
- • Run with --offline to disable all telemetry transmission
306
- • Full source code: https://github.com/RelayPlane/proxy
307
-
308
- To opt out completely:
309
- $ relayplane-proxy telemetry off
310
-
311
- Learn more: https://relayplane.com/privacy
312
-
313
- `);
314
- }
315
- //# sourceMappingURL=telemetry.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"telemetry.js","sourceRoot":"","sources":["../src/telemetry.ts"],"names":[],"mappings":"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"}
package/src/cli.ts DELETED
@@ -1,341 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * RelayPlane Proxy CLI
4
- *
5
- * Intelligent AI model routing proxy server.
6
- *
7
- * Usage:
8
- * npx @relayplane/proxy [command] [options]
9
- * relayplane-proxy [command] [options]
10
- *
11
- * Commands:
12
- * (default) Start the proxy server
13
- * telemetry [on|off|status] Manage telemetry settings
14
- * stats Show usage statistics
15
- * config Show configuration
16
- *
17
- * Options:
18
- * --port <number> Port to listen on (default: 3001)
19
- * --host <string> Host to bind to (default: 127.0.0.1)
20
- * --offline Disable all network calls except LLM endpoints
21
- * --audit Show telemetry payloads before sending
22
- * -v, --verbose Enable verbose logging
23
- * -h, --help Show this help message
24
- * --version Show version
25
- *
26
- * Environment Variables:
27
- * ANTHROPIC_API_KEY Anthropic API key
28
- * OPENAI_API_KEY OpenAI API key
29
- * GEMINI_API_KEY Google Gemini API key
30
- * XAI_API_KEY xAI/Grok API key
31
- * MOONSHOT_API_KEY Moonshot API key
32
- *
33
- * @packageDocumentation
34
- */
35
-
36
- import { startProxy } from '@relayplane/openclaw';
37
- import {
38
- loadConfig,
39
- isFirstRun,
40
- markFirstRunComplete,
41
- isTelemetryEnabled,
42
- enableTelemetry,
43
- disableTelemetry,
44
- getConfigPath,
45
- setApiKey,
46
- } from './config.js';
47
- import {
48
- printTelemetryDisclosure,
49
- setAuditMode,
50
- setOfflineMode,
51
- getTelemetryStats,
52
- getTelemetryPath,
53
- } from './telemetry.js';
54
-
55
- const VERSION = '0.2.0';
56
-
57
- function printHelp(): void {
58
- console.log(`
59
- RelayPlane Proxy - Intelligent AI Model Routing
60
-
61
- Usage:
62
- npx @relayplane/proxy [command] [options]
63
- relayplane-proxy [command] [options]
64
-
65
- Commands:
66
- (default) Start the proxy server
67
- telemetry [on|off|status] Manage telemetry settings
68
- stats Show usage statistics
69
- config Show configuration
70
-
71
- Options:
72
- --port <number> Port to listen on (default: 3001)
73
- --host <string> Host to bind to (default: 127.0.0.1)
74
- --offline Disable all network calls except LLM endpoints
75
- --audit Show telemetry payloads before sending
76
- -v, --verbose Enable verbose logging
77
- -h, --help Show this help message
78
- --version Show version
79
-
80
- Environment Variables:
81
- ANTHROPIC_API_KEY Anthropic API key
82
- OPENAI_API_KEY OpenAI API key
83
- GEMINI_API_KEY Google Gemini API key (optional)
84
- XAI_API_KEY xAI/Grok API key (optional)
85
- MOONSHOT_API_KEY Moonshot API key (optional)
86
-
87
- Example:
88
- # Start proxy on default port
89
- npx @relayplane/proxy
90
-
91
- # Start with audit mode (see telemetry before it's sent)
92
- npx @relayplane/proxy --audit
93
-
94
- # Start in offline mode (no telemetry transmission)
95
- npx @relayplane/proxy --offline
96
-
97
- # Disable telemetry completely
98
- npx @relayplane/proxy telemetry off
99
-
100
- # Then point your SDKs to the proxy
101
- export ANTHROPIC_BASE_URL=http://localhost:3001
102
- export OPENAI_BASE_URL=http://localhost:3001
103
-
104
- Learn more: https://relayplane.com/docs
105
- `);
106
- }
107
-
108
- function printVersion(): void {
109
- console.log(`RelayPlane Proxy v${VERSION}`);
110
- }
111
-
112
- function handleTelemetryCommand(args: string[]): void {
113
- const subcommand = args[0];
114
-
115
- switch (subcommand) {
116
- case 'on':
117
- enableTelemetry();
118
- console.log('✅ Telemetry enabled');
119
- console.log(' Anonymous usage data will be collected to improve routing.');
120
- console.log(' Run with --audit to see exactly what\'s collected.');
121
- break;
122
-
123
- case 'off':
124
- disableTelemetry();
125
- console.log('✅ Telemetry disabled');
126
- console.log(' No usage data will be collected.');
127
- console.log(' The proxy will continue to work normally.');
128
- break;
129
-
130
- case 'status':
131
- default:
132
- const enabled = isTelemetryEnabled();
133
- console.log('');
134
- console.log('📊 Telemetry Status');
135
- console.log('───────────────────');
136
- console.log(` Enabled: ${enabled ? '✅ Yes' : '❌ No'}`);
137
- console.log(` Data file: ${getTelemetryPath()}`);
138
- console.log('');
139
- console.log(' To enable: relayplane-proxy telemetry on');
140
- console.log(' To disable: relayplane-proxy telemetry off');
141
- console.log(' To audit: relayplane-proxy --audit');
142
- console.log('');
143
- break;
144
- }
145
- }
146
-
147
- function handleStatsCommand(): void {
148
- const stats = getTelemetryStats();
149
-
150
- console.log('');
151
- console.log('📊 Usage Statistics');
152
- console.log('═══════════════════');
153
- console.log('');
154
- console.log(` Total requests: ${stats.totalEvents}`);
155
- console.log(` Total cost: $${stats.totalCost.toFixed(2)}`);
156
- console.log(` Success rate: ${(stats.successRate * 100).toFixed(1)}%`);
157
- console.log('');
158
-
159
- if (Object.keys(stats.byModel).length > 0) {
160
- console.log(' By Model:');
161
- for (const [model, data] of Object.entries(stats.byModel)) {
162
- console.log(` ${model}: ${data.count} requests, $${data.cost.toFixed(2)}`);
163
- }
164
- console.log('');
165
- }
166
-
167
- if (Object.keys(stats.byTaskType).length > 0) {
168
- console.log(' By Task Type:');
169
- for (const [taskType, data] of Object.entries(stats.byTaskType)) {
170
- console.log(` ${taskType}: ${data.count} requests, $${data.cost.toFixed(2)}`);
171
- }
172
- console.log('');
173
- }
174
-
175
- if (stats.totalEvents === 0) {
176
- console.log(' No data yet. Start using the proxy to collect statistics.');
177
- console.log('');
178
- }
179
- }
180
-
181
- function handleConfigCommand(args: string[]): void {
182
- const subcommand = args[0];
183
-
184
- if (subcommand === 'set-key' && args[1]) {
185
- setApiKey(args[1]);
186
- console.log('✅ API key saved');
187
- console.log(' Pro features will be enabled on next proxy start.');
188
- return;
189
- }
190
-
191
- const config = loadConfig();
192
-
193
- console.log('');
194
- console.log('⚙️ Configuration');
195
- console.log('═════════════════');
196
- console.log('');
197
- console.log(` Config file: ${getConfigPath()}`);
198
- console.log(` Device ID: ${config.device_id}`);
199
- console.log(` Telemetry: ${config.telemetry_enabled ? '✅ Enabled' : '❌ Disabled'}`);
200
- console.log(` API Key: ${config.api_key ? '••••' + config.api_key.slice(-4) : 'Not set'}`);
201
- console.log(` Created: ${config.created_at}`);
202
- console.log('');
203
- console.log(' To set API key: relayplane-proxy config set-key <your-key>');
204
- console.log('');
205
- }
206
-
207
- async function main(): Promise<void> {
208
- const args = process.argv.slice(2);
209
-
210
- // Check for help
211
- if (args.includes('-h') || args.includes('--help')) {
212
- printHelp();
213
- process.exit(0);
214
- }
215
-
216
- // Check for version
217
- if (args.includes('--version')) {
218
- printVersion();
219
- process.exit(0);
220
- }
221
-
222
- // Handle commands
223
- const command = args[0];
224
-
225
- if (command === 'telemetry') {
226
- handleTelemetryCommand(args.slice(1));
227
- process.exit(0);
228
- }
229
-
230
- if (command === 'stats') {
231
- handleStatsCommand();
232
- process.exit(0);
233
- }
234
-
235
- if (command === 'config') {
236
- handleConfigCommand(args.slice(1));
237
- process.exit(0);
238
- }
239
-
240
- // Parse server options
241
- let port = 3001;
242
- let host = '127.0.0.1';
243
- let verbose = false;
244
- let audit = false;
245
- let offline = false;
246
-
247
- for (let i = 0; i < args.length; i++) {
248
- const arg = args[i];
249
-
250
- if (arg === '--port' && args[i + 1]) {
251
- port = parseInt(args[i + 1]!, 10);
252
- if (isNaN(port) || port < 1 || port > 65535) {
253
- console.error('Error: Invalid port number');
254
- process.exit(1);
255
- }
256
- i++;
257
- } else if (arg === '--host' && args[i + 1]) {
258
- host = args[i + 1]!;
259
- i++;
260
- } else if (arg === '-v' || arg === '--verbose') {
261
- verbose = true;
262
- } else if (arg === '--audit') {
263
- audit = true;
264
- } else if (arg === '--offline') {
265
- offline = true;
266
- }
267
- }
268
-
269
- // Set modes
270
- setAuditMode(audit);
271
- setOfflineMode(offline);
272
-
273
- // First run disclosure
274
- if (isFirstRun()) {
275
- printTelemetryDisclosure();
276
- markFirstRunComplete();
277
-
278
- // Wait for user to read (brief pause)
279
- await new Promise(resolve => setTimeout(resolve, 1000));
280
- }
281
-
282
- // Check for at least one API key
283
- const hasAnthropicKey = !!process.env['ANTHROPIC_API_KEY'];
284
- const hasOpenAIKey = !!process.env['OPENAI_API_KEY'];
285
- const hasGeminiKey = !!process.env['GEMINI_API_KEY'];
286
- const hasXAIKey = !!process.env['XAI_API_KEY'];
287
- const hasMoonshotKey = !!process.env['MOONSHOT_API_KEY'];
288
-
289
- if (!hasAnthropicKey && !hasOpenAIKey && !hasGeminiKey && !hasXAIKey && !hasMoonshotKey) {
290
- console.error('Error: No API keys found. Set at least one of:');
291
- console.error(' ANTHROPIC_API_KEY, OPENAI_API_KEY, GEMINI_API_KEY, XAI_API_KEY, MOONSHOT_API_KEY');
292
- process.exit(1);
293
- }
294
-
295
- // Print startup info
296
- console.log('');
297
- console.log(' ╭─────────────────────────────────────────╮');
298
- console.log(` │ RelayPlane Proxy v${VERSION} │`);
299
- console.log(' │ Intelligent AI Model Routing │');
300
- console.log(' ╰─────────────────────────────────────────╯');
301
- console.log('');
302
-
303
- // Show modes
304
- const telemetryEnabled = isTelemetryEnabled();
305
- console.log(' Mode:');
306
- if (offline) {
307
- console.log(' 🔒 Offline (no telemetry transmission)');
308
- } else if (audit) {
309
- console.log(' 🔍 Audit (showing telemetry payloads)');
310
- } else if (telemetryEnabled) {
311
- console.log(' 📊 Telemetry enabled (--audit to inspect, telemetry off to disable)');
312
- } else {
313
- console.log(' 📴 Telemetry disabled');
314
- }
315
-
316
- console.log('');
317
- console.log(' Providers:');
318
- if (hasAnthropicKey) console.log(' ✓ Anthropic');
319
- if (hasOpenAIKey) console.log(' ✓ OpenAI');
320
- if (hasGeminiKey) console.log(' ✓ Google Gemini');
321
- if (hasXAIKey) console.log(' ✓ xAI (Grok)');
322
- if (hasMoonshotKey) console.log(' ✓ Moonshot');
323
- console.log('');
324
-
325
- try {
326
- await startProxy({ port, host, verbose });
327
-
328
- console.log('');
329
- console.log(' To use, set these environment variables:');
330
- console.log(` export ANTHROPIC_BASE_URL=http://${host}:${port}`);
331
- console.log(` export OPENAI_BASE_URL=http://${host}:${port}`);
332
- console.log('');
333
- console.log(' Then run your agent (OpenClaw, Cursor, Aider, etc.)');
334
- console.log('');
335
- } catch (err) {
336
- console.error('Failed to start proxy:', err);
337
- process.exit(1);
338
- }
339
- }
340
-
341
- main();