@xelth/eck-snapshot 4.2.4 → 5.4.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.

Potentially problematic release.


This version of @xelth/eck-snapshot might be problematic. Click here for more details.

Files changed (51) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +106 -0
  3. package/index.js +14 -0
  4. package/package.json +64 -9
  5. package/scripts/mcp-eck-core.js +101 -0
  6. package/scripts/mcp-glm-zai-worker.mjs +243 -0
  7. package/scripts/verify_changes.js +68 -0
  8. package/setup.json +845 -0
  9. package/src/cli/cli.js +369 -0
  10. package/src/cli/commands/claudeSettings.js +93 -0
  11. package/src/cli/commands/consilium.js +86 -0
  12. package/src/cli/commands/createSnapshot.js +906 -0
  13. package/src/cli/commands/detectProfiles.js +98 -0
  14. package/src/cli/commands/detectProject.js +112 -0
  15. package/src/cli/commands/doctor.js +60 -0
  16. package/src/cli/commands/envSync.js +319 -0
  17. package/src/cli/commands/generateProfileGuide.js +144 -0
  18. package/src/cli/commands/pruneSnapshot.js +106 -0
  19. package/src/cli/commands/restoreSnapshot.js +173 -0
  20. package/src/cli/commands/setupGemini.js +149 -0
  21. package/src/cli/commands/setupGemini.test.js +115 -0
  22. package/src/cli/commands/setupMcp.js +269 -0
  23. package/src/cli/commands/showFile.js +39 -0
  24. package/src/cli/commands/trainTokens.js +38 -0
  25. package/src/cli/commands/updateSnapshot.js +219 -0
  26. package/src/config.js +125 -0
  27. package/src/core/skeletonizer.js +201 -0
  28. package/src/mcp-server/index.js +211 -0
  29. package/src/services/claudeCliService.js +626 -0
  30. package/src/services/claudeCliService.test.js +267 -0
  31. package/src/templates/agent-prompt.template.md +43 -0
  32. package/src/templates/architect-prompt.template.md +164 -0
  33. package/src/templates/claude-code/README.md +105 -0
  34. package/src/templates/claude-code/mcp-config-template.json +11 -0
  35. package/src/templates/claude-code/mcp-server-template.js +206 -0
  36. package/src/templates/claude-code/settings-claude.json +1 -0
  37. package/src/templates/envScanRequest.md +4 -0
  38. package/src/templates/gitWorkflow.md +32 -0
  39. package/src/templates/multiAgent.md +118 -0
  40. package/src/templates/opencode/coder.template.md +22 -0
  41. package/src/templates/opencode/junior-architect.template.md +85 -0
  42. package/src/templates/skeleton-instruction.md +16 -0
  43. package/src/templates/update-prompt.template.md +19 -0
  44. package/src/utils/aiHeader.js +678 -0
  45. package/src/utils/claudeMdGenerator.js +148 -0
  46. package/src/utils/eckProtocolParser.js +221 -0
  47. package/src/utils/fileUtils.js +1017 -0
  48. package/src/utils/gitUtils.js +44 -0
  49. package/src/utils/opencodeAgentsGenerator.js +271 -0
  50. package/src/utils/projectDetector.js +704 -0
  51. package/src/utils/tokenEstimator.js +201 -0
