lance-context 1.36.2 → 1.37.1
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.
- package/dist/config.d.ts +23 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +85 -0
- package/dist/config.js.map +1 -1
- package/dist/dashboard/routes.d.ts.map +1 -1
- package/dist/dashboard/routes.js +135 -2
- package/dist/dashboard/routes.js.map +1 -1
- package/dist/dashboard/ui.d.ts.map +1 -1
- package/dist/dashboard/ui.js +740 -250
- package/dist/dashboard/ui.js.map +1 -1
- package/package.json +1 -1
package/dist/dashboard/ui.js
CHANGED
|
@@ -220,26 +220,17 @@ export function getDashboardHTML() {
|
|
|
220
220
|
|
|
221
221
|
.grid {
|
|
222
222
|
display: grid;
|
|
223
|
-
grid-template-columns: repeat(
|
|
223
|
+
grid-template-columns: repeat(2, 1fr);
|
|
224
224
|
gap: 16px;
|
|
225
225
|
}
|
|
226
226
|
|
|
227
|
-
/* Tablet: 2 cards per row */
|
|
228
|
-
@media (max-width: 1024px) {
|
|
229
|
-
.grid {
|
|
230
|
-
grid-template-columns: repeat(2, 1fr);
|
|
231
|
-
}
|
|
232
|
-
.card.double-width {
|
|
233
|
-
grid-column: span 2;
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
|
|
237
227
|
/* Mobile: 1 card per row */
|
|
238
228
|
@media (max-width: 768px) {
|
|
239
229
|
.grid {
|
|
240
230
|
grid-template-columns: 1fr;
|
|
241
231
|
}
|
|
242
|
-
.card.double-width
|
|
232
|
+
.card.double-width,
|
|
233
|
+
.card.half-width {
|
|
243
234
|
grid-column: span 1;
|
|
244
235
|
}
|
|
245
236
|
}
|
|
@@ -563,6 +554,29 @@ export function getDashboardHTML() {
|
|
|
563
554
|
grid-column: span 2;
|
|
564
555
|
}
|
|
565
556
|
|
|
557
|
+
/* Half-width: takes 1 column (50% on 2-col grid) */
|
|
558
|
+
.card.half-width {
|
|
559
|
+
grid-column: span 1;
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
/* Compact card style */
|
|
563
|
+
.card.compact {
|
|
564
|
+
padding: 16px;
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
.card.compact .stat {
|
|
568
|
+
margin-bottom: 8px;
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
.card.compact .stat-value {
|
|
572
|
+
font-size: 20px;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
.card.compact .reindex-actions {
|
|
576
|
+
margin-top: 8px;
|
|
577
|
+
padding-top: 8px;
|
|
578
|
+
}
|
|
579
|
+
|
|
566
580
|
.empty-state {
|
|
567
581
|
text-align: center;
|
|
568
582
|
padding: 40px 20px;
|
|
@@ -783,16 +797,28 @@ export function getDashboardHTML() {
|
|
|
783
797
|
|
|
784
798
|
/* Beads Section Styles */
|
|
785
799
|
.beads-section {
|
|
786
|
-
|
|
787
|
-
padding-top: 24px;
|
|
788
|
-
border-top: 1px solid var(--border-color);
|
|
800
|
+
/* Now a standalone tab, no border needed */
|
|
789
801
|
}
|
|
790
802
|
|
|
791
803
|
.beads-header {
|
|
792
804
|
display: flex;
|
|
793
805
|
align-items: center;
|
|
806
|
+
justify-content: space-between;
|
|
794
807
|
gap: 12px;
|
|
795
808
|
margin-bottom: 16px;
|
|
809
|
+
flex-wrap: wrap;
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
.beads-header-left {
|
|
813
|
+
display: flex;
|
|
814
|
+
align-items: center;
|
|
815
|
+
gap: 12px;
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
.beads-header-right {
|
|
819
|
+
display: flex;
|
|
820
|
+
align-items: center;
|
|
821
|
+
gap: 24px;
|
|
796
822
|
}
|
|
797
823
|
|
|
798
824
|
.beads-logo {
|
|
@@ -816,7 +842,6 @@ export function getDashboardHTML() {
|
|
|
816
842
|
.beads-stats {
|
|
817
843
|
display: flex;
|
|
818
844
|
gap: 24px;
|
|
819
|
-
margin-bottom: 16px;
|
|
820
845
|
}
|
|
821
846
|
|
|
822
847
|
.beads-stat {
|
|
@@ -909,7 +934,6 @@ export function getDashboardHTML() {
|
|
|
909
934
|
gap: 8px;
|
|
910
935
|
font-size: 12px;
|
|
911
936
|
color: var(--text-secondary);
|
|
912
|
-
margin-top: 12px;
|
|
913
937
|
}
|
|
914
938
|
|
|
915
939
|
.beads-empty {
|
|
@@ -967,6 +991,194 @@ export function getDashboardHTML() {
|
|
|
967
991
|
font-style: italic;
|
|
968
992
|
color: var(--text-muted);
|
|
969
993
|
}
|
|
994
|
+
|
|
995
|
+
/* Tab navigation */
|
|
996
|
+
.tab-container {
|
|
997
|
+
margin-bottom: 24px;
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
.tab-nav {
|
|
1001
|
+
display: flex;
|
|
1002
|
+
gap: 4px;
|
|
1003
|
+
border-bottom: 1px solid var(--border-color);
|
|
1004
|
+
padding-bottom: 0;
|
|
1005
|
+
}
|
|
1006
|
+
|
|
1007
|
+
.tab-btn {
|
|
1008
|
+
padding: 10px 20px;
|
|
1009
|
+
font-size: 14px;
|
|
1010
|
+
font-weight: 500;
|
|
1011
|
+
color: var(--text-secondary);
|
|
1012
|
+
background: transparent;
|
|
1013
|
+
border: none;
|
|
1014
|
+
border-bottom: 2px solid transparent;
|
|
1015
|
+
cursor: pointer;
|
|
1016
|
+
transition: all 0.2s ease;
|
|
1017
|
+
margin-bottom: -1px;
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
.tab-btn:hover {
|
|
1021
|
+
color: var(--text-primary);
|
|
1022
|
+
background-color: var(--bg-tertiary);
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
.tab-btn.active {
|
|
1026
|
+
color: var(--accent-blue);
|
|
1027
|
+
border-bottom-color: var(--accent-blue);
|
|
1028
|
+
}
|
|
1029
|
+
|
|
1030
|
+
.tab-content {
|
|
1031
|
+
display: none;
|
|
1032
|
+
}
|
|
1033
|
+
|
|
1034
|
+
.tab-content.active {
|
|
1035
|
+
display: block;
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
/* Slider styles */
|
|
1039
|
+
.form-slider {
|
|
1040
|
+
width: 100%;
|
|
1041
|
+
height: 8px;
|
|
1042
|
+
border-radius: 4px;
|
|
1043
|
+
background: var(--bg-tertiary);
|
|
1044
|
+
outline: none;
|
|
1045
|
+
-webkit-appearance: none;
|
|
1046
|
+
appearance: none;
|
|
1047
|
+
cursor: pointer;
|
|
1048
|
+
}
|
|
1049
|
+
|
|
1050
|
+
.form-slider::-webkit-slider-thumb {
|
|
1051
|
+
-webkit-appearance: none;
|
|
1052
|
+
appearance: none;
|
|
1053
|
+
width: 20px;
|
|
1054
|
+
height: 20px;
|
|
1055
|
+
border-radius: 50%;
|
|
1056
|
+
background: var(--accent-blue);
|
|
1057
|
+
cursor: pointer;
|
|
1058
|
+
border: 2px solid var(--bg-primary);
|
|
1059
|
+
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
|
|
1060
|
+
}
|
|
1061
|
+
|
|
1062
|
+
.form-slider::-moz-range-thumb {
|
|
1063
|
+
width: 20px;
|
|
1064
|
+
height: 20px;
|
|
1065
|
+
border-radius: 50%;
|
|
1066
|
+
background: var(--accent-blue);
|
|
1067
|
+
cursor: pointer;
|
|
1068
|
+
border: 2px solid var(--bg-primary);
|
|
1069
|
+
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
|
|
1070
|
+
}
|
|
1071
|
+
|
|
1072
|
+
.slider-labels {
|
|
1073
|
+
display: flex;
|
|
1074
|
+
justify-content: space-between;
|
|
1075
|
+
margin-top: 8px;
|
|
1076
|
+
font-size: 12px;
|
|
1077
|
+
color: var(--text-muted);
|
|
1078
|
+
}
|
|
1079
|
+
|
|
1080
|
+
.slider-value {
|
|
1081
|
+
text-align: center;
|
|
1082
|
+
font-size: 14px;
|
|
1083
|
+
font-weight: 500;
|
|
1084
|
+
color: var(--text-primary);
|
|
1085
|
+
margin-top: 8px;
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1088
|
+
/* Chip styles */
|
|
1089
|
+
.chips-container {
|
|
1090
|
+
display: flex;
|
|
1091
|
+
flex-wrap: wrap;
|
|
1092
|
+
gap: 8px;
|
|
1093
|
+
margin-bottom: 12px;
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
.chip {
|
|
1097
|
+
display: inline-flex;
|
|
1098
|
+
align-items: center;
|
|
1099
|
+
gap: 6px;
|
|
1100
|
+
padding: 6px 10px;
|
|
1101
|
+
font-size: 13px;
|
|
1102
|
+
font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
|
|
1103
|
+
background-color: var(--bg-tertiary);
|
|
1104
|
+
border: 1px solid var(--border-color);
|
|
1105
|
+
border-radius: 16px;
|
|
1106
|
+
color: var(--text-secondary);
|
|
1107
|
+
}
|
|
1108
|
+
|
|
1109
|
+
.chip.exclude {
|
|
1110
|
+
color: var(--accent-red);
|
|
1111
|
+
border-color: rgba(248, 81, 73, 0.3);
|
|
1112
|
+
background-color: rgba(248, 81, 73, 0.1);
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1115
|
+
.chip-remove {
|
|
1116
|
+
display: flex;
|
|
1117
|
+
align-items: center;
|
|
1118
|
+
justify-content: center;
|
|
1119
|
+
width: 16px;
|
|
1120
|
+
height: 16px;
|
|
1121
|
+
border-radius: 50%;
|
|
1122
|
+
background: transparent;
|
|
1123
|
+
border: none;
|
|
1124
|
+
color: var(--text-muted);
|
|
1125
|
+
cursor: pointer;
|
|
1126
|
+
padding: 0;
|
|
1127
|
+
font-size: 14px;
|
|
1128
|
+
line-height: 1;
|
|
1129
|
+
transition: all 0.2s ease;
|
|
1130
|
+
}
|
|
1131
|
+
|
|
1132
|
+
.chip-remove:hover {
|
|
1133
|
+
background-color: var(--accent-red);
|
|
1134
|
+
color: white;
|
|
1135
|
+
}
|
|
1136
|
+
|
|
1137
|
+
.chip-input-group {
|
|
1138
|
+
display: flex;
|
|
1139
|
+
gap: 8px;
|
|
1140
|
+
margin-top: 8px;
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1143
|
+
.chip-input-group .form-input {
|
|
1144
|
+
flex: 1;
|
|
1145
|
+
}
|
|
1146
|
+
|
|
1147
|
+
.chip-input-group .btn {
|
|
1148
|
+
flex-shrink: 0;
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
.chips-empty {
|
|
1152
|
+
color: var(--text-muted);
|
|
1153
|
+
font-size: 13px;
|
|
1154
|
+
font-style: italic;
|
|
1155
|
+
}
|
|
1156
|
+
|
|
1157
|
+
/* Patterns section layout */
|
|
1158
|
+
.patterns-section {
|
|
1159
|
+
display: flex;
|
|
1160
|
+
flex-direction: column;
|
|
1161
|
+
gap: 24px;
|
|
1162
|
+
}
|
|
1163
|
+
|
|
1164
|
+
.patterns-group {
|
|
1165
|
+
display: flex;
|
|
1166
|
+
flex-direction: column;
|
|
1167
|
+
gap: 8px;
|
|
1168
|
+
}
|
|
1169
|
+
|
|
1170
|
+
.patterns-group-header {
|
|
1171
|
+
display: flex;
|
|
1172
|
+
align-items: center;
|
|
1173
|
+
gap: 8px;
|
|
1174
|
+
margin-bottom: 4px;
|
|
1175
|
+
}
|
|
1176
|
+
|
|
1177
|
+
.patterns-group-title {
|
|
1178
|
+
font-size: 14px;
|
|
1179
|
+
font-weight: 600;
|
|
1180
|
+
color: var(--text-primary);
|
|
1181
|
+
}
|
|
970
1182
|
</style>
|
|
971
1183
|
</head>
|
|
972
1184
|
<body>
|
|
@@ -997,6 +1209,18 @@ export function getDashboardHTML() {
|
|
|
997
1209
|
</div>
|
|
998
1210
|
</header>
|
|
999
1211
|
|
|
1212
|
+
<!-- Tab Navigation -->
|
|
1213
|
+
<div class="tab-container">
|
|
1214
|
+
<nav class="tab-nav">
|
|
1215
|
+
<button class="tab-btn active" data-tab="status">Status</button>
|
|
1216
|
+
<button class="tab-btn" data-tab="beads">Beads</button>
|
|
1217
|
+
<button class="tab-btn" data-tab="settings">Settings</button>
|
|
1218
|
+
</nav>
|
|
1219
|
+
</div>
|
|
1220
|
+
|
|
1221
|
+
<!-- Status Tab -->
|
|
1222
|
+
<div id="tab-status" class="tab-content active">
|
|
1223
|
+
|
|
1000
1224
|
<!-- Backend Fallback Warning Banner -->
|
|
1001
1225
|
<div class="warning-banner" id="fallbackBanner">
|
|
1002
1226
|
<div class="warning-banner-header">
|
|
@@ -1014,8 +1238,29 @@ export function getDashboardHTML() {
|
|
|
1014
1238
|
</div>
|
|
1015
1239
|
|
|
1016
1240
|
<div class="grid">
|
|
1241
|
+
<!-- Command Usage Card -->
|
|
1242
|
+
<div class="card full-width">
|
|
1243
|
+
<div class="card-header">
|
|
1244
|
+
<span class="card-title">Command Usage</span>
|
|
1245
|
+
<span class="badge" id="sessionBadge">This Session</span>
|
|
1246
|
+
</div>
|
|
1247
|
+
<div id="usageChartContainer">
|
|
1248
|
+
<div class="usage-empty" id="usageEmpty">No commands executed yet</div>
|
|
1249
|
+
<div id="chartWrapper">
|
|
1250
|
+
<table class="charts-css column show-primary-axis data-spacing-5" id="usage-chart" style="display: none;">
|
|
1251
|
+
<tbody id="usageChartBody"></tbody>
|
|
1252
|
+
</table>
|
|
1253
|
+
</div>
|
|
1254
|
+
<ul class="charts-css legend legend-inline legend-square" id="chartLegend" style="display: none;"></ul>
|
|
1255
|
+
<div class="usage-total" id="usageTotal" style="display: none;">
|
|
1256
|
+
<span class="usage-total-label">Total Commands</span>
|
|
1257
|
+
<span class="usage-total-count" id="totalCount">0</span>
|
|
1258
|
+
</div>
|
|
1259
|
+
</div>
|
|
1260
|
+
</div>
|
|
1261
|
+
|
|
1017
1262
|
<!-- Index Status Card -->
|
|
1018
|
-
<div class="card">
|
|
1263
|
+
<div class="card half-width compact">
|
|
1019
1264
|
<div class="card-header">
|
|
1020
1265
|
<span class="card-title">Index Status</span>
|
|
1021
1266
|
<span class="badge" id="indexBadge">Loading...</span>
|
|
@@ -1045,132 +1290,8 @@ export function getDashboardHTML() {
|
|
|
1045
1290
|
</div>
|
|
1046
1291
|
</div>
|
|
1047
1292
|
|
|
1048
|
-
<!-- Embedding Backend Card -->
|
|
1049
|
-
<div class="card">
|
|
1050
|
-
<div class="card-header">
|
|
1051
|
-
<span class="card-title">Embedding Backend</span>
|
|
1052
|
-
<span class="badge" id="embeddingStatus">-</span>
|
|
1053
|
-
</div>
|
|
1054
|
-
<div class="stat">
|
|
1055
|
-
<div class="stat-label">Current Backend</div>
|
|
1056
|
-
<div class="stat-value small" id="embeddingBackend">-</div>
|
|
1057
|
-
</div>
|
|
1058
|
-
<div class="stat">
|
|
1059
|
-
<div class="stat-label">Index Path</div>
|
|
1060
|
-
<div class="stat-value small" id="indexPath">-</div>
|
|
1061
|
-
</div>
|
|
1062
|
-
<div class="settings-form" id="embeddingSettingsForm">
|
|
1063
|
-
<div class="form-group">
|
|
1064
|
-
<label for="backendSelect">Select Backend</label>
|
|
1065
|
-
<select id="backendSelect" class="form-select">
|
|
1066
|
-
<option value="ollama">Ollama (local)</option>
|
|
1067
|
-
<option value="gemini" selected>Google Gemini (free - requires API key)</option>
|
|
1068
|
-
</select>
|
|
1069
|
-
</div>
|
|
1070
|
-
<div class="form-group" id="ollamaSettingsGroup">
|
|
1071
|
-
<label for="concurrencySelect">Ollama Concurrency</label>
|
|
1072
|
-
<select id="concurrencySelect" class="form-select">
|
|
1073
|
-
<option value="1" selected>1 (default)</option>
|
|
1074
|
-
<option value="2">2</option>
|
|
1075
|
-
<option value="3">3</option>
|
|
1076
|
-
<option value="5">5</option>
|
|
1077
|
-
<option value="10">10</option>
|
|
1078
|
-
<option value="25">25</option>
|
|
1079
|
-
<option value="50">50</option>
|
|
1080
|
-
<option value="100">100</option>
|
|
1081
|
-
<option value="250">250</option>
|
|
1082
|
-
<option value="500">500</option>
|
|
1083
|
-
<option value="1000">1000</option>
|
|
1084
|
-
</select>
|
|
1085
|
-
</div>
|
|
1086
|
-
<div class="form-group" id="batchSizeGroup">
|
|
1087
|
-
<label for="batchSizeSelect">Batch Size</label>
|
|
1088
|
-
<select id="batchSizeSelect" class="form-select">
|
|
1089
|
-
<option value="32">32</option>
|
|
1090
|
-
<option value="64">64</option>
|
|
1091
|
-
<option value="128">128</option>
|
|
1092
|
-
<option value="256" selected>256 (default)</option>
|
|
1093
|
-
<option value="512">512</option>
|
|
1094
|
-
<option value="1024">1024</option>
|
|
1095
|
-
<option value="2048">2048</option>
|
|
1096
|
-
<option value="4096">4096</option>
|
|
1097
|
-
<option value="8192">8192</option>
|
|
1098
|
-
<option value="16384">16384</option>
|
|
1099
|
-
</select>
|
|
1100
|
-
</div>
|
|
1101
|
-
<div class="form-group" id="apiKeyGroup" style="display: none;">
|
|
1102
|
-
<label for="apiKeyInput" id="apiKeyLabel">API Key</label>
|
|
1103
|
-
<input type="password" id="apiKeyInput" class="form-input" placeholder="" />
|
|
1104
|
-
<div class="form-hint" id="apiKeyHint"></div>
|
|
1105
|
-
</div>
|
|
1106
|
-
<div class="form-actions">
|
|
1107
|
-
<button type="button" id="saveEmbeddingBtn" class="btn btn-primary">Save Settings</button>
|
|
1108
|
-
<span id="saveStatus" class="save-status"></span>
|
|
1109
|
-
</div>
|
|
1110
|
-
</div>
|
|
1111
|
-
</div>
|
|
1112
|
-
|
|
1113
|
-
<!-- Dashboard Settings Card -->
|
|
1114
|
-
<div class="card">
|
|
1115
|
-
<div class="card-header">
|
|
1116
|
-
<span class="card-title">Dashboard Settings</span>
|
|
1117
|
-
<span class="badge" id="dashboardBadge">Enabled</span>
|
|
1118
|
-
</div>
|
|
1119
|
-
<div class="stat">
|
|
1120
|
-
<div class="stat-label">Auto-Start on MCP Launch</div>
|
|
1121
|
-
<div class="stat-value small" id="dashboardEnabled">-</div>
|
|
1122
|
-
</div>
|
|
1123
|
-
<div class="settings-form" id="dashboardSettingsForm">
|
|
1124
|
-
<div class="form-group">
|
|
1125
|
-
<label for="dashboardEnabledSelect">Dashboard Auto-Start</label>
|
|
1126
|
-
<select id="dashboardEnabledSelect" class="form-select">
|
|
1127
|
-
<option value="true">Enabled (auto-start with MCP server)</option>
|
|
1128
|
-
<option value="false">Disabled (manual start only)</option>
|
|
1129
|
-
</select>
|
|
1130
|
-
</div>
|
|
1131
|
-
<div class="form-hint">
|
|
1132
|
-
When disabled, use the <code>open_dashboard</code> MCP tool to start manually.
|
|
1133
|
-
</div>
|
|
1134
|
-
<div class="form-actions">
|
|
1135
|
-
<button type="button" id="saveDashboardBtn" class="btn btn-primary" style="display: none;">Save Settings</button>
|
|
1136
|
-
<span id="saveDashboardStatus" class="save-status"></span>
|
|
1137
|
-
</div>
|
|
1138
|
-
</div>
|
|
1139
|
-
</div>
|
|
1140
|
-
|
|
1141
|
-
<!-- Configuration Card -->
|
|
1142
|
-
<div class="card">
|
|
1143
|
-
<div class="card-header">
|
|
1144
|
-
<span class="card-title">Configuration</span>
|
|
1145
|
-
</div>
|
|
1146
|
-
<div class="stat">
|
|
1147
|
-
<div class="stat-label">Project Path</div>
|
|
1148
|
-
<div class="stat-value small" id="projectPath">-</div>
|
|
1149
|
-
</div>
|
|
1150
|
-
<div class="stat">
|
|
1151
|
-
<div class="stat-label">Chunk Size</div>
|
|
1152
|
-
<div class="stat-value small" id="chunkSize">-</div>
|
|
1153
|
-
</div>
|
|
1154
|
-
<div class="stat">
|
|
1155
|
-
<div class="stat-label">Search Weights</div>
|
|
1156
|
-
<div class="stat-value small" id="searchWeights">-</div>
|
|
1157
|
-
</div>
|
|
1158
|
-
<div class="stat">
|
|
1159
|
-
<div class="stat-label">Include Patterns</div>
|
|
1160
|
-
<div class="patterns-list" id="includePatterns">
|
|
1161
|
-
<span class="pattern-tag">Loading...</span>
|
|
1162
|
-
</div>
|
|
1163
|
-
</div>
|
|
1164
|
-
<div class="stat">
|
|
1165
|
-
<div class="stat-label">Exclude Patterns</div>
|
|
1166
|
-
<div class="patterns-list" id="excludePatterns">
|
|
1167
|
-
<span class="pattern-tag exclude">Loading...</span>
|
|
1168
|
-
</div>
|
|
1169
|
-
</div>
|
|
1170
|
-
</div>
|
|
1171
|
-
|
|
1172
1293
|
<!-- Token Savings Card -->
|
|
1173
|
-
<div class="card">
|
|
1294
|
+
<div class="card half-width compact">
|
|
1174
1295
|
<div class="card-header">
|
|
1175
1296
|
<span class="card-title">Token Savings</span>
|
|
1176
1297
|
<span class="badge" id="savingsBadge">This Session</span>
|
|
@@ -1191,103 +1312,244 @@ export function getDashboardHTML() {
|
|
|
1191
1312
|
<div class="stat-label">Operations Tracked</div>
|
|
1192
1313
|
<div class="stat-value small" id="operationCount">0</div>
|
|
1193
1314
|
</div>
|
|
1194
|
-
<div class="form-hint" style="margin-top: 10px;">
|
|
1195
|
-
Semantic search returns only relevant code chunks instead of entire files, saving context tokens.
|
|
1196
|
-
</div>
|
|
1197
1315
|
</div>
|
|
1316
|
+
</div>
|
|
1198
1317
|
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
<
|
|
1318
|
+
<!-- Server Log Section -->
|
|
1319
|
+
<div class="log-section" id="logSection">
|
|
1320
|
+
<div class="log-header" id="logHeader">
|
|
1321
|
+
<svg class="log-toggle" id="logToggle" width="16" height="16" viewBox="0 0 16 16" fill="currentColor">
|
|
1322
|
+
<path d="M6 4l4 4-4 4"/>
|
|
1323
|
+
</svg>
|
|
1324
|
+
<span class="log-title">Server Logs</span>
|
|
1325
|
+
<span class="badge" id="logCount">0</span>
|
|
1326
|
+
<div class="log-actions">
|
|
1327
|
+
<button type="button" id="clearLogsBtn">Clear</button>
|
|
1204
1328
|
</div>
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1329
|
+
</div>
|
|
1330
|
+
<div class="log-container" id="logContainer">
|
|
1331
|
+
<div class="log-empty" id="logEmpty">No logs yet. Logs will appear when indexing or other server operations occur.</div>
|
|
1332
|
+
</div>
|
|
1333
|
+
</div>
|
|
1334
|
+
|
|
1335
|
+
</div><!-- End Status Tab -->
|
|
1336
|
+
|
|
1337
|
+
<!-- Beads Tab -->
|
|
1338
|
+
<div id="tab-beads" class="tab-content">
|
|
1339
|
+
<div class="beads-section" id="beadsSection">
|
|
1340
|
+
<div class="beads-header">
|
|
1341
|
+
<div class="beads-header-left">
|
|
1342
|
+
<svg class="beads-logo" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
1343
|
+
<circle cx="12" cy="5" r="3"/>
|
|
1344
|
+
<circle cx="12" cy="12" r="3"/>
|
|
1345
|
+
<circle cx="12" cy="19" r="3"/>
|
|
1346
|
+
<line x1="12" y1="8" x2="12" y2="9"/>
|
|
1347
|
+
<line x1="12" y1="15" x2="12" y2="16"/>
|
|
1348
|
+
</svg>
|
|
1349
|
+
<span class="beads-title">Beads Issue Tracker</span>
|
|
1350
|
+
<span class="badge success" id="beadsBadge" style="display: none;">Active</span>
|
|
1211
1351
|
</div>
|
|
1212
|
-
<
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1352
|
+
<div class="beads-header-right" id="beadsHeaderStats" style="display: none;">
|
|
1353
|
+
<div class="beads-daemon-status" id="beadsDaemonStatus">
|
|
1354
|
+
<div class="status-dot" id="beadsDaemonDot"></div>
|
|
1355
|
+
<span id="beadsDaemonText">Daemon status unknown</span>
|
|
1356
|
+
</div>
|
|
1357
|
+
<div class="beads-stats">
|
|
1358
|
+
<div class="beads-stat">
|
|
1359
|
+
<span class="beads-stat-value" id="beadsReadyCount">0</span>
|
|
1360
|
+
<span class="beads-stat-label">Ready</span>
|
|
1361
|
+
</div>
|
|
1362
|
+
<div class="beads-stat">
|
|
1363
|
+
<span class="beads-stat-value" id="beadsOpenCount">0</span>
|
|
1364
|
+
<span class="beads-stat-label">Open</span>
|
|
1365
|
+
</div>
|
|
1366
|
+
<div class="beads-stat">
|
|
1367
|
+
<span class="beads-stat-value" id="beadsTotalCount">0</span>
|
|
1368
|
+
<span class="beads-stat-label">Total</span>
|
|
1369
|
+
</div>
|
|
1370
|
+
</div>
|
|
1371
|
+
</div>
|
|
1372
|
+
</div>
|
|
1373
|
+
<div id="beadsUnavailable" class="beads-unavailable">
|
|
1374
|
+
<p>Beads is not configured for this project.</p>
|
|
1375
|
+
<p style="margin-top: 8px; font-size: 13px;">Visit <a href="https://github.com/steveyegge/beads" target="_blank" style="color: var(--accent-blue);">github.com/steveyegge/beads</a> to learn more.</p>
|
|
1376
|
+
</div>
|
|
1377
|
+
<div id="beadsContent" style="display: none;">
|
|
1378
|
+
<div class="card">
|
|
1379
|
+
<div class="card-header">
|
|
1380
|
+
<span class="card-title">Ready Tasks</span>
|
|
1381
|
+
<span class="badge" id="readyTasksBadge">0 tasks</span>
|
|
1382
|
+
</div>
|
|
1383
|
+
<div class="beads-issues" id="beadsIssuesList">
|
|
1384
|
+
<div class="beads-empty">No ready tasks</div>
|
|
1385
|
+
</div>
|
|
1216
1386
|
</div>
|
|
1217
1387
|
</div>
|
|
1218
1388
|
</div>
|
|
1219
|
-
</div
|
|
1389
|
+
</div><!-- End Beads Tab -->
|
|
1220
1390
|
|
|
1221
|
-
<!--
|
|
1222
|
-
<div
|
|
1223
|
-
<div class="beads-header">
|
|
1224
|
-
<svg class="beads-logo" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
1225
|
-
<circle cx="12" cy="5" r="3"/>
|
|
1226
|
-
<circle cx="12" cy="12" r="3"/>
|
|
1227
|
-
<circle cx="12" cy="19" r="3"/>
|
|
1228
|
-
<line x1="12" y1="8" x2="12" y2="9"/>
|
|
1229
|
-
<line x1="12" y1="15" x2="12" y2="16"/>
|
|
1230
|
-
</svg>
|
|
1231
|
-
<span class="beads-title">Beads Issue Tracker</span>
|
|
1232
|
-
</div>
|
|
1391
|
+
<!-- Settings Tab -->
|
|
1392
|
+
<div id="tab-settings" class="tab-content">
|
|
1233
1393
|
<div class="grid">
|
|
1394
|
+
<!-- Embedding Backend Card -->
|
|
1234
1395
|
<div class="card">
|
|
1235
1396
|
<div class="card-header">
|
|
1236
|
-
<span class="card-title">
|
|
1237
|
-
<span class="badge
|
|
1397
|
+
<span class="card-title">Embedding Backend</span>
|
|
1398
|
+
<span class="badge" id="embeddingStatus">-</span>
|
|
1399
|
+
</div>
|
|
1400
|
+
<div class="stat">
|
|
1401
|
+
<div class="stat-label">Current Backend</div>
|
|
1402
|
+
<div class="stat-value small" id="embeddingBackend">-</div>
|
|
1403
|
+
</div>
|
|
1404
|
+
<div class="stat">
|
|
1405
|
+
<div class="stat-label">Index Path</div>
|
|
1406
|
+
<div class="stat-value small" id="indexPath">-</div>
|
|
1238
1407
|
</div>
|
|
1239
|
-
<div class="
|
|
1240
|
-
<div class="
|
|
1241
|
-
<
|
|
1242
|
-
<
|
|
1408
|
+
<div class="settings-form" id="embeddingSettingsForm">
|
|
1409
|
+
<div class="form-group">
|
|
1410
|
+
<label for="backendSelect">Select Backend</label>
|
|
1411
|
+
<select id="backendSelect" class="form-select">
|
|
1412
|
+
<option value="ollama">Ollama (local)</option>
|
|
1413
|
+
<option value="gemini" selected>Google Gemini (free - requires API key)</option>
|
|
1414
|
+
</select>
|
|
1243
1415
|
</div>
|
|
1244
|
-
<div class="
|
|
1245
|
-
<
|
|
1246
|
-
<
|
|
1416
|
+
<div class="form-group" id="ollamaSettingsGroup">
|
|
1417
|
+
<label for="concurrencySelect">Ollama Concurrency</label>
|
|
1418
|
+
<select id="concurrencySelect" class="form-select">
|
|
1419
|
+
<option value="1" selected>1 (default)</option>
|
|
1420
|
+
<option value="2">2</option>
|
|
1421
|
+
<option value="3">3</option>
|
|
1422
|
+
<option value="5">5</option>
|
|
1423
|
+
<option value="10">10</option>
|
|
1424
|
+
<option value="25">25</option>
|
|
1425
|
+
<option value="50">50</option>
|
|
1426
|
+
<option value="100">100</option>
|
|
1427
|
+
<option value="250">250</option>
|
|
1428
|
+
<option value="500">500</option>
|
|
1429
|
+
<option value="1000">1000</option>
|
|
1430
|
+
</select>
|
|
1247
1431
|
</div>
|
|
1248
|
-
<div class="
|
|
1249
|
-
<
|
|
1250
|
-
<
|
|
1432
|
+
<div class="form-group" id="batchSizeGroup">
|
|
1433
|
+
<label for="batchSizeSelect">Batch Size</label>
|
|
1434
|
+
<select id="batchSizeSelect" class="form-select">
|
|
1435
|
+
<option value="32">32</option>
|
|
1436
|
+
<option value="64">64</option>
|
|
1437
|
+
<option value="128">128</option>
|
|
1438
|
+
<option value="256" selected>256 (default)</option>
|
|
1439
|
+
<option value="512">512</option>
|
|
1440
|
+
<option value="1024">1024</option>
|
|
1441
|
+
<option value="2048">2048</option>
|
|
1442
|
+
<option value="4096">4096</option>
|
|
1443
|
+
<option value="8192">8192</option>
|
|
1444
|
+
<option value="16384">16384</option>
|
|
1445
|
+
</select>
|
|
1446
|
+
</div>
|
|
1447
|
+
<div class="form-group" id="apiKeyGroup" style="display: none;">
|
|
1448
|
+
<label for="apiKeyInput" id="apiKeyLabel">API Key</label>
|
|
1449
|
+
<input type="password" id="apiKeyInput" class="form-input" placeholder="" />
|
|
1450
|
+
<div class="form-hint" id="apiKeyHint"></div>
|
|
1451
|
+
</div>
|
|
1452
|
+
<div class="form-actions">
|
|
1453
|
+
<button type="button" id="saveEmbeddingBtn" class="btn btn-primary">Save Settings</button>
|
|
1454
|
+
<span id="saveStatus" class="save-status"></span>
|
|
1251
1455
|
</div>
|
|
1252
1456
|
</div>
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1457
|
+
</div>
|
|
1458
|
+
|
|
1459
|
+
<!-- Dashboard Settings Card -->
|
|
1460
|
+
<div class="card">
|
|
1461
|
+
<div class="card-header">
|
|
1462
|
+
<span class="card-title">Dashboard Settings</span>
|
|
1463
|
+
<span class="badge" id="dashboardBadge">Enabled</span>
|
|
1464
|
+
</div>
|
|
1465
|
+
<div class="stat">
|
|
1466
|
+
<div class="stat-label">Auto-Start on MCP Launch</div>
|
|
1467
|
+
<div class="stat-value small" id="dashboardEnabled">-</div>
|
|
1256
1468
|
</div>
|
|
1257
|
-
<div class="
|
|
1258
|
-
<div class="
|
|
1259
|
-
|
|
1469
|
+
<div class="settings-form" id="dashboardSettingsForm">
|
|
1470
|
+
<div class="form-group">
|
|
1471
|
+
<label for="dashboardEnabledSelect">Dashboard Auto-Start</label>
|
|
1472
|
+
<select id="dashboardEnabledSelect" class="form-select">
|
|
1473
|
+
<option value="true">Enabled (auto-start with MCP server)</option>
|
|
1474
|
+
<option value="false">Disabled (manual start only)</option>
|
|
1475
|
+
</select>
|
|
1476
|
+
</div>
|
|
1477
|
+
<div class="form-hint">
|
|
1478
|
+
When disabled, use the <code>open_dashboard</code> MCP tool to start manually.
|
|
1479
|
+
</div>
|
|
1480
|
+
<div class="form-actions">
|
|
1481
|
+
<button type="button" id="saveDashboardBtn" class="btn btn-primary" style="display: none;">Save Settings</button>
|
|
1482
|
+
<span id="saveDashboardStatus" class="save-status"></span>
|
|
1483
|
+
</div>
|
|
1260
1484
|
</div>
|
|
1261
1485
|
</div>
|
|
1262
1486
|
|
|
1263
|
-
|
|
1487
|
+
<!-- Search Weights Card -->
|
|
1488
|
+
<div class="card">
|
|
1264
1489
|
<div class="card-header">
|
|
1265
|
-
<span class="card-title">
|
|
1266
|
-
|
|
1490
|
+
<span class="card-title">Search Weights</span>
|
|
1491
|
+
</div>
|
|
1492
|
+
<div class="stat">
|
|
1493
|
+
<div class="stat-label">Semantic vs Keyword Balance</div>
|
|
1494
|
+
<div class="slider-value" id="weightsDisplay">Semantic: 70%, Keyword: 30%</div>
|
|
1495
|
+
</div>
|
|
1496
|
+
<div class="form-group" style="margin-top: 16px;">
|
|
1497
|
+
<input type="range" id="weightsSlider" class="form-slider" min="0" max="100" value="70">
|
|
1498
|
+
<div class="slider-labels">
|
|
1499
|
+
<span>100% Keyword</span>
|
|
1500
|
+
<span>100% Semantic</span>
|
|
1501
|
+
</div>
|
|
1502
|
+
</div>
|
|
1503
|
+
<div class="form-hint" style="margin-top: 12px;">
|
|
1504
|
+
Semantic search finds conceptually similar code. Keyword search matches exact terms.
|
|
1267
1505
|
</div>
|
|
1268
|
-
<div class="
|
|
1269
|
-
<
|
|
1506
|
+
<div class="form-actions">
|
|
1507
|
+
<button type="button" id="saveWeightsBtn" class="btn btn-primary" style="display: none;">Save Weights</button>
|
|
1508
|
+
<span id="saveWeightsStatus" class="save-status"></span>
|
|
1270
1509
|
</div>
|
|
1271
1510
|
</div>
|
|
1272
|
-
</div>
|
|
1273
|
-
</div>
|
|
1274
1511
|
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1512
|
+
<!-- File Patterns Card -->
|
|
1513
|
+
<div class="card">
|
|
1514
|
+
<div class="card-header">
|
|
1515
|
+
<span class="card-title">File Patterns</span>
|
|
1516
|
+
</div>
|
|
1517
|
+
<div class="patterns-section">
|
|
1518
|
+
<div class="patterns-group">
|
|
1519
|
+
<div class="patterns-group-header">
|
|
1520
|
+
<span class="patterns-group-title">Include</span>
|
|
1521
|
+
<span class="badge" id="includePatternsCount">0</span>
|
|
1522
|
+
</div>
|
|
1523
|
+
<div class="stat-label">Files matching these patterns will be indexed</div>
|
|
1524
|
+
<div class="chips-container" id="includePatternsChips">
|
|
1525
|
+
<span class="chips-empty">Loading...</span>
|
|
1526
|
+
</div>
|
|
1527
|
+
<div class="chip-input-group">
|
|
1528
|
+
<input type="text" id="includePatternInput" class="form-input" placeholder="e.g., **/*.ts">
|
|
1529
|
+
<button type="button" id="addIncludePatternBtn" class="btn btn-secondary">Add</button>
|
|
1530
|
+
</div>
|
|
1531
|
+
<span id="includePatternStatus" class="save-status"></span>
|
|
1532
|
+
</div>
|
|
1533
|
+
<div class="patterns-group">
|
|
1534
|
+
<div class="patterns-group-header">
|
|
1535
|
+
<span class="patterns-group-title">Exclude</span>
|
|
1536
|
+
<span class="badge" id="excludePatternsCount">0</span>
|
|
1537
|
+
</div>
|
|
1538
|
+
<div class="stat-label">Files matching these patterns will be skipped</div>
|
|
1539
|
+
<div class="chips-container" id="excludePatternsChips">
|
|
1540
|
+
<span class="chips-empty">Loading...</span>
|
|
1541
|
+
</div>
|
|
1542
|
+
<div class="chip-input-group">
|
|
1543
|
+
<input type="text" id="excludePatternInput" class="form-input" placeholder="e.g., **/node_modules/**">
|
|
1544
|
+
<button type="button" id="addExcludePatternBtn" class="btn btn-secondary">Add</button>
|
|
1545
|
+
</div>
|
|
1546
|
+
<span id="excludePatternStatus" class="save-status"></span>
|
|
1547
|
+
</div>
|
|
1548
|
+
</div>
|
|
1285
1549
|
</div>
|
|
1286
1550
|
</div>
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
</div>
|
|
1290
|
-
</div>
|
|
1551
|
+
</div><!-- End Settings Tab -->
|
|
1552
|
+
|
|
1291
1553
|
</div>
|
|
1292
1554
|
|
|
1293
1555
|
<script>
|
|
@@ -1313,6 +1575,33 @@ export function getDashboardHTML() {
|
|
|
1313
1575
|
// Theme toggle button
|
|
1314
1576
|
document.getElementById('themeToggle').addEventListener('click', toggleTheme);
|
|
1315
1577
|
|
|
1578
|
+
// Tab management
|
|
1579
|
+
function getStoredTab() {
|
|
1580
|
+
return localStorage.getItem('lance-context-tab') || 'status';
|
|
1581
|
+
}
|
|
1582
|
+
|
|
1583
|
+
function setActiveTab(tabId) {
|
|
1584
|
+
// Update buttons
|
|
1585
|
+
document.querySelectorAll('.tab-btn').forEach(btn => {
|
|
1586
|
+
btn.classList.toggle('active', btn.getAttribute('data-tab') === tabId);
|
|
1587
|
+
});
|
|
1588
|
+
// Update content
|
|
1589
|
+
document.querySelectorAll('.tab-content').forEach(content => {
|
|
1590
|
+
content.classList.toggle('active', content.id === 'tab-' + tabId);
|
|
1591
|
+
});
|
|
1592
|
+
localStorage.setItem('lance-context-tab', tabId);
|
|
1593
|
+
}
|
|
1594
|
+
|
|
1595
|
+
// Initialize tabs
|
|
1596
|
+
setActiveTab(getStoredTab());
|
|
1597
|
+
|
|
1598
|
+
// Tab click handlers
|
|
1599
|
+
document.querySelectorAll('.tab-btn').forEach(btn => {
|
|
1600
|
+
btn.addEventListener('click', () => {
|
|
1601
|
+
setActiveTab(btn.getAttribute('data-tab'));
|
|
1602
|
+
});
|
|
1603
|
+
});
|
|
1604
|
+
|
|
1316
1605
|
// State
|
|
1317
1606
|
let isConnected = false;
|
|
1318
1607
|
let eventSource = null;
|
|
@@ -1331,11 +1620,6 @@ export function getDashboardHTML() {
|
|
|
1331
1620
|
const indexPath = document.getElementById('indexPath');
|
|
1332
1621
|
const fallbackBanner = document.getElementById('fallbackBanner');
|
|
1333
1622
|
const fallbackContent = document.getElementById('fallbackContent');
|
|
1334
|
-
const projectPath = document.getElementById('projectPath');
|
|
1335
|
-
const chunkSize = document.getElementById('chunkSize');
|
|
1336
|
-
const searchWeights = document.getElementById('searchWeights');
|
|
1337
|
-
const includePatterns = document.getElementById('includePatterns');
|
|
1338
|
-
const excludePatterns = document.getElementById('excludePatterns');
|
|
1339
1623
|
const progressContainer = document.getElementById('progressContainer');
|
|
1340
1624
|
const progressFill = document.getElementById('progressFill');
|
|
1341
1625
|
const progressText = document.getElementById('progressText');
|
|
@@ -1685,6 +1969,228 @@ export function getDashboardHTML() {
|
|
|
1685
1969
|
// Load dashboard settings on page load
|
|
1686
1970
|
loadDashboardSettings();
|
|
1687
1971
|
|
|
1972
|
+
// ===== Search Weights Settings =====
|
|
1973
|
+
const weightsSlider = document.getElementById('weightsSlider');
|
|
1974
|
+
const weightsDisplay = document.getElementById('weightsDisplay');
|
|
1975
|
+
const saveWeightsBtn = document.getElementById('saveWeightsBtn');
|
|
1976
|
+
const saveWeightsStatus = document.getElementById('saveWeightsStatus');
|
|
1977
|
+
let savedSemanticWeight = 70;
|
|
1978
|
+
|
|
1979
|
+
function updateWeightsDisplay() {
|
|
1980
|
+
const semantic = parseInt(weightsSlider.value, 10);
|
|
1981
|
+
const keyword = 100 - semantic;
|
|
1982
|
+
weightsDisplay.textContent = 'Semantic: ' + semantic + '%, Keyword: ' + keyword + '%';
|
|
1983
|
+
}
|
|
1984
|
+
|
|
1985
|
+
function hasWeightsChanged() {
|
|
1986
|
+
return parseInt(weightsSlider.value, 10) !== savedSemanticWeight;
|
|
1987
|
+
}
|
|
1988
|
+
|
|
1989
|
+
function updateWeightsSaveButtonVisibility() {
|
|
1990
|
+
saveWeightsBtn.style.display = hasWeightsChanged() ? 'inline-block' : 'none';
|
|
1991
|
+
saveWeightsStatus.textContent = '';
|
|
1992
|
+
}
|
|
1993
|
+
|
|
1994
|
+
weightsSlider.addEventListener('input', function() {
|
|
1995
|
+
updateWeightsDisplay();
|
|
1996
|
+
updateWeightsSaveButtonVisibility();
|
|
1997
|
+
});
|
|
1998
|
+
|
|
1999
|
+
async function loadSearchWeights() {
|
|
2000
|
+
try {
|
|
2001
|
+
const response = await fetch('/api/search-weights');
|
|
2002
|
+
if (response.ok) {
|
|
2003
|
+
const weights = await response.json();
|
|
2004
|
+
const semantic = Math.round(weights.semanticWeight * 100);
|
|
2005
|
+
savedSemanticWeight = semantic;
|
|
2006
|
+
weightsSlider.value = semantic;
|
|
2007
|
+
updateWeightsDisplay();
|
|
2008
|
+
updateWeightsSaveButtonVisibility();
|
|
2009
|
+
}
|
|
2010
|
+
} catch (error) {
|
|
2011
|
+
console.error('Failed to load search weights:', error);
|
|
2012
|
+
}
|
|
2013
|
+
}
|
|
2014
|
+
|
|
2015
|
+
saveWeightsBtn.addEventListener('click', async function() {
|
|
2016
|
+
const semantic = parseInt(weightsSlider.value, 10) / 100;
|
|
2017
|
+
const keyword = 1 - semantic;
|
|
2018
|
+
|
|
2019
|
+
saveWeightsBtn.disabled = true;
|
|
2020
|
+
saveWeightsStatus.textContent = 'Saving...';
|
|
2021
|
+
saveWeightsStatus.className = 'save-status';
|
|
2022
|
+
|
|
2023
|
+
try {
|
|
2024
|
+
const response = await fetch('/api/search-weights', {
|
|
2025
|
+
method: 'PUT',
|
|
2026
|
+
headers: { 'Content-Type': 'application/json' },
|
|
2027
|
+
body: JSON.stringify({ semanticWeight: semantic, keywordWeight: keyword })
|
|
2028
|
+
});
|
|
2029
|
+
|
|
2030
|
+
const result = await response.json();
|
|
2031
|
+
|
|
2032
|
+
if (response.ok) {
|
|
2033
|
+
savedSemanticWeight = parseInt(weightsSlider.value, 10);
|
|
2034
|
+
saveWeightsStatus.textContent = 'Saved!';
|
|
2035
|
+
saveWeightsStatus.className = 'save-status success';
|
|
2036
|
+
updateWeightsSaveButtonVisibility();
|
|
2037
|
+
fetchData(); // Refresh config display
|
|
2038
|
+
} else {
|
|
2039
|
+
saveWeightsStatus.textContent = result.error || 'Failed to save';
|
|
2040
|
+
saveWeightsStatus.className = 'save-status error';
|
|
2041
|
+
}
|
|
2042
|
+
} catch (error) {
|
|
2043
|
+
saveWeightsStatus.textContent = 'Network error';
|
|
2044
|
+
saveWeightsStatus.className = 'save-status error';
|
|
2045
|
+
} finally {
|
|
2046
|
+
saveWeightsBtn.disabled = false;
|
|
2047
|
+
}
|
|
2048
|
+
});
|
|
2049
|
+
|
|
2050
|
+
loadSearchWeights();
|
|
2051
|
+
|
|
2052
|
+
// ===== Include/Exclude Patterns =====
|
|
2053
|
+
const includePatternsChips = document.getElementById('includePatternsChips');
|
|
2054
|
+
const excludePatternsChips = document.getElementById('excludePatternsChips');
|
|
2055
|
+
const includePatternsCount = document.getElementById('includePatternsCount');
|
|
2056
|
+
const excludePatternsCount = document.getElementById('excludePatternsCount');
|
|
2057
|
+
const includePatternInput = document.getElementById('includePatternInput');
|
|
2058
|
+
const excludePatternInput = document.getElementById('excludePatternInput');
|
|
2059
|
+
const addIncludePatternBtn = document.getElementById('addIncludePatternBtn');
|
|
2060
|
+
const addExcludePatternBtn = document.getElementById('addExcludePatternBtn');
|
|
2061
|
+
const includePatternStatus = document.getElementById('includePatternStatus');
|
|
2062
|
+
const excludePatternStatus = document.getElementById('excludePatternStatus');
|
|
2063
|
+
|
|
2064
|
+
function renderPatternChips(container, patterns, type, countBadge) {
|
|
2065
|
+
// Clear container safely
|
|
2066
|
+
while (container.firstChild) {
|
|
2067
|
+
container.removeChild(container.firstChild);
|
|
2068
|
+
}
|
|
2069
|
+
|
|
2070
|
+
if (!patterns || patterns.length === 0) {
|
|
2071
|
+
const empty = document.createElement('span');
|
|
2072
|
+
empty.className = 'chips-empty';
|
|
2073
|
+
empty.textContent = 'No patterns configured';
|
|
2074
|
+
container.appendChild(empty);
|
|
2075
|
+
countBadge.textContent = '0';
|
|
2076
|
+
return;
|
|
2077
|
+
}
|
|
2078
|
+
|
|
2079
|
+
countBadge.textContent = String(patterns.length);
|
|
2080
|
+
|
|
2081
|
+
patterns.forEach(function(pattern) {
|
|
2082
|
+
const chip = document.createElement('span');
|
|
2083
|
+
chip.className = type === 'exclude' ? 'chip exclude' : 'chip';
|
|
2084
|
+
|
|
2085
|
+
const patternText = document.createTextNode(pattern);
|
|
2086
|
+
chip.appendChild(patternText);
|
|
2087
|
+
|
|
2088
|
+
const removeBtn = document.createElement('button');
|
|
2089
|
+
removeBtn.type = 'button';
|
|
2090
|
+
removeBtn.className = 'chip-remove';
|
|
2091
|
+
removeBtn.title = 'Remove pattern';
|
|
2092
|
+
removeBtn.textContent = '\\u00d7';
|
|
2093
|
+
|
|
2094
|
+
removeBtn.addEventListener('click', async function(e) {
|
|
2095
|
+
e.stopPropagation();
|
|
2096
|
+
await removePatternFromConfig(pattern, type);
|
|
2097
|
+
});
|
|
2098
|
+
|
|
2099
|
+
chip.appendChild(removeBtn);
|
|
2100
|
+
container.appendChild(chip);
|
|
2101
|
+
});
|
|
2102
|
+
}
|
|
2103
|
+
|
|
2104
|
+
async function removePatternFromConfig(pattern, type) {
|
|
2105
|
+
const statusEl = type === 'include' ? includePatternStatus : excludePatternStatus;
|
|
2106
|
+
statusEl.textContent = 'Removing...';
|
|
2107
|
+
statusEl.className = 'save-status';
|
|
2108
|
+
|
|
2109
|
+
try {
|
|
2110
|
+
const response = await fetch('/api/patterns', {
|
|
2111
|
+
method: 'DELETE',
|
|
2112
|
+
headers: { 'Content-Type': 'application/json' },
|
|
2113
|
+
body: JSON.stringify({ pattern, type })
|
|
2114
|
+
});
|
|
2115
|
+
|
|
2116
|
+
const result = await response.json();
|
|
2117
|
+
|
|
2118
|
+
if (response.ok) {
|
|
2119
|
+
statusEl.textContent = 'Removed!';
|
|
2120
|
+
statusEl.className = 'save-status success';
|
|
2121
|
+
setTimeout(function() { statusEl.textContent = ''; }, 2000);
|
|
2122
|
+
fetchData(); // Refresh patterns
|
|
2123
|
+
} else {
|
|
2124
|
+
statusEl.textContent = result.error || 'Failed to remove';
|
|
2125
|
+
statusEl.className = 'save-status error';
|
|
2126
|
+
}
|
|
2127
|
+
} catch (error) {
|
|
2128
|
+
statusEl.textContent = 'Network error';
|
|
2129
|
+
statusEl.className = 'save-status error';
|
|
2130
|
+
}
|
|
2131
|
+
}
|
|
2132
|
+
|
|
2133
|
+
async function addPatternToConfig(pattern, type) {
|
|
2134
|
+
const statusEl = type === 'include' ? includePatternStatus : excludePatternStatus;
|
|
2135
|
+
const inputEl = type === 'include' ? includePatternInput : excludePatternInput;
|
|
2136
|
+
|
|
2137
|
+
if (!pattern.trim()) {
|
|
2138
|
+
statusEl.textContent = 'Pattern is required';
|
|
2139
|
+
statusEl.className = 'save-status error';
|
|
2140
|
+
return;
|
|
2141
|
+
}
|
|
2142
|
+
|
|
2143
|
+
statusEl.textContent = 'Adding...';
|
|
2144
|
+
statusEl.className = 'save-status';
|
|
2145
|
+
|
|
2146
|
+
try {
|
|
2147
|
+
const response = await fetch('/api/patterns', {
|
|
2148
|
+
method: 'POST',
|
|
2149
|
+
headers: { 'Content-Type': 'application/json' },
|
|
2150
|
+
body: JSON.stringify({ pattern: pattern.trim(), type })
|
|
2151
|
+
});
|
|
2152
|
+
|
|
2153
|
+
const result = await response.json();
|
|
2154
|
+
|
|
2155
|
+
if (response.ok) {
|
|
2156
|
+
inputEl.value = '';
|
|
2157
|
+
statusEl.textContent = 'Added!';
|
|
2158
|
+
statusEl.className = 'save-status success';
|
|
2159
|
+
setTimeout(function() { statusEl.textContent = ''; }, 2000);
|
|
2160
|
+
fetchData(); // Refresh patterns
|
|
2161
|
+
} else {
|
|
2162
|
+
statusEl.textContent = result.error || 'Failed to add';
|
|
2163
|
+
statusEl.className = 'save-status error';
|
|
2164
|
+
}
|
|
2165
|
+
} catch (error) {
|
|
2166
|
+
statusEl.textContent = 'Network error';
|
|
2167
|
+
statusEl.className = 'save-status error';
|
|
2168
|
+
}
|
|
2169
|
+
}
|
|
2170
|
+
|
|
2171
|
+
addIncludePatternBtn.addEventListener('click', function() {
|
|
2172
|
+
addPatternToConfig(includePatternInput.value, 'include');
|
|
2173
|
+
});
|
|
2174
|
+
|
|
2175
|
+
addExcludePatternBtn.addEventListener('click', function() {
|
|
2176
|
+
addPatternToConfig(excludePatternInput.value, 'exclude');
|
|
2177
|
+
});
|
|
2178
|
+
|
|
2179
|
+
// Handle Enter key for pattern inputs
|
|
2180
|
+
includePatternInput.addEventListener('keydown', function(e) {
|
|
2181
|
+
if (e.key === 'Enter') {
|
|
2182
|
+
e.preventDefault();
|
|
2183
|
+
addPatternToConfig(includePatternInput.value, 'include');
|
|
2184
|
+
}
|
|
2185
|
+
});
|
|
2186
|
+
|
|
2187
|
+
excludePatternInput.addEventListener('keydown', function(e) {
|
|
2188
|
+
if (e.key === 'Enter') {
|
|
2189
|
+
e.preventDefault();
|
|
2190
|
+
addPatternToConfig(excludePatternInput.value, 'exclude');
|
|
2191
|
+
}
|
|
2192
|
+
});
|
|
2193
|
+
|
|
1688
2194
|
// Format date
|
|
1689
2195
|
function formatDate(isoString) {
|
|
1690
2196
|
if (!isoString) return 'Never';
|
|
@@ -1750,8 +2256,6 @@ export function getDashboardHTML() {
|
|
|
1750
2256
|
|
|
1751
2257
|
// Update config display
|
|
1752
2258
|
function updateConfig(config) {
|
|
1753
|
-
projectPath.textContent = config.projectPath || '-';
|
|
1754
|
-
|
|
1755
2259
|
// Update project name in header
|
|
1756
2260
|
if (config.projectName) {
|
|
1757
2261
|
projectNameHeader.textContent = config.projectName;
|
|
@@ -1760,33 +2264,12 @@ export function getDashboardHTML() {
|
|
|
1760
2264
|
projectNameHeader.textContent = config.projectPath.split('/').pop() || config.projectPath;
|
|
1761
2265
|
}
|
|
1762
2266
|
|
|
1763
|
-
|
|
1764
|
-
chunkSize.textContent = config.chunking.maxLines + ' lines (overlap: ' + config.chunking.overlap + ')';
|
|
1765
|
-
}
|
|
1766
|
-
|
|
1767
|
-
if (config.search) {
|
|
1768
|
-
searchWeights.textContent = 'Semantic: ' + (config.search.semanticWeight * 100) + '%, Keyword: ' + (config.search.keywordWeight * 100) + '%';
|
|
1769
|
-
}
|
|
1770
|
-
|
|
1771
|
-
// Update patterns
|
|
2267
|
+
// Update Settings tab pattern chips
|
|
1772
2268
|
if (config.patterns) {
|
|
1773
|
-
|
|
1774
|
-
.slice(0, 10)
|
|
1775
|
-
.map(p => '<span class="pattern-tag">' + escapeHtml(p) + '</span>')
|
|
1776
|
-
.join('');
|
|
1777
|
-
if (config.patterns.length > 10) {
|
|
1778
|
-
includePatterns.innerHTML += '<span class="pattern-tag">+' + (config.patterns.length - 10) + ' more</span>';
|
|
1779
|
-
}
|
|
2269
|
+
renderPatternChips(includePatternsChips, config.patterns, 'include', includePatternsCount);
|
|
1780
2270
|
}
|
|
1781
|
-
|
|
1782
2271
|
if (config.excludePatterns) {
|
|
1783
|
-
|
|
1784
|
-
.slice(0, 6)
|
|
1785
|
-
.map(p => '<span class="pattern-tag exclude">' + escapeHtml(p) + '</span>')
|
|
1786
|
-
.join('');
|
|
1787
|
-
if (config.excludePatterns.length > 6) {
|
|
1788
|
-
excludePatterns.innerHTML += '<span class="pattern-tag exclude">+' + (config.excludePatterns.length - 6) + ' more</span>';
|
|
1789
|
-
}
|
|
2272
|
+
renderPatternChips(excludePatternsChips, config.excludePatterns, 'exclude', excludePatternsCount);
|
|
1790
2273
|
}
|
|
1791
2274
|
}
|
|
1792
2275
|
|
|
@@ -1945,17 +2428,27 @@ export function getDashboardHTML() {
|
|
|
1945
2428
|
const beadsTotalCount = document.getElementById('beadsTotalCount');
|
|
1946
2429
|
const beadsDaemonDot = document.getElementById('beadsDaemonDot');
|
|
1947
2430
|
const beadsDaemonText = document.getElementById('beadsDaemonText');
|
|
1948
|
-
const beadsSyncBranch = document.getElementById('beadsSyncBranch');
|
|
1949
2431
|
const beadsIssuesList = document.getElementById('beadsIssuesList');
|
|
1950
2432
|
const readyTasksBadge = document.getElementById('readyTasksBadge');
|
|
1951
2433
|
|
|
1952
2434
|
function updateBeads(data) {
|
|
2435
|
+
const beadsUnavailable = document.getElementById('beadsUnavailable');
|
|
2436
|
+
const beadsContent = document.getElementById('beadsContent');
|
|
2437
|
+
const beadsHeaderStats = document.getElementById('beadsHeaderStats');
|
|
2438
|
+
const beadsBadgeEl = document.getElementById('beadsBadge');
|
|
2439
|
+
|
|
1953
2440
|
if (!data.available) {
|
|
1954
|
-
|
|
2441
|
+
beadsUnavailable.style.display = 'block';
|
|
2442
|
+
beadsContent.style.display = 'none';
|
|
2443
|
+
beadsHeaderStats.style.display = 'none';
|
|
2444
|
+
beadsBadgeEl.style.display = 'none';
|
|
1955
2445
|
return;
|
|
1956
2446
|
}
|
|
1957
2447
|
|
|
1958
|
-
|
|
2448
|
+
beadsUnavailable.style.display = 'none';
|
|
2449
|
+
beadsContent.style.display = 'block';
|
|
2450
|
+
beadsHeaderStats.style.display = 'flex';
|
|
2451
|
+
beadsBadgeEl.style.display = 'inline-flex';
|
|
1959
2452
|
beadsReadyCount.textContent = data.readyCount;
|
|
1960
2453
|
beadsOpenCount.textContent = data.openCount;
|
|
1961
2454
|
beadsTotalCount.textContent = data.issueCount;
|
|
@@ -1970,9 +2463,6 @@ export function getDashboardHTML() {
|
|
|
1970
2463
|
beadsDaemonText.textContent = 'Daemon not running';
|
|
1971
2464
|
}
|
|
1972
2465
|
|
|
1973
|
-
// Sync branch
|
|
1974
|
-
beadsSyncBranch.textContent = data.syncBranch || 'Not configured';
|
|
1975
|
-
|
|
1976
2466
|
// Issues list
|
|
1977
2467
|
if (data.issues && data.issues.length > 0) {
|
|
1978
2468
|
let html = '';
|