syntaxmatrix 2.6.4.4__py3-none-any.whl → 3.0.1__py3-none-any.whl

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.
Files changed (41) hide show
  1. syntaxmatrix/__init__.py +6 -4
  2. syntaxmatrix/agentic/agents.py +206 -26
  3. syntaxmatrix/agentic/agents_orchestrer.py +16 -10
  4. syntaxmatrix/client_docs.py +237 -0
  5. syntaxmatrix/commentary.py +96 -25
  6. syntaxmatrix/core.py +142 -56
  7. syntaxmatrix/dataset_preprocessing.py +2 -2
  8. syntaxmatrix/db.py +0 -17
  9. syntaxmatrix/kernel_manager.py +174 -150
  10. syntaxmatrix/page_builder_generation.py +656 -63
  11. syntaxmatrix/page_layout_contract.py +25 -3
  12. syntaxmatrix/page_patch_publish.py +368 -15
  13. syntaxmatrix/plugins/__init__.py +0 -0
  14. syntaxmatrix/premium/__init__.py +10 -2
  15. syntaxmatrix/premium/catalogue/__init__.py +121 -0
  16. syntaxmatrix/premium/gate.py +15 -3
  17. syntaxmatrix/premium/state.py +507 -0
  18. syntaxmatrix/premium/verify.py +222 -0
  19. syntaxmatrix/profiles.py +1 -1
  20. syntaxmatrix/routes.py +9847 -8004
  21. syntaxmatrix/settings/model_map.py +50 -65
  22. syntaxmatrix/settings/prompts.py +1186 -414
  23. syntaxmatrix/settings/string_navbar.py +4 -4
  24. syntaxmatrix/static/icons/bot_icon.png +0 -0
  25. syntaxmatrix/static/icons/bot_icon2.png +0 -0
  26. syntaxmatrix/templates/admin_billing.html +408 -0
  27. syntaxmatrix/templates/admin_branding.html +65 -2
  28. syntaxmatrix/templates/admin_features.html +54 -0
  29. syntaxmatrix/templates/dashboard.html +285 -8
  30. syntaxmatrix/templates/edit_page.html +199 -18
  31. syntaxmatrix/themes.py +17 -17
  32. syntaxmatrix/workspace_db.py +0 -23
  33. syntaxmatrix-3.0.1.dist-info/METADATA +219 -0
  34. {syntaxmatrix-2.6.4.4.dist-info → syntaxmatrix-3.0.1.dist-info}/RECORD +38 -33
  35. {syntaxmatrix-2.6.4.4.dist-info → syntaxmatrix-3.0.1.dist-info}/WHEEL +1 -1
  36. syntaxmatrix/settings/default.yaml +0 -13
  37. syntaxmatrix-2.6.4.4.dist-info/METADATA +0 -539
  38. syntaxmatrix-2.6.4.4.dist-info/licenses/LICENSE.txt +0 -21
  39. /syntaxmatrix/{plugin_manager.py → plugins/plugin_manager.py} +0 -0
  40. /syntaxmatrix/static/icons/{logo3.png → logo2.png} +0 -0
  41. {syntaxmatrix-2.6.4.4.dist-info → syntaxmatrix-3.0.1.dist-info}/top_level.txt +0 -0
syntaxmatrix/__init__.py CHANGED
@@ -20,8 +20,8 @@ error = _app_instance.error
20
20
  success = _app_instance.success
21
21
  info = _app_instance.info
22
22
  warning = _app_instance.warning
23
- # plt_plot = _app_instance.plt_plot
24
- # plotly_plot = _app_instance.plotly_plot
23
+ plt_plot = _app_instance.plt_plot
24
+ plotly_plot = _app_instance.plotly_plot
25
25
 
26
26
  set_user_icon = _app_instance.set_user_icon
27
27
  set_bot_icon = _app_instance.set_bot_icon
@@ -53,12 +53,14 @@ stream_process_query= _app_instance.stream_process_query
53
53
  process_query_stream = _app_instance.process_query_stream
54
54
  process_query = _app_instance.process_query
55
55
  embed_query = _app_instance.embed_query
56
- enable_user_files = _app_instance.enable_user_files
57
- enable_registration = _app_instance.enable_registration
58
56
  stream_write = _app_instance.stream_write
59
57
  enable_stream = _app_instance.enable_stream
60
58
  stream = _app_instance.stream
61
59
  get_stream_args = _app_instance.get_stream_args
