llms-py 3.0.15__py3-none-any.whl → 3.0.17__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 (29) hide show
  1. llms/extensions/app/__init__.py +0 -1
  2. llms/extensions/app/db.py +5 -1
  3. llms/extensions/computer/__init__.py +59 -0
  4. llms/extensions/{computer_use → computer}/bash.py +2 -2
  5. llms/extensions/{computer_use → computer}/edit.py +10 -14
  6. llms/extensions/computer/filesystem.py +542 -0
  7. llms/extensions/core_tools/__init__.py +0 -38
  8. llms/extensions/providers/cerebras.py +0 -1
  9. llms/extensions/providers/google.py +57 -30
  10. llms/extensions/skills/ui/index.mjs +27 -0
  11. llms/extensions/tools/__init__.py +5 -82
  12. llms/extensions/tools/ui/index.mjs +92 -4
  13. llms/main.py +225 -34
  14. llms/ui/ai.mjs +1 -1
  15. llms/ui/app.css +491 -0
  16. llms/ui/modules/chat/ChatBody.mjs +64 -9
  17. llms/ui/modules/chat/index.mjs +103 -91
  18. {llms_py-3.0.15.dist-info → llms_py-3.0.17.dist-info}/METADATA +1 -1
  19. {llms_py-3.0.15.dist-info → llms_py-3.0.17.dist-info}/RECORD +28 -27
  20. {llms_py-3.0.15.dist-info → llms_py-3.0.17.dist-info}/WHEEL +1 -1
  21. llms/extensions/computer_use/__init__.py +0 -27
  22. /llms/extensions/{computer_use → computer}/README.md +0 -0
  23. /llms/extensions/{computer_use → computer}/base.py +0 -0
  24. /llms/extensions/{computer_use → computer}/computer.py +0 -0
  25. /llms/extensions/{computer_use → computer}/platform.py +0 -0
  26. /llms/extensions/{computer_use → computer}/run.py +0 -0
  27. {llms_py-3.0.15.dist-info → llms_py-3.0.17.dist-info}/entry_points.txt +0 -0
  28. {llms_py-3.0.15.dist-info → llms_py-3.0.17.dist-info}/licenses/LICENSE +0 -0
  29. {llms_py-3.0.15.dist-info → llms_py-3.0.17.dist-info}/top_level.txt +0 -0
@@ -29,6 +29,11 @@ function embedHtml(html) {
29
29
  }
30
30
  }
31
31
  const ro = new ResizeObserver(sendHeight);
