syntaxmatrix 2.2.4__tar.gz → 2.2.5__tar.gz

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 (69) hide show
  1. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/PKG-INFO +1 -1
  2. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/SyntaxMatrix.egg-info/PKG-INFO +1 -1
  3. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/setup.py +1 -1
  4. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/syntaxmatrix/routes.py +52 -64
  5. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/LICENSE.txt +0 -0
  6. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/README.md +0 -0
  7. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/SyntaxMatrix.egg-info/SOURCES.txt +0 -0
  8. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/SyntaxMatrix.egg-info/dependency_links.txt +0 -0
  9. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/SyntaxMatrix.egg-info/requires.txt +0 -0
  10. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/SyntaxMatrix.egg-info/top_level.txt +0 -0
  11. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/pyproject.toml +0 -0
  12. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/setup.cfg +0 -0
  13. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/syntaxmatrix/__init__.py +0 -0
  14. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/syntaxmatrix/auth.py +0 -0
  15. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/syntaxmatrix/bootstrap.py +0 -0
  16. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/syntaxmatrix/commentary.py +0 -0
  17. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/syntaxmatrix/core.py +0 -0
  18. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/syntaxmatrix/db.py +0 -0
  19. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/syntaxmatrix/display.py +0 -0
  20. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/syntaxmatrix/emailer.py +0 -0
  21. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/syntaxmatrix/file_processor.py +0 -0
  22. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/syntaxmatrix/generate_page.py +0 -0
  23. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/syntaxmatrix/gpt_models_latest.py +0 -0
  24. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/syntaxmatrix/history_store.py +0 -0
  25. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/syntaxmatrix/kernel_manager.py +0 -0
  26. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/syntaxmatrix/llm_store.py +0 -0
  27. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/syntaxmatrix/model_templates.py +0 -0
  28. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/syntaxmatrix/models.py +0 -0
  29. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/syntaxmatrix/plottings.py +0 -0
  30. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/syntaxmatrix/profiles.py +0 -0
  31. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/syntaxmatrix/project_root.py +0 -0
  32. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/syntaxmatrix/session.py +0 -0
  33. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/syntaxmatrix/settings/__init__.py +0 -0
  34. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/syntaxmatrix/settings/default.yaml +0 -0
  35. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/syntaxmatrix/settings/logging.py +0 -0
  36. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/syntaxmatrix/settings/model_map.py +0 -0
  37. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/syntaxmatrix/settings/prompts.py +0 -0
  38. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/syntaxmatrix/settings/string_navbar.py +0 -0
  39. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/syntaxmatrix/smiv.py +0 -0
  40. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/syntaxmatrix/smpv.py +0 -0
  41. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/syntaxmatrix/static/css/style.css +0 -0
  42. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/syntaxmatrix/static/docs.md +0 -0
  43. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/syntaxmatrix/static/icons/favicon.png +0 -0
  44. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/syntaxmatrix/static/icons/hero_bg.jpg +0 -0
  45. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/syntaxmatrix/static/icons/logo.png +0 -0
  46. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/syntaxmatrix/static/icons/svg_497526.svg +0 -0
  47. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/syntaxmatrix/static/icons/svg_497528.svg +0 -0
  48. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/syntaxmatrix/static/js/chat.js +0 -0
  49. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/syntaxmatrix/static/js/sidebar.js +0 -0
  50. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/syntaxmatrix/static/js/widgets.js +0 -0
  51. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/syntaxmatrix/templates/code_cell.html +0 -0
  52. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/syntaxmatrix/templates/dashboard.html +0 -0
  53. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/syntaxmatrix/templates/docs.html +0 -0
  54. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/syntaxmatrix/templates/error.html +0 -0
  55. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/syntaxmatrix/templates/login.html +0 -0
  56. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/syntaxmatrix/templates/register.html +0 -0
  57. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/syntaxmatrix/themes.py +0 -0
  58. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/syntaxmatrix/ui_modes.py +0 -0
  59. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/syntaxmatrix/utils.py +0 -0
  60. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/syntaxmatrix/vector_db.py +0 -0
  61. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/syntaxmatrix/vectordb/__init__.py +0 -0
  62. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/syntaxmatrix/vectordb/adapters/__init__.py +0 -0
  63. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/syntaxmatrix/vectordb/adapters/milvus_adapter.py +0 -0
  64. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/syntaxmatrix/vectordb/adapters/pgvector_adapter.py +0 -0
  65. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/syntaxmatrix/vectordb/adapters/sqlite_adapter.py +0 -0
  66. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/syntaxmatrix/vectordb/base.py +0 -0
  67. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/syntaxmatrix/vectordb/registry.py +0 -0
  68. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/syntaxmatrix/vectorizer.py +0 -0
  69. {syntaxmatrix-2.2.4 → syntaxmatrix-2.2.5}/syntaxmatrix/workspace_db.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: syntaxmatrix
