decharge-scout 4.6.0 โ†’ 4.8.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,112 @@
1
+ /**
2
+ * Vercel API Endpoint - Fleet Data Submission
3
+ *
4
+ * POST /api/agentone/fleet-submit
5
+ * Receives fleet optimization data and stores it in Supabase
6
+ */
7
+
8
+ import { createClient } from '@supabase/supabase-js';
9
+
10
+ export const config = {
11
+ runtime: 'edge',
12
+ };
13
+
14
+ export default async function handler(req) {
15
+ // CORS headers
16
+ const headers = {
17
+ 'Access-Control-Allow-Origin': '*',
18
+ 'Access-Control-Allow-Methods': 'POST, OPTIONS',
19
+ 'Access-Control-Allow-Headers': 'Content-Type',
20
+ 'Content-Type': 'application/json',
21
+ };
22
+
23
+ // Handle OPTIONS request for CORS
24
+ if (req.method === 'OPTIONS') {
25
+ return new Response(null, { status: 200, headers });
26
+ }
27
+
28
+ // Only allow POST
29
+ if (req.method !== 'POST') {
30
+ return new Response(
31
+ JSON.stringify({ error: 'Method not allowed' }),
32
+ { status: 405, headers }
33
+ );
34
+ }
35
+
36
+ try {
37
+ const data = await req.json();
38
+
39
+ // Validate required fields for fleet submissions
40
+ if (!data.type || data.type !== 'fleet') {
41
+ return new Response(
42
+ JSON.stringify({ error: 'Invalid submission type. Expected "fleet"' }),
43
+ { status: 400, headers }
44
+ );
45
+ }
46
+
47
+ if (!data.agent_name || !data.location || !data.timestamp || !data.fleet_size || !data.summary) {
48
+ return new Response(
49
+ JSON.stringify({ error: 'Missing required fields for fleet submission' }),
50
+ { status: 400, headers }
51
+ );
52
+ }
53
+
54
+ // Initialize Supabase client
55
+ const supabase = createClient(
56
+ process.env.SUPABASE_URL,
57
+ process.env.SUPABASE_ANON_KEY
58
+ );
59
+
60
+ // Insert fleet submission
61
+ const { error: fleetError } = await supabase
62
+ .from('fleet_submissions')
63
+ .insert({
64
+ agent_name: data.agent_name,
65
+ wallet: data.wallet,
66
+ location: data.location,
67
+ timestamp: new Date(data.timestamp).toISOString(),
68
+ fleet_size: data.fleet_size,
69
+ total_distance_km: data.summary.total_distance_km,
70
+ total_cost_usd: data.summary.total_cost_usd,
71
+ savings_percent: data.summary.savings_percent,
72
+ co2_saved_kg: data.summary.co2_saved_kg,
73
+ duration_hours: data.summary.duration_hours,
74
+ route_geojson: data.route,
75
+ stops: data.stops,
76
+ simulation_basis: data.simulation_basis || 'weather-based simulation',
77
+ });
78
+
79
+ if (fleetError) throw fleetError;
80
+
81
+ // Update agent heartbeat (upsert)
82
+ const { error: heartbeatError } = await supabase
83
+ .from('agent_heartbeat')
84
+ .upsert(
85
+ {
86
+ agent_name: data.agent_name,
87
+ location: data.location,
88
+ last_seen: new Date().toISOString(),
89
+ },
90
+ { onConflict: 'agent_name' }
91
+ );
92
+
93
+ if (heartbeatError) throw heartbeatError;
94
+
95
+ return new Response(
96
+ JSON.stringify({
97
+ success: true,
98
+ message: 'Fleet data submitted successfully',
99
+ }),
100
+ { status: 200, headers }
101
+ );
102
+ } catch (error) {
103
+ console.error('Fleet submission error:', error);
104
+ return new Response(
105
+ JSON.stringify({
106
+ error: 'Internal server error',
107
+ message: error.message,
108
+ }),
109
+ { status: 500, headers }
110
+ );
111
+ }
112
+ }
@@ -65,3 +65,39 @@ FROM agent_submissions
65
65
  WHERE created_at > NOW() - INTERVAL '24 hours'
