llms-py 3.0.0b2__py3-none-any.whl → 3.0.0b3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. llms/__pycache__/main.cpython-314.pyc +0 -0
  2. llms/index.html +2 -1
  3. llms/llms.json +50 -17
  4. llms/main.py +484 -544
  5. llms/providers/__pycache__/anthropic.cpython-314.pyc +0 -0
  6. llms/providers/__pycache__/chutes.cpython-314.pyc +0 -0
  7. llms/providers/__pycache__/google.cpython-314.pyc +0 -0
  8. llms/providers/__pycache__/nvidia.cpython-314.pyc +0 -0
  9. llms/providers/__pycache__/openai.cpython-314.pyc +0 -0
  10. llms/providers/__pycache__/openrouter.cpython-314.pyc +0 -0
  11. llms/providers/anthropic.py +189 -0
  12. llms/providers/chutes.py +152 -0
  13. llms/providers/google.py +306 -0
  14. llms/providers/nvidia.py +107 -0
  15. llms/providers/openai.py +159 -0
  16. llms/providers/openrouter.py +70 -0
  17. llms/providers-extra.json +356 -0
  18. llms/providers.json +1 -1
  19. llms/ui/App.mjs +132 -60
  20. llms/ui/ai.mjs +76 -10
  21. llms/ui/app.css +1 -4962
  22. llms/ui/ctx.mjs +196 -0
  23. llms/ui/index.mjs +75 -171
  24. llms/ui/lib/charts.mjs +9 -13
  25. llms/ui/markdown.mjs +6 -0
  26. llms/ui/{Analytics.mjs → modules/analytics.mjs} +76 -64
  27. llms/ui/{Main.mjs → modules/chat/ChatBody.mjs} +56 -133
  28. llms/ui/{SettingsDialog.mjs → modules/chat/SettingsDialog.mjs} +8 -8
  29. llms/ui/{ChatPrompt.mjs → modules/chat/index.mjs} +239 -45
  30. llms/ui/modules/layout.mjs +267 -0
  31. llms/ui/modules/model-selector.mjs +851 -0
  32. llms/ui/{Recents.mjs → modules/threads/Recents.mjs} +0 -2
  33. llms/ui/{Sidebar.mjs → modules/threads/index.mjs} +46 -44
  34. llms/ui/{threadStore.mjs → modules/threads/threadStore.mjs} +10 -7
  35. llms/ui/utils.mjs +82 -123
  36. {llms_py-3.0.0b2.dist-info → llms_py-3.0.0b3.dist-info}/METADATA +1 -1
  37. llms_py-3.0.0b3.dist-info/RECORD +65 -0
  38. llms/ui/Avatar.mjs +0 -86
  39. llms/ui/Brand.mjs +0 -52
  40. llms/ui/OAuthSignIn.mjs +0 -61
  41. llms/ui/ProviderIcon.mjs +0 -36
  42. llms/ui/ProviderStatus.mjs +0 -104
  43. llms/ui/SignIn.mjs +0 -65
  44. llms/ui/Welcome.mjs +0 -8
  45. llms/ui/model-selector.mjs +0 -686
  46. llms/ui.json +0 -1069
  47. llms_py-3.0.0b2.dist-info/RECORD +0 -58
  48. {llms_py-3.0.0b2.dist-info → llms_py-3.0.0b3.dist-info}/WHEEL +0 -0
  49. {llms_py-3.0.0b2.dist-info → llms_py-3.0.0b3.dist-info}/entry_points.txt +0 -0
  50. {llms_py-3.0.0b2.dist-info → llms_py-3.0.0b3.dist-info}/licenses/LICENSE +0 -0
  51. {llms_py-3.0.0b2.dist-info → llms_py-3.0.0b3.dist-info}/top_level.txt +0 -0
@@ -1,29 +1,24 @@
1
- import { ref, onMounted, watch, nextTick, computed } from 'vue'
1
+ import { ref, onMounted, watch, nextTick, computed, inject } from 'vue'
2
2
  import { useRouter, useRoute } from 'vue-router'