60
+ enable_user_files = _app_instance.enable_user_files
61
+ enable_registration = _app_instance.enable_registration
62
+ enable_site_documentation = _app_instance.enable_site_documentation
63
+ enable_ml_lab = _app_instance.enable_ml_lab
62
64
 
63
65
 
64
66
  app = _app_instance.app
@@ -21,6 +21,7 @@ from dataclasses import dataclass
21
21
  import hashlib
22
22
  from PIL import Image
23
23
  from syntaxmatrix.page_layout_contract import normalise_layout, validate_layout
24
+ from syntaxmatrix.page_builder_generation import compile_layout_to_html
24
25
 
25
26
 
26
27
  def token_calculator(total_input_content, llm_profile):
@@ -596,6 +597,7 @@ def classify_ml_job_agent(refined_question, dataset_profile):
596
597
  def agentic_generate_page(*,
597
598
  page_slug: str,
598
599
  website_description: str,
600
+ page_instructions: str = "",
599
601
  client_dir: str,
600
602
  pixabay_api_key: str = "",
601
603
  llm_profile: dict | None = None,
@@ -707,6 +709,22 @@ def agentic_generate_page(*,
707
709
 
708
710
  llm_profile = _prof.get_profile('coder')
709
711
  llm_profile['client'] = _prof.get_client(llm_profile)
712
+
713
+ # OpenAI JSON mode requirement:
714
+ # If we request text.format={type:"json_object"} (or response_format json_object),
715
+ # OpenAI will error unless the word "JSON" appears somewhere in the prompt context.
716
+ def _ensure_json_mode_prompts(sp: str, up: str):
717
+ sp = sp or ""
718
+ up = up or ""
719
+ hint = "\n\nReturn ONLY valid JSON. Do not include markdown. JSON only."
720
+ if "json" not in sp.lower():
721
+ sp = sp + hint
722
+ if "json" not in up.lower():
723
+ up = up + "\n\nRespond in JSON."
724
+ return sp, up
725
+
726
+ system_prompt, user_prompt = _ensure_json_mode_prompts(system_prompt, user_prompt)
727
+
710
728
  client = llm_profile["client"]
711
729
  model = llm_profile["model"]
712
730
  provider = llm_profile["provider"].lower()
@@ -806,11 +824,13 @@ def agentic_generate_page(*,
806
824
  if not m:
807
825
  raise RuntimeError(f"Model did not return JSON. Output was:\n{txt[:800]}")
808
826
  return json.loads(m.group(0))
809
-
827
+
828
+ html = compile_layout_to_html(plan, page_slug=page_slug)
829
+
810
830
  return openai_sdk_response()
811
831
 
812
832
 
813
- def _page_plan_system_prompt(spec: dict) -> str:
833
+ def _page_plan_system_prompt(spec: dict, page_instructions: str = "") -> str:
814
834
  allowed_sections = spec.get("allowed_section_types") or ["hero", "features", "gallery", "testimonials", "faq", "cta", "richtext"]
815
835
  req = spec.get("required_sections") or []
816
836
 
@@ -820,6 +840,11 @@ def agentic_generate_page(*,
820
840
  [f"- {r['id']} (type: {r['type']})" for r in req]
821
841
  )
822
842
 
843
+ extra = ""
844
+ pi = (page_instructions or "").strip()
845
+ if pi:
846
+ extra = "\n\nPAGE-SPECIFIC INSTRUCTIONS (highest priority):\n" + pi + "\n"
847
+
823
848
  return f"""
824
849
  You are a senior UX designer + product copywriter for modern software websites.
825
850
 
@@ -834,6 +859,7 @@ def agentic_generate_page(*,
834
859
  - Choose icon names only from the allowed icon list.
835
860
  - Provide image search queries for items that need images. Keep queries on-topic (software/AI/tech).
836
861
 
862
+ {extra}
837
863
  {req_lines}
838
864
 
839
865
  OUTPUT:
@@ -887,7 +913,7 @@ def agentic_generate_page(*,
887
913
  """.strip()
888
914
 
889
915
 
890
- def _make_page_plan(*, page_slug: str, website_description: str, template_spec: dict) -> dict:
916
+ def _make_page_plan(*, page_slug: str, website_description: str, template_spec: dict, page_instructions: str = "") -> dict:
891
917
  slug = _slugify(page_slug)
892
918
  wd = _strip(website_description)
893
919
  if not wd:
@@ -910,7 +936,7 @@ def agentic_generate_page(*,
910
936
  }, indent=2)
911
937
 
912
938
  plan = _get_json_call(
913
- system_prompt=_page_plan_system_prompt(template_spec),
939
+ system_prompt=_page_plan_system_prompt(template_spec, page_instructions=page_instructions),
914
940
  user_prompt=user_prompt
915
941
  )
916
942
 
@@ -959,9 +985,10 @@ def agentic_generate_page(*,
959
985
  raise ValueError("Plan is too light on imagery; needs at least 4 items marked needsImage=true.")
960
986
 
961
987
 
962
- def _repair_plan(*, plan: dict, error_msg: str, website_description: str) -> dict:
963
- # Ask Gemini to repair the plan, not recreate randomly.
964
- system_prompt = _page_plan_system_prompt() + "\n\nYou are repairing an existing plan. Keep it consistent and improve only what is needed."
988
+ def _repair_plan(*, plan: dict, error_msg: str, website_description: str, template_spec: dict, page_instructions: str = "") -> dict:
989
+ # Ask the model to repair the plan, not recreate randomly.
990
+ system_prompt = _page_plan_system_prompt(template_spec, page_instructions=page_instructions) + "\n\nYou are repairing an existing plan. Keep it consistent and improve only what is needed."
991
+
965
992
  user_prompt = json.dumps({
966
993
  "ERROR": error_msg,
967
994
  "WEBSITE_DESCRIPTION": website_description,
@@ -1023,6 +1050,88 @@ def agentic_generate_page(*,
1023
1050
  else:
1024
1051
  hero["items"] = [{"id": "hero_media", "type": "card", "title": "Hero image", "text": "", "imageUrl": img}]
1025
1052
 
1053
+
1054
+ def _ensure_gallery_section(plan: dict, template_spec: dict) -> None:
1055
+ """
1056
+ If we're generating a gallery page, guarantee at least one section has type="gallery"
1057
+ so compile_layout_to_html activates the horizontal rail + arrows + lightbox.
1058
+ """
1059
+ try:
1060
+ if (template_spec or {}).get("category") != "gallery":
1061
+ return
1062
+ except Exception:
1063
+ return
1064
+
1065
+ secs = plan.get("sections")
1066
+ if not isinstance(secs, list) or not secs:
1067
+ return
1068
+
1069
+ def _stype(s):
1070
+ return str((s or {}).get("type") or "").strip().lower()
1071
+
1072
+ # If already has a gallery section, we're done.
1073
+ for s in secs:
1074
+ if isinstance(s, dict) and _stype(s) == "gallery":
1075
+ return
1076
+
1077
+ # Otherwise, convert the most image-heavy non-hero section into a gallery.
1078
+ best = None
1079
+ best_score = -1
1080
+ for s in secs:
1081
+ if not isinstance(s, dict):
1082
+ continue
1083
+ if _stype(s) == "hero":
1084
+ continue
1085
+ items = s.get("items") if isinstance(s.get("items"), list) else []
1086
+ score = 0
1087
+ for it in items:
1088
+ if not isinstance(it, dict):
1089
+ continue
1090
+ if it.get("needsImage") or it.get("imgQuery") or it.get("imageUrl"):
1091
+ score += 1
1092
+ if score > best_score:
1093
+ best_score = score
1094
+ best = s
1095
+
1096
+ if best and best_score > 0:
1097
+ best["type"] = "gallery"
1098
+ best.setdefault("id", "sec_gallery")
1099
+ if not str(best.get("title") or "").strip():
1100
+ best["title"] = "Gallery"
1101
+ if "cols" not in best:
1102
+ best["cols"] = 3
1103
+ return
1104
+
1105
+ # If nothing suitable exists, insert a fresh gallery section after the hero.
1106
+ new_sec = {
1107
+ "id": "sec_gallery",
1108
+ "type": "gallery",
1109
+ "title": "Gallery",
1110
+ "text": "Browse highlights from the platform modules and UI surfaces.",
1111
+ "cols": 3,
1112
+ "items": [
1113
+ {"id": "g1", "type": "card", "title": "Admin panel", "text": "Page Studio controls and content management.", "icon": "", "imgQuery": "admin panel dashboard ui", "needsImage": True},
1114
+ {"id": "g2", "type": "card", "title": "Docs hub", "text": "Two-column documentation view with navigation.", "icon": "", "imgQuery": "documentation website sidebar layout", "needsImage": True},
1115
+ {"id": "g3", "type": "card", "title": "ML lab", "text": "EDA and model results exported as reports.", "icon": "", "imgQuery": "machine learning dashboard analytics", "needsImage": True},
1116
+ {"id": "g4", "type": "card", "title": "Chat assistant", "text": "Grounded answers with retrieval context.", "icon": "", "imgQuery": "chatbot interface web app", "needsImage": True},
1117
+ {"id": "g5", "type": "card", "title": "Uploads", "text": "PDF and CSV ingestion workflows.", "icon": "", "imgQuery": "file upload web interface", "needsImage": True},
1118
+ {"id": "g6", "type": "card", "title": "Deployment", "text": "Client instances, roles, and configuration.", "icon": "", "imgQuery": "cloud deployment dashboard", "needsImage": True},
1119
+ ],
1120
+ }
1121
+
1122
+ # Insert after hero if present; else prepend.
1123
+ hero_idx = None
1124
+ for i, s in enumerate(secs):
1125
+ if isinstance(s, dict) and _stype(s) == "hero":
1126
+ hero_idx = i
1127
+ break
1128
+
1129
+ if hero_idx is None:
1130
+ secs.insert(0, new_sec)
1131
+ else:
1132
+ secs.insert(hero_idx + 1, new_sec)
1133
+
1134
+
1026
1135
  TEMPLATE_SPECS = {
1027
1136
  "generic_v1": {
1028
1137
  "category": "landing",
@@ -1084,16 +1193,36 @@ def agentic_generate_page(*,
1084
1193
  "min_images": 6,
1085
1194
  "max_images": 9,
1086
1195
  },
1196
+ "gallery_rail_v1": {
1197
+ "category": "gallery",
1198
+ "template": {"id": "gallery_rail_v1", "version": "1.0.0"},
1199
+ "allowed_section_types": ["hero", "gallery", "testimonials", "faq", "cta", "richtext"],
1200
+ "required_sections": [
1201
+ {"id": "sec_hero", "type": "hero"},
1202
+ {"id": "sec_gallery", "type": "gallery"},
1203
+ {"id": "sec_cta", "type": "cta"},
1204
+ ],
1205
+ "min_sections": 3,
1206
+ "max_sections": 6,
1207
+ "min_images": 6,
1208
+ "max_images": 9,
1209
+ },
1087
1210
  }
1088
1211
 
1089
1212
  def _select_template_spec(slug: str) -> dict:
1090
1213
  s = _slugify(slug)
1214
+
1215
+ if any(k in s for k in ("gallery", "portfolio", "showcase", "screenshots", "photos")):
1216
+ return TEMPLATE_SPECS["gallery_rail_v1"]
1217
+
1091
1218
  if "service" in s:
1092
1219
  if any(k in s for k in ("pricing", "plan", "plans", "package", "packages", "tier", "tiers")):
1093
1220
  return TEMPLATE_SPECS["services_detail_v1"]
1094
1221
  return TEMPLATE_SPECS["services_grid_v1"]
1222
+
1095
1223
  if "about" in s:
1096
1224
  return TEMPLATE_SPECS["about_glass_hero_v1"]
1225
+
1097
1226
  return TEMPLATE_SPECS["generic_v1"]
1098
1227
 
1099
1228
 
@@ -1134,7 +1263,16 @@ def agentic_generate_page(*,
1134
1263
  return r.content
1135
1264
 
1136
1265
 
1137
- def _save_image(img_bytes: bytes, out_path_no_ext: str, *, max_width: int = 1920) -> str:
1266
+ def _save_image(
1267
+ img_bytes: bytes,
1268
+ out_path_no_ext: str,
1269
+ *,
1270
+ max_width: int = 1920,
1271
+ thumb_out_path_no_ext: str | None = None,
1272
+ thumb_max_w: int = 640,
1273
+ thumb_max_h: int = 420,
1274
+ ) -> tuple[str, str | None]:
1275
+
1138
1276
  img = Image.open(io.BytesIO(img_bytes))
1139
1277
  img.load()
1140
1278
 
@@ -1154,7 +1292,26 @@ def agentic_generate_page(*,
1154
1292
  else:
1155
1293
  img.save(out_path, "PNG", optimize=True)
1156
1294
 
1157
- return out_path
1295
+ thumb_path = None
1296
+ if thumb_out_path_no_ext:
1297
+ try:
1298
+ # Create a thumbnail derived from the already-decoded image
1299
+ t = img.copy()
1300
+ t.thumbnail((int(thumb_max_w), int(thumb_max_h)))
1301
+ t_has_alpha = ("A" in t.getbands())
1302
+ t_ext = ".png" if t_has_alpha else ".jpg"
1303
+ thumb_path = thumb_out_path_no_ext + t_ext
1304
+ os.makedirs(os.path.dirname(thumb_path), exist_ok=True)
1305
+
1306
+ if t_ext == ".jpg":
1307
+ rgbt = t.convert("RGB") if t.mode != "RGB" else t
1308
+ rgbt.save(thumb_path, "JPEG", quality=80, optimize=True, progressive=True)
1309
+ else:
1310
+ t.save(thumb_path, "PNG", optimize=True)
1311
+ except Exception:
1312
+ thumb_path = None
1313
+
1314
+ return out_path, thumb_path
1158
1315
 
1159
1316
 
1160
1317
  def _pick_pixabay_hit(hits: list[dict], *, min_width: int) -> dict | None:
@@ -1255,9 +1412,24 @@ def agentic_generate_page(*,
1255
1412
  except Exception:
1256
1413
  pass
1257
1414
 
1258
- saved = _save_image(chosen_bytes, base, max_width=max_width)
1415
+ thumb_base = os.path.join(media_dir, "images", "thumbs", f"pixabay-{pid}")
1416
+
1417
+ saved, thumb_saved = _save_image(
1418
+ chosen_bytes,
1419
+ base,
1420
+ max_width=max_width,
1421
+ thumb_out_path_no_ext=thumb_base,
1422
+ thumb_max_w=640,
1423
+ thumb_max_h=420,
1424
+ )
1425
+
1259
1426
  rel = os.path.relpath(saved, media_dir).replace("\\", "/")
1260
1427
  it["imageUrl"] = f"/uploads/media/{rel}"
1428
+
1429
+ if thumb_saved:
1430
+ trel = os.path.relpath(thumb_saved, media_dir).replace("\\", "/")
1431
+ it["thumbUrl"] = f"/uploads/media/{trel}"
1432
+
1261
1433
  downloads += 1
1262
1434
  except Exception:
1263
1435
  continue
@@ -1306,21 +1478,21 @@ def agentic_generate_page(*,
1306
1478
  css = f"""
1307
1479
  <style>
1308
1480
  #{page_id} {{
1309
- --r: 18px;
1310
- --bd: rgba(148,163,184,.25);
1311
- --fg: #0f172a;
1312
- --mut: #475569;
1313
- --card: rgba(255,255,255,.78);
1314
- --bg: #f8fafc;
1315
- font-family: system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif;
1316
- background: var(--bg);
1317
- color: var(--fg);
1318
- overflow-x: clip;
1481
+ --r: 18px;
1482
+ --bd: rgba(148,163,184,.25);
1483
+ --fg: #0f172a;
1484
+ --mut: #000000;
1485
+ --card: rgba(255,255,255,.78);
1486
+ --bg: #f8fafc;
1487
+ font-family: system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif;
1488
+ background: var(--bg);
1489
+ color: var(--fg);
1490
+ overflow-x: clip;
1319
1491
  }}
1320
1492
  @media (prefers-color-scheme: dark){{
1321
1493
  #{page_id} {{
1322
1494
  --fg: #e2e8f0;
1323
- --mut: #a7b3c6;
1495
+ --mut: #000000;
1324
1496
  --card: rgba(2,6,23,.45);
1325
1497
  --bg: radial-gradient(circle at 20% 10%, rgba(30,64,175,.25), rgba(2,6,23,.95) 55%);
1326
1498
  --bd: rgba(148,163,184,.18);
@@ -1383,13 +1555,15 @@ def agentic_generate_page(*,
1383
1555
  #{page_id} .hero-panel{{
1384
1556
  max-width:700px;
1385
1557
  border:1px solid rgba(148,163,184,.30);
1386
- background:rgba(2,6,23,.24);
1387
1558
  border-radius:var(--r);
1388
1559
  padding:18px;
1389
- backdrop-filter: blur(4px);
1390
1560
  -webkit-backdrop-filter: blur(4px);
1391
1561
  box-shadow: 0 18px 40px rgba(2,6,23,.18);
1392
1562
  color:#e2e8f0;
1563
+ background:rgba(2,6,23,.13); /* more transparent */
1564
+ backdrop-filter: blur(18px) saturate(155%);
1565
+ -webkit-backdrop-filter: blur(18px) saturate(155%);
1566
+
1393
1567
  }}
1394
1568
  #{page_id} .hero-panel p{{ color:rgba(226,232,240,.84); }}
1395
1569
  #{page_id} .hero-panel h1{{ text-shadow:0 10px 30px rgba(2,6,23,.45); }}
@@ -1610,8 +1784,13 @@ def agentic_generate_page(*,
1610
1784
  notes = []
1611
1785
 
1612
1786
  tpl_spec = _select_template_spec(page_slug)
1613
- plan = _make_page_plan(page_slug=page_slug, website_description=website_description, template_spec=tpl_spec)
1787
+ plan = _make_page_plan(
1788
+ page_slug=page_slug,
1789
+ website_description=website_description,
1790
+ template_spec=tpl_spec, page_instructions=page_instructions
1791
+ )
1614
1792
 
1793
+ _ensure_gallery_section(plan, tpl_spec)
1615
1794
 
1616
1795
  for attempt in range(max_retries + 1):
1617
1796
  try:
@@ -1621,7 +1800,8 @@ def agentic_generate_page(*,
1621
1800
  notes.append(f"plan_validation_failed: {e}")
1622
1801
  if attempt >= max_retries:
1623
1802
  raise
1624
- plan = _repair_plan(plan=plan, error_msg=str(e), website_description=website_description)
1803
+ plan = _repair_plan(plan=plan, error_msg=str(e), website_description=website_description, template_spec=tpl_spec, page_instructions=page_instructions)
1804
+
1625
1805
 
1626
1806
  # Fill images locally (Pixabay) to avoid broken links
1627
1807
  if pixabay_api_key:
@@ -1659,7 +1839,7 @@ def agentic_generate_page(*,
1659
1839
  if _contains_placeholders(blob):
1660
1840
  raise RuntimeError("Refusing to publish: plan still contains placeholder-style text.")
1661
1841
 
1662
- html = compile_plan_to_html(plan)
1842
+ html = compile_layout_to_html(plan, page_slug=page_slug)
1663
1843
  return {
1664
1844
  "slug": _slugify(plan.get("page") or page_slug),
1665
1845
  "plan": plan,
@@ -299,25 +299,31 @@ class OrchestrateMLSystem:
299
299
  REFINED ML TASKS & SPECS:
300
300
  {refined_tasks}
301
301
 
302
- CONSTRAINTS:
302
+ ### CONSTRAINTS:
303
303
  - Assume 'df' is already loaded in the namespace. Do not use pd.read_csv.
304
304
  - Include all up-to-dateimports (pandas, numpy, sklearn, matplotlib, seaborn, etc.).
305
305
  - Avoid any deprecated mehods, imports, statements.
306
- - FIRST: Implement the 'Cold Start' cleaning and preprocessing logic (Check for nulls and impute based on column types in context).
306
+ - FIRST: Implement the 'Cold Start' cleaning (if not already done) and preprocessing logic (Check for nulls and impute based on column types in context).
307
307
  - SECOND: (Modeling) Implement the ML pipeline (Split, Scale, Train, Predict).
308
308
  - THIRD: Implement the visualizations using the specific templates requested.
309
- - Return ONLY the executable Python code. NO MARKDOWN (```), NO EXPLANATION.
310
-
311
- PLOTS:
312
- - Ensure that you display all the figures that you plotted nicely using plt.show.
313
-
314
- TABLES:
315
- - Use html tables for tabular data.
309
+ - Return ONLY the executable Python code. NO MARKDOWN (```), NO EXPLANATION, NO PRELUDE, NO PREAMBLE.
310
+
311
+ ### Output rendering rules (STRICT)
312
+ - NEVER use: print(df.to_html()), DataFrame.to_html(), Styler.to_html(), or printing raw "<table>...</table>" strings.
313
+ - For any DataFrame (including classification reports, contingency tables, summary tables, head/tail/middle samples):
314
+ - Always render with:
315
+ from IPython.display import display
316
+ display(df)
317
+ - For styled tables you may use:
318
+ display(df.style)
319
+ but only if it improves readability (keep it simple).
320
+ - If you need text commentary, use print("...") ONLY for plain text. Do not print HTML.
321
+ Always import display when you intend to show DataFrames: from IPython.display import display
316
322
  """
317
323
  coder_profile = _prof.get_profile("coder")
318
324
  if not coder_profile:
319
325
  return "Error!: Set an appropriate coder profile"
320
-
326
+
321
327
  thought, raw_code, usage = self._generate_ml_response(coder_profile ,system_prompt, user_prompt)
322
328
 
323
329
  # Robustly strip any potential markdown formatting