@goldensheepai/toknxr-cli 0.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.
@@ -0,0 +1,77 @@
1
+ #!/usr/bin/env node
2
+
3
+ // Direct test of code analysis functions
4
+ import { analyzeCodeQuality, scoreEffectiveness, extractCodeFromResponse } from './src/code-analysis.ts';
5
+
6
+ console.log('๐Ÿงช Testing AI Code Quality Analysis Feature\n');
7
+
8
+ // Test 1: Code Quality Analysis
9
+ const testCode = `/**
10
+ * Calculate fibonacci sequence
11
+ * @param {number} n - number of terms
12
+ * @returns {number[]} fibonacci sequence
13
+ */
14
+ function fibonacci(n) {
15
+ if (typeof n !== 'number' || n < 1 || n > 100) {
16
+ throw new Error('Invalid input: n must be a number between 1 and 100');
17
+ }
18
+
19
+ const sequence = [0, 1];
20
+ for (let i = 2; i < n; i++) {
21
+ sequence.push(sequence[i - 1] + sequence[i - 2]);
22
+ }
23
+
24
+ return sequence.slice(0, n);
25
+ }`;
26
+
27
+ console.log('1. Testing Code Quality Analysis:');
28
+ console.log('๐Ÿ“ Input code length:', testCode.length, 'characters');
29
+ console.log('๐Ÿ“ Code:');
30
+ console.log(testCode.substring(0, 100) + '...\n');
31
+
32
+ // Analyze code quality
33
+ const qualityMetrics = analyzeCodeQuality(testCode, 'javascript');
34
+
35
+ console.log('๐Ÿ” Analysis Results:');
36
+ console.log('โœ… Syntax Valid:', qualityMetrics.syntaxValid);
37
+ console.log('๐Ÿ“Š Lines of Code:', qualityMetrics.linesOfCode);
38
+ console.log('๐ŸŽฏ Has Functions:', qualityMetrics.hasFunctions);
39
+ console.log('๐Ÿ“š Estimated Readability:', `${qualityMetrics.estimatedReadability}/10`);
40
+ console.log('โš ๏ธ Potential Issues:', qualityMetrics.potentialIssues.length || 'None');
41
+ console.log();
42
+
43
+ // Test 2: Effectiveness Scoring
44
+ const userPrompt = "Write a JavaScript function to calculate the fibonacci sequence up to n terms. Include proper error handling and use JSDoc comments.";
45
+
46
+ const aiResponse = `Here's a JavaScript function for calculating the Fibonacci sequence:
47
+
48
+ \`\`\`javascript
49
+ ${testCode}
50
+ \`\`\`
51
+
52
+ This function includes error handling and JSDoc comments as requested.`;
53
+
54
+ console.log('2. Testing Effectiveness Analysis:');
55
+ console.log('๐Ÿ‘ค User Prompt:', userPrompt.substring(0, 80) + '...');
56
+ console.log('๐Ÿค– AI Response preview:', aiResponse.substring(0, 80) + '...\n');
57
+
58
+ // Extract code and score effectiveness
59
+ const extractedCode = extractCodeFromResponse(aiResponse);
60
+ if (extractedCode) {
61
+ console.log('๐Ÿ” Extracted Code Language:', extractedCode.language);
62
+
63
+ const effectiveness = scoreEffectiveness(userPrompt, aiResponse, extractedCode.code);
64
+
65
+ console.log('๐Ÿ“Š Effectiveness Scores:');
66
+ console.log('๐ŸŽฏ Prompt Clarity Match:', `${effectiveness.promptClarityMatch}/100`);
67
+ console.log('โœ… Code Completeness:', `${effectiveness.codeCompleteness}/100`);
68
+ console.log('๐Ÿ”ง Code Correctness:', `${effectiveness.codeCorrectness}/100`);
69
+ console.log('โšก Code Efficiency:', `${effectiveness.codeEfficiency}/100`);
70
+ console.log('๐Ÿ† Overall Effectiveness:', `${effectiveness.overallEffectiveness}/100`);
71
+ } else {
72
+ console.log('โŒ Failed to extract code from response');
73
+ }
74
+
75
+ console.log('\n๐ŸŽ‰ Code Analysis Feature is WORKING! ๐ŸŽ‰');
76
+ console.log('\n๐Ÿ’ก This same analysis runs on every coding request through the TokNxr proxy.');
77
+ console.log('๐Ÿ“ˆ It provides insights into AI performance beyond just token costs.');
@@ -0,0 +1,27 @@
1
+ // Test the code analysis feature with Gemini (working API)
2
+ import axios from 'axios';
3
+
4
+ const prompt = "Write a JavaScript function to calculate the fibonacci sequence up to n terms. Include proper error handling and comments.";
5
+
6
+ const geminiRequest = {
7
+ contents: [{
8
+ parts: [{
9
+ text: prompt
10
+ }]
11
+ }]
12
+ };
13
+
14
+ console.log('๐ŸŽฏ Sending coding request to Gemini via proxy...');
15
+ console.log('๐Ÿ“ Prompt:', prompt.substring(0, 100) + '...');
16
+
17
+ try {
18
+ const response = await axios.post('http://localhost:8787/gemini/v1beta/models/gemini-2.5-flash:generateContent', geminiRequest, {
19
+ headers: { 'Content-Type': 'application/json' }
20
+ });
21
+
22
+ console.log('โœ… Request successful!');
23
+ console.log('๐Ÿ“Š Response preview:', response.data.candidates[0].content.parts[0].text.substring(0, 200) + '...');
24
+
25
+ } catch (error) {
26
+ console.error('โŒ Request failed:', error.response?.data || error.message);
27
+ }
@@ -0,0 +1,118 @@
1
+ // Quick script to generate sample coding interactions for testing the dashboard
2
+ import fs from 'fs';
3
+ import path from 'path';
4
+ import { fileURLToPath } from 'url';
5
+
6
+ const __filename = fileURLToPath(import.meta.url);
7
+ const __dirname = path.dirname(__filename);
8
+
9
+ const sampleInteractions = [
10
+ {
11
+ timestamp: new Date(Date.now() - 1000 * 60 * 30).toISOString(), // 30 min ago
12
+ provider: 'Gemini-Pro',
13
+ model: 'gemini-2.5-flash',
14
+ promptTokens: 150,
15
+ completionTokens: 200,
16
+ totalTokens: 350,
17
+ costUSD: 0.05,
18
+ taskType: 'coding',
19
+ userPrompt: 'Create a React component for a todo list',
20
+ aiResponse: 'Here\'s a React todo component...',
21
+ extractedCode: `function TodoList() {
22
+ const [todos, setTodos] = useState([]);
23
+ return (
24
+ <div>
25
+ <h1>My Todos</h1>
26
+ {/* Todo implementation */}
27
+ </div>
28
+ );
29
+ }`,
30
+ codeQualityScore: 85,
31
+ codeQualityMetrics: {
32
+ syntaxValid: true,
33
+ estimatedReadability: 0.8,
34
+ hasFunctions: true,
35
+ hasClasses: false,
36
+ linesOfCode: 12,
37
+ potentialIssues: []
38
+ },
39
+ effectivenessScore: 88
40
+ },
41
+ {
42
+ timestamp: new Date(Date.now() - 1000 * 60 * 15).toISOString(), // 15 min ago
43
+ provider: 'OpenAI-GPT4',
44
+ model: 'gpt-4',
45
+ promptTokens: 80,
46
+ completionTokens: 120,
47
+ totalTokens: 200,
48
+ costUSD: 0.02,
49
+ taskType: 'coding',
50
+ userPrompt: 'Write a Python function to calculate fibonacci',
51
+ aiResponse: 'def fibonacci(n):...',
52
+ extractedCode: `def fibonacci(n):
53
+ if n <= 1:
54
+ return n
55
+ return fibonacci(n-1) + fibonacci(n-2)`,
56
+ codeQualityScore: 92,
57
+ codeQualityMetrics: {
58
+ syntaxValid: true,
59
+ estimatedReadability: 0.9,
60
+ hasFunctions: true,
61
+ hasClasses: false,
62
+ linesOfCode: 4,
63
+ potentialIssues: []
64
+ },
65
+ effectivenessScore: 95
66
+ },
67
+ {
68
+ timestamp: new Date(Date.now() - 1000 * 60 * 5).toISOString(), // 5 min ago
69
+ provider: 'Gemini-Pro',
70
+ model: 'gemini-2.5-flash',
71
+ promptTokens: 200,
72
+ completionTokens: 300,
73
+ totalTokens: 500,
74
+ costUSD: 0.08,
75
+ taskType: 'coding',
76
+ userPrompt: 'Create a TypeScript API endpoint',
77
+ aiResponse: 'Here\'s a TypeScript API endpoint...',
78
+ extractedCode: `import express from 'express';
79
+
80
+ const app = express();
81
+
82
+ app.get('/api/users', async (req, res) => {
83
+ // Implementation here
84
+ });
85
+
86
+ export default app;`,
87
+ codeQualityScore: 78,
88
+ codeQualityMetrics: {
89
+ syntaxValid: true,
90
+ estimatedReadability: 0.7,
91
+ hasFunctions: true,
92
+ hasClasses: false,
93
+ linesOfCode: 8,
94
+ potentialIssues: ['Missing error handling']
95
+ },
96
+ effectivenessScore: 82
97
+ }
98
+ ];
99
+
100
+ const logFilePath = path.resolve(process.cwd(), 'interactions.log');
101
+
102
+ // Read existing log file
103
+ let existingContent = '';
104
+ if (fs.existsSync(logFilePath)) {
105
+ existingContent = fs.readFileSync(logFilePath, 'utf8');
106
+ }
107
+
108
+ // Combine existing and sample data
109
+ const allInteractions = existingContent.trim()
110
+ ? existingContent.trim() + '\n' + sampleInteractions.map(i => JSON.stringify(i)).join('\n')
111
+ : sampleInteractions.map(i => JSON.stringify(i)).join('\n');
112
+
113
+ // Write back to file
114
+ fs.writeFileSync(logFilePath, allInteractions + '\n');
115
+
116
+ console.log(`โœ… Generated ${sampleInteractions.length} sample coding interactions`);
117
+ console.log(`๐Ÿ“Š Total interactions in log: ${allInteractions.split('\n').filter(Boolean).length}`);
118
+ console.log(`๐Ÿ”— Dashboard available at: http://localhost:8788/dashboard`);
package/test-proxy.mjs ADDED
@@ -0,0 +1,25 @@
1
+ import axios from 'axios';
2
+
3
+ const PROXY_URL = 'http://localhost:8787/api/chat';
4
+
5
+ async function runTest() {
6
+ console.log('Sending test request to proxy for Ollama...');
7
+ try {
8
+ const response = await axios.post(PROXY_URL, {
9
+ model: 'llama3.2:3b',
10
+ messages: [{ role: 'user', content: 'Hello, world!' }],
11
+ stream: false, // For this test, we will not stream the response
12
+ }, {
13
+ headers: {
14
+ 'Content-Type': 'application/json',
15
+ },
16
+ });
17
+
18
+ console.log('Received response from proxy:');
19
+ console.log(response.data);
20
+ } catch (error) {
21
+ console.error('Error during test:', error.message);
22
+ }
23
+ }
24
+
25
+ runTest();
@@ -0,0 +1,63 @@
1
+ {
2
+ "providers": [
3
+ {
4
+ "name": "Ollama-Llama3",
5
+ "routePrefix": "/ollama",
6
+ "targetUrl": "http://localhost:11434/api/chat",
7
+ "apiKeyEnvVar": null,
8
+ "tokenMapping": {
9
+ "prompt": "prompt_eval_count",
10
+ "completion": "eval_count"
11
+ }
12
+ },
13
+ {
14
+ "name": "Gemini-Pro",
15
+ "routePrefix": "/gemini",
16
+ "targetUrl": "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent",
17
+ "apiKeyEnvVar": "GEMINI_API_KEY",
18
+ "authHeader": "x-goog-api-key",
19
+ "tokenMapping": {
20
+ "prompt": "usageMetadata.promptTokenCount",
21
+ "completion": "usageMetadata.candidatesTokenCount",
22
+ "total": "usageMetadata.totalTokenCount"
23
+ }
24
+ },
25
+ {
26
+ "name": "Gemini-Free",
27
+ "routePrefix": "/gemini-free",
28
+ "targetUrl": "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent",
29
+ "apiKeyEnvVar": "GEMINI_API_KEY",
30
+ "authHeader": "x-goog-api-key",
31
+ "tokenMapping": {
32
+ "prompt": "usageMetadata.promptTokenCount",
33
+ "completion": "usageMetadata.candidatesTokenCount",
34
+ "total": "usageMetadata.totalTokenCount"
35
+ }
36
+ },
37
+ {
38
+ "name": "OpenAI-GPT4",
39
+ "routePrefix": "/openai",
40
+ "targetUrl": "https://api.openai.com/v1/chat/completions",
41
+ "apiKeyEnvVar": "OPENAI_API_KEY",
42
+ "authHeader": "Authorization",
43
+ "authScheme": "Bearer",
44
+ "tokenMapping": {
45
+ "prompt": "usage.prompt_tokens",
46
+ "completion": "usage.completion_tokens",
47
+ "total": "usage.total_tokens"
48
+ }
49
+ },
50
+ {
51
+ "name": "Anthropic-Claude",
52
+ "routePrefix": "/anthropic",
53
+ "targetUrl": "https://api.anthropic.com/v1/messages",
54
+ "apiKeyEnvVar": "ANTHROPIC_API_KEY",
55
+ "authHeader": "x-api-key",
56
+ "tokenMapping": {
57
+ "prompt": "usage.input_tokens",
58
+ "completion": "usage.output_tokens",
59
+ "total": "usage.total_tokens"
60
+ }
61
+ }
62
+ ]
63
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "version": "1",
3
+ "monthlyUSD": 50,
4
+ "perProviderMonthlyUSD": {
5
+ "Gemini-Pro": 30,
6
+ "Gemini-Free": 10,
7
+ "Ollama-Llama3": 0,
8
+ "OpenAI-GPT4": 20,
9
+ "Anthropic-Claude": 15
10
+ },
11
+ "webhookUrl": "",
12
+ "_comments": {
13
+ "monthlyUSD": "Total monthly budget across all providers in USD",
14
+ "perProviderMonthlyUSD": "Individual provider budget limits",
15
+ "webhookUrl": "Optional webhook URL for budget alert notifications (leave empty for no alerts)",
16
+ "supportedProviders": ["Gemini-Pro", "Ollama-Llama3", "OpenAI-GPT4", "Gemini-Free", "Anthropic-Claude"]
17
+ }
18
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,19 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "module": "NodeNext",
5
+ "moduleResolution": "NodeNext",
6
+ "outDir": "./lib",
7
+ "rootDir": "./src",
8
+ "strict": true,
9
+ "esModuleInterop": true,
10
+ "allowSyntheticDefaultImports": true,
11
+ "skipLibCheck": true,
12
+ "forceConsistentCasingInFileNames": true,
13
+ "downlevelIteration": true,
14
+ "jsx": "react-jsx",
15
+ "jsxImportSource": "react"
16
+ },
17
+ "include": ["src/**/*"],
18
+ "exclude": ["node_modules", "lib"]
19
+ }