66
66
  GROUP BY DATE_TRUNC('hour', created_at)
67
67
  ORDER BY hour DESC;
68
+
69
+ -- Table: fleet_submissions
70
+ -- Stores fleet optimization submissions
71
+ CREATE TABLE IF NOT EXISTS fleet_submissions (
72
+ id SERIAL PRIMARY KEY,
73
+ agent_name VARCHAR(255) NOT NULL,
74
+ wallet VARCHAR(255),
75
+ location VARCHAR(255) NOT NULL,
76
+ timestamp TIMESTAMP NOT NULL,
77
+ fleet_size INTEGER NOT NULL,
78
+ total_distance_km INTEGER NOT NULL,
79
+ total_cost_usd DECIMAL(10, 2) NOT NULL,
80
+ savings_percent INTEGER NOT NULL,
81
+ co2_saved_kg INTEGER NOT NULL,
82
+ duration_hours INTEGER NOT NULL,
83
+ route_geojson JSONB,
84
+ stops JSONB,
85
+ simulation_basis VARCHAR(255),
86
+ created_at TIMESTAMP DEFAULT NOW()
87
+ );
88
+
89
+ -- Indexes for fleet queries
90
+ CREATE INDEX idx_fleet_created_at ON fleet_submissions(created_at DESC);
91
+ CREATE INDEX idx_fleet_agent ON fleet_submissions(agent_name);
92
+ CREATE INDEX idx_fleet_location ON fleet_submissions(location);
93
+
94
+ -- View: Fleet stats (last 24h)
95
+ CREATE OR REPLACE VIEW fleet_stats_daily AS
96
+ SELECT
97
+ COUNT(*) as total_fleets,
98
+ SUM(fleet_size) as total_vehicles,
99
+ SUM(total_distance_km) as total_distance,
100
+ AVG(savings_percent) as avg_savings,
101
+ SUM(co2_saved_kg) as total_co2_saved
102
+ FROM fleet_submissions
103
+ WHERE created_at > NOW() - INTERVAL '24 hours';
@@ -10,6 +10,10 @@
10
10
  "src": "/api/stats",
11
11
  "dest": "/api/stats.js"
12
12
  },
