python-codex 0.2.4__py3-none-any.whl → 0.2.6__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.
@@ -4,25 +4,37 @@
4
4
  <meta charset="utf-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1">
6
6
  <title>__WORKSPACE_TITLE__</title>
7
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.22/dist/katex.min.css">
7
8
  <style>
8
9
  :root {
9
10
  color-scheme: light;
10
- --bg: #f2f6f3;
11
- --panel: #ffffff;
12
- --ink: #1e2529;
13
- --muted: #5f6f75;
14
- --line: #d2ddd5;
15
- --accent: #0f8f55;
11
+ --bg: #eef3f6;
12
+ --panel: #f8fbfd;
13
+ --panel-deep: #f2f6f8;
14
+ --panel-raised: #ffffff;
15
+ --panel-hover: #e8f1f5;
16
+ --board-chrome: #ffffff;
17
+ --ink: #172630;
18
+ --muted: #60727d;
19
+ --line: #cbd8df;
20
+ --line-strong: #aebfc9;
21
+ --accent: #087f9a;
16
22
  --accent-ink: #ffffff;
17
- --warn-soft: #fff5cf;
18
- --info: #1f6fa4;
19
- --info-soft: #edf8ff;
20
- --danger: #b23a3a;
21
- --danger-soft: #fff1ef;
22
- --violet: #6b4fb0;
23
- --violet-soft: #f5f0ff;
24
- --code: #f3f7f8;
25
- --entry-shadow: 0 1px 2px rgba(25, 35, 31, 0.04);
23
+ --accent-soft: #e6f6f8;
24
+ --warn: #b77908;
25
+ --warn-ink: #62480c;
26
+ --warn-soft: #fff7df;
27
+ --info: #2868b2;
28
+ --info-soft: #edf5ff;
29
+ --success: #247a52;
30
+ --success-line: #8bc9a8;
31
+ --success-soft: #edf9f2;
32
+ --danger: #b33d50;
33
+ --danger-soft: #fff0f2;
34
+ --violet: #6850a4;
35
+ --violet-soft: #f4f0ff;
36
+ --code: #f1f5f7;
37
+ --entry-shadow: 0 1px 2px rgba(27, 57, 72, 0.06);
26
38
  --space-1: 2px;
27
39
  --space-2: 4px;
28
40
  --space-3: 6px;
@@ -51,14 +63,14 @@
51
63
  min-width: 0;
52
64
  }
53
65
  .workspace.collapsed .splitter::after {
54
- background: #4f6f60;
66
+ background: var(--accent);
55
67
  }
56
68
  .board-pane {
57
69
  min-width: 0;
58
70
  height: 100dvh;
59
71
  display: grid;
60
72
  grid-template-rows: auto minmax(0, 1fr);
61
- background: #fff;
73
+ background: var(--board-chrome);
62
74
  }
63
75
  .boardbar {
64
76
  min-width: 0;
@@ -100,10 +112,10 @@
100
112
  text-decoration: none;
101
113
  }
102
114
  .workspace-back:hover {
103
- background: #eef7f1;
115
+ background: var(--accent-soft);
104
116
  }
105
117
  .workspace-back:focus {
106
- outline: 2px solid #9bb7a6;
118
+ outline: 2px solid var(--accent);
107
119
  outline-offset: 1px;
108
120
  }
109
121
  .workspace-back::before {
@@ -119,16 +131,16 @@
119
131
  min-width: 0;
120
132
  width: 100%;
121
133
  height: 100%;
122
- background: #fff;
134
+ background: var(--board-chrome);
123
135
  }
124
136
  .splitter {
125
137
  position: relative;
126
138
  width: 8px;
127
139
  height: 100dvh;
128
140
  border: 0;
129
- border-left: 1px solid #c1cec6;
130
- border-right: 1px solid #c1cec6;
131
- background: #dfe8e2;
141
+ border-left: 1px solid var(--line);
142
+ border-right: 1px solid var(--line);
143
+ background: var(--panel-hover);
132
144
  cursor: col-resize;
133
145
  padding: 0;
134
146
  touch-action: none;
@@ -141,17 +153,17 @@
141
153
  width: 3px;
142
154
  height: 42px;
143
155
  border-radius: 999px;
144
- background: #7d9588;
156
+ background: var(--muted);
145
157
  transform: translate(-50%, -50%);
146
158
  }