3
- import { useFormatters } from "@servicestack/vue"
4
3
  import { leftPart } from '@servicestack/client'
5
4
  import { Chart, registerables } from "chart.js"
6
- import { useThreadStore } from './threadStore.mjs'
7
- import { formatCost } from './utils.mjs'
8
5
  Chart.register(...registerables)
9
6
 
10
- const { humanifyNumber, humanifyMs } = useFormatters()
11
-
12
7
  export const colors = [
13
- { background: 'rgba(54, 162, 235, 0.2)', border: 'rgb(54, 162, 235)' }, //blue
14
- { background: 'rgba(255, 99, 132, 0.2)', border: 'rgb(255, 99, 132)' },
8
+ { background: 'rgba(54, 162, 235, 0.2)', border: 'rgb(54, 162, 235)' }, //blue
9
+ { background: 'rgba(255, 99, 132, 0.2)', border: 'rgb(255, 99, 132)' },
15
10
  { background: 'rgba(153, 102, 255, 0.2)', border: 'rgb(153, 102, 255)' },
16
- { background: 'rgba(54, 162, 235, 0.2)', border: 'rgb(54, 162, 235)' },
17
- { background: 'rgba(255, 159, 64, 0.2)', border: 'rgb(255, 159, 64)' },
18
- { background: 'rgba(67, 56, 202, 0.2)', border: 'rgb(67, 56, 202)' },
19
- { background: 'rgba(255, 99, 132, 0.2)', border: 'rgb(255, 99, 132)' },
20
- { background: 'rgba(14, 116, 144, 0.2)', border: 'rgb(14, 116, 144)' },
21
- { background: 'rgba(162, 28, 175, 0.2)', border: 'rgb(162, 28, 175)' },
11
+ { background: 'rgba(54, 162, 235, 0.2)', border: 'rgb(54, 162, 235)' },
12
+ { background: 'rgba(255, 159, 64, 0.2)', border: 'rgb(255, 159, 64)' },
13
+ { background: 'rgba(67, 56, 202, 0.2)', border: 'rgb(67, 56, 202)' },
14
+ { background: 'rgba(255, 99, 132, 0.2)', border: 'rgb(255, 99, 132)' },
15
+ { background: 'rgba(14, 116, 144, 0.2)', border: 'rgb(14, 116, 144)' },
16
+ { background: 'rgba(162, 28, 175, 0.2)', border: 'rgb(162, 28, 175)' },
22
17
  { background: 'rgba(201, 203, 207, 0.2)', border: 'rgb(201, 203, 207)' },
23
18
  ]
24
19
 
25
20
  const MonthSelector = {
26
- template:`
21
+ template: `
27
22
  <div class="flex flex-col sm:flex-row gap-2 sm:gap-4 items-stretch sm:items-center w-full sm:w-auto">
28
23
  <!-- Months Row -->
29
24
  <div class="flex gap-1 sm:gap-2 flex-wrap justify-center overflow-x-auto">
@@ -109,10 +104,7 @@ const MonthSelector = {
109
104
  }
110
105
  }
111
106
 
