zaturn 0.2.1__py3-none-any.whl → 0.3.0__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 (42) hide show
  1. zaturn/mcp/__init__.py +9 -10
  2. zaturn/studio/agent_wrapper.py +36 -112
  3. zaturn/studio/app.py +48 -41
  4. zaturn/studio/storage.py +14 -4
  5. zaturn/studio/templates/_shell.html +3 -3
  6. zaturn/studio/templates/ai_message.html +1 -2
  7. zaturn/studio/templates/c_source_card.html +3 -3
  8. zaturn/studio/templates/chat.html +27 -19
  9. zaturn/studio/templates/chat_metadata.html +10 -0
  10. zaturn/studio/templates/css/style.css +146 -21
  11. zaturn/studio/templates/function_call.html +5 -4
  12. zaturn/studio/templates/icons/arrow-left.svg +3 -0
  13. zaturn/studio/templates/icons/arrow-right.svg +3 -0
  14. zaturn/studio/templates/icons/chat-bubble.svg +6 -0
  15. zaturn/studio/templates/icons/check-circle-solid.svg +3 -0
  16. zaturn/studio/templates/icons/database.svg +5 -0
  17. zaturn/studio/templates/icons/fire-flame.svg +4 -0
  18. zaturn/studio/templates/icons/floppy-disk.svg +5 -0
  19. zaturn/studio/templates/icons/link.svg +4 -0
  20. zaturn/studio/templates/icons/play.svg +3 -0
  21. zaturn/studio/templates/icons/settings.svg +4 -0
  22. zaturn/studio/templates/icons/timer.svg +5 -0
  23. zaturn/studio/templates/icons/trash.svg +4 -0
  24. zaturn/studio/templates/icons/upload.svg +4 -0
  25. zaturn/studio/templates/icons/user.svg +4 -0
  26. zaturn/studio/templates/icons/warning-triangle.svg +5 -0
  27. zaturn/studio/templates/icons/wrench.svg +4 -0
  28. zaturn/studio/templates/loader.html +1 -1
  29. zaturn/studio/templates/manage_sources.html +5 -5
  30. zaturn/studio/templates/new_conversation.html +2 -2
  31. zaturn/studio/templates/settings.html +24 -3
  32. zaturn/studio/templates/setup_prompt.html +3 -2
  33. zaturn/studio/templates/user_message.html +2 -2
  34. zaturn/tools/config.py +0 -83
  35. {zaturn-0.2.1.dist-info → zaturn-0.3.0.dist-info}/METADATA +5 -5
  36. zaturn-0.3.0.dist-info/RECORD +55 -0
  37. zaturn/studio/static/noto_emoji.ttf +0 -0
  38. zaturn-0.2.1.dist-info/RECORD +0 -39
  39. {zaturn-0.2.1.dist-info → zaturn-0.3.0.dist-info}/WHEEL +0 -0
  40. {zaturn-0.2.1.dist-info → zaturn-0.3.0.dist-info}/entry_points.txt +0 -0
  41. {zaturn-0.2.1.dist-info → zaturn-0.3.0.dist-info}/licenses/LICENSE +0 -0
  42. {zaturn-0.2.1.dist-info → zaturn-0.3.0.dist-info}/top_level.txt +0 -0
@@ -15,11 +15,6 @@
15
15
  src: url('/static/fira_code.ttf');
16
16
  }
17
17
 
18
- @font-face {
19
- font-family: "Noto Emoji";
20
- src: url('/static/noto_emoji.ttf');
21
- }
22
-
23
18
  /* Global Styles */