@@ -0,0 +1,201 @@
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 ECK_DIR = path.join(__dirname, '..', '..', '.eck');
12
+ const ESTIMATION_DATA_FILE = path.join(ECK_DIR, 'token-training.json');
13
+
14
+ /**
15
+ * Default coefficients for different project types (bytes to tokens ratio)
16
+ * Format: [constant, linear, quadratic, cubic] coefficients
17
+ */
18
+ const DEFAULT_COEFFICIENTS = {
19
+ 'android': [0, 0.25, 0, 0], // Start with simple 1/4 ratio
20
+ 'nodejs': [0, 0.20, 0, 0],
21
+ 'python': [0, 0.22, 0, 0],
22
+ 'rust': [0, 0.18, 0, 0],
23
+ 'go': [0, 0.19, 0, 0],
24
+ 'c': [0, 0.23, 0, 0],
25
+ 'unknown': [0, 0.25, 0, 0]
26
+ };
27
+
28
+ /**
29
+ * Load training data from file
30
+ */
31
+ async function loadTrainingData() {
32
+ try {
33
+ const data = await fs.readFile(ESTIMATION_DATA_FILE, 'utf-8');
34
+ const parsedData = JSON.parse(data);
35
+ // Ensure the structure is complete by merging with defaults
36
+ return {
37
+ coefficients: { ...DEFAULT_COEFFICIENTS, ...parsedData.coefficients },
38
+ trainingPoints: parsedData.trainingPoints || {}
39
+ };
40
+ } catch (error) {
41
+ // If file doesn't exist or is malformed, return default structure
42
+ return {
43
+ coefficients: { ...DEFAULT_COEFFICIENTS },
44
+ trainingPoints: {}
45
+ };
46
+ }
47
+ }
48
+
49
+ /**
50
+ * Save training data to file
51
+ */
52
+ async function saveTrainingData(data) {
53
+ // Ensure .eck directory exists
54
+ await fs.mkdir(ECK_DIR, { recursive: true });
55
+ await fs.writeFile(ESTIMATION_DATA_FILE, JSON.stringify(data, null, 2));
56
+ }
57
+
58
+ /**
59
+ * Calculate polynomial value
60
+ */
61
+ function evaluatePolynomial(coefficients, x) {
62
+ let result = 0;
63
+ for (let i = 0; i < coefficients.length; i++) {
64
+ result += coefficients[i] * Math.pow(x, i);
65
+ }
66
+ return Math.max(0, result); // Ensure non-negative result
67
+ }
68
+
69
+ /**
70
+ * Estimate tokens using project-specific polynomial
71
+ */
72
+ export async function estimateTokensWithPolynomial(projectType, fileSizeInBytes) {
73
+ const data = await loadTrainingData();
74
+ const coefficients = data.coefficients[projectType] || data.coefficients['unknown'];
75
+
76
+ const estimatedTokens = evaluatePolynomial(coefficients, fileSizeInBytes);
77
+ return Math.round(estimatedTokens);
78
+ }
79
+
80
+ /**
81
+ * Generate training command string for data collection
82
+ */
83
+ export function generateTrainingCommand(projectType, estimatedTokens, fileSizeInBytes, projectPath) {
84
+ const projectName = path.basename(projectPath);
85
+
86
+ return `eck-snapshot train-tokens ${projectType} ${fileSizeInBytes} ${estimatedTokens} `;
87
+ }
88
+
89
+ /**
90
+ * Add training point and update polynomial coefficients
91
+ */
92
+ export async function addTrainingPoint(projectType, fileSizeInBytes, estimatedTokens, actualTokens) {
93
+ const data = await loadTrainingData();
94
+
95
+ // Initialize training points array for project type if it doesn't exist
96
+ if (!data.trainingPoints[projectType]) {
97
+ data.trainingPoints[projectType] = [];
98
+ }
99
+
100
+ // Add new training point
101
+ const trainingPoint = {
102
+ fileSizeInBytes,
103
+ estimatedTokens,
104
+ actualTokens,
105
+ timestamp: new Date().toISOString()
106
+ };
107
+
108
+ data.trainingPoints[projectType].push(trainingPoint);
109
+
110
+ // Recalculate coefficients using least squares fitting
111
+ updateCoefficients(data, projectType);
112
+
113
+ await saveTrainingData(data);
114
+
115
+ console.log(`āœ… Added training point for ${projectType}:`);
116
+ console.log(` File size: ${fileSizeInBytes} bytes`);
117
+ console.log(` Estimated: ${estimatedTokens} tokens`);
118
+ console.log(` Actual: ${actualTokens} tokens`);
119
+ console.log(` Error: ${Math.abs(actualTokens - estimatedTokens)} tokens (${Math.round(Math.abs(actualTokens - estimatedTokens) / actualTokens * 100)}%)`);
120
+ }
121
+
122
+ /**
123
+ * Update polynomial coefficients using least squares fitting
124
+ * For now, we'll use a simple adaptive approach
125
+ */
126
+ function updateCoefficients(data, projectType) {
127
+ const points = data.trainingPoints[projectType];
128
+
129
+ if (!points || points.length === 0) {
130
+ // No points, nothing to do.
131
+ return;
132
+ }
133
+
134
+ if (points.length === 1) {
135
+ // With one point, use a direct ratio for the linear coefficient.
136
+ const point = points[0];
137
+ if (point.fileSizeInBytes > 0) { // Avoid division by zero
138
+ const ratio = point.actualTokens / point.fileSizeInBytes;
139
+ data.coefficients[projectType] = [
140
+ 0, // intercept
141
+ Math.max(0, ratio), // linear term (slope)
142
+ 0, 0 // quadratic, cubic
143
+ ];
144
+ }
145
+ return;
146
+ }
147
+
148
+ // Use linear regression for 2 or more points.
149
+ let sumX = 0, sumY = 0, sumXY = 0, sumX2 = 0;
150
+ const n = points.length;
151
+
152
+ for (const point of points) {
153
+ const x = point.fileSizeInBytes;
154
+ const y = point.actualTokens;
155
+
156
+ sumX += x;
157
+ sumY += y;
158
+ sumXY += x * y;
159
+ sumX2 += x * x;
160
+ }
161
+
162
+ const denominator = (n * sumX2 - sumX * sumX);
163
+ if (denominator === 0) return; // Avoid division by zero, can't calculate slope
164
+
165
+ // Calculate linear coefficients: y = a + bx
166
+ const slope = (n * sumXY - sumX * sumY) / denominator;
167
+ const intercept = (sumY - slope * sumX) / n;
168
+
169
+ // Update coefficients [constant, linear, quadratic, cubic]
170
+ data.coefficients[projectType] = [
171
+ Math.max(0, intercept), // constant term (ensure non-negative)
172
+ Math.max(0, slope), // linear term (ensure non-negative)
173
+ 0, // quadratic (not used yet)
174
+ 0 // cubic (not used yet)
175
+ ];
176
+ }
177
+
178
+ /**
179
+ * Show current estimation statistics
180
+ */
181
+ export async function showEstimationStats() {
182
+ const data = await loadTrainingData();
183
+
184
+ console.log('\nšŸ“Š Token Estimation Statistics:');
185
+ console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
186
+
187
+ for (const [projectType, coefficients] of Object.entries(data.coefficients)) {
188
+ const points = data.trainingPoints[projectType] || [];
189
+ console.log(`\nšŸ”ø ${projectType}:`);
190
+ console.log(` Coefficients: [${coefficients.map(c => c.toFixed(6)).join(', ')}]`);
191
+ console.log(` Training points: ${points.length}`);
192
+
193
+ if (points.length > 0) {
194
+ const errors = points.map(p => Math.abs(p.actualTokens - p.estimatedTokens));
195
+ const avgError = errors.reduce((a, b) => a + b, 0) / errors.length;
196
+ console.log(` Average error: ${Math.round(avgError)} tokens`);
197
+ }
198
+ }
199
+
200
+ console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
201
+ }