llms-py 3.0.26__tar.gz → 3.0.27__tar.gz

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 (227) hide show
  1. {llms_py-3.0.26/llms_py.egg-info → llms_py-3.0.27}/PKG-INFO +1 -1
  2. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/computer/filesystem.py +16 -1
  3. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/core_tools/__init__.py +1 -169
  4. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/skills/ui/index.mjs +12 -3
  5. {llms_py-3.0.26 → llms_py-3.0.27}/llms/main.py +1 -1
  6. {llms_py-3.0.26 → llms_py-3.0.27}/llms/ui/ai.mjs +1 -1
  7. {llms_py-3.0.26 → llms_py-3.0.27/llms_py.egg-info}/PKG-INFO +1 -1
  8. {llms_py-3.0.26 → llms_py-3.0.27}/pyproject.toml +1 -1
  9. {llms_py-3.0.26 → llms_py-3.0.27}/setup.py +1 -1
  10. {llms_py-3.0.26 → llms_py-3.0.27}/LICENSE +0 -0
  11. {llms_py-3.0.26 → llms_py-3.0.27}/MANIFEST.in +0 -0
  12. {llms_py-3.0.26 → llms_py-3.0.27}/README.md +0 -0
  13. {llms_py-3.0.26 → llms_py-3.0.27}/llms/__init__.py +0 -0
  14. {llms_py-3.0.26 → llms_py-3.0.27}/llms/__main__.py +0 -0
  15. {llms_py-3.0.26 → llms_py-3.0.27}/llms/db.py +0 -0
  16. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/analytics/ui/index.mjs +0 -0
  17. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/app/README.md +0 -0
  18. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/app/__init__.py +0 -0
  19. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/app/db.py +0 -0
  20. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/app/ui/Recents.mjs +0 -0
  21. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/app/ui/index.mjs +0 -0
  22. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/app/ui/threadStore.mjs +0 -0
  23. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/computer/README.md +0 -0
  24. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/computer/__init__.py +0 -0
  25. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/computer/base.py +0 -0
  26. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/computer/bash.py +0 -0
  27. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/computer/computer.py +0 -0
  28. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/computer/edit.py +0 -0
  29. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/computer/platform.py +0 -0
  30. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/computer/run.py +0 -0
  31. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/core_tools/CALCULATOR.md +0 -0
  32. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/core_tools/ui/codemirror/addon/edit/closebrackets.js +0 -0
  33. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/core_tools/ui/codemirror/addon/edit/closetag.js +0 -0
  34. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/core_tools/ui/codemirror/addon/edit/continuelist.js +0 -0
  35. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/core_tools/ui/codemirror/addon/edit/matchbrackets.js +0 -0
  36. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/core_tools/ui/codemirror/addon/edit/matchtags.js +0 -0
  37. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/core_tools/ui/codemirror/addon/edit/trailingspace.js +0 -0
  38. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/core_tools/ui/codemirror/addon/selection/active-line.js +0 -0
  39. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/core_tools/ui/codemirror/addon/selection/mark-selection.js +0 -0
  40. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/core_tools/ui/codemirror/addon/selection/selection-pointer.js +0 -0
  41. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/core_tools/ui/codemirror/codemirror.css +0 -0
  42. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/core_tools/ui/codemirror/codemirror.js +0 -0
  43. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/core_tools/ui/codemirror/doc/docs.css +0 -0
  44. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/core_tools/ui/codemirror/doc/source_sans.woff +0 -0
  45. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/core_tools/ui/codemirror/mode/clike/clike.js +0 -0
  46. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/core_tools/ui/codemirror/mode/javascript/index.html +0 -0
  47. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/core_tools/ui/codemirror/mode/javascript/javascript.js +0 -0
  48. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/core_tools/ui/codemirror/mode/javascript/typescript.html +0 -0
  49. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/core_tools/ui/codemirror/mode/python/python.js +0 -0
  50. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/core_tools/ui/codemirror/theme/dracula.css +0 -0
  51. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/core_tools/ui/codemirror/theme/mocha.css +0 -0
  52. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/core_tools/ui/index.mjs +0 -0
  53. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/gallery/README.md +0 -0
  54. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/gallery/__init__.py +0 -0
  55. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/gallery/db.py +0 -0
  56. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/gallery/ui/index.mjs +0 -0
  57. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/github_auth/README.md +0 -0
  58. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/github_auth/__init__.py +0 -0
  59. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/github_auth/ui/index.mjs +0 -0
  60. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/README.md +0 -0
  61. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/__init__.py +0 -0
  62. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/README.md +0 -0
  63. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/contrib/auto-render.js +0 -0
  64. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/contrib/auto-render.min.js +0 -0
  65. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/contrib/auto-render.mjs +0 -0
  66. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/contrib/copy-tex.js +0 -0
  67. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/contrib/copy-tex.min.js +0 -0
  68. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/contrib/copy-tex.mjs +0 -0
  69. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/contrib/mathtex-script-type.js +0 -0
  70. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/contrib/mathtex-script-type.min.js +0 -0
  71. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/contrib/mathtex-script-type.mjs +0 -0
  72. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/contrib/mhchem.js +0 -0
  73. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/contrib/mhchem.min.js +0 -0
  74. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/contrib/mhchem.mjs +0 -0
  75. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/contrib/render-a11y-string.js +0 -0
  76. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/contrib/render-a11y-string.min.js +0 -0
  77. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/contrib/render-a11y-string.mjs +0 -0
  78. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_AMS-Regular.ttf +0 -0
  79. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_AMS-Regular.woff +0 -0
  80. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_AMS-Regular.woff2 +0 -0
  81. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_Caligraphic-Bold.ttf +0 -0
  82. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_Caligraphic-Bold.woff +0 -0
  83. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
  84. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_Caligraphic-Regular.ttf +0 -0
  85. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_Caligraphic-Regular.woff +0 -0
  86. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
  87. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_Fraktur-Bold.ttf +0 -0
  88. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_Fraktur-Bold.woff +0 -0
  89. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
  90. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_Fraktur-Regular.ttf +0 -0
  91. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_Fraktur-Regular.woff +0 -0
  92. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
  93. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_Main-Bold.ttf +0 -0
  94. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_Main-Bold.woff +0 -0
  95. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_Main-Bold.woff2 +0 -0
  96. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_Main-BoldItalic.ttf +0 -0
  97. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_Main-BoldItalic.woff +0 -0
  98. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
  99. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_Main-Italic.ttf +0 -0
  100. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_Main-Italic.woff +0 -0
  101. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_Main-Italic.woff2 +0 -0
  102. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_Main-Regular.ttf +0 -0
  103. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_Main-Regular.woff +0 -0
  104. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_Main-Regular.woff2 +0 -0
  105. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_Math-BoldItalic.ttf +0 -0
  106. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_Math-BoldItalic.woff +0 -0
  107. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
  108. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_Math-Italic.ttf +0 -0
  109. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_Math-Italic.woff +0 -0
  110. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_Math-Italic.woff2 +0 -0
  111. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Bold.ttf +0 -0
  112. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Bold.woff +0 -0
  113. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
  114. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Italic.ttf +0 -0
  115. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Italic.woff +0 -0
  116. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
  117. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Regular.ttf +0 -0
  118. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Regular.woff +0 -0
  119. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
  120. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_Script-Regular.ttf +0 -0
  121. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_Script-Regular.woff +0 -0
  122. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_Script-Regular.woff2 +0 -0
  123. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_Size1-Regular.ttf +0 -0
  124. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_Size1-Regular.woff +0 -0
  125. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_Size1-Regular.woff2 +0 -0
  126. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_Size2-Regular.ttf +0 -0
  127. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_Size2-Regular.woff +0 -0
  128. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_Size2-Regular.woff2 +0 -0
  129. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_Size3-Regular.ttf +0 -0
  130. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_Size3-Regular.woff +0 -0
  131. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_Size3-Regular.woff2 +0 -0
  132. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_Size4-Regular.ttf +0 -0
  133. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_Size4-Regular.woff +0 -0
  134. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_Size4-Regular.woff2 +0 -0
  135. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_Typewriter-Regular.ttf +0 -0
  136. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_Typewriter-Regular.woff +0 -0
  137. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
  138. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/index.mjs +0 -0
  139. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/katex-swap.css +0 -0
  140. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/katex-swap.min.css +0 -0
  141. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/katex.css +0 -0
  142. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/katex.js +0 -0
  143. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/katex.min.css +0 -0
  144. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/katex.min.js +0 -0
  145. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/katex.min.mjs +0 -0
  146. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/katex/ui/katex.mjs +0 -0
  147. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/providers/__init__.py +0 -0
  148. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/providers/anthropic.py +0 -0
  149. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/providers/cerebras.py +0 -0
  150. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/providers/chutes.py +0 -0
  151. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/providers/google.py +0 -0
  152. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/providers/nvidia.py +0 -0
  153. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/providers/openai.py +0 -0
  154. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/providers/openrouter.py +0 -0
  155. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/providers/zai.py +0 -0
  156. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/skills/LICENSE +0 -0
  157. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/skills/README.md +0 -0
  158. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/skills/__init__.py +0 -0
  159. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/skills/errors.py +0 -0
  160. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/skills/installer.py +0 -0
  161. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/skills/models.py +0 -0
  162. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/skills/parser.py +0 -0
  163. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/skills/ui/data/skills-top-5000.json +0 -0
  164. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/skills/ui/skills/create-plan/SKILL.md +0 -0
  165. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/skills/ui/skills/skill-creator/LICENSE.txt +0 -0
  166. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/skills/ui/skills/skill-creator/SKILL.md +0 -0
  167. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/skills/ui/skills/skill-creator/references/output-patterns.md +0 -0
  168. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/skills/ui/skills/skill-creator/references/workflows.md +0 -0
  169. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/skills/ui/skills/skill-creator/scripts/init_skill.py +0 -0
  170. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/skills/ui/skills/skill-creator/scripts/package_skill.py +0 -0
  171. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/skills/ui/skills/skill-creator/scripts/quick_validate.py +0 -0
  172. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/skills/validator.py +0 -0
  173. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/system_prompts/README.md +0 -0
  174. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/system_prompts/__init__.py +0 -0
  175. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/system_prompts/ui/index.mjs +0 -0
  176. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/system_prompts/ui/prompts.json +0 -0
  177. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/tools/__init__.py +0 -0
  178. {llms_py-3.0.26 → llms_py-3.0.27}/llms/extensions/tools/ui/index.mjs +0 -0
  179. {llms_py-3.0.26 → llms_py-3.0.27}/llms/index.html +0 -0
  180. {llms_py-3.0.26 → llms_py-3.0.27}/llms/llms.json +0 -0
  181. {llms_py-3.0.26 → llms_py-3.0.27}/llms/providers-extra.json +0 -0
  182. {llms_py-3.0.26 → llms_py-3.0.27}/llms/providers.json +0 -0
  183. {llms_py-3.0.26 → llms_py-3.0.27}/llms/ui/App.mjs +0 -0
  184. {llms_py-3.0.26 → llms_py-3.0.27}/llms/ui/app.css +0 -0
  185. {llms_py-3.0.26 → llms_py-3.0.27}/llms/ui/ctx.mjs +0 -0
  186. {llms_py-3.0.26 → llms_py-3.0.27}/llms/ui/fav.svg +0 -0
  187. {llms_py-3.0.26 → llms_py-3.0.27}/llms/ui/index.mjs +0 -0
  188. {llms_py-3.0.26 → llms_py-3.0.27}/llms/ui/lib/chart.js +0 -0
  189. {llms_py-3.0.26 → llms_py-3.0.27}/llms/ui/lib/charts.mjs +0 -0
  190. {llms_py-3.0.26 → llms_py-3.0.27}/llms/ui/lib/color.js +0 -0
  191. {llms_py-3.0.26 → llms_py-3.0.27}/llms/ui/lib/highlight.min.mjs +0 -0
  192. {llms_py-3.0.26 → llms_py-3.0.27}/llms/ui/lib/idb.min.mjs +0 -0
  193. {llms_py-3.0.26 → llms_py-3.0.27}/llms/ui/lib/marked.min.mjs +0 -0
  194. {llms_py-3.0.26 → llms_py-3.0.27}/llms/ui/lib/servicestack-client.mjs +0 -0
  195. {llms_py-3.0.26 → llms_py-3.0.27}/llms/ui/lib/servicestack-vue.mjs +0 -0
  196. {llms_py-3.0.26 → llms_py-3.0.27}/llms/ui/lib/vue-router.min.mjs +0 -0
  197. {llms_py-3.0.26 → llms_py-3.0.27}/llms/ui/lib/vue.min.mjs +0 -0
  198. {llms_py-3.0.26 → llms_py-3.0.27}/llms/ui/lib/vue.mjs +0 -0
  199. {llms_py-3.0.26 → llms_py-3.0.27}/llms/ui/markdown.mjs +0 -0
  200. {llms_py-3.0.26 → llms_py-3.0.27}/llms/ui/modules/chat/ChatBody.mjs +0 -0
  201. {llms_py-3.0.26 → llms_py-3.0.27}/llms/ui/modules/chat/SettingsDialog.mjs +0 -0
  202. {llms_py-3.0.26 → llms_py-3.0.27}/llms/ui/modules/chat/index.mjs +0 -0
  203. {llms_py-3.0.26 → llms_py-3.0.27}/llms/ui/modules/icons.mjs +0 -0
  204. {llms_py-3.0.26 → llms_py-3.0.27}/llms/ui/modules/layout.mjs +0 -0
  205. {llms_py-3.0.26 → llms_py-3.0.27}/llms/ui/modules/model-selector.mjs +0 -0
  206. {llms_py-3.0.26 → llms_py-3.0.27}/llms/ui/tailwind.input.css +0 -0
  207. {llms_py-3.0.26 → llms_py-3.0.27}/llms/ui/typography.css +0 -0
  208. {llms_py-3.0.26 → llms_py-3.0.27}/llms/ui/utils.mjs +0 -0
  209. {llms_py-3.0.26 → llms_py-3.0.27}/llms_py.egg-info/SOURCES.txt +0 -0
  210. {llms_py-3.0.26 → llms_py-3.0.27}/llms_py.egg-info/dependency_links.txt +0 -0
  211. {llms_py-3.0.26 → llms_py-3.0.27}/llms_py.egg-info/entry_points.txt +0 -0
  212. {llms_py-3.0.26 → llms_py-3.0.27}/llms_py.egg-info/not-zip-safe +0 -0
  213. {llms_py-3.0.26 → llms_py-3.0.27}/llms_py.egg-info/requires.txt +0 -0
  214. {llms_py-3.0.26 → llms_py-3.0.27}/llms_py.egg-info/top_level.txt +0 -0
  215. {llms_py-3.0.26 → llms_py-3.0.27}/requirements.txt +0 -0
  216. {llms_py-3.0.26 → llms_py-3.0.27}/setup.cfg +0 -0
  217. {llms_py-3.0.26 → llms_py-3.0.27}/tests/test_async.py +0 -0
  218. {llms_py-3.0.26 → llms_py-3.0.27}/tests/test_config.py +0 -0
  219. {llms_py-3.0.26 → llms_py-3.0.27}/tests/test_core_tools_direct.py +0 -0
  220. {llms_py-3.0.26 → llms_py-3.0.27}/tests/test_extensions.py +0 -0
  221. {llms_py-3.0.26 → llms_py-3.0.27}/tests/test_gemini_tool_calling.py +0 -0
  222. {llms_py-3.0.26 → llms_py-3.0.27}/tests/test_gemini_upload.py +0 -0
  223. {llms_py-3.0.26 → llms_py-3.0.27}/tests/test_integration.py +0 -0
  224. {llms_py-3.0.26 → llms_py-3.0.27}/tests/test_interleaved_thinking.py +0 -0
  225. {llms_py-3.0.26 → llms_py-3.0.27}/tests/test_provider_checks.py +0 -0
  226. {llms_py-3.0.26 → llms_py-3.0.27}/tests/test_provider_config.py +0 -0
  227. {llms_py-3.0.26 → llms_py-3.0.27}/tests/test_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: llms-py