24
19
  * {
25
20
  box-sizing: border-box;
@@ -37,7 +32,7 @@
37
32
  --red: #d43a3a;
38
33
  --fg2: #3a4d74;
39
34
  --fg1: #182030;
40
- --base-size: clamp(16px, 1.4vw, 32px);
35
+ --base-size: clamp(16px, 1.3vw, 32px);
41
36
  --max-width: calc(var(--base-size)*36);
42
37
  font-size: var(--base-size);
43
38
  letter-spacing: 0.02rem;
@@ -55,6 +50,7 @@ body {
55
50
  align-content: stretch;
56
51
  height: 99vh;
57
52
  line-height: 170%;
53
+ overflow-y: hidden;
58
54
  }
59
55
 
60
56
  a {
@@ -80,6 +76,11 @@ header .logo {
80
76
  height: 2rem;
81
77
  }
82
78
 
79
+ header svg {
80
+ width: 1.25rem;
81
+ height: 1.25rem;
82
+ }
83
+
83
84
  #sidebar {
84
85
  grid-area: 2 / 1 / 3 / 2;
85
86
  background: var(--bg0);
@@ -120,12 +121,22 @@ section {
120
121
 
121
122
  section h1 {
122
123
  margin-bottom: 2rem;
124
+ display: flex;
125
+ align-items: center;
126
+ gap: 0.5rem;
127
+ }
128
+
129
+ section h1 svg {
130
+ width: 1.5rem;
131
+ height: 1.5rem;
123
132
  }
124
133
 
125
134
  .btn, button {
126
135
  text-decoration: none;
127
136
  background: var(--bg2);
128
- display: inline-block;
137
+ display: inline-flex;
138
+ align-items: center;
139
+ gap: 0.5rem;
129
140
  padding: 0.5rem 1rem;
130
141
  border-radius: 0.2rem;
131
142
  color: var(--t1);
@@ -145,6 +156,11 @@ section h1 {
145
156
  opacity: 0.8;
146
157
  }
147
158
 
159
+ .btn svg {
160
+ width: 1rem;
161
+ height: 1rem;
162
+ }
163
+
148
164
  code {
149
165
  font-family: "Fira Code", monospace;
150
166
  font-size: 0.8rem;
@@ -160,6 +176,14 @@ code {
160
176
  background: var(--bg0);
161
177
  padding: 0.5rem;
162
178
  border: 1px solid var(--bg2);
179
+ display: flex;
180
+ align-items: center;
181
+ gap: 0.5rem;
182
+ }
183
+
184
+ .alert svg {
185
+ width: 1rem;
186
+ height: 1rem;
163
187
  }
164
188
 
165
189
 
@@ -178,6 +202,9 @@ form label {
178
202
 
179
203
  form small {
180
204
  font-size: 0.8rem;
205
+ }
206
+
207
+ form small:first-child {
181
208
  font-weight: bold;
182
209
  }
183
210
 
@@ -196,8 +223,32 @@ form input:focus {
196
223
  border-bottom: 1px solid var(--t1);
197
224
  }
198
225
 
226
+ form select {
227
+ border: none;
228
+ outline: none;
229
+ background: none;
230
+ font-family: "Fira Code", monospace;
231
+ border-bottom: 1px solid var(--fg1);
232
+ color: var(--fg1);
233
+ font-size: 0.8rem;
234
+ padding: 0.2rem;
235
+ }
236
+
237
+ form select:focus {
238
+ color: var(--t1);
239
+ border-bottom: 1px solid var(--t1);
240
+ }
241
+
199
242
  form button {
200
243
  justify-self: start;
244
+ display: inline-flex;
245
+ align-items: center;
246
+ gap: 0.5rem;
247
+ }
248
+
249
+ form button svg {
250
+ width: 1.25rem;
251
+ height: 1.25rem;
201
252
  }
202
253
 
203
254
  form progress[value="0"] {
@@ -205,12 +256,17 @@ form progress[value="0"] {
205
256
  }
206
257
 
207
258
  form textarea {
208
- font-size: inherit;
259
+ font-family: "Fira Code", monospace;
260
+ font-size: 0.8rem;
209
261
  padding: 0.5rem;
210
262
  border: none;
211
263
  outline: none;
212
264
  }
213
265
 
266
+ form textarea.large {
267
+ height: 7rem;
268
+ }
269
+
214
270
  form.htmx-request {
215
271
  display: none;
216
272
  }
@@ -224,7 +280,14 @@ form ~ .loader {
224
280
  }
225
281
 
226
282
  form.htmx-request + .loader {
227
- display: block;
283
+ display: flex;
284
+ align-items: center;
285
+ gap: 0.5rem;
286
+ }
287
+
288
+ form ~ .loader svg {
289
+ width: 1.2rem;
290
+ height: 1.2rem;
228
291
  }
229
292
 
230
293
  @keyframes loadanim {
@@ -265,12 +328,19 @@ form.htmx-request + .loader {
265
328
  #manage-sources .source-card button {
266
329
  font-size: 0.75rem;
267
330
  padding: 0.25rem 0.5rem;
331
+ display: inline-flex;
332
+ align-items: center;
268
333
  }
269
334
 
270
335
  #manage-sources .source-card button.inactive {
271
336
  filter: grayscale(100%);
272
337
  }
273
338
 
339
+ #manage-sources .source-card button svg {
340
+ width: 0.75rem;
341
+ height: 0.75rem;
342
+ }
343
+
274
344
  #manage-sources .row-c2 {
275
345
  margin-top: 1.5rem;
276
346
  }
@@ -301,10 +371,29 @@ form.htmx-request + .loader {
301
371
  padding: 1.5rem 0.5rem;
302
372
  }
303
373
 
304
- #chat ul {
374
+ #chat ul, #chat ol {
305
375
  list-style-position: inside;
306
376
  }
307
377
 
378
+ #chat .chat-metadata * {
379
+ font-family: "Fira Code", monospace;
380
+ font-size: 0.9rem;
381
+ }
382
+
383
+ #chat dt, #chat dd {
384
+ display: inline-block;
385
+ }
386
+
387
+ #chat dt {
388
+ font-weight: 700;
389
+ }
390
+
391
+
392
+ #chat .system-prompt-message summary {
393
+ cursor: pointer;
394
+ margin: 1rem 0;
395
+ }
396
+
308
397
  #chat .user-message {