3
- Version: 2.2.4
3
+ Version: 2.2.5
4
4
  Summary: SyntaxMUI: A customizable framework for Python AI Assistant Projects.
5
5
  Home-page: https://github.com/bobganti/syntaxmatrix_demo
6
6
  Author: Bob Nti
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: syntaxmatrix
3
- Version: 2.2.4
3
+ Version: 2.2.5
4
4
  Summary: SyntaxMUI: A customizable framework for Python AI Assistant Projects.
5
5
  Home-page: https://github.com/bobganti/syntaxmatrix_demo
6
6
  Author: Bob Nti
@@ -8,7 +8,7 @@ with open(os.path.join(this_directory, "README.md"), encoding="utf-8") as f:
8
8
 
9
9
  setup(
10
10
  name="syntaxmatrix",
11
- version="2.2.4",
11
+ version="2.2.5",
12
12
  author="Bob Nti",
13
13
  author_email="bob.nti@syntaxmatrix.com",
14
14
  description="SyntaxMUI: A customizable framework for Python AI Assistant Projects.",
@@ -46,6 +46,7 @@ except Exception:
46
46
  _CLIENT_DIR = detect_project_root()
47
47
  _stream_q = queue.Queue()
48
48
  _stream_cancelled = {}
49
+ _last_result_html = {} # { session_id: html_doc }
49
50
 
50
51
  # store per-client so it stays alongside uploads
51
52
  MLEARNING_OUTPUTS = os.path.join(_CLIENT_DIR, "mlearning_outputs")
@@ -5380,18 +5381,37 @@ def setup_routes(smx):
5380
5381
  "</html>"
5381
5382
  )
5382
5383
 
5383
- html_path = os.path.join(MLEARNING_OUTPUTS, f"result_{session_id}.html")
5384
- with open(html_path, "w", encoding="utf-8") as f:
5385
- f.write(html_doc)
5384
+ _last_result_html[session_id] = html_doc
5386
5385
 
5387
- # 2.4 Append a single download button (no template edits needed)
5386
+ # 2.4 Append a single download button (explicit click fetch → download)
5387
+ download_url = url_for("download_result_html", session_id=session_id)
5388
5388
  dl_html = f"""
5389
- <div style="margin:14px 0;display:flex;gap:10px;flex-wrap:wrap">
5390
- <a class="btn" href="/download/result/html/{session_id}"
5391
- style="padding:8px 12px;border:1px solid #0b6;border-radius:6px;text-decoration:none;">
5389
+ <button type="button"
5390
+ class="btn"
5391
+ style="padding:8px 12px;border:1px solid #0b6;border-radius:6px;background:#fff;color:#0b6;cursor:pointer;"
5392
+ onclick="(function() {{
5393
+ fetch('{download_url}', {{
5394
+ method: 'POST',
5395
+ headers: {{ 'X-Requested-With': 'fetch' }}
5396
+ }}).then(function(resp) {{
5397
+ if (!resp.ok) throw new Error('Download failed');
5398
+ return resp.blob();
5399
+ }}).then(function(blob) {{
5400
+ const url = window.URL.createObjectURL(blob);
5401
+ const a = document.createElement('a');
5402
+ a.href = url;
5403
+ a.download = 'result.html';
5404
+ document.body.appendChild(a);
5405
+ a.click();
5406
+ a.remove();
5407
+ window.URL.revokeObjectURL(url);
5408
+ }}).catch(function(err) {{
5409
+ console.error(err);
5410
+ alert('Could not download the result. Please try again.');
5411
+ }});
5412
+ }})()">
5392
5413
  Download Result (HTML)
5393
- </a>
5394
- </div>
5414
+ </button>
5395
5415
  """
5396
5416
  ai_outputs.append(Markup(dl_html))
5397
5417
  ################################################################
@@ -5469,6 +5489,28 @@ def setup_routes(smx):
5469
5489
  session_id=session_id,
5470
5490
  )
5471
5491
 
