syntaxmatrix 2.5.6__py3-none-any.whl → 2.6.2__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/agentic/agents.py +1220 -169
  2. syntaxmatrix/agentic/agents_orchestrer.py +326 -0
  3. syntaxmatrix/agentic/code_tools_registry.py +27 -32
  4. syntaxmatrix/commentary.py +16 -16
  5. syntaxmatrix/core.py +185 -81
  6. syntaxmatrix/db.py +460 -4
  7. syntaxmatrix/{display.py → display_html.py} +2 -6
  8. syntaxmatrix/gpt_models_latest.py +1 -1
  9. syntaxmatrix/media/__init__.py +0 -0
  10. syntaxmatrix/media/media_pixabay.py +277 -0
  11. syntaxmatrix/models.py +1 -1
  12. syntaxmatrix/page_builder_defaults.py +183 -0
  13. syntaxmatrix/page_builder_generation.py +1122 -0
  14. syntaxmatrix/page_layout_contract.py +644 -0
  15. syntaxmatrix/page_patch_publish.py +1471 -0
  16. syntaxmatrix/preface.py +142 -21
  17. syntaxmatrix/profiles.py +28 -10
  18. syntaxmatrix/routes.py +1740 -453
  19. syntaxmatrix/selftest_page_templates.py +360 -0
  20. syntaxmatrix/settings/client_items.py +28 -0
  21. syntaxmatrix/settings/model_map.py +1022 -207
  22. syntaxmatrix/settings/prompts.py +328 -130
  23. syntaxmatrix/static/assets/hero-default.svg +22 -0
  24. syntaxmatrix/static/icons/bot-icon.png +0 -0
  25. syntaxmatrix/static/icons/favicon.png +0 -0
  26. syntaxmatrix/static/icons/logo.png +0 -0
  27. syntaxmatrix/static/icons/logo3.png +0 -0
  28. syntaxmatrix/templates/admin_branding.html +104 -0
  29. syntaxmatrix/templates/admin_features.html +63 -0
  30. syntaxmatrix/templates/admin_secretes.html +108 -0
  31. syntaxmatrix/templates/dashboard.html +296 -133
  32. syntaxmatrix/templates/dataset_resize.html +535 -0
  33. syntaxmatrix/templates/edit_page.html +2535 -0
  34. syntaxmatrix/utils.py +2431 -2383
  35. {syntaxmatrix-2.5.6.dist-info → syntaxmatrix-2.6.2.dist-info}/METADATA +6 -2
  36. {syntaxmatrix-2.5.6.dist-info → syntaxmatrix-2.6.2.dist-info}/RECORD +39 -24
  37. syntaxmatrix/generate_page.py +0 -644
  38. syntaxmatrix/static/icons/hero_bg.jpg +0 -0
  39. {syntaxmatrix-2.5.6.dist-info → syntaxmatrix-2.6.2.dist-info}/WHEEL +0 -0
  40. {syntaxmatrix-2.5.6.dist-info → syntaxmatrix-2.6.2.dist-info}/licenses/LICENSE.txt +0 -0
  41. {syntaxmatrix-2.5.6.dist-info → syntaxmatrix-2.6.2.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,535 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>Dataset Resizer · SyntaxMatrix ML Lab</title>
6
+ <meta name="viewport" content="width=device-width, initial-scale=1">
7
+
8
+ <style>
9
+ :root {
10
+ --smx-bg: #0f172a;
11
+ --smx-bg-soft: #020617;
12
+ --smx-card: #020617;
13
+ --smx-card-soft: #020617;
14
+ --smx-border: #1f2937;
15
+ --smx-border-soft: #111827;
16
+ --smx-accent: #38bdf8;
17
+ --smx-accent-soft: rgba(56, 189, 248, 0.16);
18
+ --smx-accent-strong: #0ea5e9;
19
+ --smx-text-main: #e5e7eb;
20
+ --smx-text-soft: #9ca3af;
21
+ --smx-danger: #f97373;
22
+ --smx-success: #22c55e;
23
+ }
24
+
25
+ * {
26
+ box-sizing: border-box;
27
+ }
28
+
29
+ body {
30
+ margin: 0;
31
+ padding: 0;
32
+ font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
33
+ background: radial-gradient(circle at 0 0, #1e293b 0, #020617 55%, #000000 100%);
34
+ color: var(--smx-text-main);
35
+ min-height: 100vh;
36
+ }
37
+
38
+ .smx-shell {
39
+ max-width: 1120px;
40
+ margin: 0 auto;
41
+ padding: 24px 16px 32px;
42
+ }
43
+
44
+ .smx-topbar {
45
+ display: flex;
46
+ align-items: center;
47
+ justify-content: space-between;
48
+ gap: 12px;
49
+ margin-bottom: 20px;
50
+ }
51
+
52
+ .smx-topbar-left {
53
+ display: flex;
54
+ align-items: center;
55
+ gap: 10px;
56
+ min-width: 0;
57
+ }
58
+
59
+ .smx-logo-pill {
60
+ width: 32px;
61
+ height: 32px;
62
+ border-radius: 999px;
63
+ background: radial-gradient(circle at 30% 20%, #38bdf8 0, #0ea5e9 35%, #22c55e 80%);
64
+ display: flex;
65
+ align-items: center;
66
+ justify-content: center;
67
+ font-size: 0.85rem;
68
+ font-weight: 700;
69
+ colour: #0b1120;
70
+ }
71
+
72
+ .smx-topbar-title {
73
+ display: flex;
74
+ flex-direction: column;
75
+ gap: 2px;
76
+ }
77
+
78
+ .smx-topbar-title-main {
79
+ font-size: 1.1rem;
80
+ font-weight: 600;
81
+ letter-spacing: 0.02em;
82
+ }
83
+
84
+ .smx-topbar-title-sub {
85
+ font-size: 0.8rem;
86
+ colour: var(--smx-text-soft);
87
+ }
88
+
89
+ .smx-back-link {
90
+ display: inline-flex;
91
+ align-items: center;
92
+ gap: 6px;
93
+ padding: 6px 12px;
94
+ border-radius: 999px;
95
+ border: 1px solid rgba(148, 163, 184, 0.5);
96
+ text-decoration: none;
97
+ font-size: 0.8rem;
98
+ colour: var(--smx-text-main);
99
+ background: rgba(15, 23, 42, 0.7);
100
+ backdrop-filter: blur(10px);
101
+ }
102
+
103
+ .smx-back-link:hover {
104
+ border-colour: var(--smx-accent);
105
+ colour: var(--smx-accent-strong);
106
+ }
107
+
108
+ .smx-layout {
109
+ display: grid;
110
+ grid-template-columns: minmax(0, 1.7fr) minmax(0, 1.1fr);
111
+ gap: 18px;
112
+ align-items: flex-start;
113
+ }
114
+
115
+ .smx-card {
116
+ background: radial-gradient(circle at 0 0, rgba(56, 189, 248, 0.08), rgba(15, 23, 42, 0.98));
117
+ border-radius: 16px;
118
+ border: 1px solid rgba(15, 23, 42, 0.9);
119
+ padding: 18px 18px 18px;
120
+ box-shadow:
121
+ 0 18px 40px rgba(15, 23, 42, 0.80),
122
+ 0 0 0 0.5px rgba(148, 163, 184, 0.35);
123
+ }
124
+
125
+ .smx-card-secondary {
126
+ background: radial-gradient(circle at 100% 0, rgba(56, 189, 248, 0.15), rgba(15, 23, 42, 0.98));
127
+ border-radius: 16px;
128
+ border: 1px solid rgba(30, 64, 175, 0.7);
129
+ padding: 18px 18px;
130
+ box-shadow:
131
+ 0 16px 32px rgba(15, 23, 42, 0.85),
132
+ 0 0 0 0.5px rgba(30, 64, 175, 0.55);
133
+ }
134
+
135
+ .smx-card-header {
136
+ display: flex;
137
+ align-items: center;
138
+ justify-content: space-between;
139
+ gap: 10px;
140
+ margin-bottom: 12px;
141
+ }
142
+
143
+ .smx-card-title {
144
+ font-size: 1rem;
145
+ font-weight: 600;
146
+ display: inline-flex;
147
+ align-items: center;
148
+ gap: 8px;
149
+ }
150
+
151
+ .smx-pill {
152
+ padding: 2px 8px;
153
+ border-radius: 999px;
154
+ background: rgba(56, 189, 248, 0.12);
155
+ border: 1px solid rgba(56, 189, 248, 0.5);
156
+ font-size: 0.7rem;
157
+ font-weight: 500;
158
+ letter-spacing: 0.04em;
159
+ text-transform: uppercase;
160
+ colour: var(--smx-accent-strong);
161
+ }
162
+
163
+ .smx-card-body {
164
+ font-size: 0.85rem;
165
+ colour: var(--smx-text-soft);
166
+ }
167
+
168
+ .smx-description {
169
+ margin: 0 0 10px;
170
+ line-height: 1.5;
171
+ }
172
+
173
+ label {
174
+ display: block;
175
+ font-weight: 500;
176
+ font-size: 0.82rem;
177
+ margin-bottom: 4px;
178
+ }
179
+
180
+ .smx-field {
181
+ margin-bottom: 10px;
182
+ }
183
+
184
+ input[type="file"],
185
+ input[type="number"],
186
+ input[type="text"] {
187
+ width: 100%;
188
+ padding: 7px 10px;
189
+ border-radius: 10px;
190
+ border: 1px solid rgba(148, 163, 184, 0.55);
191
+ background: rgba(15, 23, 42, 0.9);
192
+ colour: var(--smx-text-main);
193
+ font-size: 0.85rem;
194
+ color: #fff5;
195
+ }
196
+
197
+ input[type="file"] {
198
+ padding: 6px 0;
199
+ }
200
+
201
+ input[type="number"]:focus,
202
+ input[type="text"]:focus {
203
+ outline: none;
204
+ border-colour: var(--smx-accent);
205
+ box-shadow: 0 0 0 1px rgba(56, 189, 248, 0.45);
206
+ }
207
+
208
+ .smx-hint {
209
+ font-size: 0.75rem;
210
+ colour: var(--smx-text-soft);
211
+ margin: 0 0 6px;
212
+ }
213
+
214
+ .smx-actions {
215
+ margin-top: 10px;
216
+ display: flex;
217
+ align-items: center;
218
+ justify-content: flex-start;
219
+ gap: 10px;
220
+ }
221
+
222
+ .btn-primary {
223
+ display: inline-flex;
224
+ align-items: center;
225
+ justify-content: center;
226
+ padding: 7px 16px;
227
+ border-radius: 999px;
228
+ border: none;
229
+ background: linear-gradient(135deg, #0ea5e9, #22c55e);
230
+ colour: #0b1120;
231
+ font-size: 0.85rem;
232
+ font-weight: 600;
233
+ cursor: pointer;
234
+ box-shadow: 0 10px 22px rgba(8, 47, 73, 0.7);
235
+ }
236
+
237
+ .btn-primary:hover {
238
+ filter: brightness(1.05);
239
+ box-shadow: 0 14px 28px rgba(8, 47, 73, 0.85);
240
+ }
241
+
242
+ .smx-adv-toggle {
243
+ font-size: 0.8rem;
244
+ colour: var(--smx-accent);
245
+ cursor: pointer;
246
+ text-decoration: none;
247
+ display: inline-flex;
248
+ align-items: centre;
249
+ gap: 4px;
250
+ }
251
+
252
+ .smx-adv-toggle:hover {
253
+ text-decoration: underline;
254
+ }
255
+
256
+ #advanced-box {
257
+ display: none;
258
+ margin-top: 8px;
259
+ padding: 10px 10px 8px;
260
+ border-radius: 10px;
261
+ border: 1px dashed rgba(148, 163, 184, 0.6);
262
+ background: rgba(15, 23, 42, 0.8);
263
+ }
264
+
265
+ .flashes {
266
+ list-style: none;
267
+ padding-left: 0;
268
+ margin: 0 0 10px;
269
+ font-size: 0.78rem;
270
+ }
271
+
272
+ .flashes li {
273
+ margin-bottom: 4px;
274
+ padding: 6px 8px;
275
+ border-radius: 8px;
276
+ border: 1px solid rgba(250, 204, 21, 0.8);
277
+ background: rgba(251, 191, 36, 0.06);
278
+ colour: #facc15;
279
+ }
280
+
281
+ .flashes li.error {
282
+ border-colour: rgba(248, 113, 113, 0.9);
283
+ background: rgba(248, 113, 113, 0.08);
284
+ colour: #fecaca;
285
+ }
286
+
287
+ .flashes li.success {
288
+ border-colour: rgba(34, 197, 94, 0.9);
289
+ background: rgba(22, 163, 74, 0.08);
290
+ colour: #bbf7d0;
291
+ }
292
+
293
+ .flashes li.warning {
294
+ border-colour: rgba(234, 179, 8, 0.9);
295
+ background: rgba(234, 179, 8, 0.08);
296
+ colour: #fef3c7;
297
+ }
298
+
299
+ .meta-list {
300
+ list-style: none;
301
+ padding-left: 0;
302
+ margin: 0 0 10px;
303
+ font-size: 0.8rem;
304
+ colour: var(--smx-text-soft);
305
+ }
306
+
307
+ .meta-list li {
308
+ margin-bottom: 3px;
309
+ }
310
+
311
+ .download-link {
312
+ display: inline-flex;
313
+ align-items: center;
314
+ justify-content: center;
315
+ padding: 7px 16px;
316
+ border-radius: 999px;
317
+ border: 1px solid rgba(34, 197, 94, 0.9);
318
+ colour: #bbf7d0;
319
+ font-weight: 600;
320
+ font-size: 0.85rem;
321
+ text-decoration: none;
322
+ background: rgba(22, 163, 74, 0.23);
323
+ box-shadow: 0 10px 22px rgba(4, 52, 35, 0.8);
324
+ }
325
+
326
+ .download-link:hover {
327
+ background: rgba(21, 128, 61, 0.9);
328
+ colour: #ecfdf5;
329
+ }
330
+
331
+ .smx-side-note-title {
332
+ font-size: 0.9rem;
333
+ font-weight: 600;
334
+ margin-bottom: 6px;
335
+ }
336
+
337
+ .smx-side-note-text {
338
+ font-size: 0.8rem;
339
+ colour: var(--smx-text-soft);
340
+ margin: 0 0 10px;
341
+ line-height: 1.5;
342
+ }
343
+
344
+ .smx-badge-dot {
345
+ display: inline-block;
346
+ width: 7px;
347
+ height: 7px;
348
+ border-radius: 999px;
349
+ background: var(--smx-accent);
350
+ margin-right: 6px;
351
+ }
352
+
353
+ @media (max-width: 880px) {
354
+ .smx-layout {
355
+ grid-template-columns: minmax(0, 1fr);
356
+ }
357
+ }
358
+
359
+ @media (max-width: 640px) {
360
+ .smx-shell {
361
+ padding-top: 16px;
362
+ }
363
+ .smx-card,
364
+ .smx-card-secondary {
365
+ border-radius: 12px;
366
+ }
367
+ }
368
+ </style>
369
+ </head>
370
+ <body>
371
+ <div class="smx-shell">
372
+ <div class="smx-topbar">
373
+ <div class="smx-topbar-left">
374
+ <div class="smx-logo-pill">SM</div>
375
+ <div class="smx-topbar-title">
376
+ <div class="smx-topbar-title-main">Dataset Resizer</div>
377
+ <div class="smx-topbar-title-sub">Subset of Explore · ML Lab</div>
378
+ </div>
379
+ </div>
380
+ <a href="{{ url_for('dashboard', section='explore') }}" class="smx-back-link">
381
+ <span aria-hidden="true">←</span>
382
+ <span>Back to ML Lab</span>
383
+ </a>
384
+ </div>
385
+
386
+ <div class="smx-layout">
387
+ <!-- Main card: form -->
388
+ <div class="smx-card">
389
+ {% with msgs = get_flashed_messages(with_categories=true) %}
390
+ {% if msgs %}
391
+ <ul class="flashes">
392
+ {% for category, msg in msgs %}
393
+ <li class="{{ category }}">{{ msg }}</li>
394
+ {% endfor %}
395
+ </ul>
396
+ {% endif %}
397
+ {% endwith %}
398
+
399
+ <div class="smx-card-header">
400
+ <div class="smx-card-title">
401
+ <span>Resize a dataset</span>
402
+ <span class="smx-pill">Explore subset</span>
403
+ </div>
404
+ </div>
405
+ <div class="smx-card-body">
406
+ <p class="smx-description">
407
+ Upload any CSV that feels too large to work with. Choose the percentage you want to keep,
408
+ and the resizer will return a smaller sample that preserves the overall feel of the data.
409
+ </p>
410
+
411
+ <form method="post" enctype="multipart/form-data">
412
+ <div class="smx-field">
413
+ <label for="dataset_file">CSV file</label>
414
+ <input id="dataset_file" type="file" name="dataset_file" accept=".csv" required>
415
+ <p class="smx-hint">
416
+ This is independent of the datasets listed in the ML Lab sidebar. You can bring in any CSV here.
417
+ </p>
418
+ </div>
419
+
420
+ <div class="smx-field">
421
+ <label for="target_pct">Target size (%)</label>
422
+ <input
423
+ id="target_pct"
424
+ name="target_pct"
425
+ type="number"
426
+ min="1"
427
+ max="100"
428
+ step="1"
429
+ placeholder="For example: 20 for 20% of the rows"
430
+ required
431
+ >
432
+ <p class="smx-hint">
433
+ We will sample roughly this share of rows. For very large files, even 5–10&nbsp;% can be enough
434
+ to explore patterns.
435
+ </p>
436
+ </div>
437
+
438
+ <a href="#" id="advToggle" class="smx-adv-toggle">
439
+ <span aria-hidden="true">▸</span>
440
+ <span>Show advanced options</span>
441
+ </a>
442
+
443
+ <div id="advanced-box">
444
+ <div class="smx-field" style="margin-top:4px;">
445
+ <label for="strat_col">Stratify by column (optional)</label>
446
+ <input
447
+ id="strat_col"
448
+ name="strat_col"
449
+ type="text"
450
+ placeholder="Type a label/segment column to keep class balance"
451
+ >
452
+ <p class="smx-hint">
453
+ If you supply a valid column name (for example a target label), the resizer will allocate rows per
454
+ class so proportions remain close to the original.
455
+ </p>
456
+ </div>
457
+ </div>
458
+
459
+ <div class="smx-actions">
460
+ <button type="submit" class="btn-primary">
461
+ Create resized CSV
462
+ </button>
463
+ </div>
464
+ </form>
465
+ </div>
466
+ </div>
467
+
468
+ <!-- Side card: summary + download -->
469
+ <div class="smx-card-secondary">
470
+ <div class="smx-card-header">
471
+ <div class="smx-card-title">
472
+ <span class="smx-badge-dot"></span>
473
+ <span>Resize summary</span>
474
+ </div>
475
+ </div>
476
+ <div class="smx-card-body">
477
+ {% if resize_info %}
478
+ <p class="smx-side-note-text">
479
+ Here is a quick view of what was produced from your last run. You can download the resized CSV
480
+ and pass it straight into your modelling workflow.
481
+ </p>
482
+ <ul class="meta-list">
483
+ <li><strong>Original rows:</strong> {{ resize_info.rows_in }}</li>
484
+ <li><strong>Resized rows:</strong> {{ resize_info.rows_out }}</li>
485
+ <li><strong>Target size:</strong> {{ "%.1f"|format(resize_info.pct) }}&nbsp;%</li>
486
+ {% if resize_info.used_strat and resize_info.strat_col %}
487
+ <li><strong>Stratified by:</strong> {{ resize_info.strat_col }}</li>
488
+ {% endif %}
489
+ </ul>
490
+ <a href="{{ url_for('download_resized_dataset') }}" class="download-link">
491
+ Download resized CSV
492
+ </a>
493
+ {% else %}
494
+ <p class="smx-side-note-title">No resized dataset yet</p>
495
+ <p class="smx-side-note-text">
496
+ Once you upload a file and choose a percentage, this panel will display the row counts and a download
497
+ button for the resized sample.
498
+ </p>
499
+ {% endif %}
500
+ </div>
501
+ </div>
502
+ </div>
503
+ </div>
504
+
505
+ <script>
506
+ (function () {
507
+ const toggle = document.getElementById("advToggle");
508
+ const box = document.getElementById("advanced-box");
509
+ if (!toggle || !box) return;
510
+
511
+ let open = false;
512
+ const labelSpan = toggle.querySelector("span:nth-child(2)");
513
+ const arrowSpan = toggle.querySelector("span:nth-child(1)");
514
+
515
+ function refresh() {
516
+ box.style.display = open ? "block" : "none";
517
+ if (labelSpan) {
518
+ labelSpan.textContent = open ? "Hide advanced options" : "Show advanced options";
519
+ }
520
+ if (arrowSpan) {
521
+ arrowSpan.textContent = open ? "▾" : "▸";
522
+ }
523
+ }
524
+
525
+ toggle.addEventListener("click", function (ev) {
526
+ ev.preventDefault();
527
+ open = !open;
528
+ refresh();
529
+ });
530
+
531
+ refresh();
532
+ })();
533
+ </script>
534
+ </body>
535
+ </html>