309
398
  display: grid;
310
399
  grid-template-columns: auto 1fr;
@@ -314,13 +403,26 @@ form.htmx-request + .loader {
314
403
  }
315
404
 
316
405
  #chat .user-message .sender {
406
+ font-size: 75%;
407
+ display: inline-flex;
408
+ align-items: center;
409
+ gap: 0.5rem;
410
+ background: none;
411
+ border: 0.1rem solid var(--t1);
412
+ padding: 0.125rem 0.75rem;
413
+ border-radius: 2rem;
317
414
  color: var(--t1);
318
- border: 1px solid var(--t1);
319
- padding: 0.125rem 0.5rem;
320
- font-size: 70%;
415
+ margin-right: 0.5rem;
321
416
  }
322
417
 
418
+ #chat .user-message .sender svg {
419
+ width: 1rem;
420
+ height: 1rem;
421
+ }
323
422
 
423
+ #chat .user-message>p {
424
+ padding-top: 0.25rem;
425
+ }
324
426
 
325
427
  #chat .ai-message {
326
428
  display: grid;
@@ -332,30 +434,51 @@ form.htmx-request + .loader {
332
434
  font-size: 70%;
333
435
  }
334
436
 
437
+ #chat .ai-message>div>* {
438
+ margin: 0.25rem 0;
439
+ }
440
+
335
441
 
336
442
  #chat .function-call {
337
443
  display: grid;
338
444
  gap: 0.75rem;
339
445
  align-items: center;
446
+ grid-template-columns: auto 1fr;
340
447
  }
341
448
 
342
- #chat .function-name b {
449
+ #chat .function-name {
343
450
  font-size: 75%;
344
- display: inline-block;
451
+ justify-self: start;
452
+ display: inline-flex;
453
+ align-items: center;
454
+ gap: 0.5rem;
345
455
  background: var(--t1);
346
- padding: 0rem 0.5rem;
456
+ border: 0.1rem solid var(--t1);
457
+ padding: 0.125rem 0.75rem;
347
458
  border-radius: 2rem;
348
459
  color: var(--bg0);
349
460
  margin-right: 0.5rem;
350
461
  }
351
462
 
352
- #chat .function-call pre {
353
- overflow-x: auto;
463
+ #chat .function-name svg {
464
+ width: 1rem;
465
+ height: 1rem;
354
466
  }
355
467
 
356
- #chat .function-name code {
357
- color: var(--t1);
358
- font-weight: 700;
468
+ #chat .function-call .exec-time {
469
+ display: inline-flex;
470
+ align-items: center;
471
+ gap: 0.5rem;
472
+ font-size: 0.8rem;
473
+ }
474
+
475
+ #chat .function-call .exec-time svg {
476
+ width: 0.8rem;
477
+ height: 0.8rem;
478
+ }
479
+
480
+ #chat .function-call pre {
481
+ overflow-x: auto;
359
482
  }
360
483
 
361
484
  #chat .function-call .args {