5492
+
5493
+ @smx.app.route("/download/result/html/<session_id>", methods=["POST"])
5494
+ def download_result_html(session_id):
5495
+ """Send the last-built result HTML as a download (only when user clicks)."""
5496
+ path = os.path.join(MLEARNING_OUTPUTS, f"result_{session_id}.html")
5497
+ # Prefer in-memory result (set during the query render)
5498
+ html_doc = _last_result_html.get(session_id)
5499
+
5500
+ html_doc = _last_result_html.get(session_id)
5501
+ if not html_doc:
5502
+ return jsonify({"ok": False, "error": "No result available."}), 404
5503
+
5504
+ os.makedirs(MLEARNING_OUTPUTS, exist_ok=True)
5505
+ path = os.path.join(MLEARNING_OUTPUTS, f"result_{session_id}.html")
5506
+ with open(path, "w", encoding="utf-8") as f:
5507
+ f.write(html_doc)
5508
+
5509
+ # free memory for this session copy (optional)
5510
+ _last_result_html.pop(session_id, None)
5511
+
5512
+ return jsonify({"ok": True, "path": path})
5513
+
5472
5514
  # ── UPLOAD DATASET --------------------------------------
5473
5515
  @smx.app.route("/dashboard/upload", methods=["POST"])
5474
5516
  def upload_dataset():
@@ -5504,45 +5546,6 @@ def setup_routes(smx):
5504
5546
  # go back to the dashboard; dashboard() will auto-select the next file
5505
5547
  return redirect(url_for("dashboard"))
5506
5548
 
5507
- @smx.app.route("/download_result", methods=["POST"])
5508
- def download_result():
5509
- """Download the 'Result' block (figures + commentary) as a PDF."""
5510
- html_fragment = (request.form.get("html") or "").strip()
5511
- if not html_fragment:
5512
- return "No content to export.", 400
5513
-
5514
- # Wrap the fragment into a minimal full HTML doc
5515
- full_html = f"""<!doctype html>
5516
- <html>
5517
- <head>
5518
- <meta charset="utf-8">
5519
- <title>Result</title>
5520
- <style>
5521
- @page {{ size: A4; margin: 16mm; }}
5522
- body {{ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Arial, sans-serif; font-size: 11pt; }}
5523
- h1,h2,h3 {{ margin: 0 0 8px 0; }}
5524
- .smx-commentary-card {{ border: 1px solid #e5e7eb; border-radius: 12px; padding: 12px; background: #fafafa; }}
5525
- img {{ max-width: 100%; height: auto; }}
5526
- table {{ width: 100%; border-collapse: collapse; }}
5527
- th, td {{ border: 1px solid #e5e7eb; padding: 4px 6px; }}
5528
- </style>
5529
- </head>
5530
- <body>{html_fragment}</body>
5531
- </html>"""
5532
-
5533
- # Try WeasyPrint first
5534
- if HTML is not None:
5535
- try:
5536
- pdf_io = io.BytesIO()
5537
- HTML(string=full_html, base_url=request.url_root).write_pdf(pdf_io)
5538
- pdf_io.seek(0)
5539
- return send_file(pdf_io, as_attachment=True, download_name="result.pdf", mimetype="application/pdf")
5540
- except Exception as e:
5541
- #return None
5542
- smx.logger.exception("WeasyPrint render failed: %s", e)
5543
-
5544
- # Fallback: build a simple but faithful PDF with ReportLab (works everywhere)
5545
- return _pdf_fallback_reportlab(full_html)
5546
5549
 
5547
5550
  def _pdf_fallback_reportlab(full_html: str):
5548
5551
  """ReportLab fallback: extract text + base64 <img> and lay them out."""
@@ -5636,19 +5639,4 @@ def setup_routes(smx):
5636
5639
  {footer}
5637
5640
  </body>
5638
5641
  </html>
5639
- """, error_message=str(e)), 500
5640
-
5641
- @smx.app.route("/download/result/html/<session_id>")
5642
- def download_result_html(session_id):
5643
- path = os.path.join(MLEARNING_OUTPUTS, f"result_{session_id}.html")
5644
- if not os.path.exists(path):
5645
- return "No result available to download.", 404
5646
- return send_file(path, as_attachment=True, download_name="result.html", mimetype="text/html")
5647
-
5648
- @smx.app.route("/download/result/tables/<session_id>")
5649
- def download_result_tables(session_id):
5650
- path = os.path.join(MLEARNING_OUTPUTS, f"result_tables_{session_id}.zip")
5651
- if not os.path.exists(path):
5652
- return "No tables found in the last result.", 404
5653
- return send_file(path, as_attachment=True, download_name="result_tables.zip", mimetype="application/zip")
5654
-
5642
+ """, error_message=str(e)), 500
File without changes
File without changes
File without changes