llms-py 2.0.25__py3-none-any.whl → 2.0.27__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.
llms/ui/Recents.mjs CHANGED
@@ -7,33 +7,33 @@ const RecentResults = {
7
7
  template:`
8
8
  <div class="flex-1 overflow-y-auto" @scroll="onScroll">
9
9
  <div class="mx-auto max-w-6xl px-4 py-4">
10
- <div class="text-sm text-gray-600 mb-3" v-if="threads.length">
10
+ <div class="text-sm text-gray-600 dark:text-gray-400 mb-3" v-if="threads.length">
11
11
  <span v-if="q">{{ filtered.length }} result{{ filtered.length===1?'':'s' }}</span>
12
12
  <span v-else>Searching {{ threads.length }} conversation{{ threads.length===1?'':'s' }}</span>
13
13
  </div>
14
14
 
15
- <div v-if="!threads.length" class="text-gray-500">No conversations yet.</div>
15
+ <div v-if="!threads.length" class="text-gray-500 dark:text-gray-400">No conversations yet.</div>
16
16
 
17
17
  <table class="w-full">
18
18
  <tbody>
19
- <tr v-for="t in displayed" :key="t.id" class="hover:bg-gray-50">
20
- <td class="py-3 px-1 border-b border-gray-200 max-w-3xl">
19
+ <tr v-for="t in displayed" :key="t.id" class="hover:bg-gray-50 dark:hover:bg-gray-800">
20
+ <td class="py-3 px-1 border-b border-gray-200 dark:border-gray-700 max-w-3xl">
21
21
  <button type="button" @click="open(t.id)" class="w-full text-left">
22
22
  <div class="flex items-start justify-between gap-3">
23
23
  <div class="min-w-0 flex-1">
24
- <div class="font-medium text-gray-900 truncate" :title="t.title">{{ t.title || 'Untitled chat' }}</div>
25
- <div class="mt-1 text-sm text-gray-600 line-clamp-2">
24
+ <div class="font-medium text-gray-900 dark:text-gray-100 truncate" :title="t.title">{{ t.title || 'Untitled chat' }}</div>
25
+ <div class="mt-1 text-sm text-gray-600 dark:text-gray-400 line-clamp-2">
26
26
  <div v-html="snippet(t)"></div>
27
27
  </div>
28
28
  </div>
29
29
  </div>
30
30
  </button>
31
31
  </td>
32
- <td class="py-3 px-1 border-b border-gray-200">
32
+ <td class="py-3 px-1 border-b border-gray-200 dark:border-gray-700">
33
33
  <div class="text-right whitespace-nowrap">
34
- <div class="text-xs text-gray-500">{{ formatDate(t.updatedAt || t.createdAt) }}</div>
35
- <div class="text-[11px] text-gray-500/80">{{ (t.messages?.length || 0) }} messages</div>
36
- <div v-if="t.model" class="text-[11px] text-blue-600">{{ t.model }}</div>
34
+ <div class="text-xs text-gray-500 dark:text-gray-400">{{ formatDate(t.updatedAt || t.createdAt) }}</div>
35
+ <div class="text-[11px] text-gray-500/80 dark:text-gray-400/80">{{ (t.messages?.length || 0) }} messages</div>
36
+ <div v-if="t.model" class="text-[11px] text-blue-600 dark:text-blue-400">{{ t.model }}</div>
37
37
  </div>
38
38
  </td>
39
39
  </tr>
@@ -152,16 +152,16 @@ export default {
152
152
  template: `
153
153
  <div class="flex flex-col h-full w-full">
154
154
  <!-- Header -->
155
- <div class="border-b border-gray-200 bg-white px-4 py-3 min-h-16">
155
+ <div class="border-b border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 px-4 py-3 min-h-16">
156
156
  <div class="max-w-6xl mx-auto flex items-center justify-between gap-3">
157
- <h2 class="text-lg font-semibold text-gray-900">Search Chats</h2>
157
+ <h2 class="text-lg font-semibold text-gray-900 dark:text-gray-100">Search Chats</h2>
158
158
  <div class="flex-1 flex items-center gap-2">
159
159
  <input
160
160
  v-model="q"
161
161
  type="search"
162
162
  placeholder="Search titles and messages..."
163
163
  spellcheck="false"
164
- class="w-full rounded-md border border-gray-300 px-3 py-2 text-sm placeholder-gray-500 focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500"
164
+ class="w-full rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100 px-3 py-2 text-sm placeholder-gray-500 dark:placeholder-gray-400 focus:border-blue-500 dark:focus:border-blue-400 focus:outline-none focus:ring-1 focus:ring-blue-500 dark:focus:ring-blue-400"
165
165
  />
166
166
  </div>
167
167
  </div>
@@ -113,11 +113,11 @@ export default {
113
113
  <div class="fixed inset-0 bg-black/40 transition-opacity" @click="close"></div>
114
114
 
115
115
  <!-- Dialog -->
116
- <div class="relative bg-white rounded-lg shadow-xl max-w-2xl w-full max-h-[90vh] overflow-hidden">
116
+ <div class="relative bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-2xl w-full max-h-[90vh] overflow-hidden">
117
117
  <!-- Header -->
118
- <div class="flex items-center justify-between px-6 py-4 border-b border-gray-200">
119
- <h2 class="text-xl font-semibold text-gray-900">Chat Request Settings</h2>
120
- <button type="button" @click="close" class="text-gray-400 hover:text-gray-600">
118
+ <div class="flex items-center justify-between px-6 py-4 border-b border-gray-200 dark:border-gray-700">
119
+ <h2 class="text-xl font-semibold text-gray-900 dark:text-gray-100">Chat Request Settings</h2>
120
+ <button type="button" @click="close" class="text-gray-400 dark:text-gray-500 hover:text-gray-600 dark:hover:text-gray-300">
121
121
  <svg class="size-6" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
122
122
  <path fill="currentColor" d="M19 6.41L17.59 5L12 10.59L6.41 5L5 6.41L10.59 12L5 17.59L6.41 19L12 13.41L17.59 19L19 17.59L13.41 12z"/>
123
123
  </svg>
@@ -126,201 +126,201 @@ export default {
126
126
 
127
127
  <!-- Content -->
128
128
  <form class="px-6 py-4 overflow-y-auto max-h-[calc(90vh-140px)]" @submit.prevent="save">
129
- <p class="text-sm text-gray-600 mb-4">
129
+ <p class="text-sm text-gray-600 dark:text-gray-400 mb-4">
130
130
  Configure default values for chat request options. Leave empty to use model defaults.
131
131
  </p>
132
132
 
133
133
  <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
134
134
  <!-- Temperature -->
135
135
  <div>
136
- <label class="block text-sm font-medium text-gray-700 mb-1">
136
+ <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
137
137
  Temperature
138
- <span class="text-gray-500 font-normal">(0-2)</span>
138
+ <span class="text-gray-500 dark:text-gray-400 font-normal">(0-2)</span>
139
139
  </label>
140
- <input type="number" v-model="localSettings.temperature"
140
+ <input type="number" v-model="localSettings.temperature"
141
141
  step="0.1" min="0" max="2"
142
142
  placeholder="e.g., 0.7"
143
- class="block w-full rounded-md border border-gray-300 px-3 py-2 text-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500" />
144
- <p class="mt-1 text-xs text-gray-500">Higher values more random, lower for more focus</p>
143
+ class="block w-full rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100 px-3 py-2 text-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500" />
144
+ <p class="mt-1 text-xs text-gray-500 dark:text-gray-400">Higher values more random, lower for more focus</p>
145
145
  </div>
146
146
 
147
147
  <!-- Max Completion Tokens -->
148
148
  <div>
149
- <label class="block text-sm font-medium text-gray-700 mb-1">
149
+ <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
150
150
  Max Completion Tokens
151
151
  </label>
152
- <input type="number" v-model="localSettings.max_completion_tokens"
152
+ <input type="number" v-model="localSettings.max_completion_tokens"
153
153
  step="1" min="1"
154
154
  placeholder="e.g., 2048"
155
- class="block w-full rounded-md border border-gray-300 px-3 py-2 text-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500" />
156
- <p class="mt-1 text-xs text-gray-500">Max tokens for completion (inc. reasoning tokens)</p>
155
+ class="block w-full rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100 px-3 py-2 text-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500" />
156
+ <p class="mt-1 text-xs text-gray-500 dark:text-gray-400">Max tokens for completion (inc. reasoning tokens)</p>
157
157
  </div>
158
158
 
159
159
  <!-- Seed -->
160
160
  <div>
161
- <label class="block text-sm font-medium text-gray-700 mb-1">
161
+ <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
162
162
  Seed
163
163
  </label>
164
- <input type="number" v-model="localSettings.seed"
164
+ <input type="number" v-model="localSettings.seed"
165
165
  step="1"
166
166
  placeholder="e.g., 42"
167
- class="block w-full rounded-md border border-gray-300 px-3 py-2 text-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500" />
168
- <p class="mt-1 text-xs text-gray-500">For deterministic sampling (Beta feature)</p>
167
+ class="block w-full rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100 px-3 py-2 text-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500" />
168
+ <p class="mt-1 text-xs text-gray-500 dark:text-gray-400">For deterministic sampling (Beta feature)</p>
169
169
  </div>
170
170
 
171
171
  <!-- Top P -->
172
172
  <div>
173
- <label class="block text-sm font-medium text-gray-700 mb-1">
173
+ <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
174
174
  Top P
175
- <span class="text-gray-500 font-normal">(0-1)</span>
175
+ <span class="text-gray-500 dark:text-gray-400 font-normal">(0-1)</span>
176
176
  </label>
177
- <input type="number" v-model="localSettings.top_p"
177
+ <input type="number" v-model="localSettings.top_p"
178
178
  step="0.1" min="0" max="1"
179
179
  placeholder="e.g., 0.9"
180
- class="block w-full rounded-md border border-gray-300 px-3 py-2 text-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500" />
181
- <p class="mt-1 text-xs text-gray-500">Nucleus sampling - alternative to temperature</p>
180
+ class="block w-full rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100 px-3 py-2 text-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500" />
181
+ <p class="mt-1 text-xs text-gray-500 dark:text-gray-400">Nucleus sampling - alternative to temperature</p>
182
182
  </div>
183
183
 
184
184
  <!-- Frequency Penalty -->
185
185
  <div>
186
- <label class="block text-sm font-medium text-gray-700 mb-1">
186
+ <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
187
187
  Frequency Penalty
188
- <span class="text-gray-500 font-normal">(-2.0 to 2.0)</span>
188
+ <span class="text-gray-500 dark:text-gray-400 font-normal">(-2.0 to 2.0)</span>
189
189
  </label>
190
- <input type="number" v-model="localSettings.frequency_penalty"
190
+ <input type="number" v-model="localSettings.frequency_penalty"
191
191
  step="0.1" min="-2" max="2"
192
192
  placeholder="e.g., 0.5"
193
- class="block w-full rounded-md border border-gray-300 px-3 py-2 text-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500" />
194
- <p class="mt-1 text-xs text-gray-500">Penalize tokens based on frequency in text</p>
193
+ class="block w-full rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100 px-3 py-2 text-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500" />
194
+ <p class="mt-1 text-xs text-gray-500 dark:text-gray-400">Penalize tokens based on frequency in text</p>
195
195
  </div>
196
196
 
197
197
  <!-- Presence Penalty -->
198
198
  <div>
199
- <label class="block text-sm font-medium text-gray-700 mb-1">
199
+ <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
200
200
  Presence Penalty
201
- <span class="text-gray-500 font-normal">(-2.0 to 2.0)</span>
201
+ <span class="text-gray-500 dark:text-gray-400 font-normal">(-2.0 to 2.0)</span>
202
202
  </label>
203
- <input type="number" v-model="localSettings.presence_penalty"
203
+ <input type="number" v-model="localSettings.presence_penalty"
204
204
  step="0.1" min="-2" max="2"
205
205
  placeholder="e.g., 0.5"
206
- class="block w-full rounded-md border border-gray-300 px-3 py-2 text-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500" />
207
- <p class="mt-1 text-xs text-gray-500">Penalize tokens based on presence in text</p>
206
+ class="block w-full rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100 px-3 py-2 text-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500" />
207
+ <p class="mt-1 text-xs text-gray-500 dark:text-gray-400">Penalize tokens based on presence in text</p>
208
208
  </div>
209
209
 
210
210
  <!-- Stop Sequences -->
211
211
  <div>
212
- <label for="stop" class="block text-sm font-medium text-gray-700 mb-1">
212
+ <label for="stop" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
213
213
  Stop Sequences
214
214
  </label>
215
215
  <TagInput id="stop" inputClass="h-[37px] !shadow-none"
216
216
  v-model="localSettings.stop"
217
- placeholder=""
217
+ placeholder=""
218
218
  label=""
219
219
  />
220
- <p class="mt-1 text-xs text-gray-500">Up to 4 sequences where API stops generating</p>
220
+ <p class="mt-1 text-xs text-gray-500 dark:text-gray-400">Up to 4 sequences where API stops generating</p>
221
221
  </div>
222
222
 
223
223
  <!-- Reasoning Effort -->
224
224
  <div>
225
- <label class="block text-sm font-medium text-gray-700 mb-1">
225
+ <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
226
226
  Reasoning Effort
227
227
  </label>
228
228
  <select v-model="localSettings.reasoning_effort"
229
- class="block w-full rounded-md border border-gray-300 px-3 py-2 text-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500">
229
+ class="block w-full rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100 px-3 py-2 text-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500">
230
230
  <option value="">Default</option>
231
231
  <option value="minimal">Minimal</option>
232
232
  <option value="low">Low</option>
233
233
  <option value="medium">Medium</option>
234
234
  <option value="high">High</option>
235
235
  </select>
236
- <p class="mt-1 text-xs text-gray-500">Constrains effort on reasoning for reasoning models</p>
236
+ <p class="mt-1 text-xs text-gray-500 dark:text-gray-400">Constrains effort on reasoning for reasoning models</p>
237
237
  </div>
238
238
 
239
239
  <!-- Verbosity -->
240
240
  <div>
241
- <label class="block text-sm font-medium text-gray-700 mb-1">
241
+ <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
242
242
  Verbosity
243
243
  </label>
244
244
  <select v-model="localSettings.verbosity"
245
- class="block w-full rounded-md border border-gray-300 px-3 py-2 text-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500">
245
+ class="block w-full rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100 px-3 py-2 text-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500">
246
246
  <option value="">Default</option>
247
247
  <option value="low">Low</option>
248
248
  <option value="medium">Medium</option>
249
249
  <option value="high">High</option>
250
250
  </select>
251
- <p class="mt-1 text-xs text-gray-500">Constrains verbosity of model's response</p>
251
+ <p class="mt-1 text-xs text-gray-500 dark:text-gray-400">Constrains verbosity of model's response</p>
252
252
  </div>
253
253
 
254
254
  <!-- Service Tier -->
255
255
  <div>
256
- <label class="block text-sm font-medium text-gray-700 mb-1">
256
+ <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
257
257
  Service Tier
258
258
  </label>
259
- <input type="text" v-model="localSettings.service_tier"
259
+ <input type="text" v-model="localSettings.service_tier"
260
260
  placeholder="e.g., auto, default"
261
- class="block w-full rounded-md border border-gray-300 px-3 py-2 text-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500" />
262
- <p class="mt-1 text-xs text-gray-500">Processing type for serving the request</p>
261
+ class="block w-full rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100 px-3 py-2 text-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500" />
262
+ <p class="mt-1 text-xs text-gray-500 dark:text-gray-400">Processing type for serving the request</p>
263
263
  </div>
264
264
 
265
265
  <!-- Top Logprobs -->
266
266
  <div>
267
- <label class="block text-sm font-medium text-gray-700 mb-1">
267
+ <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
268
268
  Top Logprobs
269
- <span class="text-gray-500 font-normal">(0-20)</span>
269
+ <span class="text-gray-500 dark:text-gray-400 font-normal">(0-20)</span>
270
270
  </label>
271
- <input type="number" v-model="localSettings.top_logprobs"
271
+ <input type="number" v-model="localSettings.top_logprobs"
272
272
  step="1" min="0" max="20"
273
273
  placeholder="e.g., 5"
274
- class="block w-full rounded-md border border-gray-300 px-3 py-2 text-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500" />
275
- <p class="mt-1 text-xs text-gray-500">Number of most likely tokens to return with log probs</p>
274
+ class="block w-full rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100 px-3 py-2 text-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500" />
275
+ <p class="mt-1 text-xs text-gray-500 dark:text-gray-400">Number of most likely tokens to return with log probs</p>
276
276
  </div>
277
277
 
278
278
  <!-- Safety Identifier -->
279
279
  <div>
280
- <label class="block text-sm font-medium text-gray-700 mb-1">
280
+ <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
281
281
  Safety Identifier
282
282
  </label>
283
- <input type="text" v-model="localSettings.safety_identifier"
283
+ <input type="text" v-model="localSettings.safety_identifier"
284
284
  placeholder="Unique user identifier"
285
- class="block w-full rounded-md border border-gray-300 px-3 py-2 text-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500" />
286
- <p class="mt-1 text-xs text-gray-500">Identifier to help detect policy violations</p>
285
+ class="block w-full rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100 px-3 py-2 text-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500" />
286
+ <p class="mt-1 text-xs text-gray-500 dark:text-gray-400">Identifier to help detect policy violations</p>
287
287
  </div>
288
288
 
289
289
  <!-- Store -->
290
290
  <div>
291
291
  <label class="flex items-center">
292
292
  <input type="checkbox" v-model="localSettings.store"
293
- class="rounded border-gray-300 text-blue-600 focus:ring-blue-500" />
294
- <span class="ml-2 text-sm font-medium text-gray-700">Store Output</span>
293
+ class="rounded border-gray-300 dark:border-gray-600 text-blue-600 focus:ring-blue-500" />
294
+ <span class="ml-2 text-sm font-medium text-gray-700 dark:text-gray-300">Store Output</span>
295
295
  </label>
296
- <p class="mt-1 text-xs text-gray-500">Store output for model distillation or evals</p>
296
+ <p class="mt-1 text-xs text-gray-500 dark:text-gray-400">Store output for model distillation or evals</p>
297
297
  </div>
298
298
 
299
299
  <!-- Enable Thinking -->
300
300
  <div>
301
301
  <label class="flex items-center">
302
302
  <input type="checkbox" v-model="localSettings.enable_thinking"
303
- class="rounded border-gray-300 text-blue-600 focus:ring-blue-500" />
304
- <span class="ml-2 text-sm font-medium text-gray-700">Enable Thinking</span>
303
+ class="rounded border-gray-300 dark:border-gray-600 text-blue-600 focus:ring-blue-500" />
304
+ <span class="ml-2 text-sm font-medium text-gray-700 dark:text-gray-300">Enable Thinking</span>
305
305
  </label>
306
- <p class="mt-1 text-xs text-gray-500">Enable thinking mode for supported models (Qwen)</p>
306
+ <p class="mt-1 text-xs text-gray-500 dark:text-gray-400">Enable thinking mode for supported models (Qwen)</p>
307
307
  </div>
308
308
  </div>
309
309
  </form>
310
310
 
311
311
  <!-- Footer -->
312
- <div class="flex items-center justify-between px-6 py-4 border-t border-gray-200 bg-gray-50">
312
+ <div class="flex items-center justify-between px-6 py-4 border-t border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-800">
313
313
  <button type="button" @click="reset"
314
- class="px-4 py-2 text-sm font-medium text-gray-700 hover:text-gray-900">
314
+ class="px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:text-gray-900 dark:hover:text-gray-100">
315
315
  Reset to Defaults
316
316
  </button>
317
317
  <div class="flex space-x-3">
318
318
  <button type="button" @click="close"
319
- class="px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-md hover:bg-gray-50">
319
+ class="px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-600 rounded-md hover:bg-gray-50 dark:hover:bg-gray-700">
320
320
  Cancel
321
321
  </button>
322
322
  <button type="submit" @click="save"
323
- class="px-4 py-2 text-sm font-medium text-white bg-blue-600 rounded-md hover:bg-blue-700">
323
+ class="px-4 py-2 text-sm font-medium text-white bg-blue-600 dark:bg-blue-500 rounded-md hover:bg-blue-700 dark:hover:bg-blue-600">
324
324
  Save Settings
325
325
  </button>
326
326
  </div>
llms/ui/Sidebar.mjs CHANGED
@@ -12,22 +12,22 @@ const ThreadItem = {
12
12
  template: `
13
13
  <div
14
14
  class="group relative mx-2 mb-1 rounded-md cursor-pointer transition-colors border border-transparent"
15
- :class="isActive ? 'bg-blue-100 border-blue-200' : 'hover:bg-gray-100'"
15
+ :class="isActive ? 'bg-blue-100 dark:bg-blue-900 border-blue-200 dark:border-blue-700' : 'hover:bg-gray-100 dark:hover:bg-gray-800'"
16
16
  @click="$emit('select', thread.id)"
17
17
  >
18
18
  <div class="flex items-center px-3 py-2">
19
19
  <div class="flex-1 min-w-0">
20
- <div class="text-sm font-medium text-gray-900 truncate" :title="thread.title">
20
+ <div class="text-sm font-medium text-gray-900 dark:text-gray-100 truncate" :title="thread.title">
21
21
  {{ thread.title }}
22
22
  </div>
23
- <div class="text-xs text-gray-500 truncate">
23
+ <div class="text-xs text-gray-500 dark:text-gray-400 truncate">
24
24
  <span>{{ formatRelativeTime(thread.updatedAt) }} • {{ thread.messages.length }} msgs</span>
25
25
  <span v-if="thread.stats?.inputTokens" :title="statsTitle(thread.stats)">
26
26
  &#8226; {{ humanifyNumber(thread.stats.inputTokens + thread.stats.outputTokens) }} toks
27
27
  {{ thread.stats.cost ? ' ' + formatCost(thread.stats.cost) : '' }}
28
28
  </span>
29
29
  </div>
30
- <div v-if="thread.model" class="text-xs text-blue-600 truncate">
30
+ <div v-if="thread.model" class="text-xs text-blue-600 dark:text-blue-400 truncate">
31
31
  {{ thread.model }}
32
32
  </div>
33
33
  </div>
@@ -35,7 +35,7 @@ const ThreadItem = {
35
35
  <!-- Delete button (shown on hover) -->
36
36
  <button type="button"
37
37
  @click.stop="$emit('delete', thread.id)"
38
- class="opacity-0 group-hover:opacity-100 ml-2 p-1 rounded text-gray-400 hover:text-red-600 hover:bg-red-50 transition-all"
38
+ class="opacity-0 group-hover:opacity-100 ml-2 p-1 rounded text-gray-400 dark:text-gray-500 hover:text-red-600 dark:hover:text-red-400 hover:bg-red-50 dark:hover:bg-red-900/30 transition-all"
39
39
  title="Delete conversation"
40
40
  >
41
41
  <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
@@ -89,7 +89,7 @@ const GroupedThreads = {
89
89
  template: `
90
90
  <!-- Today -->
91
91
  <div v-if="groupedThreads.today.length > 0" class="mb-4">
92
- <h3 class="px-4 py-2 text-xs font-semibold text-gray-500 uppercase tracking-wider select-none">Today</h3>
92
+ <h3 class="px-4 py-2 text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider select-none">Today</h3>
93
93
  <ThreadItem
94
94
  v-for="thread in groupedThreads.today"
95
95
  :key="thread.id"
@@ -102,7 +102,7 @@ const GroupedThreads = {
102
102
 
103
103
  <!-- Last 7 Days -->
104
104
  <div v-if="groupedThreads.lastWeek.length > 0" class="mb-4">
105
- <h3 class="px-4 py-2 text-xs font-semibold text-gray-500 uppercase tracking-wider select-none">Last 7 Days</h3>
105
+ <h3 class="px-4 py-2 text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider select-none">Last 7 Days</h3>
106
106
  <ThreadItem
107
107
  v-for="thread in groupedThreads.lastWeek"
108
108
  :key="thread.id"
@@ -115,7 +115,7 @@ const GroupedThreads = {
115
115
 
116
116
  <!-- Last 30 Days -->
117
117
  <div v-if="groupedThreads.lastMonth.length > 0" class="mb-4">
118
- <h3 class="px-4 py-2 text-xs font-semibold text-gray-500 uppercase tracking-wider select-none">Last 30 Days</h3>
118
+ <h3 class="px-4 py-2 text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider select-none">Last 30 Days</h3>
119
119
  <ThreadItem
120
120
  v-for="thread in groupedThreads.lastMonth"
121
121
  :key="thread.id"
@@ -128,7 +128,7 @@ const GroupedThreads = {
128
128
 
129
129
  <!-- Older (grouped by month/year) -->
130
130
  <div v-for="(monthThreads, monthKey) in groupedThreads.older" :key="monthKey" class="mb-4">
131
- <h3 class="px-4 py-2 text-xs font-semibold text-gray-500 uppercase tracking-wider select-none">{{ monthKey }}</h3>
131
+ <h3 class="px-4 py-2 text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider select-none">{{ monthKey }}</h3>
132
132
  <ThreadItem
133
133
  v-for="thread in monthThreads"
134
134
  :key="thread.id"
@@ -140,7 +140,7 @@ const GroupedThreads = {
140
140
  </div>
141
141
  <div class="mb-4 flex w-full justify-center">
142
142
  <button @click="$router.push($ai.base + '/recents')" type="button"
143
- class="flex text-sm space-x-1 font-semibold text-gray-900 hover:text-blue-600 focus:outline-none transition-colors">
143
+ class="flex text-sm space-x-1 font-semibold text-gray-900 dark:text-gray-100 hover:text-blue-600 dark:hover:text-blue-400 focus:outline-none transition-colors">
144
144
  <svg class="size-5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill="currentColor" d="M8 2.19c3.13 0 5.68 2.25 5.68 5s-2.55 5-5.68 5a5.7 5.7 0 0 1-1.89-.29l-.75-.26l-.56.56a14 14 0 0 1-2 1.55a.13.13 0 0 1-.07 0v-.06a6.58 6.58 0 0 0 .15-4.29a5.25 5.25 0 0 1-.55-2.16c0-2.77 2.55-5 5.68-5M8 .94c-3.83 0-6.93 2.81-6.93 6.27a6.4 6.4 0 0 0 .64 2.64a5.53 5.53 0 0 1-.18 3.48a1.32 1.32 0 0 0 2 1.5a15 15 0 0 0 2.16-1.71a6.8 6.8 0 0 0 2.31.36c3.83 0 6.93-2.81 6.93-6.27S11.83.94 8 .94"></path><ellipse cx="5.2" cy="7.7" fill="currentColor" rx=".8" ry=".75"></ellipse><ellipse cx="8" cy="7.7" fill="currentColor" rx=".8" ry=".75"></ellipse><ellipse cx="10.8" cy="7.7" fill="currentColor" rx=".8" ry=".75"></ellipse></svg>
145
145
  <span>All Chats</span>
146
146
  </button>
@@ -163,26 +163,26 @@ const Sidebar = {
163
163
  ThreadItem,
164
164
  },
165
165
  template: `
166
- <div class="flex flex-col h-full bg-gray-50 border-r border-gray-200">
166
+ <div class="flex flex-col h-full bg-gray-50 dark:bg-gray-800 border-r border-gray-200 dark:border-gray-700">
167
167
  <Brand @home="goToInitialState" @new="createNewThread" @analytics="goToAnalytics" />
168
168
  <!-- Thread List -->
169
169
  <div class="flex-1 overflow-y-auto">
170
- <div v-if="isLoading" class="p-4 text-center text-gray-500">
171
- <div class="animate-spin rounded-full h-6 w-6 border-b-2 border-blue-600 mx-auto"></div>
170
+ <div v-if="isLoading" class="p-4 text-center text-gray-500 dark:text-gray-400">
171
+ <div class="animate-spin rounded-full h-6 w-6 border-b-2 border-blue-600 dark:border-blue-400 mx-auto"></div>
172
172
  <p class="mt-2 text-sm">Loading threads...</p>
173
173
  </div>
174
174
 
175
- <div v-else-if="threads.length === 0" class="p-4 text-center text-gray-500">
175
+ <div v-else-if="threads.length === 0" class="p-4 text-center text-gray-500 dark:text-gray-400">
176
176
  <div class="mb-2 flex justify-center">
177
177
  <svg class="size-8" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill="currentColor" d="M8 2.19c3.13 0 5.68 2.25 5.68 5s-2.55 5-5.68 5a5.7 5.7 0 0 1-1.89-.29l-.75-.26l-.56.56a14 14 0 0 1-2 1.55a.13.13 0 0 1-.07 0v-.06a6.58 6.58 0 0 0 .15-4.29a5.25 5.25 0 0 1-.55-2.16c0-2.77 2.55-5 5.68-5M8 .94c-3.83 0-6.93 2.81-6.93 6.27a6.4 6.4 0 0 0 .64 2.64a5.53 5.53 0 0 1-.18 3.48a1.32 1.32 0 0 0 2 1.5a15 15 0 0 0 2.16-1.71a6.8 6.8 0 0 0 2.31.36c3.83 0 6.93-2.81 6.93-6.27S11.83.94 8 .94"/><ellipse cx="5.2" cy="7.7" fill="currentColor" rx=".8" ry=".75"/><ellipse cx="8" cy="7.7" fill="currentColor" rx=".8" ry=".75"/><ellipse cx="10.8" cy="7.7" fill="currentColor" rx=".8" ry=".75"/></svg>
178
178
  </div>
179
179
  <p class="text-sm">No conversations yet</p>
180
- <p class="text-xs text-gray-400 mt-1">Start a new chat to begin</p>
180
+ <p class="text-xs text-gray-400 dark:text-gray-500 mt-1">Start a new chat to begin</p>
181
181
  </div>
182
182
 
183
183
  <div v-else class="py-2">
184
- <GroupedThreads :currentThread="currentThread" :groupedThreads="threadStore.getGroupedThreads(18)"
185
- @select="selectThread" @delete="deleteThread" />
184
+ <GroupedThreads :currentThread="currentThread" :groupedThreads="threadStore.getGroupedThreads(18)"
185
+ @select="selectThread" @delete="deleteThread" />
186
186
  </div>
187
187
  </div>
188
188
  </div>
@@ -1,10 +1,10 @@
1
1
  export default {
2
2
  template:`
3
- <div class="border-b border-gray-200 bg-gray-50 px-6 py-4">
3
+ <div class="border-b border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-800 px-6 py-4">
4
4
  <div class="max-w-6xl mx-auto">
5
- <label class="block text-sm font-medium text-gray-700 mb-2">
5
+ <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
6
6
  System Prompt
7
- <span v-if="selected" class="text-gray-500 font-normal">
7
+ <span v-if="selected" class="text-gray-500 dark:text-gray-400 font-normal">
8
8
  ({{ prompts.find(p => p.id === selected.id)?.name || 'Custom' }})
9
9
  </span>
10
10
  </label>
@@ -12,9 +12,9 @@ export default {
12
12
  :value="modelValue" @input="$emit('update:modelValue', $event.target.value)"
13
13
  placeholder="Enter a system prompt to guide AI's behavior..."
14
14
  rows="6"
15
- class="block w-full resize-vertical rounded-md border border-gray-300 px-3 py-2 text-sm placeholder-gray-500 focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500"
15
+ class="block w-full resize-vertical rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100 px-3 py-2 text-sm placeholder-gray-500 dark:placeholder-gray-400 focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500"
16
16
  ></textarea>
17
- <div class="mt-2 text-xs text-gray-500">
17
+ <div class="mt-2 text-xs text-gray-500 dark:text-gray-400">
18
18
  You can modify this system prompt before sending messages. Changes will only apply to new conversations.
19
19
  </div>
20
20
  </div>
@@ -1,9 +1,9 @@
1
1
  export default {
2
2
  template:`
3
3
  <button v-if="modelValue" type="button" title="Clear System Prompt" @click="$emit('update:modelValue', null)">
4
- <svg class="size-4 text-gray-500" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="currentColor" d="M19 6.41L17.59 5L12 10.59L6.41 5L5 6.41L10.59 12L5 17.59L6.41 19L12 13.41L17.59 19L19 17.59L13.41 12z"/></svg>
4
+ <svg class="size-4 text-gray-500 dark:text-gray-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="currentColor" d="M19 6.41L17.59 5L12 10.59L6.41 5L5 6.41L10.59 12L5 17.59L6.41 19L12 13.41L17.59 19L19 17.59L13.41 12z"/></svg>
5
5
  </button>
6
-
6
+
7
7
  <Autocomplete id="prompt" :options="prompts" label=""
8
8
  :modelValue="modelValue" @update:modelValue="$emit('update:modelValue', $event)"
9
9
  class="w-72 xl:w-84"
@@ -17,8 +17,8 @@ export default {
17
17
  <!-- Toggle System Prompt Visibility -->
18
18
  <button type="button"
19
19
  @click="$emit('toggle')"
20
- :class="show ? 'text-blue-700' : 'text-gray-600'"
21
- class="p-1 rounded-md hover:bg-blue-100 hover:text-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2"
20
+ :class="show ? 'text-blue-700 dark:text-blue-400' : 'text-gray-600 dark:text-gray-400'"
21
+ class="p-1 rounded-md hover:bg-blue-100 dark:hover:bg-blue-900/30 hover:text-blue-700 dark:hover:text-blue-400 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2"
22
22
  :title="show ? 'Hide system prompt' : 'Show system prompt'"
23
23
  >
24
24
  <svg v-if="!show" class="size-6" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="currentColor" d="M33.62 17.53c-3.37-6.23-9.28-10-15.82-10S5.34 11.3 2 17.53l-.28.47l.26.48c3.37 6.23 9.28 10 15.82 10s12.46-3.72 15.82-10l.26-.48Zm-15.82 8.9C12.17 26.43 7 23.29 4 18c3-5.29 8.17-8.43 13.8-8.43S28.54 12.72 31.59 18c-3.05 5.29-8.17 8.43-13.79 8.43"/><path fill="currentColor" d="M18.09 11.17A6.86 6.86 0 1 0 25 18a6.86 6.86 0 0 0-6.91-6.83m0 11.72A4.86 4.86 0 1 1 23 18a4.87 4.87 0 0 1-4.91 4.89"/><path fill="none" d="M0 0h36v36H0z"/></svg>
llms/ui/Welcome.mjs CHANGED
@@ -1,8 +1,8 @@
1
1
  export default {
2
2
  template: `
3
3
  <div class="mb-2 flex justify-center">
4
- <svg class="size-20 text-gray-700" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill="currentColor" d="M8 2.19c3.13 0 5.68 2.25 5.68 5s-2.55 5-5.68 5a5.7 5.7 0 0 1-1.89-.29l-.75-.26l-.56.56a14 14 0 0 1-2 1.55a.13.13 0 0 1-.07 0v-.06a6.58 6.58 0 0 0 .15-4.29a5.25 5.25 0 0 1-.55-2.16c0-2.77 2.55-5 5.68-5M8 .94c-3.83 0-6.93 2.81-6.93 6.27a6.4 6.4 0 0 0 .64 2.64a5.53 5.53 0 0 1-.18 3.48a1.32 1.32 0 0 0 2 1.5a15 15 0 0 0 2.16-1.71a6.8 6.8 0 0 0 2.31.36c3.83 0 6.93-2.81 6.93-6.27S11.83.94 8 .94"/><ellipse cx="5.2" cy="7.7" fill="currentColor" rx=".8" ry=".75"/><ellipse cx="8" cy="7.7" fill="currentColor" rx=".8" ry=".75"/><ellipse cx="10.8" cy="7.7" fill="currentColor" rx=".8" ry=".75"/></svg>
4
+ <svg class="size-20 text-gray-700 dark:text-gray-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill="currentColor" d="M8 2.19c3.13 0 5.68 2.25 5.68 5s-2.55 5-5.68 5a5.7 5.7 0 0 1-1.89-.29l-.75-.26l-.56.56a14 14 0 0 1-2 1.55a.13.13 0 0 1-.07 0v-.06a6.58 6.58 0 0 0 .15-4.29a5.25 5.25 0 0 1-.55-2.16c0-2.77 2.55-5 5.68-5M8 .94c-3.83 0-6.93 2.81-6.93 6.27a6.4 6.4 0 0 0 .64 2.64a5.53 5.53 0 0 1-.18 3.48a1.32 1.32 0 0 0 2 1.5a15 15 0 0 0 2.16-1.71a6.8 6.8 0 0 0 2.31.36c3.83 0 6.93-2.81 6.93-6.27S11.83.94 8 .94"/><ellipse cx="5.2" cy="7.7" fill="currentColor" rx=".8" ry=".75"/><ellipse cx="8" cy="7.7" fill="currentColor" rx=".8" ry=".75"/><ellipse cx="10.8" cy="7.7" fill="currentColor" rx=".8" ry=".75"/></svg>
5
5
  </div>
6
- <h2 class="text-2xl font-semibold text-gray-900 mb-2">{{ $ai.welcome }}</h2>
6
+ <h2 class="text-2xl font-semibold text-gray-900 dark:text-gray-100 mb-2">{{ $ai.welcome }}</h2>
7
7
  `
8
8
  }