@@ -365,10 +488,12 @@ form.htmx-request + .loader {
365
488
  font-family: Fira Code, monospace;
366
489
  font-size: 75%;
367
490
  line-height: 180%;
491
+ grid-column: 1 / -1;
368
492
  }
369
493
 
370
494
  #chat .function-output {
371
495
  overflow-x: auto;
496
+ grid-column: 1 / -1;
372
497
  }
373
498
 
374
499
  #chat table {
@@ -1,7 +1,8 @@
1
1
  <div class="function-call">
2
- <pre class="function-name"><b>fn_call</b><code>{{msg['call_details']['name']}}</code></pre>
3
- {% if msg['call_details']['arguments'] %}
4
- <p class="args">{{msg['call_details']['arguments'] | safe}}</p>
2
+ <b class="function-name">{% include('icons/wrench.svg') %} {{part['call_details']['name']}}</b>
3
+ <b class="exec-time">{% include('icons/timer.svg') %} {{part['call_details']['exec_time']}}s</b>
4
+ {% if part['call_details']['args_html'] %}
5
+ <p class="args">{{part['call_details']['args_html'] | safe}}</p>
5
6
  {% endif %}
6
- <div class="function-output">{{ msg['html'] | safe}}</div>
7
+ <div class="function-output">{{ part['html_content'] | safe}}</div>
7
8
  </div>
@@ -0,0 +1,3 @@
1
+ <svg viewBox="0 0 24 24" stroke-width="1.5" fill="none">
2
+ <path d="M21 12L3 12M3 12L11.5 3.5M3 12L11.5 20.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
3
+ </svg>
@@ -0,0 +1,3 @@
1
+ <svg viewBox="0 0 24 24" stroke-width="1.5" fill="none">
2
+ <path d="M3 12L21 12M21 12L12.5 3.5M21 12L12.5 20.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
3
+ </svg>
@@ -0,0 +1,6 @@
1
+ <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" fill="none">
2
+ <path d="M17 12.5C17.2761 12.5 17.5 12.2761 17.5 12C17.5 11.7239 17.2761 11.5 17 11.5C16.7239 11.5 16.5 11.7239 16.5 12C16.5 12.2761 16.7239 12.5 17 12.5Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
3
+ <path d="M12 12.5C12.2761 12.5 12.5 12.2761 12.5 12C12.5 11.7239 12.2761 11.5 12 11.5C11.7239 11.5 11.5 11.7239 11.5 12C11.5 12.2761 11.7239 12.5 12 12.5Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
4
+ <path d="M7 12.5C7.27614 12.5 7.5 12.2761 7.5 12C7.5 11.7239 7.27614 11.5 7 11.5C6.72386 11.5 6.5 11.7239 6.5 12C6.5 12.2761 6.72386 12.5 7 12.5Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
5
+ <path d="M12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2C6.47715 2 2 6.47715 2 12C2 13.8214 2.48697 15.5291 3.33782 17L2.5 21.5L7 20.6622C8.47087 21.513 10.1786 22 12 22Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
6
+ </svg>
@@ -0,0 +1,3 @@
1
+ <svg viewBox="0 0 24 24" fill="none">
2
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M12 1.25C6.06294 1.25 1.25 6.06294 1.25 12C1.25 17.9371 6.06294 22.75 12 22.75C17.9371 22.75 22.75 17.9371 22.75 12C22.75 6.06294 17.9371 1.25 12 1.25ZM7.53044 11.9697C7.23755 11.6768 6.76268 11.6768 6.46978 11.9697C6.17689 12.2626 6.17689 12.7374 6.46978 13.0303L9.46978 16.0303C9.76268 16.3232 10.2376 16.3232 10.5304 16.0303L17.5304 9.03033C17.8233 8.73744 17.8233 8.26256 17.5304 7.96967C17.2375 7.67678 16.7627 7.67678 16.4698 7.96967L10.0001 14.4393L7.53044 11.9697Z" fill="currentColor" stroke-width="1.5"></path>
3
+ </svg>
@@ -0,0 +1,5 @@
1
+ <svg width="24px" height="24px" viewBox="0 0 24 24" fill="none">
2
+ <path d="M5 12V18C5 18 5 21 12 21C19 21 19 18 19 18V12" stroke="currentColor" stroke-width="1.5"></path>
3
+ <path d="M5 6V12C5 12 5 15 12 15C19 15 19 12 19 12V6" stroke="currentColor" stroke-width="1.5"></path>
4
+ <path d="M12 3C19 3 19 6 19 6C19 6 19 9 12 9C5 9 5 6 5 6C5 6 5 3 12 3Z" stroke="currentColor" stroke-width="1.5"></path>
5
+ </svg>
@@ -0,0 +1,4 @@
1
+ <svg stroke-width="1.5" viewBox="0 0 24 24" fill="none">
2
+ <path d="M8 18C8 20.4148 9.79086 21 12 21C15.7587 21 17 18.5 14.5 13.5C11 18 10.5 11 11 9C9.5 12 8 14.8177 8 18Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
3
+ <path d="M12 21C17.0495 21 20 18.0956 20 13.125C20 8.15444 12 3 12 3C12 3 4 8.15444 4 13.125C4 18.0956 6.95054 21 12 21Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
4
+ </svg>
@@ -0,0 +1,5 @@
1
+ <svg stroke-width="1.5" viewBox="0 0 24 24" fill="none">
2
+ <path d="M3 19V5C3 3.89543 3.89543 3 5 3H16.1716C16.702 3 17.2107 3.21071 17.5858 3.58579L20.4142 6.41421C20.7893 6.78929 21 7.29799 21 7.82843V19C21 20.1046 20.1046 21 19 21H5C3.89543 21 3 20.1046 3 19Z" stroke="currentColor" stroke-width="1.5"></path>
3
+ <path d="M8.6 9H15.4C15.7314 9 16 8.73137 16 8.4V3.6C16 3.26863 15.7314 3 15.4 3H8.6C8.26863 3 8 3.26863 8 3.6V8.4C8 8.73137 8.26863 9 8.6 9Z" stroke="currentColor" stroke-width="1.5"></path>
4
+ <path d="M6 13.6V21H18V13.6C18 13.2686 17.7314 13 17.4 13H6.6C6.26863 13 6 13.2686 6 13.6Z" stroke="currentColor" stroke-width="1.5"></path>
5
+ </svg>
@@ -0,0 +1,4 @@
1
+ <svg viewBox="0 0 24 24" fill="none">
2
+ <path d="M14 11.9976C14 9.5059 11.683 7 8.85714 7C8.52241 7 7.41904 7.00001 7.14286 7.00001C4.30254 7.00001 2 9.23752 2 11.9976C2 14.376 3.70973 16.3664 6 16.8714C6.36756 16.9525 6.75006 16.9952 7.14286 16.9952" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
3
+ <path d="M10 11.9976C10 14.4893 12.317 16.9952 15.1429 16.9952C15.4776 16.9952 16.581 16.9952 16.8571 16.9952C19.6975 16.9952 22 14.7577 22 11.9976C22 9.6192 20.2903 7.62884 18 7.12383C17.6324 7.04278 17.2499 6.99999 16.8571 6.99999" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
4
+ </svg>
@@ -0,0 +1,3 @@
1
+ <svg stroke-width="1.5" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M6.90588 4.53682C6.50592 4.2998 6 4.58808 6 5.05299V18.947C6 19.4119 6.50592 19.7002 6.90588 19.4632L18.629 12.5162C19.0211 12.2838 19.0211 11.7162 18.629 11.4838L6.90588 4.53682Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
3
+ </svg>
@@ -0,0 +1,4 @@
1
+ <svg viewBox="0 0 24 24" fill="none">
2
+ <path d="M12 15C13.6569 15 15 13.6569 15 12C15 10.3431 13.6569 9 12 9C10.3431 9 9 10.3431 9 12C9 13.6569 10.3431 15 12 15Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
3
+ <path d="M19.6224 10.3954L18.5247 7.7448L20 6L18 4L16.2647 5.48295L13.5578 4.36974L12.9353 2H10.981L10.3491 4.40113L7.70441 5.51596L6 4L4 6L5.45337 7.78885L4.3725 10.4463L2 11V13L4.40111 13.6555L5.51575 16.2997L4 18L6 20L7.79116 18.5403L10.397 19.6123L11 22H13L13.6045 19.6132L16.2551 18.5155C16.6969 18.8313 18 20 18 20L20 18L18.5159 16.2494L19.6139 13.598L21.9999 12.9772L22 11L19.6224 10.3954Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
4
+ </svg>
@@ -0,0 +1,5 @@
1
+ <svg stroke-width="1.5" viewBox="0 0 24 24" fill="none">
2
+ <path d="M9 2L15 2" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
3
+ <path d="M12 10L12 14" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
4
+ <path d="M12 22C16.4183 22 20 18.4183 20 14C20 9.58172 16.4183 6 12 6C7.58172 6 4 9.58172 4 14C4 18.4183 7.58172 22 12 22Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
5
+ </svg>
@@ -0,0 +1,4 @@
1
+ <svg viewBox="0 0 24 24" stroke-width="1.5" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M20 9L18.005 20.3463C17.8369 21.3026 17.0062 22 16.0353 22H7.96474C6.99379 22 6.1631 21.3026 5.99496 20.3463L4 9" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
3
+ <path d="M21 6L15.375 6M3 6L8.625 6M8.625 6V4C8.625 2.89543 9.52043 2 10.625 2H13.375C14.4796 2 15.375 2.89543 15.375 4V6M8.625 6L15.375 6" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
4
+ </svg>
@@ -0,0 +1,4 @@
1
+ <svg viewBox="0 0 24 24" fill="none">
2
+ <path d="M6 20L18 20" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
3
+ <path d="M12 16V4M12 4L15.5 7.5M12 4L8.5 7.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
4
+ </svg>
@@ -0,0 +1,4 @@
1
+ <svg stroke-width="1.5" viewBox="0 0 24 24" fill="none">
2
+ <path d="M5 20V19C5 15.134 8.13401 12 12 12V12C15.866 12 19 15.134 19 19V20" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
3
+ <path d="M12 12C14.2091 12 16 10.2091 16 8C16 5.79086 14.2091 4 12 4C9.79086 4 8 5.79086 8 8C8 10.2091 9.79086 12 12 12Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
4
+ </svg>
@@ -0,0 +1,5 @@
1
+ <svg stroke-width="1.5" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M20.0429 21H3.95705C2.41902 21 1.45658 19.3364 2.22324 18.0031L10.2662 4.01533C11.0352 2.67792 12.9648 2.67791 13.7338 4.01532L21.7768 18.0031C22.5434 19.3364 21.581 21 20.0429 21Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"></path>
3
+ <path d="M12 9V13" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"></path>
4
+ <path d="M12 17.01L12.01 16.9989" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
5
+ </svg>
@@ -0,0 +1,4 @@
1
+ <svg viewBox="0 0 24 24" stroke-width="1.5" fill="none">
2
+ <path d="M10.0503 10.6066L2.97923 17.6777C2.19818 18.4587 2.19818 19.725 2.97923 20.5061V20.5061C3.76027 21.2871 5.0266 21.2871 5.80765 20.5061L12.8787 13.435" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
3
+ <path d="M10.0502 10.6066C9.20638 8.45358 9.37134 5.6286 11.1109 3.88909C12.8504 2.14957 16.0606 1.76777 17.8284 2.82843L14.7877 5.8691L14.5051 8.98014L17.6161 8.69753L20.6568 5.65685C21.7175 7.42462 21.3357 10.6349 19.5961 12.3744C17.8566 14.1139 15.0316 14.2789 12.8786 13.435" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
4
+ </svg>
@@ -1 +1 @@
1
- <p class="loader">💆‍♀️ Relax, Zaturn is running...</p>
1
+ <p class="loader">{% include('icons/play.svg') %} Relax, Zaturn is running...</p>
@@ -1,13 +1,13 @@
1
1
  <section id="manage-sources">
