@xelth/eck-snapshot 2.2.0 β 4.0.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/LICENSE +21 -0
- package/README.md +119 -225
- package/index.js +14 -776
- package/package.json +25 -7
- package/setup.json +805 -0
- package/src/cli/cli.js +427 -0
- package/src/cli/commands/askGpt.js +29 -0
- package/src/cli/commands/autoDocs.js +150 -0
- package/src/cli/commands/consilium.js +86 -0
- package/src/cli/commands/createSnapshot.js +601 -0
- package/src/cli/commands/detectProfiles.js +98 -0
- package/src/cli/commands/detectProject.js +112 -0
- package/src/cli/commands/generateProfileGuide.js +91 -0
- package/src/cli/commands/pruneSnapshot.js +106 -0
- package/src/cli/commands/restoreSnapshot.js +173 -0
- package/src/cli/commands/setupGemini.js +149 -0
- package/src/cli/commands/setupGemini.test.js +115 -0
- package/src/cli/commands/trainTokens.js +38 -0
- package/src/config.js +81 -0
- package/src/services/authService.js +20 -0
- package/src/services/claudeCliService.js +621 -0
- package/src/services/claudeCliService.test.js +267 -0
- package/src/services/dispatcherService.js +33 -0
- package/src/services/gptService.js +302 -0
- package/src/services/gptService.test.js +120 -0
- package/src/templates/agent-prompt.template.md +29 -0
- package/src/templates/architect-prompt.template.md +50 -0
- package/src/templates/envScanRequest.md +4 -0
- package/src/templates/gitWorkflow.md +32 -0
- package/src/templates/multiAgent.md +164 -0
- package/src/templates/vectorMode.md +22 -0
- package/src/utils/aiHeader.js +303 -0
- package/src/utils/fileUtils.js +928 -0
- package/src/utils/projectDetector.js +704 -0
- package/src/utils/tokenEstimator.js +198 -0
- package/.ecksnapshot.config.js +0 -35
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import fs from 'fs/promises';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Adaptive token estimation system with project-specific polynomials
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
10
|
+
const __dirname = path.dirname(__filename);
|
|
11
|
+
const ESTIMATION_DATA_FILE = path.join(__dirname, '..', '..', '.eck-token-training.json');
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Default coefficients for different project types (bytes to tokens ratio)
|
|
15
|
+
* Format: [constant, linear, quadratic, cubic] coefficients
|
|
16
|
+
*/
|
|
17
|
+
const DEFAULT_COEFFICIENTS = {
|
|
18
|
+
'android': [0, 0.25, 0, 0], // Start with simple 1/4 ratio
|
|
19
|
+
'nodejs': [0, 0.20, 0, 0],
|
|
20
|
+
'python': [0, 0.22, 0, 0],
|
|
21
|
+
'rust': [0, 0.18, 0, 0],
|
|
22
|
+
'go': [0, 0.19, 0, 0],
|
|
23
|
+
'c': [0, 0.23, 0, 0],
|
|
24
|
+
'unknown': [0, 0.25, 0, 0]
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Load training data from file
|
|
29
|
+
*/
|
|
30
|
+
async function loadTrainingData() {
|
|
31
|
+
try {
|
|
32
|
+
const data = await fs.readFile(ESTIMATION_DATA_FILE, 'utf-8');
|
|
33
|
+
const parsedData = JSON.parse(data);
|
|
34
|
+
// Ensure the structure is complete by merging with defaults
|
|
35
|
+
return {
|
|
36
|
+
coefficients: { ...DEFAULT_COEFFICIENTS, ...parsedData.coefficients },
|
|
37
|
+
trainingPoints: parsedData.trainingPoints || {}
|
|
38
|
+
};
|
|
39
|
+
} catch (error) {
|
|
40
|
+
// If file doesn't exist or is malformed, return default structure
|
|
41
|
+
return {
|
|
42
|
+
coefficients: { ...DEFAULT_COEFFICIENTS },
|
|
43
|
+
trainingPoints: {}
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Save training data to file
|
|
50
|
+
*/
|
|
51
|
+
async function saveTrainingData(data) {
|
|
52
|
+
await fs.writeFile(ESTIMATION_DATA_FILE, JSON.stringify(data, null, 2));
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Calculate polynomial value
|
|
57
|
+
*/
|
|
58
|
+
function evaluatePolynomial(coefficients, x) {
|
|
59
|
+
let result = 0;
|
|
60
|
+
for (let i = 0; i < coefficients.length; i++) {
|
|
61
|
+
result += coefficients[i] * Math.pow(x, i);
|
|
62
|
+
}
|
|
63
|
+
return Math.max(0, result); // Ensure non-negative result
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Estimate tokens using project-specific polynomial
|
|
68
|
+
*/
|
|
69
|
+
export async function estimateTokensWithPolynomial(projectType, fileSizeInBytes) {
|
|
70
|
+
const data = await loadTrainingData();
|
|
71
|
+
const coefficients = data.coefficients[projectType] || data.coefficients['unknown'];
|
|
72
|
+
|
|
73
|
+
const estimatedTokens = evaluatePolynomial(coefficients, fileSizeInBytes);
|
|
74
|
+
return Math.round(estimatedTokens);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Generate training command string for data collection
|
|
79
|
+
*/
|
|
80
|
+
export function generateTrainingCommand(projectType, estimatedTokens, fileSizeInBytes, projectPath) {
|
|
81
|
+
const projectName = path.basename(projectPath);
|
|
82
|
+
|
|
83
|
+
return `eck-snapshot train-tokens ${projectType} ${fileSizeInBytes} ${estimatedTokens} `;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Add training point and update polynomial coefficients
|
|
88
|
+
*/
|
|
89
|
+
export async function addTrainingPoint(projectType, fileSizeInBytes, estimatedTokens, actualTokens) {
|
|
90
|
+
const data = await loadTrainingData();
|
|
91
|
+
|
|
92
|
+
// Initialize training points array for project type if it doesn't exist
|
|
93
|
+
if (!data.trainingPoints[projectType]) {
|
|
94
|
+
data.trainingPoints[projectType] = [];
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Add new training point
|
|
98
|
+
const trainingPoint = {
|
|
99
|
+
fileSizeInBytes,
|
|
100
|
+
estimatedTokens,
|
|
101
|
+
actualTokens,
|
|
102
|
+
timestamp: new Date().toISOString()
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
data.trainingPoints[projectType].push(trainingPoint);
|
|
106
|
+
|
|
107
|
+
// Recalculate coefficients using least squares fitting
|
|
108
|
+
updateCoefficients(data, projectType);
|
|
109
|
+
|
|
110
|
+
await saveTrainingData(data);
|
|
111
|
+
|
|
112
|
+
console.log(`β
Added training point for ${projectType}:`);
|
|
113
|
+
console.log(` File size: ${fileSizeInBytes} bytes`);
|
|
114
|
+
console.log(` Estimated: ${estimatedTokens} tokens`);
|
|
115
|
+
console.log(` Actual: ${actualTokens} tokens`);
|
|
116
|
+
console.log(` Error: ${Math.abs(actualTokens - estimatedTokens)} tokens (${Math.round(Math.abs(actualTokens - estimatedTokens) / actualTokens * 100)}%)`);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Update polynomial coefficients using least squares fitting
|
|
121
|
+
* For now, we'll use a simple adaptive approach
|
|
122
|
+
*/
|
|
123
|
+
function updateCoefficients(data, projectType) {
|
|
124
|
+
const points = data.trainingPoints[projectType];
|
|
125
|
+
|
|
126
|
+
if (!points || points.length === 0) {
|
|
127
|
+
// No points, nothing to do.
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (points.length === 1) {
|
|
132
|
+
// With one point, use a direct ratio for the linear coefficient.
|
|
133
|
+
const point = points[0];
|
|
134
|
+
if (point.fileSizeInBytes > 0) { // Avoid division by zero
|
|
135
|
+
const ratio = point.actualTokens / point.fileSizeInBytes;
|
|
136
|
+
data.coefficients[projectType] = [
|
|
137
|
+
0, // intercept
|
|
138
|
+
Math.max(0, ratio), // linear term (slope)
|
|
139
|
+
0, 0 // quadratic, cubic
|
|
140
|
+
];
|
|
141
|
+
}
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Use linear regression for 2 or more points.
|
|
146
|
+
let sumX = 0, sumY = 0, sumXY = 0, sumX2 = 0;
|
|
147
|
+
const n = points.length;
|
|
148
|
+
|
|
149
|
+
for (const point of points) {
|
|
150
|
+
const x = point.fileSizeInBytes;
|
|
151
|
+
const y = point.actualTokens;
|
|
152
|
+
|
|
153
|
+
sumX += x;
|
|
154
|
+
sumY += y;
|
|
155
|
+
sumXY += x * y;
|
|
156
|
+
sumX2 += x * x;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const denominator = (n * sumX2 - sumX * sumX);
|
|
160
|
+
if (denominator === 0) return; // Avoid division by zero, can't calculate slope
|
|
161
|
+
|
|
162
|
+
// Calculate linear coefficients: y = a + bx
|
|
163
|
+
const slope = (n * sumXY - sumX * sumY) / denominator;
|
|
164
|
+
const intercept = (sumY - slope * sumX) / n;
|
|
165
|
+
|
|
166
|
+
// Update coefficients [constant, linear, quadratic, cubic]
|
|
167
|
+
data.coefficients[projectType] = [
|
|
168
|
+
Math.max(0, intercept), // constant term (ensure non-negative)
|
|
169
|
+
Math.max(0, slope), // linear term (ensure non-negative)
|
|
170
|
+
0, // quadratic (not used yet)
|
|
171
|
+
0 // cubic (not used yet)
|
|
172
|
+
];
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Show current estimation statistics
|
|
177
|
+
*/
|
|
178
|
+
export async function showEstimationStats() {
|
|
179
|
+
const data = await loadTrainingData();
|
|
180
|
+
|
|
181
|
+
console.log('\nπ Token Estimation Statistics:');
|
|
182
|
+
console.log('βββββββββββββββββββββββββββββββββββββββββββββββββββ');
|
|
183
|
+
|
|
184
|
+
for (const [projectType, coefficients] of Object.entries(data.coefficients)) {
|
|
185
|
+
const points = data.trainingPoints[projectType] || [];
|
|
186
|
+
console.log(`\nπΈ ${projectType}:`);
|
|
187
|
+
console.log(` Coefficients: [${coefficients.map(c => c.toFixed(6)).join(', ')}]`);
|
|
188
|
+
console.log(` Training points: ${points.length}`);
|
|
189
|
+
|
|
190
|
+
if (points.length > 0) {
|
|
191
|
+
const errors = points.map(p => Math.abs(p.actualTokens - p.estimatedTokens));
|
|
192
|
+
const avgError = errors.reduce((a, b) => a + b, 0) / errors.length;
|
|
193
|
+
console.log(` Average error: ${Math.round(avgError)} tokens`);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
console.log('βββββββββββββββββββββββββββββββββββββββββββββββββββ');
|
|
198
|
+
}
|
package/.ecksnapshot.config.js
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
// .ecksnapshot.config.js
|
|
2
|
-
|
|
3
|
-
// Π― Π·Π°ΠΌΠ΅Π½ΠΈΠ» "module.exports =" Π½Π° "export default"
|
|
4
|
-
export default {
|
|
5
|
-
filesToIgnore: [
|
|
6
|
-
'package-lock.json',
|
|
7
|
-
'yarn.lock',
|
|
8
|
-
'pnpm-lock.yaml'
|
|
9
|
-
],
|
|
10
|
-
extensionsToIgnore: [
|
|
11
|
-
'.sqlite3',
|
|
12
|
-
'.db',
|
|
13
|
-
'.DS_Store',
|
|
14
|
-
'.env',
|
|
15
|
-
'.log',
|
|
16
|
-
'.tmp',
|
|
17
|
-
'.bak',
|
|
18
|
-
'.swp',
|
|
19
|
-
'.ico',
|
|
20
|
-
'.png',
|
|
21
|
-
'.jpg',
|
|
22
|
-
'.jpeg',
|
|
23
|
-
'.gif',
|
|
24
|
-
'.svg'
|
|
25
|
-
],
|
|
26
|
-
dirsToIgnore: [
|
|
27
|
-
'node_modules/',
|
|
28
|
-
'.git/',
|
|
29
|
-
'.idea/',
|
|
30
|
-
'snapshots/',
|
|
31
|
-
'dist/',
|
|
32
|
-
'build/',
|
|
33
|
-
'coverage/'
|
|
34
|
-
],
|
|
35
|
-
};
|