@xelth/eck-snapshot 5.8.6 → 6.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.

Potentially problematic release.


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

@@ -0,0 +1,98 @@
1
+ import fs from 'fs/promises';
2
+ import path from 'path';
3
+ import chalk from 'chalk';
4
+
5
+ const TELEMETRY_URL = 'https://xelth.com/T/report';
6
+
7
+ /**
8
+ * Parses the AnswerToSA.md file to extract telemetry data.
9
+ * @param {string} content The markdown content
10
+ * @returns {object|null} The parsed telemetry data or null if invalid
11
+ */
12
+ export function parseAgentReport(content) {
13
+ if (!content) return null;
14
+
15
+ const data = {
16
+ model_name: 'Unknown',
17
+ agent_role: 'Coder',
18
+ task_scope: 'general',
19
+ status: 'UNKNOWN',
20
+ duration_sec: null,
21
+ error_summary: null
22
+ };
23
+
24
+ // Extract Executor (Model Name)
25
+ const executorMatch = content.match(/\*\*Executor:\*\*\s*(.+)/i);
26
+ if (executorMatch) {
27
+ data.model_name = executorMatch[1].trim();
28
+ }
29
+
30
+ // Extract Status
31
+ const statusMatch = content.match(/\*\*Status:\*\*\s*\[?(SUCCESS|FAILED|BLOCKED)\]?/i);
32
+ if (statusMatch) {
33
+ data.status = statusMatch[1].toUpperCase();
34
+ }
35
+
36
+ // Extract Task Name / Scope
37
+ const titleMatch = content.match(/#\s*Report:\s*(.+)/i);
38
+ if (titleMatch) {
39
+ data.task_scope = titleMatch[1].trim().substring(0, 100);
40
+ }
41
+
42
+ // If failed/blocked, capture next few lines as error summary
43
+ if (data.status === 'FAILED' || data.status === 'BLOCKED') {
44
+ const lines = content.split('\n');
45
+ const statusIndex = lines.findIndex(l => l.match(/\*\*Status:\*\*/i));
46
+ if (statusIndex !== -1 && statusIndex + 1 < lines.length) {
47
+ data.error_summary = lines.slice(statusIndex + 1, statusIndex + 4).join(' ').trim().substring(0, 500);
48
+ }
49
+ }
50
+
51
+ return data;
52
+ }
53
+
54
+ /**
55
+ * Reads the latest report and pushes it to the telemetry server.
56
+ * @param {string} repoPath
57
+ * @param {boolean} silent If true, suppresses console output (for automated runs)
58
+ */
59
+ export async function pushTelemetry(repoPath, silent = false) {
60
+ const reportPath = path.join(repoPath, '.eck', 'lastsnapshot', 'AnswerToSA.md');
61
+
62
+ try {
63
+ const content = await fs.readFile(reportPath, 'utf-8');
64
+
65
+ // Don't push if already pushed
66
+ if (content.includes('[TELEMETRY: PUSHED]')) {
67
+ if (!silent) console.log(chalk.yellow('i Telemetry already pushed for this report.'));
68
+ return;
69
+ }
70
+
71
+ const payload = parseAgentReport(content);
72
+ if (!payload || payload.status === 'UNKNOWN') {
73
+ if (!silent) console.log(chalk.yellow('i Could not parse a valid agent report for telemetry.'));
74
+ return;
75
+ }
76
+
77
+ const response = await fetch(TELEMETRY_URL, {
78
+ method: 'POST',
79
+ headers: { 'Content-Type': 'application/json' },
80
+ body: JSON.stringify(payload)
81
+ });
82
+
83
+ if (response.ok) {
84
+ if (!silent) console.log(chalk.green(`Telemetry pushed successfully for ${payload.model_name} (${payload.status})`));
85
+ await fs.appendFile(reportPath, '\n\n[TELEMETRY: PUSHED]\n', 'utf-8');
86
+ } else {
87
+ if (!silent) console.log(chalk.red(`Telemetry push failed: ${response.statusText}`));
88
+ }
89
+ } catch (error) {
90
+ if (!silent) {
91
+ if (error.code === 'ENOENT') {
92
+ console.log(chalk.yellow('i No AnswerToSA.md found. Nothing to push.'));
93
+ } else {
94
+ console.log(chalk.red(`Telemetry error: ${error.message}`));
95
+ }
96
+ }
97
+ }
98
+ }
@@ -117,8 +117,50 @@ export async function addTrainingPoint(projectType, fileSizeInBytes, estimatedTo
117
117
  console.log(` Estimated: ${estimatedTokens} tokens`);
118
118
  console.log(` Actual: ${actualTokens} tokens`);
119
119
  console.log(` Error: ${Math.abs(actualTokens - estimatedTokens)} tokens (${Math.round(Math.abs(actualTokens - estimatedTokens) / actualTokens * 100)}%)`);
120
+
121
+ // Push training point to Telemetry Hub
122
+ try {
123
+ const res = await fetch('https://xelth.com/T/tokens/train', {
124
+ method: 'POST',
125
+ headers: { 'Content-Type': 'application/json' },
126
+ body: JSON.stringify({
127
+ project_type: projectType,
128
+ file_size_bytes: fileSizeInBytes,
129
+ actual_tokens: actualTokens
130
+ })
131
+ });
132
+ if (res.ok) {
133
+ console.log(' Training point pushed to Telemetry Hub');
134
+ }
135
+ } catch (e) {
136
+ // Fail silently, network might be down
137
+ }
120
138
  }
121
139
 
140
+ /**
141
+ * Fetch global token weights from Telemetry Hub and merge them into local training data
142
+ */
143
+ export async function syncTokenWeights(silent = false) {
144
+ try {
145
+ if (!silent) console.log('Fetching global token weights from Telemetry Hub...');
146
+ const res = await fetch('https://xelth.com/T/tokens/weights');
147
+ if (!res.ok) throw new Error(res.statusText);
148
+ const data = await res.json();
149
+
150
+ if (data && data.coefficients && Object.keys(data.coefficients).length > 0) {
151
+ const localData = await loadTrainingData();
152
+ // Global coefficients override local ones
153
+ localData.coefficients = { ...localData.coefficients, ...data.coefficients };
154
+ await saveTrainingData(localData);
155
+ if (!silent) console.log('Global token weights synchronized successfully.');
156
+ } else {
157
+ if (!silent) console.log('No global weights available yet.');
158
+ }
159
+ } catch (e) {
160
+ if (!silent) console.log('Failed to sync token weights: ' + e.message);
161
+ }
162
+ }
163
+
122
164
  /**
123
165
  * Update polynomial coefficients using least squares fitting
124
166
  * For now, we'll use a simple adaptive approach
@@ -175,27 +217,31 @@ function updateCoefficients(data, projectType) {
175
217
  ];
176
218
  }
177
219
 
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('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
220
+ /**
221
+ * Show current estimation statistics
222
+ */
223
+ export async function showEstimationStats() {
224
+ const data = await loadTrainingData();
225
+
226
+ console.log('\nšŸ“Š Token Estimation Statistics:');
227
+ console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
228
+
229
+ for (const [projectType, coefficients] of Object.entries(data.coefficients)) {
230
+ const points = data.trainingPoints[projectType] || [];
231
+ console.log(`\nšŸ”ø ${projectType}:`);
232
+ console.log(` Coefficients: [${coefficients.map(c => c.toFixed(6)).join(', ')}]`);
233
+ console.log(` Training points: ${points.length}`);
234
+
235
+ if (points.length > 0) {
236
+ // Recalculate error against current coefficients, ignoring old stored estimate
237
+ const errors = points.map(p => {
238
+ const currentEstimate = evaluatePolynomial(coefficients, p.fileSizeInBytes);
239
+ return Math.abs(p.actualTokens - currentEstimate);
240
+ });
241
+ const avgError = errors.reduce((a, b) => a + b, 0) / errors.length;
242
+ console.log(` Average error: ${Math.round(avgError)} tokens`);
243
+ }
244
+ }
245
+
246
+ console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
201
247
  }