32
+ window.addEventListener('message', (e) => {
33
+ if (e.data && e.data.type === 'stop-resize') {
34
+ ro.disconnect();
35
+ }
36
+ });
32
37
  window.addEventListener('load', () => {
33
38
  // Inject styles to prevent infinite loops
34
39
  const style = document.createElement('style');
@@ -56,7 +61,7 @@ function embedHtml(html) {
56
61
  export const TypeText = {
57
62
  template: `
58
63
  <div data-type="text" v-if="text.type === 'text'">
59
- !<div v-html="html?.trim()" class="whitespace-pre-wrap"></div>
64
+ <div v-html="html?.trim()" class="whitespace-pre-wrap"></div>
60
65
  </div>
61
66
  `,
62
67
  props: {
@@ -377,6 +382,12 @@ export const TextViewer = {
377
382
  {{ $fmt.humanifyNumber(text.length) }}
378
383
  </span>
379
384
 
385
+ <!-- Copy Button -->
386
+ <button type="button" @click="copyToClipboard" class="text-gray-500 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-200 focus:outline-none p-0.5 rounded transition-colors" title="Copy to clipboard">
387
+ <svg v-if="copied" class="size-4 text-green-600 dark:text-green-500" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="currentColor" d="m9.55 18l-5.7-5.7l1.425-1.425L9.55 15.15l9.175-9.175L20.15 7.4z"/></svg>
388
+ <svg v-else xmlns="http://www.w3.org/2000/svg" class="size-4" viewBox="0 0 24 24"><path fill="currentColor" d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2m0 16H8V7h11z"/></svg>
389
+ </button>
390
+
380
391
  <!-- Maximize Toggle -->
381
392
  <button type="button" @click="toggleMaximized" class="text-gray-500 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-200 focus:outline-none p-0.5 rounded transition-colors" :title="isMaximized ? 'Minimize' : 'Maximize'">
382
393
  <svg class="size-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
@@ -391,6 +402,9 @@ export const TextViewer = {
391
402
  <div v-if="prefs === 'markdown'" class="prose prose-sm max-w-none dark:prose-invert">
392
403
  <div v-html="$fmt.markdown(text)"></div>
393
404
  </div>
405
+ <div v-else-if="prefs === 'preview' && jsonValue">
406
+ <HtmlFormat :value="jsonValue" />
407
+ </div>
394
408
  <div v-else :class="['p-0.5', contentClass]">{{ text }}</div>
395
409
  </div>
396
410
  </div>
@@ -402,16 +416,32 @@ export const TextViewer = {
402
416
  },
403
417
  setup(props) {
404
418
  const ctx = inject('ctx')
405
- const textStyles = ['pre', 'normal', 'markdown']
406
419
  const prefs = ref('pre')
407
420
  const maximized = ref({})
408
421
  const dropdownOpen = ref(false)
409
422
  const hash = computed(() => ctx.utils.hashString(props.text))
423
+ const jsonValue = computed(() => ctx.utils.toJsonObject(props.text))
424
+ const textStyles = computed(() => {
425
+ const ret = ['pre', 'normal', 'markdown']
426
+ if (jsonValue.value) {
427
+ ret.push('preview')
428
+ }
429
+ return ret
430
+ })
410
431
 
411
432
  const toggleDropdown = () => {
412
433
  dropdownOpen.value = !dropdownOpen.value
413
434
  }
414
435
 
436
+ const copied = ref(false)
437
+ const copyToClipboard = () => {
438
+ navigator.clipboard.writeText(props.text)
439
+ copied.value = true
440
+ setTimeout(() => {
441
+ copied.value = false
442
+ }, 2000)
443
+ }
444
+
415
445
  const setStyle = (style) => {
416
446
  prefs.value = style
417
447
  dropdownOpen.value = false
@@ -453,13 +483,17 @@ export const TextViewer = {
453
483
  hash,
454
484
  textStyles,
455
485
  prefs,
486
+ jsonValue,
456
487
  dropdownOpen,
457
488
  toggleDropdown,
458
489
  setStyle,
459
490
  isMaximized,
460
491
  toggleMaximized,
492
+
461
493
  containerClass,
462
- contentClass
494
+ contentClass,
495
+ copied,
496
+ copyToClipboard
463
497
  }
464
498
  }
465
499
  }
@@ -507,11 +541,23 @@ export const ToolArguments = {
507
541
  })
508
542
 
509
543
  const handleMessage = (event) => {
544
+ console.log('handleMessage', event)
510
545
  if (event.data?.type === 'iframe-resize' && typeof event.data.height === 'number') {
511
546
  const iframes = refArgs.value?.querySelectorAll('iframe')
512
547
  iframes?.forEach(iframe => {
513
548
  if (iframe.contentWindow === event.source) {
514
- iframe.style.height = (event.data.height + 30) + 'px'
549
+ const messages = document.getElementById('messages')
550
+ const maxHeight = messages ? messages.clientHeight : window.innerHeight
551
+ const calculatedHeight = event.data.height + 30
552
+ const targetHeight = Math.min(calculatedHeight, maxHeight)
553
+
554
+ if (iframe.style.height !== targetHeight + 'px') {
555
+ iframe.style.height = targetHeight + 'px'
556
+ }
557
+
558
+ if (calculatedHeight > maxHeight) {
559
+ event.source.postMessage({ type: 'stop-resize' }, '*')
560
+ }
515
561
  }
516
562
  })
517
563
  }
@@ -591,7 +637,7 @@ export const ChatBody = {
591
637
  template: `
592
638
  <div class="flex flex-col h-full">
593
639
  <!-- Messages Area -->
594
- <div class="flex-1 overflow-y-auto" ref="messagesContainer">
640
+ <div id="messages" class="flex-1 overflow-y-auto" ref="messagesContainer">
595
641
  <div class="mx-auto max-w-6xl px-4 py-6">
596
642
 
597
643
  <div v-if="!$ai.hasAccess">
@@ -609,7 +655,7 @@ export const ChatBody = {
609
655
  <ThreadHeader v-if="currentThread" :thread="currentThread" class="mb-2" />
610
656
  <div class="space-y-2" v-if="currentThread?.messages?.length">
611
657
  <div
612
- v-for="message in currentThread.messages.filter(x => x.role !== 'system')"
658
+ v-for="message in currentThreadMessages"
613
659
  :key="message.timestamp"
614
660
  v-show="!(message.role === 'tool' && isToolLinked(message))"
615
661
  class="flex items-start space-x-3 group"
@@ -791,7 +837,7 @@ export const ChatBody = {
791
837
  </div>
792
838
 
793
839
  <!-- Thread error message bubble -->
794
- <div v-if="currentThread?.error" class="mt-8 flex items-center space-x-3">
840
+ <div v-if="currentThread?.error" class="mt-8 flex items-center">
795
841
  <!-- Avatar outside the bubble -->
796
842
  <div class="flex-shrink-0">
797
843
  <div class="size-8 rounded-full bg-red-600 dark:bg-red-500 text-white flex items-center justify-center text-lg font-bold">
@@ -799,13 +845,17 @@ export const ChatBody = {
799
845
  </div>
800
846
  </div>
801
847
  <!-- Error bubble -->
802
- <div class="max-w-[85%] rounded-lg px-3 py-1 bg-red-50 dark:bg-red-900/30 border border-red-200 dark:border-red-800 text-red-800 dark:text-red-200 shadow-sm">
848
+ <div class="ml-3 max-w-[85%] rounded-lg px-3 py-1 bg-red-50 dark:bg-red-900/30 border border-red-200 dark:border-red-800 text-red-800 dark:text-red-200 shadow-sm">
803
849
  <div class="flex items-start space-x-2">
804
850
  <div class="flex-1 min-w-0">
805
851
  <div v-if="currentThread.error" class="text-base mb-1">{{ currentThread.error }}</div>
806
852
  </div>
807
853
  </div>
808
854
  </div>
855
+ <button type="button" @click="$chat.sendUserMessage('retry')" title="Retry request"
856
+ class="ml-1 px-3 py-1 rounded text-sm text-gray-400 dark:text-gray-500 hover:text-gray-600 dark:hover:text-gray-400 hover:bg-gray-50 dark:hover:bg-gray-900/30 border border-transparent hover:border-gray-300 dark:hover:border-gray-600 transition-all">
857
+ retry
858
+ </button>
809
859
  </div>
810
860
 
811
861
  <!-- Error message bubble -->
@@ -839,7 +889,7 @@ export const ChatBody = {
839
889
  </div>
840
890
  </div>
841
891
  </div>
842
- <ThreadFooter v-if="$threads.threadDetails.value[currentThread.id]" :thread="$threads.threadDetails.value[currentThread.id]" />
892
+ <ThreadFooter v-if="!$threads.watchingThread && $threads.threadDetails.value[currentThread.id]" :thread="$threads.threadDetails.value[currentThread.id]" />
843
893
  </div>
844
894
  </div>
845
895
  </div>
@@ -1074,12 +1124,17 @@ export const ChatBody = {
1074
1124
  ctx.setPrefs(prefs.value)
1075
1125
  }
1076
1126
 
1127
+ const ignoreUserMessages = ['proceed', 'retry']
1128
+ const currentThreadMessages = computed(() =>
1129
+ currentThread.value?.messages?.filter(x => x.role !== 'system' && !(x.role === 'user' && Array.isArray(x.content) && ignoreUserMessages.includes(x.content[0]?.text))))
1130
+
1077
1131
  return {
1078
1132
  prefs,
1079
1133
  setPrefs,
1080
1134
  config,
1081
1135
  models,
1082
1136
  currentThread,
1137
+ currentThreadMessages,
1083
1138
  selectedModel,
1084
1139
  selectedModelObj,
1085
1140
  messagesContainer,
@@ -350,6 +350,105 @@ export function useChatPrompt(ctx) {
350
350
  ctx.setState({ selectedAspectRatio })
351
351
  }
352
352
 
353
+ async function sendUserMessage(text, { model, redirect = true } = {}) {
354
+ ctx.clearError()
355
+
356
+ if (!model) {
357
+ model = getSelectedModel()
358
+ }
359
+
360
+ let content = createContent({ text, files: attachedFiles.value })
361
+
362
+ let thread
363
+
364
+ // Create thread if none exists
365
+ if (!ctx.threads.currentThread.value) {
366
+ thread = await ctx.threads.startNewThread({ model, redirect })
367
+ } else {
368
+ thread = ctx.threads.currentThread.value
369
+ }
370
+
371
+ let threadId = thread.id
372
+ let messages = thread.messages || []
373
+ if (!threadId) {
374
+ console.error('No thread ID found', thread, ctx.threads.currentThread.value)
375
+ return
376
+ }
377
+
378
+ // Handle Editing / Redo Logic
379
+ const editingMsg = editingMessage.value
380
+ if (editingMsg) {
381
+ let messageIndex = messages.findIndex(m => m.timestamp === editingMsg)
382
+ if (messageIndex == -1) {
383
+ messageIndex = messages.findLastIndex(m => m.role === 'user')
384
+ }
385
+ console.log('Editing message', editingMsg, messageIndex, messages)
386
+
387
+ if (messageIndex >= 0) {
388
+ messages[messageIndex].content = content
389
+ // Truncate messages to only include up to the edited message
390
+ messages.length = messageIndex + 1
391
+ } else {
392
+ messages.push({
393
+ timestamp: new Date().valueOf(),
394
+ role: 'user',
395
+ content,
396
+ })
397
+ }
398
+ } else {
399
+ // Regular Send Logic
400
+ const lastMessage = messages[messages.length - 1]
401
+
402
+ // Check duplicate based on text content extracted from potential array
403
+ const getLastText = (msgContent) => {
404
+ if (typeof msgContent === 'string') return msgContent
405
+ if (Array.isArray(msgContent)) return msgContent.find(c => c.type === 'text')?.text || ''
406
+ return ''
407
+ }
408
+ const newText = text // content[0].text
409
+ const lastText = lastMessage && lastMessage.role === 'user' ? getLastText(lastMessage.content) : null
410
+ const isDuplicate = lastText === newText
411
+
412
+ // Add user message only if it's not a duplicate
413
+ // Note: We are saving the FULL STRUCTURED CONTENT array here
414
+ if (!isDuplicate) {
415
+ messages.push({
416
+ timestamp: new Date().valueOf(),
417
+ role: 'user',
418
+ content,
419
+ })
420
+ }
421
+ }
422
+
423
+ const request = createRequest({ model })
424
+
425
+ // Add Thread History
426
+ messages.forEach(m => {
427
+ request.messages.push(m)
428
+ })
429
+
430
+ // Update Thread Title if not set or is default
431
+ if (!thread.title || thread.title === 'New Chat' || request.title === 'New Chat') {
432
+ request.title = text.length > 100
433
+ ? text.slice(0, 100) + '...'
434
+ : text
435
+ console.debug(`changing thread title from '${thread.title}' to '${request.title}'`)
436
+ } else {
437
+ console.debug(`thread title is '${thread.title}'`, request.title)
438
+ }
439
+
440
+ const api = await ctx.threads.queueChat({ request, thread })
441
+ if (api.response) {
442
+ // success
443
+ editingMessage.value = null
444
+ attachedFiles.value = []
445
+ thread = api.response
446
+ ctx.threads.replaceThread(thread)
447
+ } else {
448
+ ctx.setError(api.error)
449
+ }
450
+ }
451
+
353
452
  return {
354
453
  completion,
355
454
  createContent,
@@ -374,6 +473,7 @@ export function useChatPrompt(ctx) {
374
473
  getTextContent,
375
474
  getAnswer,
376
475
  selectAspectRatio,
476
+ sendUserMessage,
377
477
  }
378
478
  }
379
479
 
@@ -490,6 +590,7 @@ const ChatPrompt = {
490
590
  hasAudio,
491
591
  hasFile,
492
592
  getTextContent,
593
+ sendUserMessage,
493
594
  } = ctx.chat
494
595
 
495
596
  const fileInput = ref(null)
@@ -631,8 +732,6 @@ const ChatPrompt = {
631
732
  if (!messageText.value?.trim() && !hasImage() && !hasAudio() && !hasFile()) return
632
733
  if (ctx.threads.isWatchingThread.value || !props.model) return
633
734
 
634
- ctx.clearError()
635
-
636
735
  // 1. Construct Structured Content (Text + Attachments)
637
736
  let text = messageText.value.trim()
638
737
 
@@ -645,96 +744,8 @@ const ChatPrompt = {
645
744
  }
646
745
 
647
746
  messageText.value = ''
648
- let content = ctx.chat.createContent({ text, files: ctx.chat.attachedFiles.value })
649
-
650
- let thread
651
-
652
- // Create thread if none exists
653
- if (!ctx.threads.currentThread.value) {
654
- thread = await ctx.threads.startNewThread({ model: props.model, redirect: true })
655
- } else {
656
- thread = ctx.threads.currentThread.value
657
- }
658
-
659
- let threadId = thread.id
660
- let messages = thread.messages || []
661
- if (!threadId) {
662
- console.error('No thread ID found', thread, ctx.threads.currentThread.value)
663
- return
664
- }
665
-
666
- // Handle Editing / Redo Logic
667
- const editingMessage = ctx.chat.editingMessage.value
668
- if (editingMessage) {
669
- let messageIndex = messages.findIndex(m => m.timestamp === editingMessage)
670
- if (messageIndex == -1) {
671
- messageIndex = messages.findLastIndex(m => m.role === 'user')
672
- }
673
- console.log('Editing message', editingMessage, messageIndex, messages)
674
-
675
- if (messageIndex >= 0) {
676
- messages[messageIndex].content = content
677
- // Truncate messages to only include up to the edited message
678
- messages.length = messageIndex + 1
679
- } else {
680
- messages.push({
681
- timestamp: new Date().valueOf(),
682
- role: 'user',
683
- content,
684
- })
685
- }
686
- } else {
687
- // Regular Send Logic
688
- const lastMessage = messages[messages.length - 1]
689
-
690
- // Check duplicate based on text content extracted from potential array
691
- const getLastText = (msgContent) => {
692
- if (typeof msgContent === 'string') return msgContent
693
- if (Array.isArray(msgContent)) return msgContent.find(c => c.type === 'text')?.text || ''
694
- return ''
695
- }
696
- const newText = text // content[0].text
697
- const lastText = lastMessage && lastMessage.role === 'user' ? getLastText(lastMessage.content) : null
698
- const isDuplicate = lastText === newText
699
-
700
- // Add user message only if it's not a duplicate
701
- // Note: We are saving the FULL STRUCTURED CONTENT array here
702
- if (!isDuplicate) {
703
- messages.push({
704
- timestamp: new Date().valueOf(),
705
- role: 'user',
706
- content,
707
- })
708
- }
709
- }
710
-
711
- const request = ctx.chat.createRequest({ model: props.model })
712
747
 
713
- // Add Thread History
714
- messages.forEach(m => {
715
- request.messages.push(m)
716
- })
717
-
718
- // Update Thread Title if not set or is default
719
- if (!thread.title || thread.title === 'New Chat' || request.title === 'New Chat') {
720
- request.title = text.length > 100
721
- ? text.slice(0, 100) + '...'
722
- : text
723
- console.debug(`changing thread title from '${thread.title}' to '${request.title}'`)
724
- } else {
725
- console.debug(`thread title is '${thread.title}'`, request.title)
726
- }
727
-
728
- const api = await ctx.threads.queueChat({ request, thread })
729
- if (api.response) {
730
- // success
731
- ctx.chat.editingMessage.value = null
732
- ctx.chat.attachedFiles.value = []
733
- thread = api.response
734
- ctx.threads.replaceThread(thread)
735
- } else {
736
- ctx.setError(api.error)
737
- }
748
+ await sendUserMessage(text, { model: props.model })
738
749
 
739
750
  // Restore focus to the textarea
740
751
  nextTick(() => {
@@ -819,6 +830,7 @@ const ChatPrompt = {
819
830
  addNewLine,
820
831
  onKeyDown,
821
832
  imageAspectRatios,
833
+ sendUserMessage,
822
834
  }
823
835
  }
824
836
  }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: llms-py
3
- Version: 3.0.15
3
+ Version: 3.0.17
4
4
  Summary: A lightweight CLI tool and OpenAI-compatible server for querying multiple Large Language Model (LLM) providers
5
5
  Home-page: https://github.com/ServiceStack/llms
6
6
  Author: ServiceStack
@@ -3,26 +3,27 @@ llms/__main__.py,sha256=hrBulHIt3lmPm1BCyAEVtB6DQ0Hvc3gnIddhHCmJasg,151
3
3
  llms/db.py,sha256=oozp5I5lECVO8oZEFwcZl3ES5mARqWeR1BkoqG5kSqM,11687
4
4
  llms/index.html,sha256=nGk1Djtn9p7l6LuKp4Kg0JIB9fCzxtTWXFfmDb4ggpc,1658
5
5
  llms/llms.json,sha256=NEr9kJRkUGZ2YZHbWC-haGPlVVL2Qtnx4kKZENGH1wk,11494
6
- llms/main.py,sha256=xEWU18A6dTncIFOroN2PDQdnSDhQ9Yr22OHuBbrCYSU,176425
6
+ llms/main.py,sha256=GyuQiCJNY23j2GPDR5obucpHENbOLCTyqSE41Hwrvd8,183589
7
7
  llms/providers-extra.json,sha256=_6DmGBiQY9LM6_Y0zOiObYn7ba4g3akSNQfmHcYlENc,11101
8
8
  llms/providers.json,sha256=yjhDurlwo70xqfV0HNLiZaCpw3WvtIgkjoLahQIKX2w,282530
9
9
  llms/extensions/analytics/ui/index.mjs,sha256=m1XwaqYCLwK267JAUCAltkN_nOXep0GxfpvGNS5i4_w,69547
10
10
  llms/extensions/app/README.md,sha256=TKoblZpHlheLCh_dfXOxqTc5OvxlgMBa-vKo8Hqb2gg,1370
11
- llms/extensions/app/__init__.py,sha256=aU8Bfliw--Xj1bsKL3PSoX6MY1ZNgweNyMWS1V_YG4s,20855
12
- llms/extensions/app/db.py,sha256=DU8YZ25yFsBI-O6msxh2GgzbwaqKqXkAHJLwQKcmFPI,21533
11
+ llms/extensions/app/__init__.py,sha256=5TX1QZ0c4CpTpZQvoBebNLfBToTP_Sdi2tiCvbwFMd4,20799
12
+ llms/extensions/app/db.py,sha256=eVUHkMo5va1pCkd3dP-4_DnkfYGZZ6oxOKOEI8hEKsM,21719
13
13
  llms/extensions/app/ui/Recents.mjs,sha256=2ypAKUp9_Oqcive1nUWZ8I2PQTBomBg_Pkjygi4oPgs,9261
14
14
  llms/extensions/app/ui/index.mjs,sha256=sB9176LLNuKFsZ28yL-tROA6J4xePNtvxtSrzFcinRo,13271
15
15
  llms/extensions/app/ui/threadStore.mjs,sha256=QS6mLqysw9Je_ixUKpbhAELGq-As8aFk6Qm_vO5hvUQ,12515
16
- llms/extensions/computer_use/README.md,sha256=xGQXMFtTnjOLll9rDeF1b6Msl3uK5UwjvocvW7WCmps,4293
17
- llms/extensions/computer_use/__init__.py,sha256=YOMJnMFsIi6vdZ8BpI7_uWubIwiWHAJoLpHflGC9BI0,715
18
- llms/extensions/computer_use/base.py,sha256=Igio5R6kPQOxIbmpaA7X6j6eC4cpF3jwTTR8rURfp5E,2386
19
- llms/extensions/computer_use/bash.py,sha256=5s_oYqRGnE1xIICe6qVsfUMJFIbp79Ac0X5NVkSrn_c,5929
20
- llms/extensions/computer_use/computer.py,sha256=wehwcrYwi9usCRcziE_loMhWDbVgfjLk_T4_4TZa4W4,19642
21
- llms/extensions/computer_use/edit.py,sha256=fEMylXnS07Ql3ZoQPG_l98fKrBHIHOWJzn_yp3D5XXI,12784
22
- llms/extensions/computer_use/platform.py,sha256=w5ECar8lM4Lag7rTYUQmU7wEWaqCeejNXwwM3CB8ulQ,14866
23
- llms/extensions/computer_use/run.py,sha256=ZIcoYyy2cc3IKR_T4yJgx6IUHu2m7UusIJi9Dx1s7dA,1566
16
+ llms/extensions/computer/README.md,sha256=xGQXMFtTnjOLll9rDeF1b6Msl3uK5UwjvocvW7WCmps,4293
17
+ llms/extensions/computer/__init__.py,sha256=47nBZI4VMAJ0-mU0QCNtiqKRd-0CF9z8BnBsLE1jrQw,1813
18
+ llms/extensions/computer/base.py,sha256=Igio5R6kPQOxIbmpaA7X6j6eC4cpF3jwTTR8rURfp5E,2386
19
+ llms/extensions/computer/bash.py,sha256=-xo67wVAdrqxtXgR7MK-iAkJ4Wne7Dm1JmnuHC2xW8o,5953
20
+ llms/extensions/computer/computer.py,sha256=wehwcrYwi9usCRcziE_loMhWDbVgfjLk_T4_4TZa4W4,19642
21
+ llms/extensions/computer/edit.py,sha256=QluhvRhYSSQJfbih4QyfC4M8W8aVqiOApfYXZgZTI5M,12725
22
+ llms/extensions/computer/filesystem.py,sha256=4k_aq-wDySz1yV7k3ZshKr5q8LGH8gYkXgGDNAr62lc,19703
23
+ llms/extensions/computer/platform.py,sha256=w5ECar8lM4Lag7rTYUQmU7wEWaqCeejNXwwM3CB8ulQ,14866
24
+ llms/extensions/computer/run.py,sha256=ZIcoYyy2cc3IKR_T4yJgx6IUHu2m7UusIJi9Dx1s7dA,1566
24
25
  llms/extensions/core_tools/CALCULATOR.md,sha256=pJRtCVF01BgxFrSNh2Ys_lrRi3SFwLgJzAX93AGh93Q,1944
25
- llms/extensions/core_tools/__init__.py,sha256=Y5ZlcSg5yVXxIGX_FVbDcHyeXx3ex_rzRQ2hli6Nk38,23280
26
+ llms/extensions/core_tools/__init__.py,sha256=w8ovJRgXsvrcL8NF-XOrhuBE1oQXfnSQo-Xu7ww3NQY,21641
26
27
  llms/extensions/core_tools/ui/index.mjs,sha256=KycJ2FcQ6BieBY7fjWGxVBGHN6WuFx712OFrO6flXww,31770
27
28
  llms/extensions/core_tools/ui/codemirror/codemirror.css,sha256=60lOqXLSZh74b39qxlbdZ4bXIeScnBtG4euWfktvm_M,8720
28
29
  llms/extensions/core_tools/ui/codemirror/codemirror.js,sha256=7cA89SlK249o7tVfiEWIiqDEA6ZEWxX4CoZmofVA14s,402008
@@ -137,9 +138,9 @@ llms/extensions/katex/ui/fonts/KaTeX_Typewriter-Regular.woff,sha256=4U_tArGrp86f
137
138
  llms/extensions/katex/ui/fonts/KaTeX_Typewriter-Regular.woff2,sha256=cdUX1ngneHz6vfGGkUzDNY7aU543kxlB8rL9SiH2jAs,13568
138
139
  llms/extensions/providers/__init__.py,sha256=C5zOBQEOB2L96rAZdjV42fPVk_dZxSh2Dv30Kb1w3lE,534
139
140
  llms/extensions/providers/anthropic.py,sha256=ey3G9D3drhjzaNTKC8SS_XVSjdi3K7uqYTskmf26Aic,12011
140
- llms/extensions/providers/cerebras.py,sha256=HaeFW0GwbD6V6Zrrwqyv78kQb0VXg9oHmykvJfIOOYE,1417
141
+ llms/extensions/providers/cerebras.py,sha256=iKPzsaRIBqQWXsgPQ50jsNPGx8Ud704VVUAXzDBHu7k,1368
141
142
  llms/extensions/providers/chutes.py,sha256=5ZrfbqoOhgzKLQy_qULcp4jlvW5WXPR0jP9kN2Jzb9g,6229
142
- llms/extensions/providers/google.py,sha256=oCCTE2KAw-WWE2v14XpKzgAMdFIWbjTBoa6GWuqT4dw,26215
143
+ llms/extensions/providers/google.py,sha256=rRmpmtSjTM04mZGNyEV2jcDxdDM99GNj_X68dNT1H20,27719
143
144
  llms/extensions/providers/nvidia.py,sha256=C6cwqn3EufYDfRIgbc8MDkQNyD6w3c7hbjfYaHJSDik,4279
144
145
  llms/extensions/providers/openai.py,sha256=hkE-LVsw6M92_qEbpayuPo17Z1OWKHe7lm2wduLMng8,6138
145
146
  llms/extensions/providers/openrouter.py,sha256=5SfCJKo1aGKoDGez6HXYQe9elMMo9sSEDFqqdxamAgA,3330
@@ -150,17 +151,17 @@ llms/extensions/skills/errors.py,sha256=V4DTFNtzVADDlZ0g7RmoxZRFeG01oaG3zzaPAVdt
150
151
  llms/extensions/skills/models.py,sha256=xmRfz8BMeOdzZXhW6MYFjkOVHOKD6bMDynId8aysans,1461
151
152
  llms/extensions/skills/parser.py,sha256=Mb4NOtoY3Ip4Nng8ixb26oE8U_Sp5CI3n3l_qxbg1UM,5500
152
153
  llms/extensions/skills/validator.py,sha256=te49hTfIPJWcMcLLCApSJ2Ru3lrqVF8ayDXtPEZF9sU,5154
153
- llms/extensions/skills/ui/index.mjs,sha256=2fE_npjzjaRqEMPmx1JuIxazo9Bv8qmidaKe50GPp-U,15625
154
+ llms/extensions/skills/ui/index.mjs,sha256=0_7TkyN1T1LH2j3nEz7ek-5RXqKOysEvC2NQ4rSorVE,17189
154
155
  llms/extensions/skills/ui/skills/create-plan/SKILL.md,sha256=g_SLyBid2dwj56FBzh87lZGu1t08edLs0plimT2uNzs,2481
155
156
  llms/extensions/system_prompts/README.md,sha256=ayr18lnSsGp62bunC6kxkvcSvZki775rbZ-8VoMDQEc,597
156
157
  llms/extensions/system_prompts/__init__.py,sha256=TZy1CS2dPkBNBA_Ovf9BlVetZqTt2NgnsrZi6Mtg_C0,1535
157
158
  llms/extensions/system_prompts/ui/index.mjs,sha256=Ec2dXSzEj6RnEuW2U3HxeXK3LTl_lJrVJIayozquoB4,11981
158
159
  llms/extensions/system_prompts/ui/prompts.json,sha256=t5DD3bird-87wFa4OlW-bC2wdoYDrVzfyc8TO5OaotI,128489
159
- llms/extensions/tools/__init__.py,sha256=u76604Cn_sRFQRqeA_pkVEty27V688Mt9Z7Kh63yDr8,4825
160
- llms/extensions/tools/ui/index.mjs,sha256=7hnrieDpdwbLrZ09cs0V_A6RxmjYff4Tg85lvXC8jwI,35006
160
+ llms/extensions/tools/__init__.py,sha256=PRZe0QMfsOymJ3jTqO0VFppNEWI4f2bYSOImK_YrGQM,2036
161
+ llms/extensions/tools/ui/index.mjs,sha256=4gT0mHKuzcLWe8BmrYeVNS3VMd5Me9CX6Q0A_YLyLck,38633
161
162
  llms/ui/App.mjs,sha256=CoUzO9mV__-jV19NKHYIbwHsjWMnO11jyNSbnJhe1gQ,7486
162
- llms/ui/ai.mjs,sha256=rOCaGgwqabs_rrKTocaY8PBy0KmIoDFFeOU5fkyoCGA,6541
163
- llms/ui/app.css,sha256=ZqR_QJPCYzhCxjiCnNrflYBhEEs3She-_6bq6SDlES0,187709
163
+ llms/ui/ai.mjs,sha256=6oL6leYL7INGxJKyjz9RjU8nmUc86qDrigzwsg_cn-c,6541
164
+ llms/ui/app.css,sha256=kKKICFM_85H1BDFdUYJzo93S__1OZcj2cO6zL-4VdJs,209085
164
165
  llms/ui/ctx.mjs,sha256=g1mmv87bhKCFyMbAImvX6mArmGliAoGPPupFEaMMf7c,14500
165
166
  llms/ui/fav.svg,sha256=_R6MFeXl6wBFT0lqcUxYQIDWgm246YH_3hSTW0oO8qw,734
166
167
  llms/ui/index.mjs,sha256=7GMbFyG3L4k6dxSrQYQ0BLzqL976xw5HeaqKco0THHA,4296
@@ -182,12 +183,12 @@ llms/ui/lib/vue.mjs,sha256=75FuLhUTPk19sncwNIrm0BGEL0_Qw298-_v01fPWYoI,542872
182
183
  llms/ui/modules/icons.mjs,sha256=LGcH0ys0QLS2ZKCO42qHpwPYbBV_EssoWLezU4XZEzU,27751
183
184
  llms/ui/modules/layout.mjs,sha256=8pAxs8bedQI3b3eRA9nrfpLZznLmrpp4BZvigYAQjpQ,12572
184
185
  llms/ui/modules/model-selector.mjs,sha256=6U4rAZ7vmQELFRQGWk4YEtq02v3lyHdMq6yUOp-ArXg,43184
185
- llms/ui/modules/chat/ChatBody.mjs,sha256=EOBMKmjCY7MK5UHFmKTjaJMkPWTaHeDDjJ9bvCsHprs,54981
186
+ llms/ui/modules/chat/ChatBody.mjs,sha256=Rwyr7JeqBn6LUn-VtHB9qj7kBsLsOr34SbHcK0twIZ0,58118
186
187
  llms/ui/modules/chat/SettingsDialog.mjs,sha256=HMBJTwrapKrRIAstIIqp0QlJL5O-ho4hzgvfagPfsX8,19930
187
- llms/ui/modules/chat/index.mjs,sha256=1UKfjIub7PtPmHtoIdKOqf3j9a1UJZjad8VTxtV_EIw,39667
188
- llms_py-3.0.15.dist-info/licenses/LICENSE,sha256=bus9cuAOWeYqBk2OuhSABVV1P4z7hgrEFISpyda_H5w,1532
189
- llms_py-3.0.15.dist-info/METADATA,sha256=In3z5zm1VwL5ycrJac_3tOiIH4gQbVT1hG1qWrJoSvY,2195
190
- llms_py-3.0.15.dist-info/WHEEL,sha256=qELbo2s1Yzl39ZmrAibXA2jjPLUYfnVhUNTlyF1rq0Y,92
191
- llms_py-3.0.15.dist-info/entry_points.txt,sha256=WswyE7PfnkZMIxboC-MS6flBD6wm-CYU7JSUnMhqMfM,40
192
- llms_py-3.0.15.dist-info/top_level.txt,sha256=gC7hk9BKSeog8gyg-EM_g2gxm1mKHwFRfK-10BxOsa4,5
193
- llms_py-3.0.15.dist-info/RECORD,,
188
+ llms/ui/modules/chat/index.mjs,sha256=nS_L6G1RSuCybgnA6n-q8Sn3OeSbQWL2iW3-zCIFqJk,39548
189
+ llms_py-3.0.17.dist-info/licenses/LICENSE,sha256=bus9cuAOWeYqBk2OuhSABVV1P4z7hgrEFISpyda_H5w,1532
190
+ llms_py-3.0.17.dist-info/METADATA,sha256=iwwWkuCRwIXXHAcTzqHyuYW1fNnJezrDjoYE_T3nwHU,2195
191
+ llms_py-3.0.17.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
192
+ llms_py-3.0.17.dist-info/entry_points.txt,sha256=WswyE7PfnkZMIxboC-MS6flBD6wm-CYU7JSUnMhqMfM,40
193
+ llms_py-3.0.17.dist-info/top_level.txt,sha256=gC7hk9BKSeog8gyg-EM_g2gxm1mKHwFRfK-10BxOsa4,5
194
+ llms_py-3.0.17.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.10.1)
2
+ Generator: setuptools (80.10.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,27 +0,0 @@
1
- """
2
- Anthropic's Computer Use Tools
3
- https://github.com/anthropics/claude-quickstarts/tree/main/computer-use-demo
4
- """
5
-
6
- import os
7
-
8
- from .bash import open, run_bash
9
- from .computer import computer
10
- from .edit import edit
11
- from .platform import get_display_num, get_screen_resolution
12
-
13
- width, height = get_screen_resolution()
14
- # set enviroment variables
15
- os.environ["WIDTH"] = str(width)
16
- os.environ["HEIGHT"] = str(height)
17
- os.environ["DISPLAY_NUM"] = str(get_display_num())
18
-
19
-
20
- def install(ctx):
21
- ctx.register_tool(run_bash, group="computer_use")
22
- ctx.register_tool(open, group="computer_use")
23
- ctx.register_tool(edit, group="computer_use")
24
- ctx.register_tool(computer, group="computer_use")
25
-
26
-
27
- __install__ = install
File without changes
File without changes
File without changes
File without changes
File without changes