syntaxmatrix 2.2.5__tar.gz → 2.2.7__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 (70) hide show
  1. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/PKG-INFO +1 -1
  2. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/SyntaxMatrix.egg-info/PKG-INFO +1 -1
  3. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/setup.py +1 -1
  4. syntaxmatrix-2.2.7/syntaxmatrix/project_root.py +72 -0
  5. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/syntaxmatrix/routes.py +29 -29
  6. syntaxmatrix-2.2.5/syntaxmatrix/project_root.py +0 -61
  7. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/LICENSE.txt +0 -0
  8. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/README.md +0 -0
  9. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/SyntaxMatrix.egg-info/SOURCES.txt +0 -0
  10. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/SyntaxMatrix.egg-info/dependency_links.txt +0 -0
  11. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/SyntaxMatrix.egg-info/requires.txt +0 -0
  12. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/SyntaxMatrix.egg-info/top_level.txt +0 -0
  13. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/pyproject.toml +0 -0
  14. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/setup.cfg +0 -0
  15. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/syntaxmatrix/__init__.py +0 -0
  16. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/syntaxmatrix/auth.py +0 -0
  17. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/syntaxmatrix/bootstrap.py +0 -0
  18. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/syntaxmatrix/commentary.py +0 -0
  19. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/syntaxmatrix/core.py +0 -0
  20. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/syntaxmatrix/db.py +0 -0
  21. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/syntaxmatrix/display.py +0 -0
  22. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/syntaxmatrix/emailer.py +0 -0
  23. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/syntaxmatrix/file_processor.py +0 -0
  24. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/syntaxmatrix/generate_page.py +0 -0
  25. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/syntaxmatrix/gpt_models_latest.py +0 -0
  26. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/syntaxmatrix/history_store.py +0 -0
  27. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/syntaxmatrix/kernel_manager.py +0 -0
  28. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/syntaxmatrix/llm_store.py +0 -0
  29. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/syntaxmatrix/model_templates.py +0 -0
  30. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/syntaxmatrix/models.py +0 -0
  31. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/syntaxmatrix/plottings.py +0 -0
  32. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/syntaxmatrix/profiles.py +0 -0
  33. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/syntaxmatrix/session.py +0 -0
  34. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/syntaxmatrix/settings/__init__.py +0 -0
  35. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/syntaxmatrix/settings/default.yaml +0 -0
  36. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/syntaxmatrix/settings/logging.py +0 -0
  37. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/syntaxmatrix/settings/model_map.py +0 -0
  38. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/syntaxmatrix/settings/prompts.py +0 -0
  39. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/syntaxmatrix/settings/string_navbar.py +0 -0
  40. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/syntaxmatrix/smiv.py +0 -0
  41. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/syntaxmatrix/smpv.py +0 -0
  42. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/syntaxmatrix/static/css/style.css +0 -0
  43. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/syntaxmatrix/static/docs.md +0 -0
  44. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/syntaxmatrix/static/icons/favicon.png +0 -0
  45. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/syntaxmatrix/static/icons/hero_bg.jpg +0 -0
  46. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/syntaxmatrix/static/icons/logo.png +0 -0
  47. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/syntaxmatrix/static/icons/svg_497526.svg +0 -0
  48. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/syntaxmatrix/static/icons/svg_497528.svg +0 -0
  49. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/syntaxmatrix/static/js/chat.js +0 -0
  50. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/syntaxmatrix/static/js/sidebar.js +0 -0
  51. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/syntaxmatrix/static/js/widgets.js +0 -0
  52. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/syntaxmatrix/templates/code_cell.html +0 -0
  53. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/syntaxmatrix/templates/dashboard.html +0 -0
  54. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/syntaxmatrix/templates/docs.html +0 -0
  55. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/syntaxmatrix/templates/error.html +0 -0
  56. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/syntaxmatrix/templates/login.html +0 -0
  57. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/syntaxmatrix/templates/register.html +0 -0
  58. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/syntaxmatrix/themes.py +0 -0
  59. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/syntaxmatrix/ui_modes.py +0 -0
  60. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/syntaxmatrix/utils.py +0 -0
  61. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/syntaxmatrix/vector_db.py +0 -0
  62. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/syntaxmatrix/vectordb/__init__.py +0 -0
  63. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/syntaxmatrix/vectordb/adapters/__init__.py +0 -0
  64. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/syntaxmatrix/vectordb/adapters/milvus_adapter.py +0 -0
  65. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/syntaxmatrix/vectordb/adapters/pgvector_adapter.py +0 -0
  66. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/syntaxmatrix/vectordb/adapters/sqlite_adapter.py +0 -0
  67. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/syntaxmatrix/vectordb/base.py +0 -0
  68. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/syntaxmatrix/vectordb/registry.py +0 -0
  69. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/syntaxmatrix/vectorizer.py +0 -0
  70. {syntaxmatrix-2.2.5 → syntaxmatrix-2.2.7}/syntaxmatrix/workspace_db.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: syntaxmatrix