112
- export default {
113
- components: {
114
- MonthSelector,
115
- },
107
+ export const Analytics = {
116
108
  template: `
117
109
  <div class="flex flex-col h-full w-full">
118
110
  <!-- Header -->
@@ -165,7 +157,7 @@ export default {
165
157
  <div v-if="activeTab !== 'activity'" class="grid grid-cols-1 md:grid-cols-4 gap-4 mb-6">
166
158
  <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-4">
167
159
  <div class="text-sm font-medium text-gray-600 dark:text-gray-400">Total Cost</div>
168
- <div class="text-2xl font-bold text-gray-900 dark:text-gray-100 mt-1">{{ formatCost(totalCost) }}</div>
160
+ <div class="text-2xl font-bold text-gray-900 dark:text-gray-100 mt-1">{{ $fmt.cost(totalCost) }}</div>
169
161
  </div>
170
162
  <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-4">
171
163
  <div class="text-sm font-medium text-gray-600 dark:text-gray-400">Total Requests</div>
@@ -173,11 +165,11 @@ export default {
173
165
  </div>
174
166
  <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-4">
175
167
  <div class="text-sm font-medium text-gray-600 dark:text-gray-400">Total Input Tokens</div>
176
- <div class="text-2xl font-bold text-gray-900 dark:text-gray-100 mt-1">{{ humanifyNumber(totalInputTokens) }}</div>
168
+ <div class="text-2xl font-bold text-gray-900 dark:text-gray-100 mt-1">{{ $fmt.humanifyNumber(totalInputTokens) }}</div>
177
169
  </div>
178
170
  <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-4">
179
171
  <div class="text-sm font-medium text-gray-600 dark:text-gray-400">Total Output Tokens</div>
180
- <div class="text-2xl font-bold text-gray-900 dark:text-gray-100 mt-1">{{ humanifyNumber(totalOutputTokens) }}</div>
172
+ <div class="text-2xl font-bold text-gray-900 dark:text-gray-100 mt-1">{{ $fmt.humanifyNumber(totalOutputTokens) }}</div>
181
173
  </div>
182
174
  </div>
183
175
 
@@ -224,11 +216,11 @@ export default {
224
216
  {{ new Date(selectedDay).toLocaleDateString(undefined, { year: 'numeric', month: 'long', day: 'numeric' }) }}
225
217
  </div>
226
218
  <div class="flex flex-wrap gap-x-2 gap-y-1">
227
- <span>{{ formatCost(allDailyData[selectedDay]?.cost || 0) }}</span>
219
+ <span>{{ $fmt.cost(allDailyData[selectedDay]?.cost || 0) }}</span>
228
220
  <span>&#183;</span>
229
221
  <span>{{ allDailyData[selectedDay]?.requests || 0 }} Requests</span>
230
222
  <span>&#183;</span>
231
- <span>{{ humanifyNumber(allDailyData[selectedDay]?.inputTokens || 0) }} -> {{ humanifyNumber(allDailyData[selectedDay]?.outputTokens || 0) }} Tokens</span>
223
+ <span>{{ $fmt.humanifyNumber(allDailyData[selectedDay]?.inputTokens || 0) }} -> {{ $fmt.humanifyNumber(allDailyData[selectedDay]?.outputTokens || 0) }} Tokens</span>
232
224
  </div>
233
225
  </div>
234
226
 
@@ -363,18 +355,18 @@ export default {
363
355
  <div class="grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-5 gap-3 sm:gap-4">
364
356
  <div :title="request.cost">
365
357
  <div class="text-xs text-gray-500 dark:text-gray-400 font-medium">Cost</div>
366
- <div class="text-sm font-semibold text-gray-900 dark:text-gray-100">{{ formatCost(request.cost) }}</div>
358
+ <div class="text-sm font-semibold text-gray-900 dark:text-gray-100">{{ $fmt.costLong(request.cost) }}</div>
367
359
  </div>
368
360
  <div class="col-span-2 sm:col-span-1">
369
361
  <div class="text-xs text-gray-500 dark:text-gray-400 font-medium">Tokens</div>
370
362
  <div class="text-sm font-semibold text-gray-900 dark:text-gray-100">
371
- {{ humanifyNumber(request.inputTokens) }} -> {{ humanifyNumber(request.outputTokens) }}
372
- <span v-if="request.inputCachedTokens" class="ml-1 text-xs text-gray-500 dark:text-gray-400">({{ humanifyNumber(request.inputCachedTokens) }} cached)</span>
363
+ {{ $fmt.humanifyNumber(request.inputTokens) }} -> {{ $fmt.humanifyNumber(request.outputTokens) }}
364
+ <span v-if="request.inputCachedTokens" class="ml-1 text-xs text-gray-500 dark:text-gray-400">({{ $fmt.humanifyNumber(request.inputCachedTokens) }} cached)</span>
373
365
  </div>
374
366
  </div>
375
367
  <div>
376
368
  <div class="text-xs text-gray-500 dark:text-gray-400 font-medium">Duration</div>
377
- <div class="text-sm font-semibold text-gray-900 dark:text-gray-100">{{ request.duration ? humanifyMs(request.duration) : '—' }}</div>
369
+ <div class="text-sm font-semibold text-gray-900 dark:text-gray-100">{{ request.duration ? $fmt.humanifyMs(request.duration) : '—' }}</div>
378
370
  </div>
379
371
  <div>
380
372
  <div class="text-xs text-gray-500 dark:text-gray-400 font-medium">Speed</div>
@@ -408,9 +400,10 @@ export default {
408
400
  </div>
409
401
  `,
410
402
  setup() {
403
+ const ctx = inject('ctx')
404
+ const threads = ctx.threads
411
405
  const router = useRouter()
412
406
  const route = useRoute()
413
- const threads = useThreadStore()
414
407
  const { initDB } = threads
415
408
 
416
409
  // Initialize activeTab from URL query parameter, default to 'cost'
@@ -802,7 +795,7 @@ export default {
802
795
  costChartInstance.destroy()
803
796
  }
804
797
 
805
- const ctx = costChartCanvas.value.getContext('2d')
798
+ const ctx2d = costChartCanvas.value.getContext('2d')
806
799
  const chartTypeValue = costChartType.value
807
800
 
808
801
  // Find the index of the selected day
@@ -833,7 +826,7 @@ export default {
833
826
  }]
834
827
  }
835
828
 
836
- costChartInstance = new Chart(ctx, {
829
+ costChartInstance = new Chart(ctx2d, {
837
830
  type: chartTypeValue,
838
831
  data: chartDataWithColors,
839
832
  options: {
@@ -859,14 +852,14 @@ export default {
859
852
  },
860
853
  tooltip: {
861
854
  callbacks: {
862
- title: function(context) {
855
+ title: function (context) {
863
856
  const index = context[0].dataIndex
864
857
  const dateKey = chartData.value.dateKeys[index]
865
858
  const date = new Date(dateKey + 'T00:00:00Z')
866
859
  return date.toLocaleDateString(undefined, { year: 'numeric', month: 'long', day: 'numeric' })
867
860
  },
868
- label: function(context) {
869
- return `Cost: ${formatCost(context.parsed.y)}`
861
+ label: function (context) {
862
+ return `Cost: ${ctx.fmt.cost(context.parsed.y)}`
870
863
  }
871
864
  }
872
865
  }
@@ -875,7 +868,7 @@ export default {
875
868
  y: {
876
869
  beginAtZero: true,
877
870
  ticks: {
878
- callback: function(value) {
871
+ callback: function (value) {
879
872
  return '$' + value.toFixed(4)
880
873
  }
881
874
  }
@@ -893,7 +886,7 @@ export default {
893
886
  tokenChartInstance.destroy()
894
887
  }
895
888
 
896
- const ctx = tokenChartCanvas.value.getContext('2d')
889
+ const ctx2d = tokenChartCanvas.value.getContext('2d')
897
890
 
898
891
  // Find the index of the selected day
899
892
  const selectedDayIndex = tokenChartData.value.dateKeys.indexOf(selectedDay.value)
@@ -944,7 +937,7 @@ export default {
944
937
  ]
945
938
  }
946
939
 
947
- tokenChartInstance = new Chart(ctx, {
940
+ tokenChartInstance = new Chart(ctx2d, {
948
941
  type: 'bar',
949
942
  data: chartDataWithColors,
950
943
  options: {
@@ -972,8 +965,8 @@ export default {
972
965
  stacked: true,
973
966
  beginAtZero: true,
974
967
  ticks: {
975
- callback: function(value) {
976
- return humanifyNumber(value)
968
+ callback: function (value) {
969
+ return ctx.fmt.humanifyNumber(value)
977
970
  }
978
971
  }
979
972
  }
@@ -985,14 +978,14 @@ export default {
985
978
  },
986
979
  tooltip: {
987
980
  callbacks: {
988
- title: function(context) {
981
+ title: function (context) {
989
982
  const index = context[0].dataIndex
990
983
  const dateKey = tokenChartData.value.dateKeys[index]
991
984
  const date = new Date(dateKey + 'T00:00:00Z')
992
985
  return date.toLocaleDateString(undefined, { year: 'numeric', month: 'long', day: 'numeric' })
993
986
  },
994
- label: function(context) {
995
- return `${context.dataset.label}: ${humanifyNumber(context.parsed.y)}`
987
+ label: function (context) {
988
+ return `${context.dataset.label}: ${ctx.fmt.humanifyNumber(context.parsed.y)}`
996
989
  }
997
990
  }
998
991
  }
@@ -1009,7 +1002,7 @@ export default {
1009
1002
  modelPieChartInstance.destroy()
1010
1003
  }
1011
1004
 
1012
- const ctx = modelPieCanvas.value.getContext('2d')
1005
+ const ctx2d = modelPieCanvas.value.getContext('2d')
1013
1006
 
1014
1007
  // Custom plugin to draw percentage labels on pie slices
1015
1008
  const percentagePlugin = {
@@ -1036,7 +1029,7 @@ export default {
1036
1029
  }
1037
1030
  }
1038
1031
 
1039
- modelPieChartInstance = new Chart(ctx, {
1032
+ modelPieChartInstance = new Chart(ctx2d, {
1040
1033
  type: 'pie',
1041
1034
  data: modelPieData.value,
1042
1035
  options: {
@@ -1049,8 +1042,8 @@ export default {
1049
1042
  },
1050
1043
  tooltip: {
1051
1044
  callbacks: {
1052
- label: function(context) {
1053
- return `${context.label}: ${formatCost(context.parsed)}`
1045
+ label: function (context) {
1046
+ return `${context.label}: ${ctx.fmt.cost(context.parsed)}`
1054
1047
  }
1055
1048
  }
1056
1049
  }
@@ -1068,7 +1061,7 @@ export default {
1068
1061
  providerPieChartInstance.destroy()
1069
1062
  }
1070
1063
 
1071
- const ctx = providerPieCanvas.value.getContext('2d')
1064
+ const ctx2d = providerPieCanvas.value.getContext('2d')
1072
1065
 
1073
1066
  // Custom plugin to draw percentage labels on pie slices
1074
1067
  const percentagePlugin = {
@@ -1095,7 +1088,7 @@ export default {
1095
1088
  }
1096
1089
  }
1097
1090
 
1098
- providerPieChartInstance = new Chart(ctx, {
1091
+ providerPieChartInstance = new Chart(ctx2d, {
1099
1092
  type: 'pie',
1100
1093
  data: providerPieData.value,
1101
1094
  options: {
@@ -1108,8 +1101,8 @@ export default {
1108
1101
  },
1109
1102
  tooltip: {
1110
1103
  callbacks: {
1111
- label: function(context) {
1112
- return `${context.label}: ${formatCost(context.parsed)}`
1104
+ label: function (context) {
1105
+ return `${context.label}: ${ctx.fmt.cost(context.parsed)}`
1113
1106
  }
1114
1107
  }
1115
1108
  }
@@ -1127,7 +1120,7 @@ export default {
1127
1120
  tokenModelPieChartInstance.destroy()
1128
1121
  }
1129
1122
 
1130
- const ctx = tokenModelPieCanvas.value.getContext('2d')
1123
+ const ctx2d = tokenModelPieCanvas.value.getContext('2d')
1131
1124
 
1132
1125
  // Custom plugin to draw percentage labels on pie slices
1133
1126
  const percentagePlugin = {
@@ -1154,7 +1147,7 @@ export default {
1154
1147
  }
1155
1148
  }
1156
1149
 
1157
- tokenModelPieChartInstance = new Chart(ctx, {
1150
+ tokenModelPieChartInstance = new Chart(ctx2d, {
1158
1151
  type: 'pie',
1159
1152
  data: tokenModelPieData.value,
1160
1153
  options: {
@@ -1167,8 +1160,8 @@ export default {
1167
1160
  },
1168
1161
  tooltip: {
1169
1162
  callbacks: {
1170
- label: function(context) {
1171
- return `${context.label}: ${humanifyNumber(context.parsed)}`
1163
+ label: function (context) {
1164
+ return `${context.label}: ${ctx.fmt.humanifyNumber(context.parsed)}`
1172
1165
  }
1173
1166
  }
1174
1167
  }
@@ -1186,7 +1179,7 @@ export default {
1186
1179
  tokenProviderPieChartInstance.destroy()
1187
1180
  }
1188
1181
 
1189
- const ctx = tokenProviderPieCanvas.value.getContext('2d')
1182
+ const ctx2d = tokenProviderPieCanvas.value.getContext('2d')
1190
1183
 
1191
1184
  // Custom plugin to draw percentage labels on pie slices
1192
1185
  const percentagePlugin = {
@@ -1213,7 +1206,7 @@ export default {
1213
1206
  }
1214
1207
  }
1215
1208
 
1216
- tokenProviderPieChartInstance = new Chart(ctx, {
1209
+ tokenProviderPieChartInstance = new Chart(ctx2d, {
1217
1210
  type: 'pie',
1218
1211
  data: tokenProviderPieData.value,
1219
1212
  options: {
@@ -1226,8 +1219,8 @@ export default {
1226
1219
  },
1227
1220
  tooltip: {
1228
1221
  callbacks: {
1229
- label: function(context) {
1230
- return `${context.label}: ${humanifyNumber(context.parsed)}`
1222
+ label: function (context) {
1223
+ return `${context.label}: ${ctx.fmt.humanifyNumber(context.parsed)}`
1231
1224
  }
1232
1225
  }
1233
1226
  }
@@ -1339,9 +1332,9 @@ export default {
1339
1332
 
1340
1333
  const formatActivityDate = (timestamp) => {
1341
1334
  const date = new Date(timestamp * 1000)
1342
- return date.toLocaleTimeString(undefined, { hour12: false }) + ' '
1343
- + date.toLocaleDateString(undefined, { year: 'numeric', month: 'long', day: 'numeric' })
1344
-
1335
+ return date.toLocaleTimeString(undefined, { hour12: false }) + ' '
1336
+ + date.toLocaleDateString(undefined, { year: 'numeric', month: 'long', day: 'numeric' })
1337
+
1345
1338
  }
1346
1339
 
1347
1340
  const openThread = (threadId) => {
@@ -1497,9 +1490,6 @@ export default {
1497
1490
  totalRequests,
1498
1491
  totalInputTokens,
1499
1492
  totalOutputTokens,
1500
- formatCost,
1501
- humanifyNumber,
1502
- humanifyMs,
1503
1493
  // Month/Year selection
1504
1494
  selectedMonth,
1505
1495
  selectedYear,
@@ -1526,3 +1516,25 @@ export default {
1526
1516
  }
1527
1517
  }
1528
1518
  }
1519
+
1520
+ export default {
1521
+ install(ctx) {
1522
+ ctx.components({
1523
+ MonthSelector,
1524
+ Analytics,
1525
+ })
1526
+
1527
+ ctx.setLeftIcons({
1528
+ analytics: {
1529
+ component: {
1530
+ template: `<svg @click="$ctx.togglePath('/analytics')" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="currentColor" d="M5 22a1 1 0 0 1-1-1v-8a1 1 0 0 1 2 0v8a1 1 0 0 1-1 1m5 0a1 1 0 0 1-1-1V3a1 1 0 0 1 2 0v18a1 1 0 0 1-1 1m5 0a1 1 0 0 1-1-1V9a1 1 0 0 1 2 0v12a1 1 0 0 1-1 1m5 0a1 1 0 0 1-1-1v-4a1 1 0 0 1 2 0v4a1 1 0 0 1-1 1"/></svg>`
1531
+ },
1532
+ isActive({ path }) {
1533
+ return path === '/analytics'
1534
+ }
1535
+ }
1536
+ })
1537
+
1538
+ ctx.routes.push({ path: '/analytics', component: Analytics, meta: { title: 'Analytics' } })
1539
+ }
1540
+ }