3
- Version: 3.0.26
3
+ Version: 3.0.27
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
@@ -496,15 +496,20 @@ def move_file(source: Annotated[str, "Source path"], destination: Annotated[str,
496
496
 
497
497
 
498
498
  def search_files(
499
- path: Annotated[str, "Path to search in"],
500
499
  pattern: Annotated[str, "Glob pattern to match"],
500
+ path: Annotated[str, "Path to search in"] = None,
501
501
  exclude_patterns: Annotated[List[str], "Glob patterns to exclude"] = None,
502
+ sort_by: Annotated[Literal["path", "modified", "size"], "Sort by path, modified or size"] = "path",
503
+ max_results: int = 200,
502
504
  ) -> str:
503
505
  """
504
506
  Recursively search for files and directories matching a pattern. The patterns should be glob-style patterns that match paths relative to the working directory.
505
507
  Use pattern like '.ext' to match files in current directory, and '**/.ext' to match files in all subdirectories.
506
508
  Returns full paths to all matching items. Great for finding files when you don't know their exact location. Only searches within allowed directories.
509
+ If no path is provided, searches in the first allowed directory.
507
510
  """
511
+ if not path:
512
+ path = get_allowed_directories()[0]
508
513
  valid_path = _validate_path(path)
509
514
  results = []
510
515
  if exclude_patterns is None:
@@ -533,6 +538,16 @@ def search_files(
533
538
  except Exception as e:
534
539
  raise RuntimeError(f"Error searching files in {valid_path}: {e}") from e
535
540
 
541
+ if sort_by == "size":
542
+ results.sort(key=lambda p: os.path.getsize(p) if os.path.exists(p) else 0, reverse=True)
543
+ elif sort_by == "modified":
544
+ results.sort(key=lambda p: os.path.getmtime(p) if os.path.exists(p) else 0, reverse=True)
545
+ else: # path
546
+ results.sort()
547
+
548
+ if max_results > 0:
549
+ results = results[:max_results]
550
+
536
551
  if not results:
537
552
  return "No matches found"
538
553
 
@@ -4,8 +4,6 @@ Core System Tools providing essential file operations, memory persistence, math
4
4
 
5
5
  import ast
6
6
  import contextlib
7
- import glob
8
- import json
9
7
  import math
10
8
  import operator
11
9
  import os
@@ -21,165 +19,6 @@ from aiohttp import web
21
19
 
22
20
  g_ctx = None
23
21
 
24
- # -----------------------------
25
- # In-memory storage (replace later)
26
- # -----------------------------
27
-
28
- _MEMORY_STORE: Dict[str, Any] = {}
29
- _SEMANTIC_STORE: List[Dict[str, Any]] = [] # {id, text, metadata}
30
-
31
-
32
- # -----------------------------
33
- # Memory tools
34
- # -----------------------------
35
-
36
-
37
- def memory_read(key: str) -> Any:
38
- """Read a value from persistent memory."""
39
- return _MEMORY_STORE.get(key)
40
-
41
-
42
- def memory_write(key: str, value: Any) -> bool:
43
- """Write a value to persistent memory."""
44
- _MEMORY_STORE[key] = value
45
- return True
46
-
47
-
48
- # -----------------------------
49
- # Path safety helpers
50
- # -----------------------------
51
-
52
- # Limit tools to only access files and folders within LLMS_BASE_DIR if specified, otherwise the current working directory
53
- _BASE_DIR = os.environ.get("LLMS_BASE_DIR") or os.path.realpath(os.getcwd())
54
-
55
-
56
- def _resolve_safe_path(path: str) -> str:
57
- """
58
- Resolve a path and ensure it stays within the current working directory.
59
- Raises ValueError if the path escapes the base directory.
60
- """
61
- resolved = os.path.realpath(os.path.join(_BASE_DIR, path))
62
- if not resolved.startswith(_BASE_DIR + os.sep) and resolved != _BASE_DIR:
63
- raise ValueError("Access denied: path is outside the working directory")
64
- return resolved
65
-
66
-
67
- # -----------------------------
68
- # Semantic search (placeholder)
69
- # -----------------------------
70
-
71
-
72
- def semantic_search(query: str, top_k: int = 5) -> List[Dict[str, Any]]:
73
- """
74
- Naive semantic search placeholder.
75
- Replace with embeddings + vector DB.
76
- """
77
- results = []
78
- for item in _SEMANTIC_STORE:
79
- if query.lower() in item["text"].lower():
80
- results.append(item)
81
- return results[:top_k]
82
-
83
-
84
- # -----------------------------
85
- # File system tools (restricted to CWD)
86
- # -----------------------------
87
-
88
-
89
- def read_file(path: str) -> str:
90
- """Read a text file from disk within the current working directory."""
91
- safe_path = _resolve_safe_path(path)
92
- with open(safe_path, encoding="utf-8") as f:
93
- return f.read()
94
-
95
-
96
- def write_file(path: str, content: str) -> bool:
97
- """Write text to a file within the current working directory (overwrites)."""
98
- safe_path = _resolve_safe_path(path)
99
- os.makedirs(os.path.dirname(safe_path) or _BASE_DIR, exist_ok=True)
100
- with open(safe_path, "w", encoding="utf-8") as f:
101
- f.write(content)
102
- return True
103
-
104
-
105
- def list_directory(path: str) -> str:
106
- """List directory contents"""
107
- safe_path = _resolve_safe_path(path)
108
- if not os.path.exists(safe_path):
109
- return f"Error: Path not found: {path}"
110
-
111
- entries = []
112
- try:
113
- for entry in os.scandir(safe_path):
114
- stat = entry.stat()
115
- entries.append(
116
- {
117
- "name": "/" + entry.name if entry.is_dir() else entry.name,
118
- "size": stat.st_size,
119
- "mtime": datetime.fromtimestamp(stat.st_mtime).isoformat(),
120
- }
121
- )
122
- return json.dumps({"path": os.path.relpath(safe_path, _BASE_DIR), "entries": entries}, indent=2)
123
- except Exception as e:
124
- return f"Error listing directory: {e}"
125
-
126
-
127
- def glob_paths(
128
- pattern: str,
129
- extensions: Optional[List[str]] = None,
130
- sort_by: str = "path", # "path" | "modified" | "size"
131
- max_results: int = 100,
132
- ) -> Dict[str, List[Dict[str, str]]]:
133
- """
134
- Find files and directories matching a glob pattern
135
- """
136
- if sort_by not in {"path", "modified", "size"}:
137
- raise ValueError("sort_by must be one of: path, modified, size")
138
-
139
- safe_pattern = _resolve_safe_path(pattern)
140
-
141
- results = []
142
-
143
- for path in glob.glob(safe_pattern, recursive=True):
144
- resolved = os.path.realpath(path)
145
-
146
- # Enforce CWD restriction (important for symlinks)
147
- if not resolved.startswith(_BASE_DIR):
148
- continue
149
-
150
- is_dir = os.path.isdir(resolved)
151
-
152
- # Extension filtering (files only)
153
- if extensions and not is_dir:
154
- ext = os.path.splitext(resolved)[1].lower().lstrip(".")
155
- if ext not in {e.lower().lstrip(".") for e in extensions}:
156
- continue
157
-
158
- stat = os.stat(resolved)
159
-
160
- results.append(
161
- {
162
- "path": os.path.relpath(resolved, _BASE_DIR),
163
- "type": "directory" if is_dir else "file",
164
- "size_bytes": stat.st_size,
165
- "modified_time": stat.st_mtime,
166
- }
167
- )
168
-
169
- if len(results) >= max_results:
170
- break
171
-
172
- # Sorting
173
- if sort_by == "path":
174
- results.sort(key=lambda x: x["path"])
175
- elif sort_by == "modified":
176
- results.sort(key=lambda x: x["modified_time"], reverse=True)
177
- elif sort_by == "size":
178
- results.sort(key=lambda x: x["size_bytes"], reverse=True)
179
-
180
- return {"pattern": pattern, "count": len(results), "results": results}
181
-
182
-
183
22
  # -----------------------------
184
23
  # Expression evaluation tools
185
24
  # -----------------------------
@@ -522,19 +361,12 @@ def install(ctx):
522
361
  g_ctx = ctx
523
362
  group = "core_tools"
524
363
  # Examples of registering tools using automatic definition generation
525
- ctx.register_tool(memory_read, group=group)
526
- ctx.register_tool(memory_write, group=group)
527
- # ctx.register_tool(semantic_search) # TODO: implement
528
- ctx.register_tool(read_file, group=group)
529
- ctx.register_tool(write_file, group=group)
530
- ctx.register_tool(list_directory, group=group)
531
- ctx.register_tool(glob_paths, group=group)
364
+ ctx.register_tool(get_current_time, group=group)
532
365
  ctx.register_tool(calc, group=group)
533
366
  ctx.register_tool(run_python, group=group)
534
367
  ctx.register_tool(run_typescript, group=group)
535
368
  ctx.register_tool(run_javascript, group=group)
536
369
  ctx.register_tool(run_csharp, group=group)
537
- ctx.register_tool(get_current_time, group=group)
538
370
 
539
371
  def exec_language(language: str, code: str) -> Dict[str, Any]:
540
372
  if language == "python":
@@ -921,14 +921,23 @@ export default {
921
921
  },
922
922
  show({ thread }) {
923
923
  if (thread.messages.length < 2) return false
924
- const msgRoles = thread.messages.map(m => m.role)
925
- if (msgRoles[msgRoles.length - 1] != "assistant") return false
924
+
925
+ const lastMessage = thread.messages[thread.messages.length - 1]
926
+ // only show if the last message is from the assistant
927
+ if (lastMessage.role != "assistant") return false
928
+
929
+ // and it has a skill tool call
926
930
  const hasSkillToolCall = thread.messages.some(m =>
927
931
  m.tool_calls?.some(tc => tc.type == "function" && tc.function.name == "skill"))
932
+ // or a plan system prompt
928
933
  const systemPrompt = thread.messages.find(m => m.role == "system")?.content.toLowerCase() || ''
929
934
  const line1 = leftPart(systemPrompt.trim(), "\n")
930
935
  const hasPlanSystemPrompt = line1.includes("plan") || systemPrompt.includes("# plan")
931
- return hasSkillToolCall || hasPlanSystemPrompt
936
+
937
+ // or the last message has no content but has reasoning
938
+ const hasOnlyThinking = !lastMessage.content?.trim() && lastMessage.reasoning?.trim()
939
+
940
+ return hasSkillToolCall || hasPlanSystemPrompt || hasOnlyThinking
932
941
  }
933
942
  }
934
943
  })