2
2
  {% if sources %}
3
- <h1>🔗 Your Data Sources</h1>
3
+ <h1>{% include('icons/database.svg') %} Your Data Sources</h1>
4
4
  {% for key in sources %}
5
5
  {% with key=key, active=sources[key]['active'] %}
6
6
  {% include('c_source_card.html') %}
7
7
  {% endwith %}
8
8
  {% endfor %}
9
9
  {% else %}
10
- <h1>➕ Add Some Data</h1>
10
+ <h1>{% include('icons/database.svg') %} Add Some Data</h1>
11
11
  {% endif %}
12
12
 
13
13
  <div class="row-c2">
@@ -22,7 +22,7 @@
22
22
  <input type="file" name="datafile" accept=".csv,.db,.sqlite,.sqlite3,.duckdb,.parquet,.pq" placeholder="" required>
23
23
  <small><em>CSV / SQLite / DuckDB / Parquet</em></small>
24
24
  </label>
25
- <button>⬆ Upload</button>
25
+ <button>{% include('icons/upload.svg') %} Upload</button>
26
26
  <progress value='0' max='100'></progress>
27
27
  </form>
28
28
 
@@ -36,9 +36,9 @@
36
36
  <label>
37
37
  <small>Or Link A Database Using URL</small>
38
38
  <input type="text" name="db_url" required>