147
159
  .splitter:hover,
148
160
  .workspace.resizing .splitter {
149
- background: #d3dfd7;
150
- border-color: #aebeb4;
161
+ background: #dce9ee;
162
+ border-color: var(--line-strong);
151
163
  }
152
164
  .splitter:hover::after,
153
165
  .workspace.resizing .splitter::after {
154
- background: #527465;
166
+ background: var(--accent);
155
167
  }
156
168
  .workspace.resizing,
157
169
  .workspace.resizing * {
@@ -189,8 +201,8 @@
189
201
  width: var(--context-meter-size);
190
202
  height: var(--context-meter-size);
191
203
  border-radius: 999px;
192
- background: conic-gradient(#4ca56f 0 var(--context-remaining), #cfd8d2 0 100%);
193
- color: #335243;
204
+ background: conic-gradient(var(--accent) 0 var(--context-remaining), var(--line-strong) 0 100%);
205
+ color: var(--muted);
194
206
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
195
207
  font-size: 9px;
196
208
  line-height: 1;
@@ -204,7 +216,7 @@
204
216
  position: absolute;
205
217
  inset: 4px;
206
218
  border-radius: 999px;
207
- background: #fff;
219
+ background: var(--panel);
208
220
  }
209
221
  .context-meter-value {
210
222
  position: relative;
@@ -226,9 +238,9 @@
226
238
  min-width: 88px;
227
239
  max-width: 180px;
228
240
  height: 31px;
229
- border: 1px solid #d5ddd7;
241
+ border: 1px solid var(--line);
230
242
  border-radius: var(--radius-sm);
231
- background: #f6f8f7;
243
+ background: var(--panel-raised);
232
244
  color: var(--ink);
233
245
  padding: 0 var(--space-3) 0 var(--space-4);
234
246
  font: inherit;
@@ -237,12 +249,12 @@
237
249
  }
238
250
  .tab:focus-within,
239
251
  .tab-new:focus {
240
- outline: 2px solid #9bb7a6;
252
+ outline: 2px solid var(--accent);
241
253
  outline-offset: 1px;
242
254
  }
243
255
  .tab.active {
244
- border-color: #afd6bd;
245
- background: #eef7f1;
256
+ border-color: var(--accent);
257
+ background: var(--accent-soft);
246
258
  box-shadow: inset 0 -2px 0 var(--accent);
247
259
  }
248
260
  .tab-status {
@@ -280,7 +292,7 @@
280
292
  height: 31px;
281
293
  border: 1px solid var(--line);
282
294
  border-radius: var(--radius-md);
283
- background: #eef7f1;
295
+ background: var(--panel-raised);
284
296
  color: var(--muted);
285
297
  padding: 0;
286
298
  line-height: 1;
@@ -314,7 +326,7 @@
314
326
  .tab-close:hover,
315
327
  .tab-new:hover {
316
328
  color: var(--ink);
317
- background: #ffffff;
329
+ background: var(--panel-hover);
318
330
  }
319
331
  .log {
320
332
  min-height: 0;
@@ -324,45 +336,45 @@
324
336
  display: flex;
325
337
  flex-direction: column;
326
338
  gap: var(--space-4);
327
- background: #fbfcfa;
339
+ background: var(--bg);
328
340
  }
329
341
  .entry {
330
342
  min-width: 0;
331
343
  border: 1px solid var(--line);
332
344
  border-radius: var(--radius-sm);
333
345
  padding: var(--space-4) var(--space-5);
334
- background: #fff;
346
+ background: var(--panel-raised);
335
347
  box-shadow: var(--entry-shadow);
336
348
  }
337
349
  .entry.user {
338
- border-color: #edd17a;
350
+ border-color: var(--warn);
339
351
  background: var(--warn-soft);
340
- color: #5a4714;
352
+ color: var(--warn-ink);
341
353
  }
342
354
  .entry.response,
343
355
  .entry.assistant {
344
- border-color: #d0ddd5;
345
- background: #ffffff;
356
+ border-color: var(--line);
357
+ background: var(--panel-raised);
346
358
  }
347
359
  .entry.thinking {
348
- border-color: #b9dcc5;
349
- background: #f0fbf3;
350
- color: #256b43;
360
+ border-color: var(--success-line);
361
+ background: var(--success-soft);
362
+ color: var(--success);
351
363
  animation: thinking-breathe 4.8s ease-in-out infinite;
352
364
  }
353
365
  .entry.control {
354
- border-color: #b9d8ea;
366
+ border-color: #b7d3ee;
355
367
  background: var(--info-soft);
356
368
  color: var(--info);
357
369
  }
358
370
  .entry.tool {
359
- border-color: #d7c8f0;
371
+ border-color: #d8cdf1;
360
372
  background: var(--violet-soft);
361
373
  color: var(--violet);
362
374
  font-size: 12px;
363
375
  }
364
376
  .entry.error {
365
- border-color: #efb4ad;
377
+ border-color: #efb8c1;
366
378
  background: var(--danger-soft);
367
379
  color: var(--danger);
368
380
  }
@@ -421,16 +433,35 @@
421
433
  vertical-align: top;
422
434
  }
423
435
  .markdown th {
424
- background: #eef7f1;
436
+ background: var(--accent-soft);
425
437
  font-weight: 650;
426
438
  }
427
439
  .markdown a {
428
- color: #176fa8;
440
+ color: var(--info);
429
441
  text-decoration: none;
430
442
  }
431
443
  .markdown a:hover {
432
444
  text-decoration: underline;
433
445
  }
446
+ .markdown .katex-display {
447
+ margin: 0 0 var(--space-4);
448
+ overflow-x: auto;
449
+ overflow-y: hidden;
450
+ overflow-wrap: normal;
451
+ word-break: normal;
452
+ }
453
+ .markdown .katex {
454
+ overflow-wrap: normal;
455
+ word-break: normal;
456
+ }
457
+ .markdown .katex .text {
458
+ white-space: normal;
459
+ overflow-wrap: normal;
460
+ word-break: normal;
461
+ }
462
+ .markdown .katex-display:last-child {
463
+ margin-bottom: 0;
464
+ }
434
465
  .composer {
435
466
  position: relative;
436
467
  min-width: 0;
@@ -438,7 +469,7 @@
438
469
  display: grid;
439
470
  gap: var(--space-3);
440
471
  align-content: end;
441
- background: #fff;
472
+ background: var(--panel);
442
473
  }
443
474
  textarea {
444
475
  min-width: 0;
@@ -448,15 +479,15 @@
448
479
  border: 1px solid var(--line);
449
480
  border-radius: var(--radius-sm);
450
481
  padding: var(--space-4) var(--space-5);
451
- background: #ffffff;
482
+ background: var(--panel-deep);
452
483
  color: var(--ink);
453
484
  font: inherit;
454
485
  line-height: 1.4;
455
486
  overflow-y: auto;
456
487
  }
457
488
  textarea:focus {
458
- border-color: #65b782;
459
- box-shadow: 0 0 0 3px rgba(15, 143, 85, 0.13);
489
+ border-color: var(--accent);
490
+ box-shadow: 0 0 0 3px rgba(8, 127, 154, 0.18);
460
491
  outline: 0;
461
492
  }
462
493
  .actions {
@@ -492,8 +523,8 @@
492
523
  text-overflow: ellipsis;
493
524
  padding: var(--space-1) var(--space-4) var(--space-1) 18px;
494
525
  border-radius: 999px;
495
- background: rgba(240, 250, 244, 0.96);
496
- border: 1px solid rgba(172, 216, 188, 0.9);
526
+ background: rgba(230, 246, 248, 0.96);
527
+ border: 1px solid rgba(8, 127, 154, 0.35);
497
528
  font: inherit;
498
529
  font-size: 12px;
499
530
  cursor: pointer;
@@ -505,8 +536,8 @@
505
536
  display: none;
506
537
  }
507
538
  .spinner:focus-visible {
508
- border-color: #65b782;
509
- box-shadow: 0 0 0 3px rgba(15, 143, 85, 0.13);
539
+ border-color: var(--accent);
540
+ box-shadow: 0 0 0 3px rgba(8, 127, 154, 0.18);
510
541
  outline: 0;
511
542
  }
512
543
  .spinner-wrap:has(.spinner:not(:empty)) {
@@ -525,12 +556,12 @@
525
556
  animation: spinner-pulse 1.2s cubic-bezier(0.4, 0, 0.2, 1) infinite;
526
557
  }
527
558
  .spinner.notify-enabled {
528
- color: #0b6b43;
529
- background: #e6f4eb;
530
- border-color: #4ca56f;
559
+ color: var(--success);
560
+ background: var(--success-soft);
561
+ border-color: var(--success-line);
531
562
  box-shadow:
532
- inset 0 1px 2px rgba(9, 93, 55, 0.16),
533
- inset 0 0 0 1px rgba(15, 143, 85, 0.1);
563
+ inset 0 1px 2px rgba(27, 57, 72, 0.08),
564
+ inset 0 0 0 1px rgba(36, 122, 82, 0.1);
534
565
  }
535
566
  .toast {
536
567
  position: absolute;
@@ -539,11 +570,11 @@
539
570
  z-index: 5;
540
571
  width: max-content;
541
572
  max-width: min(320px, calc(100vw - var(--space-6) * 2));
542
- border: 1px solid #bfd6c8;
573
+ border: 1px solid var(--line-strong);
543
574
  border-radius: var(--radius-sm);
544
- background: #f6fbf8;
575
+ background: var(--panel-raised);
545
576
  color: var(--ink);
546
- box-shadow: 0 8px 20px rgba(25, 35, 31, 0.12);
577
+ box-shadow: 0 8px 20px rgba(27, 57, 72, 0.14);
547
578
  padding: var(--space-4) var(--space-6);
548
579
  font-size: 12px;
549
580
  opacity: 0;
@@ -568,14 +599,14 @@
568
599
  }
569
600
  @keyframes thinking-breathe {
570
601
  0%, 100% {
571
- border-color: #b9dcc5;
602
+ border-color: var(--success-line);
572
603
  box-shadow: var(--entry-shadow);
573
604
  }
574
605
  50% {
575
- border-color: #72d494;
606
+ border-color: var(--success);
576
607
  box-shadow:
577
- 0 0 0 2px rgba(22, 168, 90, 0.16),
578
- 0 2px 7px rgba(25, 35, 31, 0.08);
608
+ 0 0 0 2px rgba(36, 122, 82, 0.14),
609
+ 0 2px 7px rgba(27, 57, 72, 0.08);
579
610
  }
580
611
  }
581
612
  @media (prefers-reduced-motion: reduce) {
@@ -641,6 +672,8 @@
641
672
  </div>
642
673
  <script src="https://cdn.jsdelivr.net/npm/markdown-it@14.1.0/dist/markdown-it.min.js"></script>
643
674
  <script src="https://cdn.jsdelivr.net/npm/dompurify@3.2.6/dist/purify.min.js"></script>
675
+ <script src="https://cdn.jsdelivr.net/npm/katex@0.16.22/dist/katex.min.js"></script>
676
+ <script src="https://cdn.jsdelivr.net/npm/katex@0.16.22/dist/contrib/auto-render.min.js"></script>
644
677
  <script>
645
678
  const log = document.getElementById("log");
646
679
  const spinner = document.getElementById("spinner");
@@ -672,6 +705,14 @@
672
705
  const markdownRenderer = window.markdownit
673
706
  ? window.markdownit({html: false, linkify: true, breaks: false})
674
707
  : null;
708
+ const mathDelimiters = [
709
+ {left: "$$", right: "$$", display: true},
710
+ {left: "\\[", right: "\\]", display: true},
711
+ {left: "\\(", right: "\\)", display: false},
712
+ {left: "$", right: "$", display: false},
713
+ ];
714
+ const mathTokenPrefix = "\uE000math";
715
+ const mathTokenSuffix = "\uE001";
675
716
 
676
717
  function relativeUrl(path) {
677
718
  return new URL(path, window.location.href).toString();
@@ -708,17 +749,213 @@
708
749
  root.textContent = source || "";
709
750
  return;
710
751
  }
711
- const dirtyHtml = markdownRenderer.render(String(source || ""));
752
+ const protectedMath = protectMath(String(source || ""));
753
+ const dirtyHtml = markdownRenderer.render(protectedMath.source);
712
754
  root.innerHTML = window.DOMPurify.sanitize(dirtyHtml, {
713
755
  USE_PROFILES: {html: true},
714
756
  ADD_ATTR: ["target", "rel"],
715
757
  });
758
+ renderProtectedMath(root, protectedMath.expressions);
716
759
  root.querySelectorAll("a").forEach((anchor) => {
717
760
  anchor.target = "_blank";
718
761
  anchor.rel = "noopener noreferrer";
719
762
  });
720
763
  }
721
764
 
765
+ function isEscapedAt(source, index) {
766
+ let slashCount = 0;
767
+ for (let cursor = index - 1; cursor >= 0 && source[cursor] === "\\"; cursor -= 1) {
768
+ slashCount += 1;
769
+ }
770
+ return slashCount % 2 === 1;
771
+ }
772
+
773
+ function countBackticks(source, index) {
774
+ let count = 0;
775
+ while (source[index + count] === "`") {
776
+ count += 1;
777
+ }
778
+ return count;
779
+ }
780
+
781
+ function findMathEnd(source, start, delimiter) {
782
+ let searchFrom = start + delimiter.left.length;
783
+ while (searchFrom < source.length) {
784
+ const end = source.indexOf(delimiter.right, searchFrom);
785
+ if (end < 0) {
786
+ return -1;
787
+ }
788
+ if (!isEscapedAt(source, end)) {
789
+ if (
790
+ delimiter.left === "$" &&
791
+ (source[end - 1] === "$" || source[end + 1] === "$")
792
+ ) {
793
+ searchFrom = end + delimiter.right.length;
794
+ continue;
795
+ }
796
+ return end;
797
+ }
798
+ searchFrom = end + delimiter.right.length;
799
+ }
800
+ return -1;
801
+ }
802
+
803
+ function protectMath(source) {
804
+ const expressions = [];
805
+ let protectedSource = "";
806
+ let index = 0;
807
+ while (index < source.length) {
808
+ if (source[index] === "`") {
809
+ const tickCount = countBackticks(source, index);
810
+ const fence = "`".repeat(tickCount);
811
+ const close = source.indexOf(fence, index + tickCount);
812
+ if (close >= 0) {
813
+ const end = close + tickCount;
814
+ protectedSource += source.slice(index, end);
815
+ index = end;
816
+ continue;
817
+ }
818
+ }
819
+
820
+ let matched = null;
821
+ if (!isEscapedAt(source, index)) {
822
+ for (const delimiter of mathDelimiters) {
823
+ if (
824
+ source.indexOf(delimiter.left, index) !== index ||
825
+ (delimiter.left === "$" && source[index + 1] === "$")
826
+ ) {
827
+ continue;
828
+ }
829
+ const end = findMathEnd(source, index, delimiter);
830
+ if (end > index + delimiter.left.length) {
831
+ matched = {
832
+ delimiter: delimiter,
833
+ start: index,
834
+ end: end,
835
+ };
836
+ break;
837
+ }
838
+ }
839
+ }
840
+
841
+ if (matched) {
842
+ const expressionIndex = expressions.length;
843
+ expressions.push({
844
+ body: source.slice(
845
+ matched.start + matched.delimiter.left.length,
846
+ matched.end,
847
+ ),
848
+ delimiter: matched.delimiter,
849
+ });
850
+ protectedSource += mathTokenPrefix + expressionIndex + mathTokenSuffix;
851
+ index = matched.end + matched.delimiter.right.length;
852
+ continue;
853
+ }
854
+
855
+ protectedSource += source[index];
856
+ index += 1;
857
+ }
858
+ return {
859
+ source: protectedSource,
860
+ expressions: expressions,
861
+ };
862
+ }
863
+
864
+ function renderProtectedMath(root, expressions) {
865
+ if (!expressions.length) {
866
+ return;
867
+ }
868
+ const expressionByToken = new Map();
869
+ expressions.forEach((expression, index) => {
870
+ expressionByToken.set(
871
+ mathTokenPrefix + index + mathTokenSuffix,
872
+ expression,
873
+ );
874
+ });
875
+ const textWalker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);
876
+ const textNodes = [];
877
+ let textNode = textWalker.nextNode();
878
+ while (textNode) {
879
+ textNodes.push(textNode);
880
+ textNode = textWalker.nextNode();
881
+ }
882
+ for (const textNode of textNodes) {
883
+ let value = textNode.nodeValue || "";
884
+ let cursor = 0;
885
+ let tokenIndex = value.indexOf(mathTokenPrefix, cursor);
886
+ if (tokenIndex < 0) {
887
+ continue;
888
+ }
889
+ const fragment = document.createDocumentFragment();
890
+ while (tokenIndex >= 0) {
891
+ const tokenEnd = value.indexOf(mathTokenSuffix, tokenIndex);
892
+ if (tokenEnd < 0) {
893
+ break;
894
+ }
895
+ const token = value.slice(tokenIndex, tokenEnd + mathTokenSuffix.length);
896
+ const expression = expressionByToken.get(token);
897
+ if (!expression) {
898
+ break;
899
+ }
900
+ if (tokenIndex > cursor) {
901
+ fragment.appendChild(
902
+ document.createTextNode(value.slice(cursor, tokenIndex)),
903
+ );
904
+ }
905
+ const mathNode = document.createElement("span");
906
+ const sourceText =
907
+ expression.delimiter.left +
908
+ expression.body +
909
+ expression.delimiter.right;
910
+ if (window.renderMathInElement) {
911
+ mathNode.textContent = sourceText;
912
+ window.renderMathInElement(mathNode, {
913
+ delimiters: [
914
+ {
915
+ left: expression.delimiter.left,
916
+ right: expression.delimiter.right,
917
+ display: expression.delimiter.display,
918
+ },
919
+ ],
920
+ throwOnError: false,
921
+ trust: false,
922
+ });
923
+ } else {
924
+ mathNode.textContent = expression.body;
925
+ }
926
+ fragment.appendChild(mathNode);
927
+ cursor = tokenEnd + mathTokenSuffix.length;
928
+ tokenIndex = value.indexOf(mathTokenPrefix, cursor);
929
+ }
930
+ if (cursor > 0) {
931
+ if (cursor < value.length) {
932
+ fragment.appendChild(document.createTextNode(value.slice(cursor)));
933
+ }
934
+ if (textNode.parentNode) {
935
+ textNode.parentNode.replaceChild(fragment, textNode);
936
+ }
937
+ }
938
+ }
939
+ restoreUnrenderedMathTokens(root, expressionByToken);
940
+ }
941
+
942
+ function restoreUnrenderedMathTokens(root, expressionByToken) {
943
+ const textWalker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);
944
+ let textNode = textWalker.nextNode();
945
+ while (textNode) {
946
+ let value = textNode.nodeValue || "";
947
+ expressionByToken.forEach((expression, token) => {
948
+ const sourceText =
949
+ expression.delimiter.left +
950
+ expression.body +
951
+ expression.delimiter.right;
952
+ value = value.split(token).join(sourceText);
953
+ });
954
+ textNode.nodeValue = value;
955
+ textNode = textWalker.nextNode();
956
+ }
957
+ }
958
+
722
959
  function loadChatWidth() {
723
960
  const stored = Number(window.localStorage.getItem("pycodex.workspace.chatWidth") || 0);
724
961
  if (stored > 0) setChatWidth(stored);