@@ -57,7 +57,7 @@ except ImportError:
57
57
  HAS_PIL = False
58
58
 
59
59
  _ROOT = None
60
- VERSION = "3.0.26"
60
+ VERSION = "3.0.27"
61
61
  DEBUG = os.getenv("DEBUG") == "1"
62
62
  MOCK = os.getenv("MOCK") == "1"
63
63
  MOCK_DIR = os.getenv("MOCK_DIR")
@@ -6,7 +6,7 @@ const headers = { 'Accept': 'application/json' }
6
6
  const prefsKey = 'llms.prefs'
7
7
 
8
8
  export const o = {
9
- version: '3.0.26',
9
+ version: '3.0.27',
10
10
  base,
11
11
  prefsKey,
12
12
  welcome: 'Welcome to llms.py',
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: llms-py
3
- Version: 3.0.26
3
+ Version: 3.0.27
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
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "llms-py"
7
- version = "3.0.26"
7
+ version = "3.0.27"
8
8
  description = "A lightweight CLI tool and OpenAI-compatible server for querying multiple Large Language Model (LLM) providers"
9
9
  readme = "README.md"
10
10
  license = "BSD-3-Clause"
@@ -15,7 +15,7 @@ with open(os.path.join(this_directory, "requirements.txt"), encoding="utf-8") as
15
15
 
16
16
  setup(
17
17
  name="llms-py",
18
- version="3.0.26",
18
+ version="3.0.27",
19
19
  author="ServiceStack",
20
20
  author_email="team@servicestack.net",
21
21
  description="A lightweight CLI tool and OpenAI-compatible server for querying multiple Large Language Model (LLM) providers",
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes