decharge-scout 4.0.6 → 4.3.1
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/index.js +135 -102
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -40,7 +40,7 @@ import { submitToOracle } from './src/oracle.js';
|
|
|
40
40
|
import { initializePoints, awardPoints, getPoints, savePoints } from './src/points.js';
|
|
41
41
|
import { getLocation } from './src/geolocation.js';
|
|
42
42
|
import { purchasePremiumData } from './src/x402.js';
|
|
43
|
-
import {
|
|
43
|
+
import { parseAlphaContribution, saveAlphaContribution, calculateAlphaBonus, getAlphaInsights, verifyContribution, getInformationSources } from './src/local-alpha.js';
|
|
44
44
|
|
|
45
45
|
const __filename = fileURLToPath(import.meta.url);
|
|
46
46
|
const __dirname = dirname(__filename);
|
|
@@ -267,7 +267,7 @@ async function runQueryCycle(wallet, agentName, location, options) {
|
|
|
267
267
|
|
|
268
268
|
// Fetch weather data and generate smart pricing simulation
|
|
269
269
|
const weatherSpinner = ora('Fetching real-time weather forecast...').start();
|
|
270
|
-
let weatherData, energyData, countryCode;
|
|
270
|
+
let weatherData, energyData, countryCode, insights;
|
|
271
271
|
|
|
272
272
|
try {
|
|
273
273
|
// Get real weather forecast from Open-Meteo (FREE!)
|
|
@@ -281,7 +281,7 @@ async function runQueryCycle(wallet, agentName, location, options) {
|
|
|
281
281
|
pricingSpinner.succeed(chalk.green(`✓ Generated ${energyData.length} hours of smart pricing data`));
|
|
282
282
|
|
|
283
283
|
// Show pricing insights
|
|
284
|
-
|
|
284
|
+
insights = getPricingInsights(energyData, countryCode);
|
|
285
285
|
console.log(chalk.blue(`\n💡 Smart Simulation Insights:`));
|
|
286
286
|
console.log(chalk.gray(` Region: ${insights.region}`));
|
|
287
287
|
console.log(chalk.gray(` Price range: $${insights.minPrice}-$${insights.maxPrice}/kWh (${insights.priceRange}% variation)`));
|
|
@@ -354,17 +354,147 @@ async function runQueryCycle(wallet, agentName, location, options) {
|
|
|
354
354
|
}
|
|
355
355
|
}
|
|
356
356
|
|
|
357
|
-
//
|
|
357
|
+
// Ask for special notes before submission (with 10s timeout)
|
|
358
|
+
console.log(chalk.cyan('\n💬 Add special notes to this submission? (optional)'));
|
|
359
|
+
console.log(chalk.gray(' Examples: "High AC usage today", "Local festival", "Grid maintenance"\n'));
|
|
360
|
+
console.log(chalk.gray(' (Will auto-submit in 10 seconds if no input)\n'));
|
|
361
|
+
|
|
362
|
+
const specialNotes = await Promise.race([
|
|
363
|
+
question(chalk.blue('Special notes (or press Enter to skip): ')),
|
|
364
|
+
new Promise((resolve) => {
|
|
365
|
+
setTimeout(() => {
|
|
366
|
+
console.log(chalk.yellow('\n⏱️ Timeout - submitting without notes'));
|
|
367
|
+
resolve('');
|
|
368
|
+
}, 10000); // 10 second timeout
|
|
369
|
+
})
|
|
370
|
+
]);
|
|
371
|
+
|
|
372
|
+
// Local Alpha Contribution - Ask BEFORE every submission for bonus points
|
|
373
|
+
console.log(chalk.cyan('\n💡 Bonus Points: Share Local Peak Time Knowledge!'));
|
|
374
|
+
console.log(chalk.gray(' Help improve global energy data by sharing when electricity is expensive/cheap in your area.\n'));
|
|
375
|
+
|
|
376
|
+
console.log(chalk.blue('💬 Examples:'));
|
|
377
|
+
console.log(chalk.gray(' • "7-9PM peak in Lagos" (evening peak)'));
|
|
378
|
+
console.log(chalk.gray(' • "1-5AM cheap in Berlin" (off-peak)'));
|
|
379
|
+
console.log(chalk.gray(' • "5-8PM peak in Mumbai" (dinner time surge)'));
|
|
380
|
+
console.log(chalk.gray(' • "2-6AM cheap in Texas" (wind energy overnight)'));
|
|
381
|
+
console.log(chalk.gray(' (Will auto-skip in 15 seconds if no input)\n'));
|
|
382
|
+
|
|
383
|
+
const alphaInput = await Promise.race([
|
|
384
|
+
question(chalk.blue('Share local peak times (or press Enter to skip): ')),
|
|
385
|
+
new Promise((resolve) => {
|
|
386
|
+
setTimeout(() => {
|
|
387
|
+
console.log(chalk.yellow('\n⏱️ Timeout - skipping bonus contribution'));
|
|
388
|
+
resolve('');
|
|
389
|
+
}, 15000); // 15 second timeout
|
|
390
|
+
})
|
|
391
|
+
]);
|
|
392
|
+
|
|
393
|
+
// Process alpha contribution if provided
|
|
394
|
+
if (alphaInput.trim()) {
|
|
395
|
+
const parsed = parseAlphaContribution(alphaInput, location);
|
|
396
|
+
if (parsed) {
|
|
397
|
+
// Verify contribution against current pricing data
|
|
398
|
+
const verification = verifyContribution(parsed, energyData);
|
|
399
|
+
|
|
400
|
+
// Save contribution with verification status
|
|
401
|
+
const contribution = saveAlphaContribution(parsed, agentName, location, verification);
|
|
402
|
+
|
|
403
|
+
// Store for dashboard submission
|
|
404
|
+
pendingAlphaContribution = {
|
|
405
|
+
type: parsed.type,
|
|
406
|
+
startHour: parsed.startHour,
|
|
407
|
+
endHour: parsed.endHour,
|
|
408
|
+
location: parsed.location,
|
|
409
|
+
verified: verification.verified,
|
|
410
|
+
confidence: verification.confidence,
|
|
411
|
+
verificationReasons: verification.reasons
|
|
412
|
+
};
|
|
413
|
+
|
|
414
|
+
// Calculate bonus (higher for verified contributions)
|
|
415
|
+
const alphaBonus = calculateAlphaBonus(parsed, verification);
|
|
416
|
+
|
|
417
|
+
awardPoints(wallet, alphaBonus);
|
|
418
|
+
|
|
419
|
+
console.log(chalk.green(`\n✅ Thanks for contributing! Earned ${alphaBonus} bonus points!`));
|
|
420
|
+
console.log(chalk.gray(` Contribution: ${parsed.type} hours ${parsed.startHour}-${parsed.endHour} in ${parsed.location}`));
|
|
421
|
+
|
|
422
|
+
// Show verification results
|
|
423
|
+
if (verification.verified) {
|
|
424
|
+
console.log(chalk.green(` 🎯 Verified! Confidence: ${(verification.confidence * 100).toFixed(0)}%`));
|
|
425
|
+
verification.reasons.forEach(reason => {
|
|
426
|
+
console.log(chalk.gray(` ${reason}`));
|
|
427
|
+
});
|
|
428
|
+
console.log(chalk.green(` +${alphaBonus - 10} extra points for verified contribution!`));
|
|
429
|
+
} else {
|
|
430
|
+
console.log(chalk.yellow(` ⚠️ Low confidence: ${(verification.confidence * 100).toFixed(0)}%`));
|
|
431
|
+
verification.reasons.forEach(reason => {
|
|
432
|
+
console.log(chalk.gray(` ${reason}`));
|
|
433
|
+
});
|
|
434
|
+
console.log(chalk.gray(` Tip: Contributions that match actual price patterns earn more points!`));
|
|
435
|
+
}
|
|
436
|
+
} else {
|
|
437
|
+
console.log(chalk.yellow('⚠️ Could not parse contribution.'));
|
|
438
|
+
console.log(chalk.gray(' Accepted formats:'));
|
|
439
|
+
console.log(chalk.gray(' • "7-9PM peak in Lagos"'));
|
|
440
|
+
console.log(chalk.gray(' • "1-5AM cheap in Berlin"'));
|
|
441
|
+
console.log(chalk.gray(' • "19-21 peak Mumbai" (24-hour format also works)'));
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
// Prepare comprehensive submission data
|
|
358
446
|
const submissionData = {
|
|
359
447
|
agent_name: agentName,
|
|
360
448
|
location: location,
|
|
361
449
|
timestamp: Date.now(),
|
|
450
|
+
|
|
451
|
+
// Summary results (for quick display)
|
|
362
452
|
results: {
|
|
363
453
|
cheapest_window: cheapestWindow.timeWindow,
|
|
364
454
|
price: cheapestWindow.price,
|
|
365
455
|
savings: savings,
|
|
366
456
|
data_points: energyData.length
|
|
367
|
-
}
|
|
457
|
+
},
|
|
458
|
+
|
|
459
|
+
// Full weather data
|
|
460
|
+
weather: {
|
|
461
|
+
location: weatherData.location,
|
|
462
|
+
forecast_summary: {
|
|
463
|
+
hours: weatherData.forecast.length,
|
|
464
|
+
temp_range: {
|
|
465
|
+
min: Math.min(...weatherData.forecast.map(f => f.temperature)),
|
|
466
|
+
max: Math.max(...weatherData.forecast.map(f => f.temperature))
|
|
467
|
+
},
|
|
468
|
+
avg_wind: weatherData.forecast.reduce((sum, f) => sum + f.windSpeed, 0) / weatherData.forecast.length,
|
|
469
|
+
avg_solar: weatherData.forecast.reduce((sum, f) => sum + f.solarRadiation, 0) / weatherData.forecast.length
|
|
470
|
+
},
|
|
471
|
+
optimal_hour_conditions: cheapestHourData?.weather || null
|
|
472
|
+
},
|
|
473
|
+
|
|
474
|
+
// Pricing insights
|
|
475
|
+
pricing: {
|
|
476
|
+
region: insights.region,
|
|
477
|
+
base_price: insights.basePrice,
|
|
478
|
+
price_range: {
|
|
479
|
+
min: insights.minPrice,
|
|
480
|
+
max: insights.maxPrice,
|
|
481
|
+
variation_percent: insights.priceRange
|
|
482
|
+
},
|
|
483
|
+
savings_potential: insights.savingsPotential,
|
|
484
|
+
country_code: countryCode
|
|
485
|
+
},
|
|
486
|
+
|
|
487
|
+
// Optimization details
|
|
488
|
+
optimization: {
|
|
489
|
+
cheapest_hour: cheapestWindow.hour,
|
|
490
|
+
time_window: cheapestWindow.timeWindow,
|
|
491
|
+
price: cheapestWindow.price,
|
|
492
|
+
savings_percent: savings,
|
|
493
|
+
reasons: cheapestHourData?.reasons || []
|
|
494
|
+
},
|
|
495
|
+
|
|
496
|
+
// Special notes from user
|
|
497
|
+
notes: specialNotes.trim() || null
|
|
368
498
|
};
|
|
369
499
|
|
|
370
500
|
// Submit to oracle
|
|
@@ -435,103 +565,6 @@ async function runQueryCycle(wallet, agentName, location, options) {
|
|
|
435
565
|
console.log(chalk.magenta(`\n⭐ Earned ${totalPointsEarned} points! (${basePoints} base${bonusPoints > 0 ? ` + ${bonusPoints} bonus` : ''})`));
|
|
436
566
|
console.log(chalk.magenta(`⭐ Total Points: ${currentPoints}`));
|
|
437
567
|
|
|
438
|
-
// Local Alpha Contribution (ask once after first run)
|
|
439
|
-
if (totalRuns === 1 && !hasBeenAskedForAlpha()) {
|
|
440
|
-
console.log(chalk.cyan('\n💡 Local Alpha Contribution - Help Improve Global Energy Data!'));
|
|
441
|
-
console.log(chalk.gray(' Share your local electricity peak time knowledge for bonus points.\n'));
|
|
442
|
-
|
|
443
|
-
// Show where to find this information
|
|
444
|
-
console.log(chalk.blue('📚 Where to find peak time information:'));
|
|
445
|
-
const sources = getInformationSources(location);
|
|
446
|
-
|
|
447
|
-
// General sources
|
|
448
|
-
sources.general.forEach(source => {
|
|
449
|
-
console.log(chalk.gray(` ${source}`));
|
|
450
|
-
});
|
|
451
|
-
|
|
452
|
-
// Region-specific sources
|
|
453
|
-
const regionKeys = Object.keys(sources.byRegion);
|
|
454
|
-
if (regionKeys.length > 0) {
|
|
455
|
-
console.log(chalk.blue('\n📍 For your region:'));
|
|
456
|
-
regionKeys.forEach(region => {
|
|
457
|
-
sources.byRegion[region].forEach(source => {
|
|
458
|
-
console.log(chalk.gray(` ${source}`));
|
|
459
|
-
});
|
|
460
|
-
});
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
console.log(chalk.blue('\n💬 Examples of good contributions:'));
|
|
464
|
-
console.log(chalk.gray(' • "7-9PM peak in Lagos" (evening peak)'));
|
|
465
|
-
console.log(chalk.gray(' • "1-5AM cheap in Berlin" (off-peak)'));
|
|
466
|
-
console.log(chalk.gray(' • "5-8PM peak in Mumbai" (dinner time surge)'));
|
|
467
|
-
console.log(chalk.gray(' • "2-6AM cheap in Texas" (wind energy overnight)'));
|
|
468
|
-
console.log(chalk.gray(' (Will auto-skip in 15 seconds if no input)\n'));
|
|
469
|
-
|
|
470
|
-
// Add timeout to prevent hanging
|
|
471
|
-
const alphaInput = await Promise.race([
|
|
472
|
-
question(chalk.blue('Share local peak times (or press Enter to skip): ')),
|
|
473
|
-
new Promise((resolve) => {
|
|
474
|
-
setTimeout(() => {
|
|
475
|
-
console.log(chalk.yellow('\n⏱️ Timeout - skipping alpha contribution'));
|
|
476
|
-
resolve('');
|
|
477
|
-
}, 15000); // 15 second timeout
|
|
478
|
-
})
|
|
479
|
-
]);
|
|
480
|
-
|
|
481
|
-
if (alphaInput.trim()) {
|
|
482
|
-
const parsed = parseAlphaContribution(alphaInput, location);
|
|
483
|
-
if (parsed) {
|
|
484
|
-
// Verify contribution against current pricing data
|
|
485
|
-
const verification = verifyContribution(parsed, energyData);
|
|
486
|
-
|
|
487
|
-
// Save contribution with verification status
|
|
488
|
-
const contribution = saveAlphaContribution(parsed, agentName, location, verification);
|
|
489
|
-
|
|
490
|
-
// Store for dashboard submission
|
|
491
|
-
pendingAlphaContribution = {
|
|
492
|
-
type: parsed.type,
|
|
493
|
-
startHour: parsed.startHour,
|
|
494
|
-
endHour: parsed.endHour,
|
|
495
|
-
location: parsed.location,
|
|
496
|
-
verified: verification.verified,
|
|
497
|
-
confidence: verification.confidence,
|
|
498
|
-
verificationReasons: verification.reasons
|
|
499
|
-
};
|
|
500
|
-
|
|
501
|
-
// Calculate bonus (higher for verified contributions)
|
|
502
|
-
const alphaBonus = calculateAlphaBonus(parsed, verification);
|
|
503
|
-
|
|
504
|
-
awardPoints(wallet, alphaBonus);
|
|
505
|
-
|
|
506
|
-
console.log(chalk.green(`\n✅ Thanks for contributing! Earned ${alphaBonus} bonus points!`));
|
|
507
|
-
console.log(chalk.gray(` Contribution: ${parsed.type} hours ${parsed.startHour}-${parsed.endHour} in ${parsed.location}`));
|
|
508
|
-
|
|
509
|
-
// Show verification results
|
|
510
|
-
if (verification.verified) {
|
|
511
|
-
console.log(chalk.green(` 🎯 Verified! Confidence: ${(verification.confidence * 100).toFixed(0)}%`));
|
|
512
|
-
verification.reasons.forEach(reason => {
|
|
513
|
-
console.log(chalk.gray(` ${reason}`));
|
|
514
|
-
});
|
|
515
|
-
console.log(chalk.green(` +${alphaBonus - 10} extra points for verified contribution!`));
|
|
516
|
-
} else {
|
|
517
|
-
console.log(chalk.yellow(` ⚠️ Low confidence: ${(verification.confidence * 100).toFixed(0)}%`));
|
|
518
|
-
verification.reasons.forEach(reason => {
|
|
519
|
-
console.log(chalk.gray(` ${reason}`));
|
|
520
|
-
});
|
|
521
|
-
console.log(chalk.gray(` Tip: Contributions that match actual price patterns earn more points!`));
|
|
522
|
-
}
|
|
523
|
-
} else {
|
|
524
|
-
console.log(chalk.yellow('⚠️ Could not parse contribution.'));
|
|
525
|
-
console.log(chalk.gray(' Accepted formats:'));
|
|
526
|
-
console.log(chalk.gray(' • "7-9PM peak in Lagos"'));
|
|
527
|
-
console.log(chalk.gray(' • "1-5AM cheap in Berlin"'));
|
|
528
|
-
console.log(chalk.gray(' • "19-21 peak Mumbai" (24-hour format also works)'));
|
|
529
|
-
}
|
|
530
|
-
}
|
|
531
|
-
|
|
532
|
-
markAskedForAlpha();
|
|
533
|
-
}
|
|
534
|
-
|
|
535
568
|
// Show alpha insights if available
|
|
536
569
|
if (totalRuns === 1) {
|
|
537
570
|
const alphaInsights = getAlphaInsights(location);
|