39
- <small><em>PostgreSQL / MySQL / Clickhouse</em></small>
39
+ <small><em>PostgreSQL / MySQL / Clickhouse / MSSQL</em></small>
40
40
  </label>
41
- <button>🔗 Connect</button>
41
+ <button>{% include('icons/link.svg') %} Connect</button>
42
42
  </form>
43
43
  </div>
44
44
 
@@ -1,5 +1,5 @@
1
1
  <section id="new-conversation">
2
- <h1>Vamos! ᯓ★</h1>
2
+ <h1>Vamos!</h1>
3
3
  <p>An AMA Session With Your Data</p>
4
4
  <form action="/create_new_chat" method="POST">
5
5
  <textarea
@@ -7,7 +7,7 @@
7
7
  name="question"
8
8
  placeholder="Type your question here...&#10E.g.: Explore the linked data and tell me something useful."
9
9
  ></textarea>
10
- <button>➡</button>
10
+ <button>{% include('icons/arrow-right.svg') %}</button>
11
11
  </form>
12
12
  {% include('loader.html') %}
13
13
  </section>
@@ -1,13 +1,13 @@
1
1
  <section id="settings">
2
2
  <h1>
3
- <a href="/">⬅</a>
3
+ <a href="/">{% include('icons/arrow-left.svg') %}</a>
4
4
  Settings
5
5
  </h1>
6
6
 
7
7
  {% if updated %}
8
8
  <p class="alert">
9
9
  <code>{{updated}}</code>
10
- Settings Updated!
10
+ {% include('icons/check-circle-solid.svg') %} Settings Updated!
11
11
  </p>
12
12
  {% endif %}
13
13
 
@@ -24,6 +24,27 @@
24
24
  <small>OPENAI API ENDPOINT (Leave blank to use default)</small>
25
25
  <input type="text" name="api_endpoint" value="{{current['api_endpoint']}}">
26
26
  </label>
27
- <button>💾 Save</button>
27
+ <label>
28
+ <small>REASONING EFFORT</small>
29
+ <select name="reasoning_effort">
30
+ <option value="none" {% if current['reasoning_effort']=='none' %}selected{% endif %}>
31
+ none
32
+ </option>
33
+ <option value="low" {% if current['reasoning_effort']=='low' %}selected{% endif %}>
34
+ low
35
+ </option>
36
+ <option value="medium" {% if current['reasoning_effort']=='medium' %}selected{% endif %}>
37
+ medium
38
+ </option>
39
+ <option value="high" {% if current['reasoning_effort']=='high' %}selected{% endif %}>
40
+ high
41
+ </option>
42
+ </select>
43
+ </label>
44
+ <label>
45
+ <small>SYSTEM PROMPT</small>
46
+ <textarea name="system_prompt" class="large" required>{{current['system_prompt']}}</textarea>
47
+ </label>
48
+ <button>{% include('icons/floppy-disk.svg') %} Save</button>
28
49
  </form>
29
50
  </section>
@@ -1,6 +1,7 @@
1
1
  <section id="setup-prompt">
2
- <h1>Are You Ready? 🔥</h1>
2
+ <h1>Are You Ready? {% include('icons/fire-flame.svg') %}</h1>
3
3
  <p>We need to set you up though.</p>
4
4
  <p>Head over to <a href="/settings">settings</a> and add your LLM API Key.</p>
5
- <p><a href="/settings" class="btn">⚙ Open Settings</a>
5
+ <br>
6
+ <p><a href="/settings" class="btn">{% include('icons/settings.svg') %} Open Settings</a>
6
7
  </section>
@@ -1,4 +1,4 @@
1
1
  <div class="user-message">
