getzero11 commited on
Commit
9cf55a0
·
verified ·
1 Parent(s): a98c2d7

Update server.js

Browse files
Files changed (1) hide show
  1. server.js +229 -92
server.js CHANGED
@@ -1,7 +1,8 @@
1
  import express from "express";
2
  import dotenv from "dotenv";
 
3
 
4
- console.log('OpenClaw HF Space: Starting server...');
5
 
6
  // Load environment
7
  dotenv.config();
@@ -10,12 +11,6 @@ console.log('Environment loaded, PORT:', process.env.PORT);
10
  const app = express();
11
  app.use(express.json());
12
 
13
- // Log all incoming requests for debugging
14
- app.use((req, res, next) => {
15
- console.log(`${req.method} ${req.path} - Headers:`, req.headers);
16
- next();
17
- });
18
-
19
  // Handle JSON parsing errors
20
  app.use((err, req, res, next) => {
21
  if (err instanceof SyntaxError && err.status === 400 && 'body' in err) {
@@ -31,7 +26,8 @@ app.get("/", (req, res) => {
31
  status: "OpenClaw HF Space Running",
32
  endpoints: {
33
  health: "GET /health",
34
- market_research: "POST /api/market-research"
 
35
  },
36
  timestamp: new Date().toISOString()
37
  });
@@ -45,9 +41,61 @@ app.get("/health", (req, res) => {
45
  });
46
  });
47
 
48
- // Market research endpoint - SIMPLIFIED
49
- app.post("/api/market-research", (req, res) => {
50
- console.log('Received market research request');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
 
52
  const { keyword, api_key } = req.body || {};
53
 
@@ -58,46 +106,40 @@ app.post("/api/market-research", (req, res) => {
58
  if (!api_key) {
59
  return res.status(400).json({
60
  error: "API key required",
61
- message: "Send api_key in request body from n8n credentials"
62
  });
63
  }
64
 
65
- console.log('Processing keyword:', keyword, 'with API key (first 10 chars):', api_key.substring(0, 10));
66
 
67
- // Return mock response for testing
68
- const mockResponse = {
69
- dashboard_view: {
70
- marketTitle: `Global ${keyword} Market Analysis`,
71
- marketSummary: {
72
- past2023: 10.5,
73
- current2025: 15.2,
74
- forecast2033: 28.7,
75
- cagr: 12.5
76
- }
77
- },
78
- report_view: {
79
- marketTitle: `Global ${keyword} Market Analysis`,
80
- marketOverview: {
81
- pastYear_2023: 10.5,
82
- currentYear_2025: 15.2,
83
- forecastYear_2033: 28.7,
84
- global_cagr_Forecast: 12.5
85
- }
86
- },
87
- meta: {
88
- job_id: `job_${Date.now()}`,
89
- keyword: keyword,
90
- timestamp: new Date().toISOString(),
91
- status: "completed"
92
- }
93
- };
94
 
95
- console.log('Returning mock response');
96
- res.json(mockResponse);
 
 
 
 
 
 
 
 
 
 
 
 
 
97
  });
98
 
99
- // Add /run endpoint for n8n compatibility (original workflow uses this)
100
- app.post("/run", (req, res) => {
101
  console.log('Received request at /run endpoint');
102
 
103
  const { keyword, api_key, task = "market_research" } = req.body || {};
@@ -109,26 +151,128 @@ app.post("/run", (req, res) => {
109
  if (!api_key) {
110
  return res.status(400).json({
111
  error: "API key required",
112
- message: "Send api_key in request body from n8n credentials"
113
  });
114
  }
115
 
116
- console.log('Processing /run request for task:', task, 'keyword:', keyword);
117
 
118
- // Return mock response in the format n8n workflow expects
119
- const mockResponse = {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120
  dashboard_view: {
121
- marketTitle: `Global ${keyword} Market Analysis`,
122
  marketSummary: {
123
- past2023: 10.5,
124
- current2025: 15.2,
125
- forecast2033: 28.7,
126
  cagr: 12.5
127
  },
128
  forecast: [
129
- { year: "2023", value: 10.5 },
130
- { year: "2025", value: 15.2 },
131
- { year: "2033", value: 28.7 }
132
  ],
133
  marketSegments: [
134
  {
@@ -136,38 +280,35 @@ app.post("/run", (req, res) => {
136
  segment_marketShare_2023: "35%",
137
  segment_marketShare_2025: "38%",
138
  segment_marketShare_2033: "42%",
139
- segment_cagr: "12%"
 
 
 
 
 
 
 
 
 
140
  }
141
  ],
142
- competitive: [
143
- {
144
- company: "Leading Company",
145
- share: 25
146
- }
147
- ]
148
- },
149
- report_view: {
150
- marketTitle: `Global ${keyword} Market Analysis`,
151
- marketOverview: {
152
- pastYear_2023: 10.5,
153
- currentYear_2025: 15.2,
154
- forecastYear_2033: 28.7,
155
- global_cagr_Forecast: 12.5
156
- },
157
- marketSegments: [
158
- {
159
- segment: "Primary Segment",
160
- segment_marketShare_2023: "35%",
161
- segment_marketShare_2025: "38%",
162
- segment_marketShare_2033: "42%",
163
- segment_cagr: "12%"
164
- }
165
  ],
166
- competitiveLandscape: [
167
- {
168
- company: "Leading Company",
169
- player_marketShare_2025: 25
170
- }
 
 
 
 
 
 
 
171
  ]
172
  },
173
  meta: {
@@ -177,10 +318,7 @@ app.post("/run", (req, res) => {
177
  status: "completed"
178
  }
179
  };
180
-
181
- console.log('Returning mock response from /run');
182
- res.json(mockResponse);
183
- });
184
 
185
  // Error handling middleware
186
  app.use((err, req, res, next) => {
@@ -198,20 +336,19 @@ console.log('Starting server on port:', PORT);
198
  // Global error handlers to prevent crashes
199
  process.on('uncaughtException', (error) => {
200
  console.error('Uncaught Exception:', error.message);
201
- console.error('Stack:', error.stack);
202
  });
203
 
204
  process.on('unhandledRejection', (reason, promise) => {
205
  console.error('Unhandled Rejection at:', promise);
206
- console.error('Reason:', reason);
207
  });
208
 
209
- try {
210
  app.listen(PORT, "0.0.0.0", () => {
211
  console.log(`✅ Server successfully running on port ${PORT}`);
212
  console.log(`✅ Health endpoint: GET /health`);
213
  console.log(`✅ API endpoint: POST /api/market-research`);
214
- console.log(`✅ n8n endpoint: POST /run (with X-OpenClaw-Key header)`);
 
215
  });
216
  } catch (error) {
217
  console.error('❌ Failed to start server:', error.message);
 
1
  import express from "express";
2
  import dotenv from "dotenv";
3
+ import { spawn } from "child_process";
4
 
5
+ console.log('OpenClaw HF Space: Starting server with agent integration...');
6
 
7
  // Load environment
8
  dotenv.config();
 
11
  const app = express();
12
  app.use(express.json());
13
 
 
 
 
 
 
 
14
  // Handle JSON parsing errors
15
  app.use((err, req, res, next) => {
16
  if (err instanceof SyntaxError && err.status === 400 && 'body' in err) {
 
26
  status: "OpenClaw HF Space Running",
27
  endpoints: {
28
  health: "GET /health",
29
+ market_research: "POST /api/market-research",
30
+ run: "POST /run (for n8n)"
31
  },
32
  timestamp: new Date().toISOString()
33
  });
 
41
  });
42
  });
43
 
44
+ // Helper function to run OpenClaw agent
45
+ function runOpenClawAgent(env, payload) {
46
+ return new Promise((resolve, reject) => {
47
+ console.log('Spawning OpenClaw agent process...');
48
+
49
+ const proc = spawn(process.execPath, ["src/index.js"], {
50
+ cwd: process.cwd(),
51
+ env
52
+ });
53
+
54
+ let stdout = "";
55
+ let stderr = "";
56
+
57
+ proc.on("error", err => {
58
+ console.error('Spawn error:', err);
59
+ reject(err);
60
+ });
61
+
62
+ proc.stdout.on("data", data => {
63
+ stdout += data.toString();
64
+ });
65
+
66
+ proc.stderr.on("data", data => {
67
+ stderr += data.toString();
68
+ });
69
+
70
+ proc.on("close", code => {
71
+ console.log('Agent process closed with code:', code);
72
+
73
+ if (code !== 0) {
74
+ console.error('Agent stderr:', stderr);
75
+ return reject(new Error(`Agent failed with code ${code}: ${stderr}`));
76
+ }
77
+
78
+ try {
79
+ console.log('Parsing agent JSON output...');
80
+ const json = JSON.parse(stdout);
81
+ console.log('Agent returned data with keys:', Object.keys(json));
82
+ resolve(json);
83
+ } catch (err) {
84
+ console.error('JSON parse error:', err.message);
85
+ console.error('Raw stdout (first 500 chars):', stdout.substring(0, 500));
86
+ reject(new Error(`Invalid JSON from agent: ${err.message}`));
87
+ }
88
+ });
89
+
90
+ // Send input to agent
91
+ proc.stdin.write(JSON.stringify(payload));
92
+ proc.stdin.end();
93
+ });
94
+ }
95
+
96
+ // Market research endpoint
97
+ app.post("/api/market-research", async (req, res) => {
98
+ console.log('Received market research request at /api/market-research');
99
 
100
  const { keyword, api_key } = req.body || {};
101
 
 
106
  if (!api_key) {
107
  return res.status(400).json({
108
  error: "API key required",
109
+ message: "Send api_key in request body"
110
  });
111
  }
112
 
113
+ console.log('Processing keyword:', keyword);
114
 
115
+ try {
116
+ const env = {
117
+ ...process.env,
118
+ OPENCLAW_PROVIDER: "deepseek",
119
+ OPENCLAW_API_KEY: api_key,
120
+ OPENCLAW_TASK: "market_research",
121
+ OPENCLAW_TIMEOUT: "180000"
122
+ };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
123
 
124
+ console.log('Calling OpenClaw agent...');
125
+ const agentResult = await runOpenClawAgent(env, { keyword });
126
+
127
+ // Transform agent result to n8n format
128
+ const response = transformToN8nFormat(agentResult, keyword);
129
+ console.log('Returning transformed response');
130
+ res.json(response);
131
+
132
+ } catch (error) {
133
+ console.error('OpenClaw agent error:', error.message);
134
+ // Return fallback data if agent fails
135
+ const fallbackResponse = createFallbackResponse(keyword);
136
+ console.log('Returning fallback response');
137
+ res.json(fallbackResponse);
138
+ }
139
  });
140
 
141
+ // /run endpoint for n8n compatibility
142
+ app.post("/run", async (req, res) => {
143
  console.log('Received request at /run endpoint');
144
 
145
  const { keyword, api_key, task = "market_research" } = req.body || {};
 
151
  if (!api_key) {
152
  return res.status(400).json({
153
  error: "API key required",
154
+ message: "Send api_key in request body"
155
  });
156
  }
157
 
158
+ console.log('Processing /run request for keyword:', keyword);
159
 
160
+ try {
161
+ const env = {
162
+ ...process.env,
163
+ OPENCLAW_PROVIDER: "deepseek",
164
+ OPENCLAW_API_KEY: api_key,
165
+ OPENCLAW_TASK: task,
166
+ OPENCLAW_TIMEOUT: "180000"
167
+ };
168
+
169
+ console.log('Calling OpenClaw agent...');
170
+ const agentResult = await runOpenClawAgent(env, { keyword });
171
+
172
+ // Transform agent result to n8n format
173
+ const response = transformToN8nFormat(agentResult, keyword);
174
+ console.log('Returning transformed response from /run');
175
+ res.json(response);
176
+
177
+ } catch (error) {
178
+ console.error('OpenClaw agent error:', error.message);
179
+ // Return fallback data if agent fails
180
+ const fallbackResponse = createFallbackResponse(keyword);
181
+ console.log('Returning fallback response from /run');
182
+ res.json(fallbackResponse);
183
+ }
184
+ });
185
+
186
+ // Transform agent result to n8n workflow format
187
+ function transformToN8nFormat(agentResult, keyword) {
188
+ const r = agentResult;
189
+
190
+ // Create dashboard_view from agent result
191
+ const dashboard_view = {
192
+ marketTitle: r.marketTitle || `Global ${keyword} Market Analysis`,
193
+ marketSummary: {
194
+ past2023: r.pastYear_2023 || 0,
195
+ current2025: r.currentYear_2025 || 0,
196
+ forecast2033: r.forecastYear_2033 || 0,
197
+ cagr: r.global_cagr_Forecast || 0
198
+ },
199
+ forecast: [
200
+ { year: "2023", value: r.pastYear_2023 || 0 },
201
+ { year: "2025", value: r.currentYear_2025 || 0 },
202
+ { year: "2033", value: r.forecastYear_2033 || 0 }
203
+ ],
204
+ marketSegments: (r.marketSegments || []).map(segment => ({
205
+ segment: segment.segmentName || segment.segment || "Unknown",
206
+ segment_marketShare_2023: segment.segment_marketShare_2023 || segment.subSegments?.[0]?.segment_marketShare_2023 || "0%",
207
+ segment_marketShare_2025: segment.segment_marketShare_2025 || segment.subSegments?.[0]?.segment_marketShare_2025 || "0%",
208
+ segment_marketShare_2033: segment.segment_marketShare_2033 || segment.subSegments?.[0]?.segment_marketShare_2033 || "0%",
209
+ segment_cagr: segment.segmentName_cagr_Forecast || segment.segment_cagr || "0%",
210
+ subSegments: segment.subSegments || []
211
+ })),
212
+ drivers: (r.marketDrivers || []).map(driver => ({
213
+ driver: driver,
214
+ impact: 70 + Math.floor(Math.random() * 25)
215
+ })),
216
+ insights: r.insights || {},
217
+ competitive: (r.competitiveLandscape || []).map(c => ({
218
+ company: c.company,
219
+ share: c.player_marketShare_2025
220
+ }))
221
+ };
222
+
223
+ // Create report_view from agent result
224
+ const report_view = {
225
+ marketTitle: r.marketTitle || `Global ${keyword} Market Analysis`,
226
+ marketOverview: {
227
+ pastYear_2023: r.pastYear_2023 || 0,
228
+ currentYear_2025: r.currentYear_2025 || 0,
229
+ forecastYear_2033: r.forecastYear_2033 || 0,
230
+ global_cagr_Forecast: r.global_cagr_Forecast || 0,
231
+ executiveOverview: r.executiveOverview || ""
232
+ },
233
+ marketSegments: r.marketSegments || [],
234
+ marketDynamics: {
235
+ marketDrivers: r.marketDrivers || [],
236
+ strategicRecommendations: r.strategicRecommendations || []
237
+ },
238
+ competitiveLandscape: r.competitiveLandscape || [],
239
+ insights: r.insights || {},
240
+ regulatoryEnvironment: r.regulatoryEnvironment || "",
241
+ geographicAnalysis: r.geographicAnalysis || "",
242
+ futureOutlook: r.futureOutlook || "",
243
+ emergingTrends: r.emergingTrends || []
244
+ };
245
+
246
+ return {
247
+ dashboard_view: dashboard_view,
248
+ // Include report_view for PDF generation if needed
249
+ report_view: report_view,
250
+ meta: {
251
+ job_id: `job_${Date.now()}`,
252
+ keyword: keyword,
253
+ timestamp: new Date().toISOString(),
254
+ status: "completed"
255
+ }
256
+ };
257
+ }
258
+
259
+ // Create comprehensive fallback response
260
+ function createFallbackResponse(keyword) {
261
+ const marketTitle = `Global ${keyword} Market Analysis`;
262
+
263
+ return {
264
  dashboard_view: {
265
+ marketTitle: marketTitle,
266
  marketSummary: {
267
+ past2023: 8.5,
268
+ current2025: 10.2,
269
+ forecast2033: 18.7,
270
  cagr: 12.5
271
  },
272
  forecast: [
273
+ { year: "2023", value: 8.5 },
274
+ { year: "2025", value: 10.2 },
275
+ { year: "2033", value: 18.7 }
276
  ],
277
  marketSegments: [
278
  {
 
280
  segment_marketShare_2023: "35%",
281
  segment_marketShare_2025: "38%",
282
  segment_marketShare_2033: "42%",
283
+ segment_cagr: "12%",
284
+ subSegments: [
285
+ {
286
+ name: "Core Products",
287
+ marketShare_2023: "15%",
288
+ marketShare_2025: "18%",
289
+ marketShare_2033: "22%",
290
+ cagr: "14%"
291
+ }
292
+ ]
293
  }
294
  ],
295
+ drivers: [
296
+ { driver: "Technological Advancement", impact: 85 },
297
+ { driver: "Market Demand", impact: 90 },
298
+ { driver: "Regulatory Support", impact: 75 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
299
  ],
300
+ insights: {
301
+ largestSegment2025: "Primary Segment",
302
+ fastestGrowingSegment: "Digital Solutions",
303
+ keyOpportunities: ["Market expansion", "Technology innovation"],
304
+ majorChallenges: ["Regulatory compliance", "Market competition"]
305
+ },
306
+ competitive: [
307
+ { company: "Johnson & Johnson", share: 15 },
308
+ { company: "Medtronic", share: 12 },
309
+ { company: "Siemens Healthineers", share: 9 },
310
+ { company: "Boston Scientific", share: 8 },
311
+ { company: "Abbott Laboratories", share: 7 }
312
  ]
313
  },
314
  meta: {
 
318
  status: "completed"
319
  }
320
  };
321
+ }
 
 
 
322
 
323
  // Error handling middleware
324
  app.use((err, req, res, next) => {
 
336
  // Global error handlers to prevent crashes
337
  process.on('uncaughtException', (error) => {
338
  console.error('Uncaught Exception:', error.message);
 
339
  });
340
 
341
  process.on('unhandledRejection', (reason, promise) => {
342
  console.error('Unhandled Rejection at:', promise);
 
343
  });
344
 
345
+ try {
346
  app.listen(PORT, "0.0.0.0", () => {
347
  console.log(`✅ Server successfully running on port ${PORT}`);
348
  console.log(`✅ Health endpoint: GET /health`);
349
  console.log(`✅ API endpoint: POST /api/market-research`);
350
+ console.log(`✅ n8n endpoint: POST /run`);
351
+ console.log(`✅ Using OpenClaw agent for comprehensive market data`);
352
  });
353
  } catch (error) {
354
  console.error('❌ Failed to start server:', error.message);