free-coding-models 0.5.28 → 0.5.30

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 (64) hide show
  1. package/README.md +1 -1
  2. package/bin/free-coding-models.js +10 -2
  3. package/changelog/v0.5.29.md +19 -0
  4. package/changelog/v0.5.30.md +15 -0
  5. package/package.json +1 -1
  6. package/sources.js +3 -2
  7. package/src/core/config.js +1 -14
  8. package/src/core/endpoint-installer.js +5 -9
  9. package/src/core/legacy-proxy-cleanup.js +2 -0
  10. package/src/core/model-merger.js +4 -13
  11. package/src/core/playground.js +6 -4
  12. package/src/core/router-daemon.js +101 -43
  13. package/src/core/router-dashboard.js +63 -25
  14. package/src/core/shared-helpers.js +117 -0
  15. package/src/core/sync-set.js +11 -24
  16. package/src/core/tool-launchers.js +24 -92
  17. package/src/core/utils.js +26 -100
  18. package/src/tui/app.js +2 -2
  19. package/src/tui/command-palette.js +1 -0
  20. package/src/tui/key-handler.js +77 -20
  21. package/src/tui/render-table.js +3 -3
  22. package/web/dist/assets/index-CsFt3qt5.css +1 -0
  23. package/web/dist/assets/index-I6N91rH7.js +40 -0
  24. package/web/dist/favicon.ico +0 -0
  25. package/web/dist/favicons/apple-touch-icon.png +0 -0
  26. package/web/dist/favicons/favicon-16x16.png +0 -0
  27. package/web/dist/favicons/favicon-192x192.png +0 -0
  28. package/web/dist/favicons/favicon-32x32.png +0 -0
  29. package/web/dist/favicons/favicon-48x48.png +0 -0
  30. package/web/dist/favicons/favicon-512x512.png +0 -0
  31. package/web/dist/favicons/favicon-96x96.png +0 -0
  32. package/web/dist/favicons/favicon.ico +0 -0
  33. package/web/dist/favicons/mstile-150x150.png +0 -0
  34. package/web/dist/favicons/mstile-310x150.png +0 -0
  35. package/web/dist/favicons/mstile-310x310.png +0 -0
  36. package/web/dist/favicons/mstile-512x512.png +0 -0
  37. package/web/dist/favicons/mstile-70x70.png +0 -0
  38. package/web/dist/index.html +2 -2
  39. package/web/public/favicon.ico +0 -0
  40. package/web/public/favicons/apple-touch-icon.png +0 -0
  41. package/web/public/favicons/favicon-16x16.png +0 -0
  42. package/web/public/favicons/favicon-192x192.png +0 -0
  43. package/web/public/favicons/favicon-32x32.png +0 -0
  44. package/web/public/favicons/favicon-48x48.png +0 -0
  45. package/web/public/favicons/favicon-512x512.png +0 -0
  46. package/web/public/favicons/favicon-96x96.png +0 -0
  47. package/web/public/favicons/favicon.ico +0 -0
  48. package/web/public/favicons/mstile-150x150.png +0 -0
  49. package/web/public/favicons/mstile-310x150.png +0 -0
  50. package/web/public/favicons/mstile-310x310.png +0 -0
  51. package/web/public/favicons/mstile-512x512.png +0 -0
  52. package/web/public/favicons/mstile-70x70.png +0 -0
  53. package/web/server.js +34 -4
  54. package/web/src/components/dashboard/ExpandedDetailRow.jsx +10 -113
  55. package/web/src/components/dashboard/ExpandedDetailRow.module.css +9 -0
  56. package/web/src/components/playground/PlaygroundChat.jsx +527 -0
  57. package/web/src/components/playground/PlaygroundChat.module.css +382 -0
  58. package/web/src/components/playground/PlaygroundView.jsx +104 -442
  59. package/web/src/components/playground/PlaygroundView.module.css +10 -0
  60. package/web/src/components/router/RouterView.jsx +268 -56
  61. package/web/src/components/router/RouterView.module.css +416 -1
  62. package/src/core/product-flags.js +0 -9
  63. package/web/dist/assets/index-BRFowJv5.css +0 -1
  64. package/web/dist/assets/index-Pr3waI0-.js +0 -41