3
- Version: 2.2.5
3
+ Version: 2.2.7
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.5
3
+ Version: 2.2.7
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.5",
11
+ version="2.2.7",
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.",
@@ -0,0 +1,72 @@
1
+ # syntaxmatrix/project_root.py
2
+
3
+ import os
4
+ import inspect
5
+ from pathlib import Path
6
+ import syntaxmatrix
7
+
8
+
9
+ def _is_writable(d: Path) -> bool:
10
+ """
11
+ Try to create the directory and a tiny test file, then remove it.
12
+ Returns True if writes work on this path (expected for a GCS mount).
13
+ """
14
+ try:
15
+ d.mkdir(parents=True, exist_ok=True)
16
+ probe = d / ".smx_write_probe"
17
+ with open(probe, "w", encoding="utf-8") as f:
18
+ f.write("ok")
19
+ try:
20
+ probe.unlink()
21
+ except Exception:
22
+ pass
23
+ return True
24
+ except Exception:
25
+ return False
26
+
27
+
28
+ def _caller_project_dir() -> Path:
29
+ """
30
+ Find the first stack frame outside the syntaxmatrix package and
31
+ return its parent folder (best local fallback for dev).
32
+ """
33
+ framework_dir = Path(syntaxmatrix.__file__).resolve().parent
34
+ for frame in inspect.stack():
35
+ fn = frame.filename or ""
36
+ p = Path(fn).resolve()
37
+ try:
38
+ p.relative_to(framework_dir)
39
+ continue # skip framework files
40
+ except Exception:
41
+ pass
42
+ if p.exists() and p.suffix == ".py":
43
+ return p.parent
44
+ return Path.cwd()
45
+
46
+
47
+ def detect_project_root() -> Path:
48
+ """
49
+ Choose the single source-of-truth for all framework data (uploads, db, media):
50
+ 1) Honour SMX_CLIENT_DIR if provided (Cloud Run: set to /app/syntaxmatrixdir).
51
+ 2) If not set, prefer the standard Cloud Run mount path /app/syntaxmatrixdir.
52
+ 3) Otherwise fall back to a local 'syntaxmatrixdir' beside the caller (dev only).
53
+
54
+ NOTE: We intentionally avoid using any other container paths to keep all I/O
55
+ on the bucket mount when running on Cloud Run.
56
+ """
57
+ # 1) Explicit environment override
58
+ env_dir = os.environ.get("SMX_CLIENT_DIR", "").strip()
59
+ if env_dir:
60
+ d = Path(env_dir).expanduser().resolve()
61
+ if _is_writable(d):
62
+ return d
63
+
64
+ # 2) Default Cloud Run mount path (as used in your deploy script)
65
+ cloud_run_mount = Path("/app/syntaxmatrixdir")
66
+ if _is_writable(cloud_run_mount):
67
+ return cloud_run_mount
68
+
69
+ # 3) Dev fallback: a local folder next to the app
70
+ local_dir = _caller_project_dir() / "syntaxmatrixdir"
71
+ local_dir.mkdir(parents=True, exist_ok=True)
72
+ return local_dir
@@ -30,9 +30,11 @@ from . import profiles as _prof
30
30
  from . import auth as _auth
31
31
  from syntaxmatrix import profiles as _prof
32
32
  from syntaxmatrix.gpt_models_latest import set_args, extract_output_text as _out
33
+ from datetime import datetime
33
34
 
34
35
  import html as _html
35
36
  import contextlib
37
+ from pathlib import Path
36
38
 
37
39
  try:
38
40
  from pygments import highlight as _hl
@@ -43,7 +45,8 @@ except Exception:
43
45
  _HAVE_PYGMENTS = False
44
46
 
45
47
 
46
- _CLIENT_DIR = detect_project_root()
48
+ # _CLIENT_DIR = detect_project_root()
49
+ _CLIENT_DIR = Path(os.environ.get("SMX_CLIENT_DIR", "/app/syntaxmatrixdir"))
47
50
  _stream_q = queue.Queue()
48
51
  _stream_cancelled = {}
49
52
  _last_result_html = {} # { session_id: html_doc }