13
+ {
14
+ "src": "/api/agentone/fleet-submit",
15
+ "dest": "/api/agentone/fleet-submit.js"
16
+ },
13
17
  {
14
18
  "src": "/(.*)",
15
19
  "dest": "/public/index.html"
@@ -0,0 +1,109 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Debug Fleet API Call
5
+ *
6
+ * This script simulates what fleet.js sends to help debug why data isn't saving
7
+ */
8
+
9
+ import fetch from 'node-fetch';
10
+ import chalk from 'chalk';
11
+
12
+ const API_URL = 'https://decharge-scout.vercel.app/api/agentone/fleet-submit';
13
+
14
+ // Simulate the exact payload fleet.js sends
15
+ const testPayload = {
16
+ type: 'fleet',
17
+ agent_name: 'DebugAgent-' + Date.now(),
18
+ wallet: 'TestWallet123',
19
+ location: 'New York โ†’ Boston',
20
+ timestamp: Date.now(),
21
+ fleet_size: 10,
22
+ route: {
23
+ type: 'LineString',
24
+ coordinates: [
25
+ [-74.0060, 40.7128], // New York
26
+ [-71.0589, 42.3601] // Boston
27
+ ]
28
+ },
29
+ stops: [
30
+ {
31
+ lat: 41.5,
32
+ lon: -72.5,
33
+ time: '3AM-4AM',
34
+ price: 0.025,
35
+ savings: 80,
36
+ location: 'Hartford, CT',
37
+ segmentId: 1
38
+ }
39
+ ],
40
+ summary: {
41
+ total_distance_km: 350,
42
+ total_cost_usd: 150.00,
43
+ savings_percent: 78,
44
+ co2_saved_kg: 45,
45
+ duration_hours: 4
46
+ },
47
+ simulation_basis: 'Task1 simulation + OSRM routing'
48
+ };
49
+
50
+ console.log(chalk.cyan('\n๐Ÿ” Fleet API Debug Tool\n'));
51
+ console.log(chalk.blue('Testing endpoint:', API_URL));
52
+ console.log(chalk.gray('\nPayload being sent:'));
53
+ console.log(chalk.gray(JSON.stringify(testPayload, null, 2)));
54
+ console.log(chalk.gray('\n' + '='.repeat(60) + '\n'));
55
+
56
+ async function testAPI() {
57
+ try {
58
+ console.log(chalk.yellow('โณ Sending request...'));
59
+
60
+ const response = await fetch(API_URL, {
61
+ method: 'POST',
62
+ headers: {
63
+ 'Content-Type': 'application/json'
64
+ },
65
+ body: JSON.stringify(testPayload)
66
+ });
67
+
68
+ console.log(chalk.blue(`\n๐Ÿ“ก Response Status: ${response.status} ${response.statusText}`));
69
+
70
+ const responseText = await response.text();
71
+ console.log(chalk.blue('๐Ÿ“„ Response Body:'));
72
+
73
+ try {
74
+ const responseJson = JSON.parse(responseText);
75
+ console.log(chalk.white(JSON.stringify(responseJson, null, 2)));
76
+ } catch (e) {
77
+ console.log(chalk.white(responseText));
78
+ }
79
+
80
+ if (response.ok) {
81
+ console.log(chalk.green('\nโœ… SUCCESS! Data should be in Supabase now.'));
82
+ console.log(chalk.gray('Check the fleet_submissions table in Supabase.'));
83
+ } else {
84
+ console.log(chalk.red('\nโŒ FAILED! API rejected the request.'));
85
+ console.log(chalk.yellow('\nCommon issues:'));
86
+ console.log(chalk.gray('- 404: API endpoint not deployed to Vercel'));
87
+ console.log(chalk.gray('- 400: Validation error (check response body above)'));
88
+ console.log(chalk.gray('- 500: Server error (table missing, env vars, etc.)'));
89
+ }
90
+
91
+ // Show headers for debugging
92
+ console.log(chalk.gray('\n๐Ÿ“‹ Response Headers:'));
93
+ response.headers.forEach((value, key) => {
94
+ console.log(chalk.gray(` ${key}: ${value}`));
95
+ });
96
+
97
+ } catch (error) {
98
+ console.log(chalk.red('\nโŒ Network Error!'));
99
+ console.log(chalk.red('Error:', error.message));
100
+ console.log(chalk.yellow('\nThis usually means:'));
101
+ console.log(chalk.gray('- No internet connection'));
102
+ console.log(chalk.gray('- DNS resolution failed'));
103
+ console.log(chalk.gray('- Vercel deployment not accessible'));
104
+ }
105
+ }
106
+
107
+ testAPI().then(() => {
108
+ console.log(chalk.gray('\n' + '='.repeat(60) + '\n'));
109
+ });
package/index.js CHANGED
@@ -511,7 +511,7 @@ async function runQueryCycle(wallet, agentName, location, options) {
511
511
  // Submit to DeCharge Scout dashboard
512
512
  try {
513
513
  const dashboardSpinner = ora('Submitting to DeCharge Scout dashboard...').start();
514
- const apiUrl = 'https://decharge-scout.vercel.app/api/agentone/submit';
514
+ const apiUrl = 'https://decharge-scout.vercel.app/api/submit';
515
515
 
516
516
  console.log(chalk.blue(`\n๐ŸŒ Dashboard API URL: ${apiUrl}`));
517
517
  console.log(chalk.gray(`๐Ÿ“ค Submitting data...`));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "decharge-scout",
3
- "version": "4.6.0",
3
+ "version": "4.8.0",
4
4
  "description": "Global Energy Scout - Weather-powered intelligent energy price forecasting with Solana integration",
5
5
  "main": "index.js",
6
6
  "type": "module",
package/src/fleet.js CHANGED
@@ -404,7 +404,9 @@ export async function runFleetOptimization(options) {
404
404
  console.log(chalk.cyan('\n๐Ÿ—บ๏ธ Your fleet optimization has been added as a new layer on the AgentOne global map!'));
405
405
  console.log(chalk.blue(' View at: https://decharge-scout.vercel.app/agentone\n'));
406
406
  } else {
407
+ const errorBody = await response.text();
407
408
  dashboardSpinner.warn(chalk.yellow(`โš ๏ธ Dashboard API returned: ${response.status}`));
409
+ console.log(chalk.red(` Error details: ${errorBody}`));
408
410
  }
409
411
  } catch (error) {
410
412
  console.log(chalk.yellow(`โš ๏ธ Dashboard submission failed: ${error.message}`));
package/test-api.js CHANGED
@@ -10,8 +10,8 @@
10
10
  import fetch from 'node-fetch';
11
11
  import chalk from 'chalk';
12
12
 
13
- const DASHBOARD_API_URL = 'https://decharge-scout.vercel.app/agentone/api/submit';
14
- const STATS_API_URL = 'https://decharge-scout.vercel.app/agentone/api/stats';
13
+ const DASHBOARD_API_URL = 'https://decharge-scout.vercel.app/api/submit';
14
+ const STATS_API_URL = 'https://decharge-scout.vercel.app/api/stats';
15
15
 
16
16
  // Sample test data
17
17
  const testData = {
@@ -0,0 +1,225 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Comprehensive API Test Script
5
+ *
6
+ * Tests both regular submit and fleet-submit endpoints
7
+ */
8
+
9
+ import fetch from 'node-fetch';
10
+ import chalk from 'chalk';
11
+
12
+ const SUBMIT_API_URL = 'https://decharge-scout.vercel.app/api/submit';
13
+ const FLEET_SUBMIT_API_URL = 'https://decharge-scout.vercel.app/api/agentone/fleet-submit';
14
+ const STATS_API_URL = 'https://decharge-scout.vercel.app/api/stats';
15
+
16
+ // Sample regular submission data
17
+ const regularSubmissionData = {
18
+ agent_name: `TestAgent-${Math.random().toString(36).substring(7).toUpperCase()}`,
19
+ location: 'Test City, TX, US',
20
+ timestamp: Date.now(),
21
+ results: {
22
+ cheapest_window: '2AM-3AM',
23
+ price: 0.0299,
24
+ savings: 75.5,
25
+ data_points: 24
26
+ }
27
+ };
28
+
29
+ // Sample fleet submission data
30
+ const fleetSubmissionData = {
31
+ type: 'fleet',
32
+ agent_name: `FleetAgent-${Math.random().toString(36).substring(7).toUpperCase()}`,
33
+ wallet: 'TestWallet123',
34
+ location: 'New York โ†’ Boston',
35
+ timestamp: Date.now(),
36
+ fleet_size: 10,
37
+ route: {
38
+ type: 'LineString',
39
+ coordinates: [
40
+ [-74.0060, 40.7128], // New York
41
+ [-71.0589, 42.3601] // Boston
42
+ ]
43
+ },
44
+ stops: [
45
+ {
46
+ lat: 41.5,
47
+ lon: -72.5,
48
+ time: '3AM-4AM',
49
+ price: 0.025,
50
+ savings: 80,
51
+ location: 'Hartford, CT',
52
+ segmentId: 1
53
+ }
54
+ ],
55
+ summary: {
56
+ total_distance_km: 350,
57
+ total_cost_usd: 150.00,
58
+ savings_percent: 78,
59
+ co2_saved_kg: 45,
60
+ duration_hours: 4
61
+ },
62
+ simulation_basis: 'Test simulation'
63
+ };
64
+
65
+ console.log(chalk.cyan.bold('\n๐Ÿงช Comprehensive API Test Suite\n'));
66
+ console.log(chalk.gray('=' .repeat(60)));
67
+
68
+ /**
69
+ * Test 1: Regular Submit Endpoint
70
+ */
71
+ async function testRegularSubmit() {
72
+ console.log(chalk.blue('\n๐Ÿ“ TEST 1: Regular Submit Endpoint'));
73
+ console.log(chalk.gray(` URL: ${SUBMIT_API_URL}`));
74
+ console.log(chalk.gray(` Agent: ${regularSubmissionData.agent_name}`));
75
+
76
+ try {
77
+ const response = await fetch(SUBMIT_API_URL, {
78
+ method: 'POST',
79
+ headers: {
80
+ 'Content-Type': 'application/json',
81
+ },
82
+ body: JSON.stringify(regularSubmissionData)
83
+ });
84
+
85
+ const responseText = await response.text();
86
+
87
+ console.log(chalk.blue(`\n ๐Ÿ“ฅ Status: ${response.status}`));
88
+ console.log(chalk.blue(` ๐Ÿ“ฅ Response: ${responseText}`));
89
+
90
+ if (response.ok) {
91
+ console.log(chalk.green('\n โœ… Regular submit: PASS'));
92
+ return { success: true, agent: regularSubmissionData.agent_name };
93
+ } else {
94
+ console.log(chalk.red('\n โŒ Regular submit: FAIL'));
95
+ return { success: false, error: responseText };
96
+ }
97
+ } catch (error) {
98
+ console.log(chalk.red(`\n โŒ Error: ${error.message}`));
99
+ return { success: false, error: error.message };
100
+ }
101
+ }
102
+
103
+ /**
104
+ * Test 2: Fleet Submit Endpoint
105
+ */
106
+ async function testFleetSubmit() {
107
+ console.log(chalk.blue('\n\n๐Ÿš› TEST 2: Fleet Submit Endpoint'));
108
+ console.log(chalk.gray(` URL: ${FLEET_SUBMIT_API_URL}`));
109
+ console.log(chalk.gray(` Agent: ${fleetSubmissionData.agent_name}`));
110
+ console.log(chalk.gray(` Fleet size: ${fleetSubmissionData.fleet_size} EVs`));
111
+
112
+ try {
113
+ const response = await fetch(FLEET_SUBMIT_API_URL, {
114
+ method: 'POST',
115
+ headers: {
116
+ 'Content-Type': 'application/json',
117
+ },
118
+ body: JSON.stringify(fleetSubmissionData)
119
+ });
120
+
121
+ const responseText = await response.text();
122
+
123
+ console.log(chalk.blue(`\n ๐Ÿ“ฅ Status: ${response.status}`));
124
+ console.log(chalk.blue(` ๐Ÿ“ฅ Response: ${responseText}`));
125
+
126
+ if (response.ok) {
127
+ console.log(chalk.green('\n โœ… Fleet submit: PASS'));
128
+ return { success: true, agent: fleetSubmissionData.agent_name };
129
+ } else {
130
+ console.log(chalk.red('\n โŒ Fleet submit: FAIL'));
131
+ return { success: false, error: responseText };
132
+ }
133
+ } catch (error) {
134
+ console.log(chalk.red(`\n โŒ Error: ${error.message}`));
135
+ return { success: false, error: error.message };
136
+ }
137
+ }
138
+
139
+ /**
140
+ * Test 3: Stats Endpoint
141
+ */
142
+ async function testStats() {
143
+ console.log(chalk.blue('\n\n๐Ÿ“Š TEST 3: Stats Endpoint'));
144
+ console.log(chalk.gray(` URL: ${STATS_API_URL}`));
145
+
146
+ try {
147
+ const response = await fetch(STATS_API_URL);
148
+ const data = await response.json();
149
+
150
+ console.log(chalk.blue(`\n ๐Ÿ“ฅ Status: ${response.status}`));
151
+
152
+ if (response.ok) {
153
+ console.log(chalk.green('\n โœ… Stats endpoint: PASS'));
154
+ console.log(chalk.magenta(` ๐Ÿ“Š Active Agents: ${data.activeAgents}`));
155
+ console.log(chalk.magenta(` ๐Ÿ“Š Total Submissions: ${data.totalSubmissions}`));
156
+ console.log(chalk.magenta(` ๐Ÿ“Š Locations tracked: ${data.locations?.length || 0}`));
157
+ return { success: true, data };
158
+ } else {
159
+ console.log(chalk.red('\n โŒ Stats endpoint: FAIL'));
160
+ return { success: false, error: await response.text() };
161
+ }
162
+ } catch (error) {
163
+ console.log(chalk.red(`\n โŒ Error: ${error.message}`));
164
+ return { success: false, error: error.message };
165
+ }
166
+ }
167
+
168
+ /**
169
+ * Main test runner
170
+ */
171
+ async function main() {
172
+ console.log(chalk.yellow('\n๐Ÿš€ Starting comprehensive API tests...\n'));
173
+
174
+ // Run all tests
175
+ const regularResult = await testRegularSubmit();
176
+ await new Promise(resolve => setTimeout(resolve, 2000)); // Wait 2 seconds
177
+
178
+ const fleetResult = await testFleetSubmit();
179
+ await new Promise(resolve => setTimeout(resolve, 2000)); // Wait 2 seconds
180
+
181
+ const statsResult = await testStats();
182
+
183
+ // Summary
184
+ console.log(chalk.gray('\n' + '=' .repeat(60)));
185
+ console.log(chalk.cyan.bold('\n๐Ÿ“‹ Test Summary:\n'));
186
+
187
+ console.log(regularResult.success
188
+ ? chalk.green(' โœ… Regular submit endpoint: PASS')
189
+ : chalk.red(' โŒ Regular submit endpoint: FAIL'));
190
+
191
+ console.log(fleetResult.success
192
+ ? chalk.green(' โœ… Fleet submit endpoint: PASS')
193
+ : chalk.red(' โŒ Fleet submit endpoint: FAIL'));
194
+
195
+ console.log(statsResult.success
196
+ ? chalk.green(' โœ… Stats endpoint: PASS')
197
+ : chalk.red(' โŒ Stats endpoint: FAIL'));
198
+
199
+ const allPassed = regularResult.success && fleetResult.success && statsResult.success;
200
+
201
+ if (allPassed) {
202
+ console.log(chalk.green.bold('\n๐ŸŽ‰ All tests passed! Both endpoints are working!\n'));
203
+ console.log(chalk.blue(' ๐ŸŒ View dashboard: https://decharge-scout.vercel.app/agentone\n'));
204
+ console.log(chalk.yellow(' ๐Ÿ“ Check Supabase for:'));
205
+ console.log(chalk.gray(` - Regular submission: ${regularResult.agent}`));
206
+ console.log(chalk.gray(` - Fleet submission: ${fleetResult.agent}\n`));
207
+ } else {
208
+ console.log(chalk.red.bold('\nโš ๏ธ Some tests failed. Check errors above.\n'));
209
+
210
+ if (!regularResult.success || !fleetResult.success) {
211
+ console.log(chalk.yellow(' Common issues:'));
212
+ console.log(chalk.gray(' 1. Supabase tables not created (run schema.sql)'));
213
+ console.log(chalk.gray(' 2. Missing Vercel environment variables'));
214
+ console.log(chalk.gray(' 3. Need to redeploy Vercel after changes'));
215
+ console.log(chalk.gray(' 4. Check Vercel logs: vercel logs\n'));
216
+ }
217
+ }
218
+
219
+ console.log(chalk.gray('=' .repeat(60) + '\n'));
220
+ }
221
+
222
+ main().catch(error => {
223
+ console.error(chalk.red('Fatal error:'), error);
224
+ process.exit(1);
225
+ });
@@ -0,0 +1,133 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Simple Live API Test - Hit both endpoints
5
+ */
6
+
7
+ import https from 'https';
8
+
9
+ const SUBMIT_API = 'https://decharge-scout.vercel.app/api/submit';
10
+ const FLEET_API = 'https://decharge-scout.vercel.app/api/agentone/fleet-submit';
11
+
12
+ // Test data for regular submit
13
+ const regularData = {
14
+ agent_name: `TestAgent-${Date.now()}`,
15
+ location: 'Test City, TX, US',
16
+ timestamp: Date.now(),
17
+ results: {
18
+ cheapest_window: '2AM-3AM',
19
+ price: 0.0299,
20
+ savings: 75.5,
21
+ data_points: 24
22
+ }
23
+ };
24
+
25
+ // Test data for fleet submit
26
+ const fleetData = {
27
+ type: 'fleet',
28
+ agent_name: `FleetAgent-${Date.now()}`,
29
+ wallet: 'TestWallet123',
30
+ location: 'New York โ†’ Boston',
31
+ timestamp: Date.now(),
32
+ fleet_size: 10,
33
+ route: {
34
+ type: 'LineString',
35
+ coordinates: [[-74.0060, 40.7128], [-71.0589, 42.3601]]
36
+ },
37
+ stops: [{
38
+ lat: 41.5,
39
+ lon: -72.5,
40
+ time: '3AM-4AM',
41
+ price: 0.025,
42
+ savings: 80,
43
+ location: 'Hartford, CT',
44
+ segmentId: 1
45
+ }],
46
+ summary: {
47
+ total_distance_km: 350,
48
+ total_cost_usd: 150.00,
49
+ savings_percent: 78,
50
+ co2_saved_kg: 45,
51
+ duration_hours: 4
52
+ },
53
+ simulation_basis: 'Test simulation'
54
+ };
55
+
56
+ function hitAPI(url, data, name) {
57
+ return new Promise((resolve, reject) => {
58
+ const urlObj = new URL(url);
59
+ const postData = JSON.stringify(data);
60
+
61
+ const options = {
62
+ hostname: urlObj.hostname,
63
+ path: urlObj.pathname,
64
+ method: 'POST',
65
+ headers: {
66
+ 'Content-Type': 'application/json',
67
+ 'Content-Length': Buffer.byteLength(postData)
68
+ }
69
+ };
70
+
71
+ console.log(`\n๐Ÿ”ต Testing ${name}...`);
72
+ console.log(` URL: ${url}`);
73
+ console.log(` Data: ${JSON.stringify(data, null, 2).substring(0, 200)}...`);
74
+
75
+ const req = https.request(options, (res) => {
76
+ let body = '';
77
+ res.on('data', (chunk) => body += chunk);
78
+ res.on('end', () => {
79
+ console.log(`\n Status: ${res.statusCode}`);
80
+ console.log(` Response: ${body}`);
81
+
82
+ if (res.statusCode === 200 || res.statusCode === 201) {
83
+ console.log(` โœ… ${name} PASSED`);
84
+ resolve({ success: true, status: res.statusCode, body });
85
+ } else {
86
+ console.log(` โŒ ${name} FAILED`);
87
+ resolve({ success: false, status: res.statusCode, body });
88
+ }
89
+ });
90
+ });
91
+
92
+ req.on('error', (error) => {
93
+ console.log(` โŒ ${name} ERROR: ${error.message}`);
94
+ reject(error);
95
+ });
96
+
97
+ req.write(postData);
98
+ req.end();
99
+ });
100
+ }
101
+
102
+ async function main() {
103
+ console.log('๐Ÿงช Testing Both APIs\n');
104
+ console.log('='.repeat(60));
105
+
106
+ try {
107
+ // Test 1: Regular Submit
108
+ const regularResult = await hitAPI(SUBMIT_API, regularData, 'Regular Submit API');
109
+
110
+ // Wait 2 seconds
111
+ await new Promise(r => setTimeout(r, 2000));
112
+
113
+ // Test 2: Fleet Submit
114
+ const fleetResult = await hitAPI(FLEET_API, fleetData, 'Fleet Submit API');
115
+
116
+ // Summary
117
+ console.log('\n' + '='.repeat(60));
118
+ console.log('\n๐Ÿ“Š RESULTS:\n');
119
+ console.log(regularResult.success ? 'โœ… Regular Submit: WORKING' : 'โŒ Regular Submit: FAILED');
120
+ console.log(fleetResult.success ? 'โœ… Fleet Submit: WORKING' : 'โŒ Fleet Submit: FAILED');
121
+
122
+ if (regularResult.success && fleetResult.success) {
123
+ console.log('\n๐ŸŽ‰ Both APIs are working correctly!\n');
124
+ } else {
125
+ console.log('\nโš ๏ธ Some APIs failed - check errors above\n');
126
+ }
127
+
128
+ } catch (error) {
129
+ console.error('\nโŒ Fatal error:', error.message);
130
+ }
131
+ }
132
+
133
+ main();