@@ -140,6 +140,13 @@
140
140
  &:disabled { opacity: 0.5; cursor: not-allowed; }
141
141
  }
142
142
 
143
+ /* 📖 Bigger start button for the stopped state — more prominent CTA. */
144
+ .startBtnBig {
145
+ padding: 10px 24px;
146
+ font-size: 15px;
147
+ border-radius: 10px;
148
+ }
149
+
143
150
  .stopBtn {
144
151
  display: flex;
145
152
  align-items: center;
@@ -175,6 +182,33 @@
175
182
  margin-bottom: 16px;
176
183
  }
177
184
 
185
+ /* 📖 Hero glow when running — makes the quick setup card visually prominent. */
186
+ .quickSetupHero {
187
+ border: 1px solid rgba(0, 200, 100, 0.25);
188
+ box-shadow: 0 0 16px rgba(0, 200, 100, 0.08);
189
+ border-radius: 10px;
190
+ padding: 12px;
191
+ background: linear-gradient(135deg, rgba(0, 200, 100, 0.05), transparent);
192
+ }
193
+
194
+ /* 📖 "Copy all" button — sits at the right of the Quick Setup title. */
195
+ .copyAllBtn {
196
+ display: inline-flex;
197
+ align-items: center;
198
+ gap: 4px;
199
+ margin-left: auto;
200
+ padding: 3px 10px;
201
+ background: var(--bg-secondary, #14141f);
202
+ border: 1px solid var(--border, #1e1e2e);
203
+ border-radius: 6px;
204
+ color: var(--text-secondary, #aaa);
205
+ font-size: 11px;
206
+ font-weight: 500;
207
+ cursor: pointer;
208
+ font-family: inherit;
209
+ &:hover { color: var(--text-primary, #e0e0e0); border-color: var(--accent, #00c864); }
210
+ }
211
+
178
212
  .sectionTitle {
179
213
  display: flex;
180
214
  align-items: center;
@@ -351,6 +385,16 @@
351
385
  text-transform: uppercase;
352
386
  }
353
387
 
388
+ .logEmpty {
389
+ padding: 16px;
390
+ text-align: center;
391
+ color: var(--text-muted, #888);
392
+ font-size: 12px;
393
+ background: var(--bg-secondary, #14141f);
394
+ border: 1px dashed var(--border, #1e1e2e);
395
+ border-radius: 8px;
396
+ }
397
+
354
398
  @keyframes fadeIn {
355
399
  from { opacity: 0; }
356
400
  to { opacity: 1; }
@@ -421,7 +465,7 @@
421
465
  }
422
466
 
423
467
  .setEmpty {
424
- padding: 16px;
468
+ padding: 20px 16px;
425
469
  text-align: center;
426
470
  color: var(--text-muted, #888);
427
471
  font-size: 12px;
@@ -430,6 +474,23 @@
430
474
  border-radius: 8px;
431
475
  }
432
476
 
477
+ .setEmptyTitle {
478
+ font-size: 13px;
479
+ font-weight: 600;
480
+ color: var(--text-secondary, #aaa);
481
+ margin-bottom: 4px;
482
+ }
483
+
484
+ .setEmptyHint {
485
+ font-size: 11px;
486
+ color: var(--text-muted, #888);
487
+ line-height: 1.5;
488
+ }
489
+
490
+ .setEmptyHint strong {
491
+ color: var(--text-secondary, #aaa);
492
+ }
493
+
433
494
  .setRow {
434
495
  display: flex;
435
496
  align-items: center;
@@ -510,6 +571,79 @@
510
571
  text-transform: uppercase;
511
572
  }
512
573
 
574
+ /* 📖 Priority badge variants — make the fallback chain semantics explicit
575
+ (issue #120). Primary gets the accent color so users instantly see which
576
+ model serves every request; fallbacks stay muted. */
577
+ .setPriorityPrimary {
578
+ min-width: 52px;
579
+ padding: 2px 8px;
580
+ border-radius: 4px;
581
+ background: rgba(0, 200, 100, 0.14);
582
+ color: var(--accent, #00c864);
583
+ border: 1px solid rgba(0, 200, 100, 0.3);
584
+ text-transform: uppercase;
585
+ letter-spacing: 0.3px;
586
+ text-align: center;
587
+ }
588
+
589
+ .setPriorityFallback {
590
+ text-transform: none;
591
+ opacity: 0.85;
592
+ }
593
+
594
+ /* 📖 Next-to-serve row — subtle accent left border + tint so the user can
595
+ see at a glance which model will handle the next chat completion.
596
+ Only applied when the daemon is running and routingOrder is known. */
597
+ .setRowNext {
598
+ background: linear-gradient(90deg, rgba(0, 200, 100, 0.07), transparent 60%);
599
+ border-left: 2px solid var(--accent, #00c864);
600
+ padding-left: 8px;
601
+ }
602
+
603
+ /* 📖 Priority legend — one-line explainer above the set list. */
604
+ .priorityLegend {
605
+ display: flex;
606
+ align-items: center;
607
+ gap: 8px;
608
+ flex-wrap: wrap;
609
+ padding: 6px 10px;
610
+ margin-bottom: 8px;
611
+ font-size: 11px;
612
+ color: var(--text-muted, #888);
613
+ background: var(--bg-secondary, #14141f);
614
+ border: 1px solid var(--border, #1e1e2e);
615
+ border-radius: 6px;
616
+ }
617
+
618
+ .legendPrimary {
619
+ display: inline-flex;
620
+ align-items: center;
621
+ gap: 3px;
622
+ font-weight: 600;
623
+ color: var(--accent, #00c864);
624
+ }
625
+
626
+ .legendFallback {
627
+ font-weight: 600;
628
+ color: var(--text-secondary, #aaa);
629
+ }
630
+
631
+ .legendSeparator {
632
+ color: var(--text-muted, #888);
633
+ opacity: 0.7;
634
+ }
635
+
636
+ .legendNext {
637
+ margin-left: auto;
638
+ color: var(--text-secondary, #aaa);
639
+ }
640
+
641
+ .legendNext code {
642
+ color: var(--accent, #00c864);
643
+ font-family: 'SF Mono', monospace;
644
+ font-size: 10px;
645
+ }
646
+
513
647
  .setRowBtns {
514
648
  display: flex;
515
649
  gap: 2px;
@@ -710,3 +844,284 @@
710
844
  flex-shrink: 0;
711
845
  }
712
846
 
847
+ /* ════════════════════════════════════════════════════════════════════════
848
+ 📖 Probe-all button + progress bar (AI Latency benchmarks on the set).
849
+ ════════════════════════════════════════════════════════════════════════ */
850
+
851
+ /* 📖 Active state for the Probe button while benchmarks run. */
852
+ .probeBtnActive {
853
+ border-color: var(--accent, #00c864);
854
+ color: var(--accent, #00c864);
855
+ cursor: progress;
856
+ }
857
+
858
+ /* 📖 Progress card shown below the set actions while probing. */
859
+ .probeProgress {
860
+ display: flex;
861
+ flex-direction: column;
862
+ gap: 6px;
863
+ padding: 8px 10px;
864
+ margin-bottom: 8px;
865
+ background: var(--bg-secondary, #14141f);
866
+ border: 1px solid rgba(0, 200, 100, 0.2);
867
+ border-radius: 6px;
868
+ }
869
+
870
+ .probeProgressLabel {
871
+ display: flex;
872
+ align-items: center;
873
+ gap: 5px;
874
+ font-size: 11px;
875
+ color: var(--accent, #00c864);
876
+ font-weight: 600;
877
+ }
878
+
879
+ .probeProgressCount {
880
+ margin-left: auto;
881
+ color: var(--text-secondary, #aaa);
882
+ font-weight: 500;
883
+ font-family: 'SF Mono', monospace;
884
+ }
885
+
886
+ .probeProgressBar {
887
+ height: 4px;
888
+ background: var(--bg-primary, #0f0f17);
889
+ border-radius: 2px;
890
+ overflow: hidden;
891
+ }
892
+
893
+ .probeProgressFill {
894
+ height: 100%;
895
+ background: linear-gradient(90deg, var(--accent, #00c864), rgba(0, 200, 100, 0.6));
896
+ border-radius: 2px;
897
+ transition: width 0.4s ease;
898
+ }
899
+
900
+ /* ════════════════════════════════════════════════════════════════════════
901
+ 📖 AI Latency cell in each set row — populated by Probe all.
902
+ ════════════════════════════════════════════════════════════════════════ */
903
+
904
+ .aiLatencyCell {
905
+ display: inline-flex;
906
+ align-items: center;
907
+ gap: 4px;
908
+ min-width: 78px;
909
+ font-size: 10px;
910
+ font-family: 'SF Mono', monospace;
911
+ justify-content: flex-end;
912
+ }
913
+
914
+ .aiLatencyMs {
915
+ font-weight: 700;
916
+ color: #b400ff;
917
+ }
918
+
919
+ .aiLatencyTps {
920
+ color: var(--text-muted, #888);
921
+ font-size: 9px;
922
+ }
923
+
924
+ .aiLatencySpin {
925
+ color: var(--accent, #00c864);
926
+ letter-spacing: 2px;
927
+ animation: probeSpin 0.8s steps(3, end) infinite;
928
+ }
929
+
930
+ @keyframes probeSpin {
931
+ 0% { opacity: 0.3; }
932
+ 50% { opacity: 1; }
933
+ 100% { opacity: 0.3; }
934
+ }
935
+
936
+ .aiLatencyErr {
937
+ color: var(--error, #ff5a5a);
938
+ font-size: 10px;
939
+ }
940
+
941
+ .aiLatencyNone {
942
+ color: var(--text-muted, #888);
943
+ opacity: 0.4;
944
+ }
945
+
946
+ /* ════════════════════════════════════════════════════════════════════════
947
+ 📖 Mini Playground — live router test inside the Router view.
948
+ ════════════════════════════════════════════════════════════════════════ */
949
+
950
+ .miniPgHint {
951
+ margin-left: auto;
952
+ font-size: 10px;
953
+ font-weight: 400;
954
+ color: var(--text-muted, #888);
955
+ }
956
+
957
+ .miniPgHint code {
958
+ color: var(--accent, #00c864);
959
+ font-family: 'SF Mono', monospace;
960
+ }
961
+
962
+ .miniPg {
963
+ max-height: 220px;
964
+ overflow-y: auto;
965
+ padding: 8px;
966
+ margin-bottom: 8px;
967
+ background: var(--bg-primary, #0f0f17);
968
+ border: 1px solid var(--border, #1e1e2e);
969
+ border-radius: 8px;
970
+ display: flex;
971
+ flex-direction: column;
972
+ gap: 8px;
973
+ scroll-behavior: smooth;
974
+ }
975
+
976
+ .miniPgEmpty {
977
+ text-align: center;
978
+ color: var(--text-muted, #888);
979
+ font-size: 11px;
980
+ padding: 18px 8px;
981
+ }
982
+
983
+ .miniPgMsg {
984
+ display: flex;
985
+ flex-direction: column;
986
+ gap: 3px;
987
+ max-width: 88%;
988
+ }
989
+
990
+ .miniPgUser {
991
+ align-self: flex-end;
992
+ align-items: flex-end;
993
+ }
994
+
995
+ .miniPgAssistant {
996
+ align-self: flex-start;
997
+ align-items: flex-start;
998
+ }
999
+
1000
+ .miniPgBubble {
1001
+ padding: 7px 11px;
1002
+ border-radius: 12px;
1003
+ font-size: 12px;
1004
+ line-height: 1.5;
1005
+ white-space: pre-wrap;
1006
+ word-break: break-word;
1007
+ color: var(--text-primary, #e0e0e0);
1008
+ }
1009
+
1010
+ .miniPgUser .miniPgBubble {
1011
+ background: rgba(0, 200, 100, 0.12);
1012
+ border: 1px solid rgba(0, 200, 100, 0.2);
1013
+ border-bottom-right-radius: 4px;
1014
+ }
1015
+
1016
+ .miniPgAssistant .miniPgBubble {
1017
+ background: var(--bg-secondary, #14141f);
1018
+ border: 1px solid var(--border, #1e1e2e);
1019
+ border-bottom-left-radius: 4px;
1020
+ }
1021
+
1022
+ .miniPgTyping {
1023
+ color: var(--accent, #00c864);
1024
+ letter-spacing: 3px;
1025
+ animation: probeSpin 0.9s steps(3, end) infinite;
1026
+ }
1027
+
1028
+ .miniPgError {
1029
+ display: block;
1030
+ margin-top: 4px;
1031
+ color: var(--error, #ff5a5a);
1032
+ font-size: 11px;
1033
+ }
1034
+
1035
+ .miniPgAborted {
1036
+ display: block;
1037
+ margin-top: 4px;
1038
+ color: var(--text-muted, #888);
1039
+ font-size: 10px;
1040
+ font-style: italic;
1041
+ }
1042
+
1043
+ /* 📖 Target badge under each user bubble — shows the Primary model the
1044
+ router will try first for this message (priority-first routing, #120).
1045
+ If failover kicks in, the reply's .miniPgRouted badge shows a different
1046
+ model, making the fallback chain visible at a glance. */
1047
+ .miniPgTarget {
1048
+ font-size: 10px;
1049
+ color: var(--text-muted, #888);
1050
+ font-family: 'SF Mono', monospace;
1051
+ padding: 0 4px;
1052
+ display: inline-flex;
1053
+ align-items: center;
1054
+ gap: 3px;
1055
+ }
1056
+
1057
+ .miniPgTarget svg {
1058
+ color: var(--accent, #00c864);
1059
+ }
1060
+
1061
+ /* 📖 Routed-via badge under each assistant reply — shows WHICH model the
1062
+ priority-first router actually picked for this message (issue #120). */
1063
+ .miniPgRouted {
1064
+ font-size: 10px;
1065
+ color: var(--text-muted, #888);
1066
+ font-family: 'SF Mono', monospace;
1067
+ padding: 0 4px;
1068
+ }
1069
+
1070
+ .miniPgRouted span {
1071
+ color: var(--accent, #00c864);
1072
+ }
1073
+
1074
+ .miniPgInputRow {
1075
+ display: flex;
1076
+ gap: 6px;
1077
+ align-items: stretch;
1078
+ }
1079
+
1080
+ .miniPgInput {
1081
+ flex: 1;
1082
+ padding: 8px 12px;
1083
+ background: var(--bg-primary, #0f0f17);
1084
+ border: 1px solid var(--border, #1e1e2e);
1085
+ border-radius: 8px;
1086
+ color: var(--text-primary, #e0e0e0);
1087
+ font-size: 12px;
1088
+ font-family: inherit;
1089
+ outline: none;
1090
+ transition: border-color 0.15s;
1091
+ }
1092
+
1093
+ .miniPgInput:focus {
1094
+ border-color: var(--accent, #00c864);
1095
+ }
1096
+
1097
+ .miniPgInput::placeholder {
1098
+ color: var(--text-muted, #888);
1099
+ }
1100
+
1101
+ .miniPgSendBtn,
1102
+ .miniPgStopBtn {
1103
+ display: flex;
1104
+ align-items: center;
1105
+ justify-content: center;
1106
+ width: 38px;
1107
+ border: none;
1108
+ border-radius: 8px;
1109
+ cursor: pointer;
1110
+ transition: opacity 0.15s, background 0.15s;
1111
+ flex-shrink: 0;
1112
+ }
1113
+
1114
+ .miniPgSendBtn {
1115
+ background: var(--accent, #00c864);
1116
+ color: #000;
1117
+ }
1118
+
1119
+ .miniPgSendBtn:disabled {
1120
+ opacity: 0.4;
1121
+ cursor: not-allowed;
1122
+ }
1123
+
1124
+ .miniPgStopBtn {
1125
+ background: var(--error, #ff5a5a);
1126
+ color: #fff;
1127
+ }
@@ -1,9 +0,0 @@
1
- /**
2
- * @file src/product-flags.js
3
- * @description Product-level flags and feature gates.
4
- *
5
- * @details
6
- * 📖 Previously held PROXY_DISABLED_NOTICE for the proxy bridge rebuild.
7
- * 📖 That notice was removed in 0.3.22 after the proxy surface was fully
8
- * 📖 retired. File kept as a home for future product-level flags.
9
- */