jetpackjules commited on
Commit
84967bd
Β·
verified Β·
1 Parent(s): 881a3b3

Upload folder using huggingface_hub

Browse files
Files changed (2) hide show
  1. app.py +121 -0
  2. vm_data_server.py +50 -0
app.py CHANGED
@@ -504,6 +504,46 @@ def refresh_raw_logs():
504
  header = f"=== RAW CRON LOGS ===\nShowing last {showing_lines} of {total_lines} total lines\n\n"
505
  return header + content
506
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
507
  # Custom CSS for gorgeous design
508
  custom_css = """
509
  .gradio-container {
@@ -571,6 +611,16 @@ custom_css = """
571
  .profit-positive { color: #00d647 !important; font-weight: 600 !important; }
572
  .profit-negative { color: #ff0080 !important; font-weight: 600 !important; }
573
  .profit-neutral { color: #8b949e !important; }
 
 
 
 
 
 
 
 
 
 
574
  """
575
 
576
  def create_dashboard():
@@ -649,6 +699,39 @@ def create_dashboard():
649
  )
650
  refresh_investment_btn = gr.Button("πŸ”„ Refresh Investment Performance", variant="primary", size="lg")
651
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
652
  # System Logs Tab
653
  with gr.Tab("πŸ“‹ System Logs"):
654
  gr.Markdown("## πŸ–₯️ Trading Bot Activity")
@@ -722,6 +805,44 @@ def create_dashboard():
722
  outputs=[investment_performance_table]
723
  )
724
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
725
  # Logs tab
726
  refresh_logs_btn.click(
727
  fn=refresh_system_logs,
 
504
  header = f"=== RAW CRON LOGS ===\nShowing last {showing_lines} of {total_lines} total lines\n\n"
505
  return header + content
506
 
507
+ def run_vm_command(command, current_output=""):
508
+ """Execute command on VM and return output"""
509
+ try:
510
+ if not command.strip():
511
+ return current_output
512
+
513
+ response = requests.post(f"{VM_API_URL}/api/execute",
514
+ json={"command": command},
515
+ timeout=10)
516
+
517
+ if response.status_code == 200:
518
+ data = response.json()
519
+ output = data.get('output', '')
520
+ exit_code = data.get('exit_code', 0)
521
+
522
+ # Format terminal-style output
523
+ new_line = f"$ {command}\n{output}"
524
+ if exit_code != 0:
525
+ new_line += f"\n[Exit code: {exit_code}]"
526
+ new_line += "\n$ "
527
+
528
+ return current_output + new_line
529
+ else:
530
+ error_line = f"$ {command}\nError: VM API returned {response.status_code}\n$ "
531
+ return current_output + error_line
532
+
533
+ except Exception as e:
534
+ error_line = f"$ {command}\nError: {str(e)}\n$ "
535
+ return current_output + error_line
536
+
537
+ def clear_terminal():
538
+ """Clear terminal output"""
539
+ return "πŸ–₯️ VM Terminal Ready\n$ "
540
+
541
+ def run_quick_command(cmd):
542
+ """Helper for quick command buttons"""
543
+ def execute(current_output):
544
+ return run_vm_command(cmd, current_output)
545
+ return execute
546
+
547
  # Custom CSS for gorgeous design
548
  custom_css = """
549
  .gradio-container {
 
611
  .profit-positive { color: #00d647 !important; font-weight: 600 !important; }
612
  .profit-negative { color: #ff0080 !important; font-weight: 600 !important; }
613
  .profit-neutral { color: #8b949e !important; }
614
+
615
+ .terminal-output {
616
+ font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace !important;
617
+ background: #1e1e1e !important;
618
+ color: #00ff00 !important;
619
+ border-radius: 8px !important;
620
+ padding: 1rem !important;
621
+ font-size: 14px !important;
622
+ line-height: 1.4 !important;
623
+ }
624
  """
625
 
626
  def create_dashboard():
 
699
  )
700
  refresh_investment_btn = gr.Button("πŸ”„ Refresh Investment Performance", variant="primary", size="lg")
701
 
702
+ # VM Terminal Tab
703
+ with gr.Tab("πŸ’» VM Terminal"):
704
+ gr.Markdown("## πŸ–₯️ Remote VM Terminal")
705
+ gr.Markdown("### Execute commands directly on your trading VM")
706
+
707
+ with gr.Row():
708
+ with gr.Column(scale=4):
709
+ command_input = gr.Textbox(
710
+ label="Command",
711
+ placeholder="Enter command to run on VM...",
712
+ interactive=True,
713
+ elem_classes=["gr-textbox"]
714
+ )
715
+ with gr.Column(scale=1):
716
+ run_command_btn = gr.Button("▢️ Run", variant="primary", size="lg")
717
+ clear_terminal_btn = gr.Button("πŸ—‘οΈ Clear", variant="secondary", size="lg")
718
+
719
+ terminal_output = gr.Textbox(
720
+ label="Terminal Output",
721
+ lines=20,
722
+ max_lines=20,
723
+ interactive=False,
724
+ elem_classes=["terminal-output"],
725
+ value="πŸ–₯️ VM Terminal Ready\n$ "
726
+ )
727
+
728
+ gr.Markdown("**Quick Commands:**")
729
+ with gr.Row():
730
+ quick_ls = gr.Button("πŸ“ ls -la", size="sm")
731
+ quick_ps = gr.Button("πŸ”„ ps aux | grep python", size="sm")
732
+ quick_logs = gr.Button("πŸ“‹ tail script.log", size="sm")
733
+ quick_vm_status = gr.Button("πŸ–₯️ VM Status", size="sm")
734
+
735
  # System Logs Tab
736
  with gr.Tab("πŸ“‹ System Logs"):
737
  gr.Markdown("## πŸ–₯️ Trading Bot Activity")
 
805
  outputs=[investment_performance_table]
806
  )
807
 
808
+ # VM Terminal tab
809
+ run_command_btn.click(
810
+ fn=run_vm_command,
811
+ inputs=[command_input, terminal_output],
812
+ outputs=[terminal_output]
813
+ )
814
+ command_input.submit(
815
+ fn=run_vm_command,
816
+ inputs=[command_input, terminal_output],
817
+ outputs=[terminal_output]
818
+ )
819
+ clear_terminal_btn.click(
820
+ fn=clear_terminal,
821
+ outputs=[terminal_output]
822
+ )
823
+
824
+ # Quick command buttons
825
+ quick_ls.click(
826
+ fn=lambda current: run_vm_command("ls -la", current),
827
+ inputs=[terminal_output],
828
+ outputs=[terminal_output]
829
+ )
830
+ quick_ps.click(
831
+ fn=lambda current: run_vm_command("ps aux | grep python", current),
832
+ inputs=[terminal_output],
833
+ outputs=[terminal_output]
834
+ )
835
+ quick_logs.click(
836
+ fn=lambda current: run_vm_command("tail -20 script.log", current),
837
+ inputs=[terminal_output],
838
+ outputs=[terminal_output]
839
+ )
840
+ quick_vm_status.click(
841
+ fn=lambda current: run_vm_command("uptime && df -h && free -h", current),
842
+ inputs=[terminal_output],
843
+ outputs=[terminal_output]
844
+ )
845
+
846
  # Logs tab
847
  refresh_logs_btn.click(
848
  fn=refresh_system_logs,
vm_data_server.py CHANGED
@@ -259,6 +259,55 @@ def get_raw_logs():
259
  except Exception as e:
260
  return jsonify({'error': str(e), 'content': ''})
261
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
262
  if __name__ == '__main__':
263
  print("πŸš€ Starting VM Data Server...")
264
  print("πŸ“‘ This exposes your trading bot data via API")
@@ -267,6 +316,7 @@ if __name__ == '__main__':
267
  print(" β€’ Raw cron logs with color coding")
268
  print(" β€’ Portfolio data from VM files")
269
  print(" β€’ Buy queue and system stats")
 
270
  print("-" * 50)
271
 
272
  # Run on all interfaces so dashboard can connect
 
259
  except Exception as e:
260
  return jsonify({'error': str(e), 'content': ''})
261
 
262
+ @app.route('/api/execute', methods=['POST'])
263
+ def execute_command():
264
+ """Execute a command on the VM"""
265
+ try:
266
+ data = request.get_json()
267
+ command = data.get('command', '').strip()
268
+
269
+ if not command:
270
+ return jsonify({'error': 'No command provided', 'output': '', 'exit_code': 1})
271
+
272
+ # Security: only allow safe commands
273
+ dangerous_commands = ['rm', 'sudo', 'passwd', 'shutdown', 'reboot', 'mkfs', 'fdisk', 'dd']
274
+ if any(cmd in command.lower() for cmd in dangerous_commands):
275
+ return jsonify({
276
+ 'error': 'Command not allowed for security reasons',
277
+ 'output': f"β›” Command '{command}' contains restricted operations",
278
+ 'exit_code': 1
279
+ })
280
+
281
+ # Execute command with timeout
282
+ import subprocess
283
+ result = subprocess.run(
284
+ command,
285
+ shell=True,
286
+ capture_output=True,
287
+ text=True,
288
+ timeout=30, # 30 second timeout
289
+ cwd='/home/jetpackjules/Stock-Trader' # Run in trading directory
290
+ )
291
+
292
+ return jsonify({
293
+ 'output': result.stdout + result.stderr,
294
+ 'exit_code': result.returncode,
295
+ 'command': command
296
+ })
297
+
298
+ except subprocess.TimeoutExpired:
299
+ return jsonify({
300
+ 'error': 'Command timed out',
301
+ 'output': '⏰ Command execution timed out (30s limit)',
302
+ 'exit_code': 124
303
+ })
304
+ except Exception as e:
305
+ return jsonify({
306
+ 'error': str(e),
307
+ 'output': f'❌ Error executing command: {str(e)}',
308
+ 'exit_code': 1
309
+ })
310
+
311
  if __name__ == '__main__':
312
  print("πŸš€ Starting VM Data Server...")
313
  print("πŸ“‘ This exposes your trading bot data via API")
 
316
  print(" β€’ Raw cron logs with color coding")
317
  print(" β€’ Portfolio data from VM files")
318
  print(" β€’ Buy queue and system stats")
319
+ print(" β€’ Remote command execution")
320
  print("-" * 50)
321
 
322
  # Run on all interfaces so dashboard can connect