2
- <b class="sender">You</b>
3
- <p>{{msg['content']}}</p>
2
+ <b class="sender">{% include('icons/user.svg') %} User</b>
3
+ <p>{{part['content']}}</p>
4
4
  </div>
zaturn/tools/config.py CHANGED
@@ -1,8 +1,5 @@
1
- import argparse
2
1
  import os
3
2
  import platformdirs
4
- import pkg_resources
5
- import sys
6
3
 
7
4
  # Basic Setup
8
5
  USER_DATA_DIR = platformdirs.user_data_dir('zaturn', 'zaturn')
@@ -13,83 +10,3 @@ SOURCES_FILE = os.path.join(USER_DATA_DIR, 'sources.txt')
13
10
  os.makedirs(QUERIES_DIR, exist_ok=True)
14
11
  os.makedirs(VISUALS_DIR, exist_ok=True)
15
12
 
16
- # Parse command line args
17
- parser = argparse.ArgumentParser(
18
- description="Zaturn: A read-only BI tool for analyzing various data sources"
19
- )
20
- parser.add_argument('--noimg', action='store_const',
21
- const=True, default=False,
22
- help='Return image file paths instead of images for visuals. Use when MCP client cannot render images.',
23
- )
24
- parser.add_argument('sources', nargs=argparse.REMAINDER, default=[],
25
- help='Data source (can be specified multiple times). Can be SQLite, MySQL, PostgreSQL connection string, or a path to CSV, Parquet, or DuckDB file.'
26
- )
27
- args = parser.parse_args()
28
-
29
- # Read and parse sources
30
- source_list = []
31
- if os.path.exists(SOURCES_FILE):
32
- with open(SOURCES_FILE) as f:
33
- source_list = [line.strip('\n') for line in f.readlines() if line.strip('\n')]
34
-
35
- if not source_list:
36
- source_list = args.sources
37
-
38
- if not source_list:
39
- source_list = [
40
- pkg_resources.resource_filename(
41
- 'zaturn',
42
- os.path.join('mcp', 'example_data', 'all_pokemon_data.csv')
43
- )
44
- ]
45
- print("No data sources provided. Loading example dataset for demonstration.")
46
- print(f"\nTo load your datasets, add them to {SOURCES_FILE} (one source URL or full file path per line)")
47
- print("\nOr use command line args to specify data sources:")
48
- print("zaturn_mcp sqlite:///path/to/mydata.db /path/to/my_file.csv")
49
- print(f"\nNOTE: Sources in command line args will be ignored if sources are found in {SOURCES_FILE}")
50
-
51
- CLI_SOURCES = {}
52
- for s in source_list:
53
- source = s.lower()
54
- if source.startswith('sqlite://'):
55
- source_type = 'sqlite'
56
- source_name = source.split('/')[-1].split('?')[0].split('.db')[0]
57
- elif source.startswith('postgresql://'):
58
- source_type = 'postgresql'
59
- source_name = source.split('/')[-1].split('?')[0]
60
- elif source.startswith("mysql://") or source.startswith("mysql+pymysql://"):
61
- source_type = 'mysql'
62
- s = s.replace('mysql://', 'mysql+pymysql://')
63
- source_name = source.split('/')[-1].split('?')[0]
64
- elif source.startswith('clickhouse://'):
65
- source_type = 'clickhouse'
66
- source_name = source.split('/')[-1].split('?')[0]
67
- elif source.endswith(".duckdb"):
68
- source_type = "duckdb"
69
- source_name = source.split('/')[-1].split('.')[0]
70
- elif source.endswith(".csv"):
71
- source_type = "csv"
72
- source_name = source.split('/')[-1].split('.')[0]
73
- elif source.endswith(".parquet") or source.endswith(".pq"):
74
- source_type = "parquet"
75
- source_name = source.split('/')[-1].split('.')[0]
76
- else:
77
- continue
78
-
79
- source_id = f'{source_name}-{source_type}'
80
- if source_id in CLI_SOURCES:
81
- i = 2
82
- while True:
83
- source_id = f'{source_name}{i}-{source_type}'
84
- if source_id not in SOURCES:
85
- break
86
- i += 1
87
-
88
- CLI_SOURCES[source_id] = {'url': s, 'type': source_type}
89
-
90
-
91
- # Other Settings
92
- CLI_RETURN_IMAGES = not args.noimg
93
-
94
-
95
-