kash-shell 0.3.16__py3-none-any.whl → 0.3.18__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 (40) hide show
  1. kash/actions/core/minify_html.py +41 -0
  2. kash/commands/base/files_command.py +2 -2
  3. kash/commands/base/show_command.py +11 -1
  4. kash/config/colors.py +20 -8
  5. kash/docs/markdown/topics/a1_what_is_kash.md +52 -23
  6. kash/docs/markdown/topics/a2_installation.md +17 -30
  7. kash/docs/markdown/topics/a3_getting_started.md +5 -19
  8. kash/exec/action_exec.py +1 -1
  9. kash/exec/fetch_url_metadata.py +9 -0
  10. kash/exec/precondition_registry.py +3 -3
  11. kash/file_storage/file_store.py +18 -1
  12. kash/llm_utils/llm_features.py +5 -1
  13. kash/llm_utils/llms.py +18 -8
  14. kash/media_base/media_cache.py +48 -24
  15. kash/media_base/media_services.py +63 -14
  16. kash/media_base/services/local_file_media.py +9 -1
  17. kash/model/actions_model.py +2 -2
  18. kash/model/items_model.py +4 -5
  19. kash/model/media_model.py +9 -1
  20. kash/model/params_model.py +9 -3
  21. kash/utils/common/function_inspect.py +97 -1
  22. kash/utils/common/testing.py +58 -0
  23. kash/utils/common/url_slice.py +329 -0
  24. kash/utils/file_utils/file_formats.py +1 -1
  25. kash/utils/text_handling/markdown_utils.py +424 -16
  26. kash/web_gen/templates/base_styles.css.jinja +204 -25
  27. kash/web_gen/templates/base_webpage.html.jinja +48 -26
  28. kash/web_gen/templates/components/toc_scripts.js.jinja +319 -0
  29. kash/web_gen/templates/components/toc_styles.css.jinja +284 -0
  30. kash/web_gen/templates/components/tooltip_scripts.js.jinja +730 -0
  31. kash/web_gen/templates/components/tooltip_styles.css.jinja +482 -0
  32. kash/web_gen/templates/content_styles.css.jinja +13 -8
  33. kash/web_gen/templates/simple_webpage.html.jinja +59 -21
  34. kash/web_gen/templates/tabbed_webpage.html.jinja +4 -2
  35. kash/workspaces/workspaces.py +10 -1
  36. {kash_shell-0.3.16.dist-info → kash_shell-0.3.18.dist-info}/METADATA +75 -72
  37. {kash_shell-0.3.16.dist-info → kash_shell-0.3.18.dist-info}/RECORD +40 -33
  38. {kash_shell-0.3.16.dist-info → kash_shell-0.3.18.dist-info}/WHEEL +0 -0
  39. {kash_shell-0.3.16.dist-info → kash_shell-0.3.18.dist-info}/entry_points.txt +0 -0
  40. {kash_shell-0.3.16.dist-info → kash_shell-0.3.18.dist-info}/licenses/LICENSE +0 -0
@@ -5,7 +5,8 @@
5
5
  --font-sans: "Source Sans 3 Variable", sans-serif, "Hack Nerd Font";
6
6
  --font-serif: "PT Serif", serif, "Hack Nerd Font";
7
7
  /* Source Sans 3 Variable better at these weights. */
8
- --font-weight-sans-bold: 620;
8
+ --font-weight-sans-medium: 565;
9
+ --font-weight-sans-bold: 650;
9
10
  --font-mono: "Hack Nerd Font", "Menlo", "DejaVu Sans Mono", Consolas, "Lucida Console", monospace;
10
11
 
11
12
  --font-size-large: 1.2rem;
@@ -68,6 +69,14 @@
68
69
  }
69
70
  {% endblock scrollbar_styles %}
70
71
 
72
+ {% block html_styles %}
73
+ /* Prevent horizontal overflow at the root level */
74
+ html {
75
+ overflow-x: hidden;
76
+ width: 100%;
77
+ }
78
+ {% endblock html_styles %}
79
+
71
80
  {% block body_styles %}
