WhoDat55 commited on
Commit
4d0ec97
·
verified ·
1 Parent(s): bf12344

Update core_mcp.py

Browse files
Files changed (1) hide show
  1. core_mcp.py +69 -76
core_mcp.py CHANGED
@@ -185,10 +185,6 @@ Generate the complete code based on these clarified requirements."""
185
  def format_strategist_audit_prompt(blueprint: str, intent: str, generated_code: str) -> str:
186
  return f"""{HEADER_PROMPT}
187
 
188
- **AUDIT PHASE INITIATED**
189
-
190
- The Coder AI has generated the following code based on the blueprint. Your task is to AUDIT this code against the original intent and blueprint.
191
-
192
  ORIGINAL BLUEPRINT:
193
  {blueprint}
194
 
@@ -198,22 +194,14 @@ ORIGINAL INTENT:
198
  GENERATED CODE:
199
  {generated_code}
200
 
201
- **INSTRUCTIONS:**
202
- 1. Review the code for logical errors, missing features from the blueprint, or deviations from the intent.
203
- 2. If the code is acceptable and meets all requirements, respond with the exact string: "AUDIT_PASSED".
204
- 3. If changes are required, provide a numbered list of specific, actionable corrections. DO NOT rewrite the code yourself. Just list the required changes.
205
- """
206
 
207
- def format_audit_resolution_prompt(blueprint: str, audit_feedback: str) -> str:
208
- return f"""{SYSTEM_PROMPT}
209
-
210
- BLUEPRINT:
211
- {blueprint}
212
 
213
- AUDIT FEEDBACK (REQUIRED CHANGES):
214
- {audit_feedback}
215
-
216
- The previous code generation failed the audit. Regenerate the code, strictly adhering to the audit feedback above."""
217
 
218
  # --- UTILITIES ---
219
 
@@ -242,6 +230,8 @@ def sanitize_error_message(error_msg: str) -> str:
242
  Scrub API keys and sensitive URLs from error messages.
243
  Removes everything after '?' in URLs to prevent API key exposure.
244
  """
 
 
245
  # Pattern to match URLs with query parameters (containing API keys)
246
  # This will find "for url: https://...?key=..." and remove everything after the ?
247
  pattern = r'(for url: https?://[^\s?]+)\?[^\s]*'
