hedgequantx 2.7.25 → 2.7.27

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hedgequantx",
3
- "version": "2.7.25",
3
+ "version": "2.7.27",
4
4
  "description": "HedgeQuantX - Prop Futures Trading CLI",
5
5
  "main": "src/app.js",
6
6
  "bin": {
@@ -23,6 +23,9 @@ const {
23
23
  getLoginUrl
24
24
  } = manager;
25
25
 
26
+ // Internal API key (must match config.yaml)
27
+ const API_KEY = 'hqx-internal-key';
28
+
26
29
  /**
27
30
  * Make HTTP request to local CLIProxyAPI
28
31
  * @param {string} path - API path
@@ -34,11 +37,14 @@ const {
34
37
  const fetchLocal = (path, method = 'GET', body = null, timeout = 60000) => {
35
38
  return new Promise((resolve) => {
36
39
  const options = {
37
- hostname: 'localhost',
40
+ hostname: '127.0.0.1',
38
41
  port: DEFAULT_PORT,
39
42
  path,
40
43
  method,
41
- headers: { 'Content-Type': 'application/json' },
44
+ headers: {
45
+ 'Content-Type': 'application/json',
46
+ 'Authorization': `Bearer ${API_KEY}`
47
+ },
42
48
  timeout
43
49
  };
44
50
 
@@ -243,10 +243,11 @@ const isRunning = async () => {
243
243
  }
244
244
  }
245
245
 
246
- // Also check by trying to connect
246
+ // Also check by trying to connect (accept 200, 401, 403 as "running")
247
247
  return new Promise((resolve) => {
248
- const req = http.get(`http://localhost:${DEFAULT_PORT}/v1/models`, (res) => {
249
- resolve({ running: res.statusCode === 200, pid: null });
248
+ const req = http.get(`http://127.0.0.1:${DEFAULT_PORT}/v1/models`, (res) => {
249
+ const running = res.statusCode === 200 || res.statusCode === 401 || res.statusCode === 403;
250
+ resolve({ running, pid: null });
250
251
  });
251
252
  req.on('error', () => resolve({ running: false, pid: null }));
252
253
  req.setTimeout(2000, () => {
@@ -256,6 +257,26 @@ const isRunning = async () => {
256
257
  });
257
258
  };
258
259
 
260
+ // Config file path
261
+ const CONFIG_PATH = path.join(INSTALL_DIR, 'config.yaml');
262
+
263
+ /**
264
+ * Create config file if not exists
265
+ */
266
+ const ensureConfig = () => {
267
+ if (fs.existsSync(CONFIG_PATH)) return;
268
+
269
+ const config = `# HQX CLIProxyAPI Config
270
+ host: "127.0.0.1"
271
+ port: ${DEFAULT_PORT}
272
+ auth-dir: "${AUTH_DIR}"
273
+ debug: false
274
+ api-keys:
275
+ - "hqx-internal-key"
276
+ `;
277
+ fs.writeFileSync(CONFIG_PATH, config);
278
+ };
279
+
259
280
  /**
260
281
  * Start CLIProxyAPI
261
282
  * @returns {Promise<Object>} { success, error, pid }
@@ -271,30 +292,42 @@ const start = async () => {
271
292
  }
272
293
 
273
294
  try {
274
- const args = [
275
- '--port', String(DEFAULT_PORT),
276
- '--auth-dir', AUTH_DIR
277
- ];
295
+ // Ensure config and auth dir exist
296
+ if (!fs.existsSync(AUTH_DIR)) fs.mkdirSync(AUTH_DIR, { recursive: true });
297
+ ensureConfig();
298
+
299
+ const args = ['-config', CONFIG_PATH];
300
+
301
+ // Capture stderr for debugging
302
+ const logPath = path.join(INSTALL_DIR, 'cliproxy.log');
303
+ const logFd = fs.openSync(logPath, 'a');
278
304
 
279
305
  const child = spawn(BINARY_PATH, args, {
280
306
  detached: true,
281
- stdio: 'ignore',
307
+ stdio: ['ignore', logFd, logFd],
282
308
  cwd: INSTALL_DIR
283
309
  });
284
310
 
285
311
  child.unref();
312
+ fs.closeSync(logFd);
286
313
 
287
314
  // Save PID
288
315
  fs.writeFileSync(PID_FILE, String(child.pid));
289
316
 
290
317
  // Wait for startup
291
- await new Promise(r => setTimeout(r, 2000));
318
+ await new Promise(r => setTimeout(r, 3000));
292
319
 
293
320
  const runStatus = await isRunning();
294
321
  if (runStatus.running) {
295
322
  return { success: true, error: null, pid: child.pid };
296
323
  } else {
297
- return { success: false, error: 'Failed to start CLIProxyAPI', pid: null };
324
+ // Read log for error details
325
+ let errorDetail = 'Failed to start CLIProxyAPI';
326
+ if (fs.existsSync(logPath)) {
327
+ const log = fs.readFileSync(logPath, 'utf8').slice(-500);
328
+ if (log) errorDetail += `: ${log.split('\n').pop()}`;
329
+ }
330
+ return { success: false, error: errorDetail, pid: null };
298
331
  }
299
332
  } catch (error) {
300
333
  return { success: false, error: error.message, pid: null };