72
81
  body {
73
82
  font-family: var(--font-serif);
@@ -109,7 +118,9 @@ a:hover {
109
118
  h1,
110
119
  h2,
111
120
  h3,
112
- h4 {
121
+ h4,
122
+ h5,
123
+ h6 {
113
124
  line-height: 1.2;
114
125
  }
115
126
 
@@ -120,7 +131,7 @@ h1 {
120
131
  }
121
132
 
122
133
  h2 {
123
- font-size: 1.4rem;
134
+ font-size: 1.42rem;
124
135
  margin-top: 2rem;
125
136
  margin-bottom: 1rem;
126
137
  }
@@ -129,17 +140,32 @@ h1 + h2 {
129
140
  margin-top: 2rem;
130
141
  }
131
142
 
143
+ h2 + h3 {
144
+ margin-top: 1.1rem;
145
+ }
146
+
132
147
  h3 {
133
- font-size: 1.03rem;
134
- margin-top: 1.6rem;
135
- margin-bottom: 0.5rem;
148
+ font-size: 1.18rem;
149
+ margin-top: 1.4rem;
150
+ margin-bottom: 0.7rem;
136
151
  }
137
152
 
138
153
  h4 {
154
+ font-size: 1.1rem;
139
155
  margin-top: 1rem;
140
156
  margin-bottom: 0.7rem;
141
157
  }
142
158
 
159
+ h5, h6 {
160
+ font-size: 1rem;
161
+ margin-top: 0.7rem;
162
+ margin-bottom: 0.5rem;
163
+ }
164
+
165
+ h4+p, h5+p, h6+p {
166
+ margin-top: 0;
167
+ }
168
+
143
169
  ul {
144
170
  list-style-type: none;
145
171
  margin-left: 1.8rem;
@@ -187,20 +213,34 @@ code {
187
213
  font-family: var(--font-mono);
188
214
  font-size: var(--font-size-mono);
189
215
  letter-spacing: -0.025em;
216
+
190
217
  transition: color 0.4s ease-in-out;
191
218
  }
219
+ /* For code inside pre we style the pre tag */
220
+ code:not(pre code) {
221
+ background-color: var(--color-bg-alt);
222
+ border-radius: 3px;
223
+ border: 1px solid var(--color-hint-gentle);
224
+ padding: 0.25em 0.2em 0.1em 0.2em;
225
+ }
226
+
227
+ /* Code block wrapper for positioning copy button */
228
+ .code-block-wrapper {
229
+ position: relative;
230
+ }
192
231
 
193
232
  /* Code blocks (pre + code) */
194
233
  pre {
195
234
  font-family: var(--font-mono);
196
235
  font-size: var(--font-size-mono);
197
236
  letter-spacing: -0.025em;
237
+
198
238
  background-color: var(--color-bg-alt);
199
- border-radius: 4px;
200
- border: 1px dotted var(--color-border-hint);
201
- padding: 0.2rem 0.2rem 0.1rem 0.2rem;
239
+ border-radius: 3px;
240
+ border: 1px solid var(--color-hint-gentle);
241
+ padding: 0.25rem 0.2rem 0.1rem 0.2rem;
202
242
  overflow-x: auto; /* Enable horizontal scrolling */
203
- position: relative; /* Create new stacking context */
243
+ margin: 0;
204
244
  transition: background-color 0.4s ease-in-out, border-color 0.4s ease-in-out;
205
245
  }
206
246
 
@@ -215,11 +255,12 @@ pre > code {
215
255
  position: absolute;
216
256
  top: 0;
217
257
  right: 0;
218
- background: var(--color-bg-alt);
258
+ margin: 1px;
259
+ background: var(--color-bg-alt-solid);
219
260
  color: var(--color-hint);
220
261
  border: none;
221
262
  border-radius: 0.25rem;
222
- padding: 0.25rem;
263
+ padding: 0;
223
264
  cursor: pointer;
224
265
  font-size: 0.75rem;
225
266
  z-index: 10;
@@ -229,7 +270,7 @@ pre > code {
229
270
  justify-content: center;
230
271
  width: 1.5rem;
231
272
  height: 1.5rem;
232
- opacity: 0.6;
273
+ opacity: 0.9;
233
274
  }
234
275
 
235
276
  .code-copy-button:hover {
@@ -240,7 +281,6 @@ pre > code {
240
281
 
241
282
  .code-copy-button.copied {
242
283
  color: var(--color-success);
243
- opacity: 1;
244
284
  }
245
285
 
246
286
  .code-copy-button svg {
@@ -248,6 +288,44 @@ pre > code {
248
288
  height: 0.875rem;
249
289
  }
250
290
 
291
+ img {
292
+ margin: 1rem 0;
293
+ }
294
+
295
+ details {
296
+ font-family: var(--font-sans);
297
+ color: var(--color-text);
298
+
299
+ border: 1px solid var(--color-hint-gentle);
300
+ border-radius: 3px;
301
+ margin: 0.75rem 0;
302
+ }
303
+
304
+ summary {
305
+ color: var(--color-secondary);
306
+ padding: .5rem 1rem;
307
+ cursor: pointer;
308
+ user-select: none;
309
+ background: var(--color-bg-alt);
310
+ transition: all 0.15s ease-in-out;
311
+ }
312
+
313
+ summary:hover {
314
+ color: var(--color-primary-light);
315
+ {# background: var(--color-hover-bg); #}
316
+ }
317
+
318
+ /* keep the border on the summary when open so it blends */
319
+ details[open] summary {
320
+ border-bottom: 1px solid var(--color-hint-gentle);
321
+ }
322
+ /* focus ring for a11y */
323
+ summary:focus-visible {
324
+ outline: 3px solid var(--color-primary);
325
+ outline-offset: 2px;
326
+ }
327
+
328
+
251
329
  hr {
252
330
  border: none;
253
331
  height: 1.5rem;
@@ -270,6 +348,7 @@ hr:before {
270
348
  {% endblock typography %}
271
349
 
272
350
  {% block long_text_styles %}
351
+
273
352
  /* Long text stylings, for nicely formatting blog post length or longer texts. */
274
353
 
275
354
  .long-text {
@@ -289,23 +368,36 @@ hr:before {
289
368
 
290
369
  .long-text h3 {
291
370
  font-family: var(--font-sans);
292
- font-weight: var(--font-weight-sans-bold);
293
- font-size: 1.05rem;
371
+ font-weight: 565;
294
372
  text-transform: uppercase;
295
373
  letter-spacing: 0.025em;
296
374
  }
297
375
 
298
376
  .long-text h4 {
377
+ font-family: var(--font-sans);
378
+ font-weight: 650;
379
+ letter-spacing: 0.02em;
380
+ }
381
+
382
+ .long-text h5 {
299
383
  font-family: var(--font-serif);
300
384
  font-weight: 700;
301
385
  }
302
386
 
387
+ .long-text h6 {
388
+ font-family: var(--font-serif);
389
+ font-weight: 400;
390
+ font-style: italic;
391
+ }
392
+
303
393
  .subtitle {
304
394
  font-family: var(--font-serif);
305
395
  font-style: italic;
306
396
  font-size: 1rem;
307
397
  }
308
398
 
399
+ /* Adjustments to long text for pure sans-serif pages. */
400
+
309
401
  .long-text .sans-text {
310
402
  font-family: var(--font-sans);
311
403
  }
@@ -333,11 +425,11 @@ hr:before {
333
425
 
334
426
  .long-text .sans-text h3 {
335
427
  font-family: var(--font-sans);
336
- font-size: 1.03rem;
428
+ font-size: 1.1rem;
337
429
  font-weight: var(--font-weight-sans-bold);
338
430
  text-transform: uppercase;
339
431
  letter-spacing: 0.03em;
340
- margin-top: 1.1rem;
432
+ margin-top: 1rem;
341
433
  margin-bottom: 0.8rem;
342
434
  }
343
435
  {% endblock long_text_styles %}
@@ -356,6 +448,7 @@ table {
356
448
  }
357
449
 
358
450
  th {
451
+ font-weight: var(--font-weight-sans-bold);
359
452
  text-transform: uppercase;
360
453
  letter-spacing: 0.03em;
361
454
  border-bottom: 1px solid var(--color-border-hint);
@@ -378,13 +471,24 @@ tbody tr:nth-child(even) {
378
471
 
379
472
  /* Container for wide tables to allow tables to break out of parent width. */
380
473
  .table-container {
381
- {# max-width: calc(100vw - 6rem); #}
382
474
  position: relative;
383
- left: 50%;
384
- transform: translateX(-50%);
385
475
  box-sizing: border-box;
386
476
  margin: 2rem 0;
387
477
  background-color: var(--color-bg-solid);
478
+ /* Default: center tables within their container */
479
+ left: 50%;
480
+ transform: translateX(-50%);
481
+ /* Prevent container from expanding beyond its content area */
482
+ overflow-x: auto;
483
+ overflow-y: visible;
484
+ }
485
+
486
+ /* When TOC is present, simplify table container positioning */
487
+ .content-with-toc.has-toc .table-container {
488
+ /* Within grid layout, position relative to the grid column */
489
+ left: 50%;
490
+ transform: translateX(-50%);
491
+ /* Let the table width be controlled by the responsive styles */
388
492
  }
389
493
  {% endblock table_styles %}
390
494
 
@@ -434,20 +538,89 @@ sup {
434
538
  }
435
539
  .table-container {
436
540
  width: calc(100vw - 6rem);
541
+ /* Ensure container doesn't expand beyond its width */
542
+ max-width: calc(100vw - 6rem);
543
+ contain: layout inline-size;
437
544
  }
438
545
 
439
546
  /* Apply shadow to long-text containers on larger screens */
440
547
  .long-text {
548
+ border: 1px solid var(--color-hint-gentle);
441
549
  box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 -2px 6px -1px rgba(0, 0, 0, 0.07);
442
550
  }
443
551
  /* But remove shadow when wrapped in no-shadow class */
444
552
  .no-shadow .long-text {
445
- box-shadow: none !important;
553
+ box-shadow: none;
554
+ border: none;
555
+ }
556
+ }
557
+
558
+ /* Handle TOC layouts specially - tables should bleed within their grid column */
559
+ @media (min-width: 1200px) {
560
+ .content-with-toc.has-toc {
561
+ /* Define reusable values for clarity */
562
+ --content-width: 48rem;
563
+ --content-min-gap: 2rem;
564
+ --table-right-margin: 2rem;
565
+ --long-text-padding: 4rem; /* md:px-16 = 4rem */
566
+
567
+ /* Where content would be if centered in viewport */
568
+ --content-centered-left: calc((100vw - var(--content-width)) / 2);
569
+
570
+ /* Content's left margin within its grid column */
571
+ --content-margin-left: max(var(--content-min-gap), calc(var(--content-centered-left) - var(--toc-width)));
572
+
573
+ /* Content text's actual position from viewport left edge (excluding padding) */
574
+ --content-text-viewport-left: calc(var(--toc-width) + var(--content-margin-left));
575
+ }
576
+
577
+ /* When TOC is present, tables should align with main content and bleed right */
578
+ .content-with-toc.has-toc .table-container {
579
+ /* Remove default positioning */
580
+ left: 0;
581
+ transform: none;
582
+
583
+ /* Pull table left to align with content's text position */
584
+ /* Need to compensate for both content margin AND long-text padding */
585
+ margin-left: calc(-1 * (var(--content-margin-left) + var(--long-text-padding)));
586
+
587
+ /* Table bleeds wide as can fit */
588
+ width: calc(100vw - var(--content-text-viewport-left) - var(--table-right-margin));
589
+ max-width: calc(100vw - var(--content-text-viewport-left) - var(--table-right-margin));
590
+
591
+ /* Ensure horizontal scroll works properly without expanding container */
592
+ overflow-x: auto;
593
+ overflow-y: visible;
594
+ contain: layout inline-size;
595
+ }
596
+
597
+ .content-with-toc.has-toc table {
598
+ /* Let table fill its container */
599
+ width: 100%;
600
+ max-width: none;
601
+ }
602
+
603
+ /* But ensure tables don't exceed their grid column space */
604
+ .content-with-toc.has-toc .long-text {
605
+ /* The content area needs to allow tables to bleed beyond the text width */
606
+ overflow: visible;
607
+ }
608
+ }
609
+
610
+ /* Medium screens (768px - TOC breakpoint) - no TOC, tables should bleed but not as wide */
611
+ @media (min-width: 768px) and (max-width: 1199px) {
612
+ table {
613
+ width: calc(100vw - 6rem);
614
+ max-width: calc(100vw - 6rem);
615
+ }
616
+ .table-container {
617
+ width: calc(100vw - 6rem);
618
+ max-width: calc(100vw - 6rem);
446
619
  }
447
620
  }
448
621
 
449
622
  /* Make narrower screens more usable for lists and tables. */
450
- @media (max-width: 768px) {
623
+ @media (max-width: 767px) {
451
624
  /* Prevent horizontal scrolling on the body */
452
625
  body {
453
626
  overflow-x: hidden;
@@ -461,20 +634,26 @@ sup {
461
634
 
462
635
  /* Make table containers scrollable without affecting page layout */
463
636
  .table-container {
464
- max-width: 100%;
637
+ width: calc(100vw - 3rem); /* Fixed width instead of max-width */
638
+ max-width: calc(100vw - 3rem);
465
639
  overflow-x: auto;
640
+ overflow-y: visible; /* Ensure vertical overflow is not hidden */
466
641
  transform: none;
467
642
  left: 0;
468
643
  position: relative;
469
644
  margin-left: auto;
470
645
  margin-right: auto;
646
+ /* Prevent container from expanding beyond its width */
647
+ box-sizing: border-box;
648
+ contain: layout inline-size; /* CSS containment to prevent width expansion */
471
649
  }
472
650
 
473
651
  table {
474
652
  font-size: var(--font-size-smaller);
475
- /* Tables can be wider than container */
653
+ /* Tables can be wider than container on mobile */
476
654
  width: auto;
477
655
  min-width: 100%;
656
+ max-width: none;
478
657
  }
479
658
 
480
659
  ul, ol {
@@ -50,57 +50,68 @@
50
50
  <link rel="preload" as="font" type="font/woff2" crossorigin
51
51
  href="https://cdn.jsdelivr.net/fontsource/fonts/source-sans-3:vf@latest/latin-wght-italic.woff2" />
52
52
 
53
- <link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet" />
53
+ <script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
54
54
  <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js" defer></script>
55
55
  {% endblock head_basic %}
56
56
 
57
57
  {% block head_extra %}{% endblock head_extra %}
58
58
 
59
59
  <style>
60
-
61
60
  body {
62
61
  background: var(--color-bg);
63
62
  color: var(--color-text);
64
63
  transition: background 0.4s ease-in-out, color 0.4s ease-in-out;
65
64
  }
66
65
 
67
- .theme-toggle {
68
- position: fixed;
69
- top: 1rem;
70
- right: 1rem;
71
- background: transparent;
72
- color: var(--color-hint);
66
+ .button {
67
+ color: var(--color-hint-strong);
68
+ background: var(--color-bg);
73
69
  border: none;
74
70
  padding: 0;
75
71
  border-radius: 0.3rem;
76
72
  cursor: pointer;
77
73
  font-size: 1rem;
78
- z-index: 100;
79
- transition: all 0.2s ease-in-out;
80
74
  display: flex;
81
75
  align-items: center;
82
76
  justify-content: center;
83
- width: 2.5rem;
84
- height: 2.5rem;
77
+ width: 2.2rem;
78
+ height: 2.2rem;
79
+
80
+ /* Separate transitions for theme vs interaction */
81
+ transition: background-color 0.4s ease-in-out,
82
+ color 0.4s ease-in-out,
83
+ transform 0.2s ease-in-out,
84
+ box-shadow 0.2s ease-in-out;
85
85
  }
86
86
 
87
- .theme-toggle:hover {
87
+ .button:hover {
88
88
  background: var(--color-hover-bg);
89
89
  color: var(--color-primary);
90
+ transition: background-color 0.4s ease-in-out, color 0.4s ease-in-out;
90
91
  }
91
92
 
92
- [data-theme="dark"] .theme-toggle {
93
- color: var(--color-primary-light);
93
+ .button svg {
94
+ width: 1.2rem;
95
+ height: 1.2rem;
96
+ transition: background-color 0.4s ease-in-out, color 0.4s ease-in-out;
94
97
  }
95
98
 
96
- [data-theme="dark"] .theme-toggle:hover {
97
- color: var(--color-bright);
98
- background: var(--color-hover-bg);
99
+
100
+ /* Positioning class for fixed buttons */
101
+ .fixed-button {
102
+ position: fixed;
103
+ top: 1rem;
99
104
  }
100
105
 
101
- .theme-toggle svg {
102
- width: 1rem;
103
- height: 1rem;
106
+ .floating-button {
107
+ border: 1px solid var(--color-hint-gentle);
108
+ background: var(--color-bg-alt);
109
+ }
110
+
111
+ /* Specific positioning and z-index for theme toggle */
112
+ .theme-toggle {
113
+ right: 1rem;
114
+ z-index: 100;
104
115
  }
105
116
 
106
117
  {% block font_faces %}
@@ -178,7 +189,7 @@
178
189
  <body>
179
190
  {% block theme_toggle %}
180
191
  {% if show_theme_toggle %}
181
- <button class="theme-toggle" aria-label="toggle dark mode">
192
+ <button class="button fixed-button theme-toggle" aria-label="toggle dark mode">
182
193
  <i data-feather="moon"></i>
183
194
  </button>
184
195
  {% endif %}
@@ -197,11 +208,20 @@
197
208
  document.addEventListener('DOMContentLoaded', () => {
198
209
  // Add copy buttons to code blocks
199
210
  document.querySelectorAll('pre').forEach(pre => {
200
- // Skip if already has a copy button
201
- if (pre.querySelector('.code-copy-button')) {
211
+ // Skip if already has a copy button (check parent for wrapper)
212
+ if (pre.parentElement.classList.contains('code-block-wrapper')) {
202
213
  return;
203
214
  }
204
215
 
216
+ // Create wrapper div
217
+ const wrapper = document.createElement('div');
218
+ wrapper.className = 'code-block-wrapper';
219
+
220
+ // Insert wrapper before pre and move pre inside it
221
+ pre.parentNode.insertBefore(wrapper, pre);
222
+ wrapper.appendChild(pre);
223
+
224
+ // Create copy button
205
225
  const copyButton = document.createElement('button');
206
226
  copyButton.className = 'code-copy-button';
207
227
  copyButton.setAttribute('aria-label', 'Copy code');
@@ -229,7 +249,8 @@
229
249
  });
230
250
  });
231
251
 
232
- pre.appendChild(copyButton);
252
+ // Add button to wrapper, not to pre
253
+ wrapper.appendChild(copyButton);
233
254
  });
234
255
 
235
256
  // Theme toggle (if present on page)
@@ -307,8 +328,9 @@
307
328
  }
308
329
  });
309
330
 
310
- {% block scripts_extra %}{% endblock scripts_extra %}
331
+
311
332
  </script>
333
+ {% block scripts_extra %}{% endblock scripts_extra %}
312
334
  {% endblock scripts %}
313
335
 
314
336
  {% block analytics %}{% endblock analytics %}