@@ -433,9 +423,7 @@ def execute_http_tool(tool_name: str, tool_config: Dict, params: Dict[str, str],
433
 
434
  def call_ai_api(full_url: str, api_key: str, messages: List[Dict[str, str]]) -> str:
435
  headers = {'Content-Type': 'application/json'}
436
- # We construct the URL with the key here for the request...
437
  url_with_key = f"{full_url}?key={api_key}"
438
-
439
  payload = {
440
  'contents': messages,
441
  'generationConfig': {
@@ -445,17 +433,14 @@ def call_ai_api(full_url: str, api_key: str, messages: List[Dict[str, str]]) ->
445
  }
446
  try:
447
  response = requests.post(url_with_key, headers=headers, json=payload, timeout=120)
448
- response.raise_for_status() # This is what usually triggers the error containing the URL
449
  data = response.json()
450
  if 'candidates' in data and len(data['candidates']) > 0:
451
  return data['candidates'][0]['content']['parts'][0]['text']
452
  else:
453
  return f"ERROR: API malformed response: {data}"
454
  except Exception as e:
455
- # SECURITY FIX: Sanitize the exception string before returning it
456
- # This strips the '?key=xyz' from the error message
457
- sanitized_error = sanitize_error_message(str(e))
458
- return f"ERROR: API call failed: {sanitized_error}"
459
 
460
  def resolve_model(selected_label: str, model_registry: Dict[str, Dict], fallback_label: str, agent_name: str) -> Tuple[str, str, str]:
461
  if selected_label and selected_label in model_registry:
@@ -482,6 +467,19 @@ def resolve_model(selected_label: str, model_registry: Dict[str, Dict], fallback
482
  )
483
  return ('', '', f"FATAL: No {agent_name} models configured.")
484
 
 
 
 
 
 
 
 
 
 
 
 
 
 
485
  # --- ENGINE ---
486
 
487
  class ConductorEngine:
@@ -491,10 +489,8 @@ class ConductorEngine:
491
  self.system_log: List[str] = []
492
  self.audit_log: List[Dict[str, Any]] = []
493
  self.loop_count: int = 0
494
- self.max_loops: int = 6 if enable_audit else 3 # Increased loop limit for audit
495
- self.enable_audit = enable_audit
496
- self.final_output_content = ""
497
-
498
  self.coder_model_id, self.coder_url, coder_log = resolve_model(
499
  coder_model_label, CONFIG['coder_models'], CONFIG['coder_model_default_label'], 'Coder'
500
  )
@@ -522,18 +518,17 @@ class ConductorEngine:
522
  "coder_log": self.coder_history,
523
  "strategist_log": self.strategist_history,
524
  "audit_log": self.audit_log,
525
- "final_output": self.final_output_content
526
  }
527
 
528
  def execute_workflow(self, blueprint: str, intent: str) -> Dict[str, Any]:
529
  """ORIGINAL: Non-streaming version (kept for backwards compatibility)"""
530
- # Note: Audit logic not implemented in legacy non-streaming version
531
  self.coder_history = []
532
  self.strategist_history = []
533
  self.system_log = []
534
  self.audit_log = []
535
  self.loop_count = 0
536
- self.final_output_content = ""
537
 
538
  self.log_system("INITIATING CONDUCTOR ENGINE...")
539
  for log_msg in self.model_resolution_logs:
@@ -557,8 +552,8 @@ class ConductorEngine:
557
 
558
  if "DETECTED" not in coder_response:
559
  self.log_system("MISSION COMPLETE: Ambiguity resolved or Code generated.")
560
- self.final_output_content = coder_response
561
- return self._compile_results(coder_response)
562
 
563
  self.log_system("Ambiguity DETECTED. Escalating to Strategist.")
564
  strategist_prompt = format_strategist_prompt(blueprint, intent, coder_response)
@@ -588,13 +583,12 @@ class ConductorEngine:
588
  return self._compile_results(coder_response)
589
 
590
  def execute_workflow_streaming(self, blueprint: str, intent: str):
591
- """NEW: Streaming version that yields updates as they happen"""
592
  self.coder_history = []
593
  self.strategist_history = []
594
  self.system_log = []
595
  self.audit_log = []
596
  self.loop_count = 0
597
- self.final_output_content = ""
598
 
599
  self.log_system("INITIATING CONDUCTOR ENGINE...")
600
  yield self._current_state()
@@ -610,7 +604,7 @@ class ConductorEngine:
610
 
611
  self.log_system(f"Engaged: Coder ({self.coder_model_id}), Strategist ({self.strategist_model_id})")
612
  if self.enable_audit:
613
- self.log_system("AUDIT PROTOCOL: ENABLED")
614
  yield self._current_state()
615
 
616
  initial_prompt = format_initial_prompt(blueprint)
@@ -626,44 +620,44 @@ class ConductorEngine:
626
  self.log_coder("assistant", coder_response)
627
  yield self._current_state()
628
 
629
- # CHECK FOR COMPLETION OR AMBIGUITY
630
  if "DETECTED" not in coder_response:
631
- # Code generated. Check if Audit is required.
632
- if self.enable_audit:
633
- self.log_system("Code Generated. INITIATING AUDIT PHASE...")
634
- yield self._current_state()
635
-
636
- audit_prompt = format_strategist_audit_prompt(blueprint, intent, coder_response)
637
- self.log_strategist("user", audit_prompt)
638
- yield self._current_state()
639
-
640
- strategist_response = call_ai_api(self.strategist_url, CONFIG['STRATEGIST_API_KEY'], self.strategist_history)
641
- self.log_strategist("assistant", strategist_response)
642
- yield self._current_state()
643
-
644
- if "AUDIT_PASSED" in strategist_response:
645
- self.log_system("AUDIT STATUS: PASSED. Mission Complete.")
646
- self.final_output_content = coder_response
647
- yield self._current_state()
648
- return
649
- else:
650
- self.log_system("AUDIT STATUS: FAILED. Revisions Requested.")
651
- yield self._current_state()
652
-
653
- # Feed audit feedback back to Coder
654
- audit_resolution_prompt = format_audit_resolution_prompt(blueprint, strategist_response)
655
- self.log_coder("user", audit_resolution_prompt)
656
- yield self._current_state()
657
- # Loop continues to next iteration
658
- continue
659
- else:
660
- # No audit, just finish
661
  self.log_system("MISSION COMPLETE: Ambiguity resolved or Code generated.")
662
- self.final_output_content = coder_response
663
- yield self._current_state()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
664
  return
 
 
 
 
 
 
 
 
 
 
665
 
666
- # AMBIGUITY DETECTED PATH
667
  self.log_system("Ambiguity DETECTED. Escalating to Strategist.")
668
  yield self._current_state()
669
 
@@ -699,7 +693,6 @@ class ConductorEngine:
699
  yield self._current_state()
700
 
701
  self.log_system("FATAL: Loop limit reached.")
702
- self.final_output_content = coder_response # Return whatever we have
703
  yield self._current_state()
704
 
705
  def _compile_results(self, final_output: str) -> Dict[str, Any]:
@@ -713,14 +706,14 @@ class ConductorEngine:
713
 
714
  # --- API ---
715
 
716
- app = FastAPI(title="Conductor MCP Server", version="4.1")
717
 
718
  class ExecutionRequest(BaseModel):
719
  blueprint: str
720
  intent: str
721
  coder_model_label: Optional[str] = None
722
  strategist_model_label: Optional[str] = None
723
- enable_audit: Optional[bool] = False
724
 
725
  class ExecutionResponse(BaseModel):
726
  system_log: List[str]
@@ -738,7 +731,7 @@ async def execute_conductor(req: ExecutionRequest):
738
 
739
  @app.post("/execute_stream")
740
  async def execute_conductor_stream(req: ExecutionRequest):
741
- """NEW: Streaming endpoint that yields real-time updates"""
742
 
743
  async def generate_updates():
744
  engine = ConductorEngine(req.coder_model_label, req.strategist_model_label, req.enable_audit)
@@ -752,4 +745,4 @@ async def execute_conductor_stream(req: ExecutionRequest):
752
  return StreamingResponse(generate_updates(), media_type="text/event-stream")
753
 
754
  if __name__ == "__main__":
755
- uvicorn.run(app, host="0.0.0.0", port=7860)
 
185
  def format_strategist_audit_prompt(blueprint: str, intent: str, generated_code: str) -> str:
186
  return f"""{HEADER_PROMPT}
187
 
 
 
 
 
188
  ORIGINAL BLUEPRINT:
189
  {blueprint}
190
 
 
194
  GENERATED CODE:
195
  {generated_code}
196
 
197
+ **[AUDIT DIRECTIVE]**
198
+ Review the generated code for compliance with the blueprint and intent.
 
 
 
199
 
200
+ Respond with EXACTLY ONE of the following:
201
+ 1. If code is acceptable: "AUDIT_PASSED"
202
+ 2. If changes required: Provide a numbered list of required changes.
 
 
203
 
204
+ Do not generate code. Only provide audit results."""
 
 
 
205
 
206
  # --- UTILITIES ---
207
 
 
230
  Scrub API keys and sensitive URLs from error messages.
231
  Removes everything after '?' in URLs to prevent API key exposure.
232
  """
233
+ import re
234
+
235
  # Pattern to match URLs with query parameters (containing API keys)
236
  # This will find "for url: https://...?key=..." and remove everything after the ?
237
  pattern = r'(for url: https?://[^\s?]+)\?[^\s]*'
 
423
 
424
  def call_ai_api(full_url: str, api_key: str, messages: List[Dict[str, str]]) -> str:
425
  headers = {'Content-Type': 'application/json'}
 
426
  url_with_key = f"{full_url}?key={api_key}"
 
427
  payload = {
428
  'contents': messages,
429
  'generationConfig': {
 
433
  }
434
  try:
435
  response = requests.post(url_with_key, headers=headers, json=payload, timeout=120)
436
+ response.raise_for_status()
437
  data = response.json()
438
  if 'candidates' in data and len(data['candidates']) > 0:
439
  return data['candidates'][0]['content']['parts'][0]['text']
440
  else:
441
  return f"ERROR: API malformed response: {data}"
442
  except Exception as e:
443
+ return f"ERROR: API call failed: {str(e)}"
 
 
 
444
 
445
  def resolve_model(selected_label: str, model_registry: Dict[str, Dict], fallback_label: str, agent_name: str) -> Tuple[str, str, str]:
446
  if selected_label and selected_label in model_registry:
 
467
  )
468
  return ('', '', f"FATAL: No {agent_name} models configured.")
469
 
470
+ def format_audit_entry(diagnostic: Dict[str, any]) -> str:
471
+ entry = {
472
+ "transaction_id": diagnostic['transaction_id'],
473
+ "timestamp": diagnostic['timestamp'],
474
+ "tool": diagnostic['tool_name'],
475
+ "status": diagnostic['status'],
476
+ "latency": diagnostic['latency'],
477
+ "request": diagnostic['request_payload'],
478
+ "response": diagnostic['response_payload'],
479
+ "error": diagnostic['error_message']
480
+ }
481
+ return json.dumps(entry, indent=2)
482
+
483
  # --- ENGINE ---
484
 
485
  class ConductorEngine:
 
489
  self.system_log: List[str] = []
490
  self.audit_log: List[Dict[str, Any]] = []
491
  self.loop_count: int = 0
492
+ self.max_loops: int = 6
493
+ self.enable_audit: bool = enable_audit
 
 
494
  self.coder_model_id, self.coder_url, coder_log = resolve_model(
495
  coder_model_label, CONFIG['coder_models'], CONFIG['coder_model_default_label'], 'Coder'
496
  )
 
518
  "coder_log": self.coder_history,
519
  "strategist_log": self.strategist_history,
520
  "audit_log": self.audit_log,
521
+ "final_output": ""
522
  }
523
 
524
  def execute_workflow(self, blueprint: str, intent: str) -> Dict[str, Any]:
525
  """ORIGINAL: Non-streaming version (kept for backwards compatibility)"""
 
526
  self.coder_history = []
527
  self.strategist_history = []
528
  self.system_log = []
529
  self.audit_log = []
530
  self.loop_count = 0
531
+ final_code = ""
532
 
533
  self.log_system("INITIATING CONDUCTOR ENGINE...")
534
  for log_msg in self.model_resolution_logs:
 
552
 
553
  if "DETECTED" not in coder_response:
554
  self.log_system("MISSION COMPLETE: Ambiguity resolved or Code generated.")
555
+ final_code = coder_response
556
+ return self._compile_results(final_code)
557
 
558
  self.log_system("Ambiguity DETECTED. Escalating to Strategist.")
559
  strategist_prompt = format_strategist_prompt(blueprint, intent, coder_response)
 
583
  return self._compile_results(coder_response)
584
 
585
  def execute_workflow_streaming(self, blueprint: str, intent: str):
586
+ """STREAMING version with TASK 3 & 4 modifications"""
587
  self.coder_history = []
588
  self.strategist_history = []
589
  self.system_log = []
590
  self.audit_log = []
591
  self.loop_count = 0
 
592
 
593
  self.log_system("INITIATING CONDUCTOR ENGINE...")
594
  yield self._current_state()
 
604
 
605
  self.log_system(f"Engaged: Coder ({self.coder_model_id}), Strategist ({self.strategist_model_id})")
606
  if self.enable_audit:
607
+ self.log_system("AUDIT MODE: ENABLED")
608
  yield self._current_state()
609
 
610
  initial_prompt = format_initial_prompt(blueprint)
 
620
  self.log_coder("assistant", coder_response)
621
  yield self._current_state()
622
 
 
623
  if "DETECTED" not in coder_response:
624
+ # TASK 4: AUDIT LOOP LOGIC
625
+ if not self.enable_audit:
626
+ # Original termination path
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
627
  self.log_system("MISSION COMPLETE: Ambiguity resolved or Code generated.")
628
+ final_state = self._current_state()
629
+ final_state["final_code"] = coder_response # TASK 3: Add final_code key
630
+ yield final_state
631
+ return
632
+ # AUDIT MODE ACTIVATED
633
+ self.log_system("AUDIT PHASE INITIATED.")
634
+ yield self._current_state()
635
+
636
+ audit_prompt = format_strategist_audit_prompt(blueprint, intent, coder_response)
637
+ self.log_strategist("user", audit_prompt)
638
+ yield self._current_state()
639
+
640
+ audit_response = call_ai_api(self.strategist_url, CONFIG['STRATEGIST_API_KEY'], self.strategist_history)
641
+ self.log_strategist("assistant", audit_response)
642
+ yield self._current_state()
643
+
644
+ if "AUDIT_PASSED" in audit_response:
645
+ self.log_system("AUDIT PASSED. MISSION COMPLETE.")
646
+ final_state = self._current_state()
647
+ final_state["final_code"] = coder_response # TASK 3: Add final_code key
648
+ yield final_state
649
  return
650
+
651
+ # Audit failed - loop back to coder
652
+ self.log_system("AUDIT FAILED. Generating revisions.")
653
+ yield self._current_state()
654
+
655
+ revision_prompt = format_resolution_prompt(blueprint, f"AUDIT CHANGES REQUIRED:\n{audit_response}")
656
+ self.log_coder("user", revision_prompt)
657
+ yield self._current_state()
658
+ # Continue loop for coder to process revisions
659
+ continue
660
 
 
661
  self.log_system("Ambiguity DETECTED. Escalating to Strategist.")
662
  yield self._current_state()
663
 
 
693
  yield self._current_state()
694
 
695
  self.log_system("FATAL: Loop limit reached.")
 
696
  yield self._current_state()
697
 
698
  def _compile_results(self, final_output: str) -> Dict[str, Any]:
 
706
 
707
  # --- API ---
708
 
709
+ app = FastAPI(title="Conductor MCP Server", version="4.0")
710
 
711
  class ExecutionRequest(BaseModel):
712
  blueprint: str
713
  intent: str
714
  coder_model_label: Optional[str] = None
715
  strategist_model_label: Optional[str] = None
716
+ enable_audit: Optional[bool] = False # TASK 4: New field
717
 
718
  class ExecutionResponse(BaseModel):
719
  system_log: List[str]
 
731
 
732
  @app.post("/execute_stream")
733
  async def execute_conductor_stream(req: ExecutionRequest):
734
+ """STREAMING endpoint with TASK 4 audit support"""
735
 
736
  async def generate_updates():
737
  engine = ConductorEngine(req.coder_model_label, req.strategist_model_label, req.enable_audit)
 
745
  return StreamingResponse(generate_updates(), media_type="text/event-stream")
746
 
747
  if __name__ == "__main__":
748
+ uvicorn.run(app, host="0.0.0.0", port=7860)