@@ -5388,32 +5391,31 @@ def setup_routes(smx):
5388
5391
  dl_html = f"""
5389
5392
  <button type="button"
5390
5393
  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) {{
5394
+ style="margin:14px 0;padding:8px 12px;border:1px solid #0b6;border-radius:6px;background:#fff;color:#0b6;cursor:pointer;"
5395
+ onclick="(async function(btn) {{
5396
+ try {{
5397
+ btn.disabled = true;
5398
+ const orig = btn.textContent;
5399
+ btn.textContent = 'Saving…';
5400
+ const resp = await fetch('{download_url}', {{
5401
+ method: 'POST',
5402
+ headers: {{ 'X-Requested-With': 'fetch' }}
5403
+ }});
5404
+ const data = await resp.json();
5405
+ if (!resp.ok || !data.ok) throw new Error(data.error || 'Save failed');
5406
+ btn.textContent = 'Saved to MLEARNING_OUTPUTS';
5407
+ }} catch (err) {{
5409
5408
  console.error(err);
5410
- alert('Could not download the result. Please try again.');
5411
- }});
5412
- }})()">
5413
- Download Result (HTML)
5409
+ alert('Could not save. Please try again.');
5410
+ }} finally {{
5411
+ btn.disabled = false;
5412
+ }}
5413
+ }})(this)">
5414
+ Download
5414
5415
  </button>
5415
5416
  """
5416
5417
  ai_outputs.append(Markup(dl_html))
5418
+
5417
5419
  ################################################################
5418
5420
 
5419
5421
 
@@ -5493,16 +5495,14 @@ def setup_routes(smx):
5493
5495
  @smx.app.route("/download/result/html/<session_id>", methods=["POST"])
5494
5496
  def download_result_html(session_id):
5495
5497
  """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)
5498
+ os.makedirs(MLEARNING_OUTPUTS, exist_ok=True)
5499
+ stamp = datetime.now().strftime("%Y%m%d-%H%M%S-%f")
5500
+ filename = f"result_{session_id}_{stamp}.html"
5501
+ path = os.path.join(MLEARNING_OUTPUTS, filename)
5499
5502
 
5500
5503
  html_doc = _last_result_html.get(session_id)
5501
5504
  if not html_doc:
5502
5505
  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
5506
  with open(path, "w", encoding="utf-8") as f:
5507
5507
  f.write(html_doc)
5508
5508
 
@@ -1,61 +0,0 @@
1
- # syntaxmatrix/project_root.py
2
-
3
- import os
4
- import inspect
5
- from pathlib import Path
6
- import syntaxmatrix
7
-
8
-
9
- def scandir() -> Path:
10
- """
11
- Find the first stack frame outside of the syntaxmatrix package
12
- whose filename is a real .py file on disk, and return its parent dir.
13
- """
14
- framework_dir = Path(syntaxmatrix.__file__).resolve().parent
15
-
16
- for frame in inspect.stack():
17
- fname = frame.filename
18
-
19
- # 1) skip internal frames (<frozen ...>) or empty names
20
- if not fname or fname.startswith("<"):
21
- continue
22
-
23
- candidate = Path(fname)
24
-
25
- # 2) skip non-.py or non-existent paths
26
- if candidate.suffix != ".py" or not candidate.exists():
27
- continue
28
-
29
- try:
30
- candidate = candidate.resolve()
31
- except (OSError, RuntimeError):
32
- # if for some reason resolve() fails, skip it
33
- continue
34
-
35
- # 3) skip anything inside the framework itself
36
- if framework_dir in candidate.parents:
37
- continue
38
-
39
- # FOUND: a user file (e.g. app.py, manage.py, etc.)
40
- return candidate.parent
41
-
42
- # fallback: whatever cwd() is
43
- return Path(os.getcwd()).resolve()
44
-
45
-
46
- def detect_project_root() -> Path:
47
- """
48
- Returns the consumer project's syntaxmatrixdir folder, creating it if necessary.
49
- All framework data & uploads live here.
50
- """
51
- # 1) First check the CWD (where your app:app is running)
52
- cwd = Path.cwd()
53
- candidate = cwd / "syntaxmatrixdir"
54
- if candidate.exists():
55
- return candidate
56
-
57
- # 2) Otherwise fall back to the old logic (e.g. inside site-packages)
58
- proj_root = scandir()
59
- fw_root = proj_root / "syntaxmatrixdir"
60
- fw_root.mkdir(exist_ok=True)
61
- return fw_root
File without changes
File without changes
File without changes