llms-py 3.0.24__tar.gz → 3.0.25__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.24/llms_py.egg-info → llms_py-3.0.25}/PKG-INFO +1 -1
  2. llms_py-3.0.25/llms/extensions/github_auth/README.md +169 -0
  3. llms_py-3.0.25/llms/extensions/github_auth/__init__.py +254 -0
  4. llms_py-3.0.25/llms/extensions/github_auth/ui/index.mjs +66 -0
  5. {llms_py-3.0.24 → llms_py-3.0.25}/llms/llms.json +0 -9
  6. {llms_py-3.0.24 → llms_py-3.0.25}/llms/main.py +87 -294
  7. {llms_py-3.0.24 → llms_py-3.0.25}/llms/ui/App.mjs +4 -1
  8. {llms_py-3.0.24 → llms_py-3.0.25}/llms/ui/ai.mjs +1 -2
  9. {llms_py-3.0.24 → llms_py-3.0.25}/llms/ui/modules/chat/ChatBody.mjs +1 -2
  10. {llms_py-3.0.24 → llms_py-3.0.25}/llms/ui/modules/layout.mjs +1 -57
  11. {llms_py-3.0.24 → llms_py-3.0.25/llms_py.egg-info}/PKG-INFO +1 -1
  12. {llms_py-3.0.24 → llms_py-3.0.25}/llms_py.egg-info/SOURCES.txt +3 -0
  13. {llms_py-3.0.24 → llms_py-3.0.25}/pyproject.toml +1 -1
  14. {llms_py-3.0.24 → llms_py-3.0.25}/setup.py +1 -1
  15. {llms_py-3.0.24 → llms_py-3.0.25}/LICENSE +0 -0
  16. {llms_py-3.0.24 → llms_py-3.0.25}/MANIFEST.in +0 -0
  17. {llms_py-3.0.24 → llms_py-3.0.25}/README.md +0 -0
  18. {llms_py-3.0.24 → llms_py-3.0.25}/llms/__init__.py +0 -0
  19. {llms_py-3.0.24 → llms_py-3.0.25}/llms/__main__.py +0 -0
  20. {llms_py-3.0.24 → llms_py-3.0.25}/llms/db.py +0 -0
  21. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/analytics/ui/index.mjs +0 -0
  22. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/app/README.md +0 -0
  23. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/app/__init__.py +0 -0
  24. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/app/db.py +0 -0
  25. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/app/ui/Recents.mjs +0 -0
  26. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/app/ui/index.mjs +0 -0
  27. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/app/ui/threadStore.mjs +0 -0
  28. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/computer/README.md +0 -0
  29. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/computer/__init__.py +0 -0
  30. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/computer/base.py +0 -0
  31. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/computer/bash.py +0 -0
  32. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/computer/computer.py +0 -0
  33. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/computer/edit.py +0 -0
  34. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/computer/filesystem.py +0 -0
  35. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/computer/platform.py +0 -0
  36. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/computer/run.py +0 -0
  37. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/core_tools/CALCULATOR.md +0 -0
  38. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/core_tools/__init__.py +0 -0
  39. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/core_tools/ui/codemirror/addon/edit/closebrackets.js +0 -0
  40. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/core_tools/ui/codemirror/addon/edit/closetag.js +0 -0
  41. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/core_tools/ui/codemirror/addon/edit/continuelist.js +0 -0
  42. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/core_tools/ui/codemirror/addon/edit/matchbrackets.js +0 -0
  43. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/core_tools/ui/codemirror/addon/edit/matchtags.js +0 -0
  44. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/core_tools/ui/codemirror/addon/edit/trailingspace.js +0 -0
  45. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/core_tools/ui/codemirror/addon/selection/active-line.js +0 -0
  46. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/core_tools/ui/codemirror/addon/selection/mark-selection.js +0 -0
  47. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/core_tools/ui/codemirror/addon/selection/selection-pointer.js +0 -0
  48. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/core_tools/ui/codemirror/codemirror.css +0 -0
  49. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/core_tools/ui/codemirror/codemirror.js +0 -0
  50. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/core_tools/ui/codemirror/doc/docs.css +0 -0
  51. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/core_tools/ui/codemirror/doc/source_sans.woff +0 -0
  52. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/core_tools/ui/codemirror/mode/clike/clike.js +0 -0
  53. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/core_tools/ui/codemirror/mode/javascript/index.html +0 -0
  54. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/core_tools/ui/codemirror/mode/javascript/javascript.js +0 -0
  55. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/core_tools/ui/codemirror/mode/javascript/typescript.html +0 -0
  56. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/core_tools/ui/codemirror/mode/python/python.js +0 -0
  57. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/core_tools/ui/codemirror/theme/dracula.css +0 -0
  58. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/core_tools/ui/codemirror/theme/mocha.css +0 -0
  59. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/core_tools/ui/index.mjs +0 -0
  60. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/gallery/README.md +0 -0
  61. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/gallery/__init__.py +0 -0
  62. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/gallery/db.py +0 -0
  63. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/gallery/ui/index.mjs +0 -0
  64. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/README.md +0 -0
  65. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/__init__.py +0 -0
  66. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/README.md +0 -0
  67. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/contrib/auto-render.js +0 -0
  68. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/contrib/auto-render.min.js +0 -0
  69. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/contrib/auto-render.mjs +0 -0
  70. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/contrib/copy-tex.js +0 -0
  71. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/contrib/copy-tex.min.js +0 -0
  72. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/contrib/copy-tex.mjs +0 -0
  73. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/contrib/mathtex-script-type.js +0 -0
  74. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/contrib/mathtex-script-type.min.js +0 -0
  75. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/contrib/mathtex-script-type.mjs +0 -0
  76. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/contrib/mhchem.js +0 -0
  77. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/contrib/mhchem.min.js +0 -0
  78. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/contrib/mhchem.mjs +0 -0
  79. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/contrib/render-a11y-string.js +0 -0
  80. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/contrib/render-a11y-string.min.js +0 -0
  81. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/contrib/render-a11y-string.mjs +0 -0
  82. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_AMS-Regular.ttf +0 -0
  83. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_AMS-Regular.woff +0 -0
  84. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_AMS-Regular.woff2 +0 -0
  85. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_Caligraphic-Bold.ttf +0 -0
  86. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_Caligraphic-Bold.woff +0 -0
  87. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
  88. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_Caligraphic-Regular.ttf +0 -0
  89. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_Caligraphic-Regular.woff +0 -0
  90. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
  91. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_Fraktur-Bold.ttf +0 -0
  92. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_Fraktur-Bold.woff +0 -0
  93. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
  94. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_Fraktur-Regular.ttf +0 -0
  95. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_Fraktur-Regular.woff +0 -0
  96. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
  97. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_Main-Bold.ttf +0 -0
  98. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_Main-Bold.woff +0 -0
  99. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_Main-Bold.woff2 +0 -0
  100. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_Main-BoldItalic.ttf +0 -0
  101. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_Main-BoldItalic.woff +0 -0
  102. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
  103. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_Main-Italic.ttf +0 -0
  104. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_Main-Italic.woff +0 -0
  105. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_Main-Italic.woff2 +0 -0
  106. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_Main-Regular.ttf +0 -0
  107. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_Main-Regular.woff +0 -0
  108. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_Main-Regular.woff2 +0 -0
  109. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_Math-BoldItalic.ttf +0 -0
  110. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_Math-BoldItalic.woff +0 -0
  111. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
  112. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_Math-Italic.ttf +0 -0
  113. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_Math-Italic.woff +0 -0
  114. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_Math-Italic.woff2 +0 -0
  115. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Bold.ttf +0 -0
  116. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Bold.woff +0 -0
  117. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
  118. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Italic.ttf +0 -0
  119. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Italic.woff +0 -0
  120. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
  121. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Regular.ttf +0 -0
  122. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Regular.woff +0 -0
  123. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
  124. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_Script-Regular.ttf +0 -0
  125. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_Script-Regular.woff +0 -0
  126. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_Script-Regular.woff2 +0 -0
  127. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_Size1-Regular.ttf +0 -0
  128. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_Size1-Regular.woff +0 -0
  129. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_Size1-Regular.woff2 +0 -0
  130. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_Size2-Regular.ttf +0 -0
  131. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_Size2-Regular.woff +0 -0
  132. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_Size2-Regular.woff2 +0 -0
  133. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_Size3-Regular.ttf +0 -0
  134. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_Size3-Regular.woff +0 -0
  135. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_Size3-Regular.woff2 +0 -0
  136. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_Size4-Regular.ttf +0 -0
  137. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_Size4-Regular.woff +0 -0
  138. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_Size4-Regular.woff2 +0 -0
  139. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_Typewriter-Regular.ttf +0 -0
  140. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_Typewriter-Regular.woff +0 -0
  141. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
  142. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/index.mjs +0 -0
  143. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/katex-swap.css +0 -0
  144. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/katex-swap.min.css +0 -0
  145. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/katex.css +0 -0
  146. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/katex.js +0 -0
  147. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/katex.min.css +0 -0
  148. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/katex.min.js +0 -0
  149. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/katex.min.mjs +0 -0
  150. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/katex/ui/katex.mjs +0 -0
  151. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/providers/__init__.py +0 -0
  152. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/providers/anthropic.py +0 -0
  153. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/providers/cerebras.py +0 -0
  154. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/providers/chutes.py +0 -0
  155. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/providers/google.py +0 -0
  156. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/providers/nvidia.py +0 -0
  157. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/providers/openai.py +0 -0
  158. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/providers/openrouter.py +0 -0
  159. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/providers/zai.py +0 -0
  160. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/skills/LICENSE +0 -0
  161. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/skills/README.md +0 -0
  162. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/skills/__init__.py +0 -0
  163. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/skills/errors.py +0 -0
  164. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/skills/installer.py +0 -0
  165. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/skills/models.py +0 -0
  166. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/skills/parser.py +0 -0
  167. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/skills/ui/data/skills-top-5000.json +0 -0
  168. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/skills/ui/index.mjs +0 -0
  169. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/skills/ui/skills/create-plan/SKILL.md +0 -0
  170. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/skills/ui/skills/skill-creator/LICENSE.txt +0 -0
  171. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/skills/ui/skills/skill-creator/SKILL.md +0 -0
  172. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/skills/ui/skills/skill-creator/references/output-patterns.md +0 -0
  173. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/skills/ui/skills/skill-creator/references/workflows.md +0 -0
  174. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/skills/ui/skills/skill-creator/scripts/init_skill.py +0 -0
  175. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/skills/ui/skills/skill-creator/scripts/package_skill.py +0 -0
  176. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/skills/ui/skills/skill-creator/scripts/quick_validate.py +0 -0
  177. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/skills/validator.py +0 -0
  178. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/system_prompts/README.md +0 -0
  179. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/system_prompts/__init__.py +0 -0
  180. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/system_prompts/ui/index.mjs +0 -0
  181. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/system_prompts/ui/prompts.json +0 -0
  182. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/tools/__init__.py +0 -0
  183. {llms_py-3.0.24 → llms_py-3.0.25}/llms/extensions/tools/ui/index.mjs +0 -0
  184. {llms_py-3.0.24 → llms_py-3.0.25}/llms/index.html +0 -0
  185. {llms_py-3.0.24 → llms_py-3.0.25}/llms/providers-extra.json +0 -0
  186. {llms_py-3.0.24 → llms_py-3.0.25}/llms/providers.json +0 -0
  187. {llms_py-3.0.24 → llms_py-3.0.25}/llms/ui/app.css +0 -0
  188. {llms_py-3.0.24 → llms_py-3.0.25}/llms/ui/ctx.mjs +0 -0
  189. {llms_py-3.0.24 → llms_py-3.0.25}/llms/ui/fav.svg +0 -0
  190. {llms_py-3.0.24 → llms_py-3.0.25}/llms/ui/index.mjs +0 -0
  191. {llms_py-3.0.24 → llms_py-3.0.25}/llms/ui/lib/chart.js +0 -0
  192. {llms_py-3.0.24 → llms_py-3.0.25}/llms/ui/lib/charts.mjs +0 -0
  193. {llms_py-3.0.24 → llms_py-3.0.25}/llms/ui/lib/color.js +0 -0
  194. {llms_py-3.0.24 → llms_py-3.0.25}/llms/ui/lib/highlight.min.mjs +0 -0
  195. {llms_py-3.0.24 → llms_py-3.0.25}/llms/ui/lib/idb.min.mjs +0 -0
  196. {llms_py-3.0.24 → llms_py-3.0.25}/llms/ui/lib/marked.min.mjs +0 -0
  197. {llms_py-3.0.24 → llms_py-3.0.25}/llms/ui/lib/servicestack-client.mjs +0 -0
  198. {llms_py-3.0.24 → llms_py-3.0.25}/llms/ui/lib/servicestack-vue.mjs +0 -0
  199. {llms_py-3.0.24 → llms_py-3.0.25}/llms/ui/lib/vue-router.min.mjs +0 -0
  200. {llms_py-3.0.24 → llms_py-3.0.25}/llms/ui/lib/vue.min.mjs +0 -0
  201. {llms_py-3.0.24 → llms_py-3.0.25}/llms/ui/lib/vue.mjs +0 -0
  202. {llms_py-3.0.24 → llms_py-3.0.25}/llms/ui/markdown.mjs +0 -0
  203. {llms_py-3.0.24 → llms_py-3.0.25}/llms/ui/modules/chat/SettingsDialog.mjs +0 -0
  204. {llms_py-3.0.24 → llms_py-3.0.25}/llms/ui/modules/chat/index.mjs +0 -0
  205. {llms_py-3.0.24 → llms_py-3.0.25}/llms/ui/modules/icons.mjs +0 -0
  206. {llms_py-3.0.24 → llms_py-3.0.25}/llms/ui/modules/model-selector.mjs +0 -0
  207. {llms_py-3.0.24 → llms_py-3.0.25}/llms/ui/tailwind.input.css +0 -0
  208. {llms_py-3.0.24 → llms_py-3.0.25}/llms/ui/typography.css +0 -0
  209. {llms_py-3.0.24 → llms_py-3.0.25}/llms/ui/utils.mjs +0 -0
  210. {llms_py-3.0.24 → llms_py-3.0.25}/llms_py.egg-info/dependency_links.txt +0 -0
  211. {llms_py-3.0.24 → llms_py-3.0.25}/llms_py.egg-info/entry_points.txt +0 -0
  212. {llms_py-3.0.24 → llms_py-3.0.25}/llms_py.egg-info/not-zip-safe +0 -0
  213. {llms_py-3.0.24 → llms_py-3.0.25}/llms_py.egg-info/requires.txt +0 -0
  214. {llms_py-3.0.24 → llms_py-3.0.25}/llms_py.egg-info/top_level.txt +0 -0
  215. {llms_py-3.0.24 → llms_py-3.0.25}/requirements.txt +0 -0
  216. {llms_py-3.0.24 → llms_py-3.0.25}/setup.cfg +0 -0
  217. {llms_py-3.0.24 → llms_py-3.0.25}/tests/test_async.py +0 -0
  218. {llms_py-3.0.24 → llms_py-3.0.25}/tests/test_config.py +0 -0
  219. {llms_py-3.0.24 → llms_py-3.0.25}/tests/test_core_tools_direct.py +0 -0
  220. {llms_py-3.0.24 → llms_py-3.0.25}/tests/test_extensions.py +0 -0
  221. {llms_py-3.0.24 → llms_py-3.0.25}/tests/test_gemini_tool_calling.py +0 -0
  222. {llms_py-3.0.24 → llms_py-3.0.25}/tests/test_gemini_upload.py +0 -0
  223. {llms_py-3.0.24 → llms_py-3.0.25}/tests/test_integration.py +0 -0
  224. {llms_py-3.0.24 → llms_py-3.0.25}/tests/test_interleaved_thinking.py +0 -0
  225. {llms_py-3.0.24 → llms_py-3.0.25}/tests/test_provider_checks.py +0 -0
  226. {llms_py-3.0.24 → llms_py-3.0.25}/tests/test_provider_config.py +0 -0
  227. {llms_py-3.0.24 → llms_py-3.0.25}/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.24
3
+ Version: 3.0.25
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
@@ -0,0 +1,169 @@
1
+ # GitHub Auth Extension
2
+
3
+ The GitHub Auth extension enables OAuth 2.0 authentication via GitHub for your llms application. When enabled, users must sign in with their GitHub account before accessing the application.
4
+
5
+ ## Features
6
+
7
+ - **GitHub OAuth 2.0** - Standard OAuth flow with CSRF protection
8
+ - **User Restrictions** - Optionally restrict access to specific GitHub users
9
+ - **Session Management** - Automatic session handling with 24-hour expiry
10
+ - **Environment Variables** - Credentials can use env vars for secure deployment
11
+
12
+ ## Configuration
13
+
14
+ Create a config file at `~/.llms/users/default/github_auth/config.json`:
15
+
16
+ ```json
17
+ {
18
+ "enabled": true,
19
+ "client_id": "$GITHUB_CLIENT_ID",
20
+ "client_secret": "$GITHUB_CLIENT_SECRET",
21
+ "redirect_uri": "http://localhost:8000/auth/github/callback",
22
+ "restrict_to": "$GITHUB_USERS"
23
+ }
24
+ ```
25
+
26
+ | Property | Description |
27
+ |-----------------|-------------|
28
+ | `client_id` | GitHub OAuth App client ID |
29
+ | `client_secret` | GitHub OAuth App client secret |
30
+ | `redirect_uri` | Callback URL registered with GitHub |
31
+ | `restrict_to` | Optional comma/space-delimited list of allowed GitHub usernames |
32
+ | `enabled` | Set to `false` to disable the extension |
33
+
34
+ Values prefixed with `$` are resolved from environment variables.
35
+
36
+ ## Creating a GitHub OAuth App
37
+
38
+ 1. Go to [GitHub Developer Settings](https://github.com/settings/developers)
39
+ 2. Click **New OAuth App**
40
+ 3. Fill in the application details:
41
+ - **Application name**: Your app name
42
+ - **Homepage URL**: Your app's homepage (e.g., `http://localhost:8000`)
43
+ - **Authorization callback URL**: Must match your `redirect_uri` (e.g., `http://localhost:8000/auth/github/callback`)
44
+ 4. Click **Register application**
45
+ 5. Copy the **Client ID** and generate a **Client Secret**
46
+
47
+ ## API Endpoints
48
+
49
+ The extension registers these routes:
50
+
51
+ | Method | Endpoint | Description |
52
+ |--------|-------------------------|-------------|
53
+ | GET | `/auth` | Check authentication status |
54
+ | GET | `/auth/github` | Initiate GitHub OAuth flow |
55
+ | GET | `/auth/github/callback` | OAuth callback handler |
56
+ | GET | `/auth/session` | Get current session info |
57
+ | POST | `/auth/logout` | End the current session |
58
+
59
+ ### GET /auth
60
+
61
+ Returns the authenticated user's info or a 401 error:
62
+
63
+ ```json
64
+ {
65
+ "userId": "12345",
66
+ "userName": "octocat",
67
+ "displayName": "The Octocat",
68
+ "profileUrl": "https://avatars.githubusercontent.com/u/12345",
69
+ "authProvider": "github"
70
+ }
71
+ ```
72
+
73
+ ### GET /auth/session
74
+
75
+ Returns full session details including the session token:
76
+
77
+ ```json
78
+ {
79
+ "userId": "12345",
80
+ "userName": "octocat",
81
+ "displayName": "The Octocat",
82
+ "profileUrl": "https://avatars.githubusercontent.com/u/12345",
83
+ "email": "octocat@github.com",
84
+ "created": 1706600000.123,
85
+ "sessionToken": "..."
86
+ }
87
+ ```
88
+
89
+ ## OAuth Flow
90
+
91
+ ```
92
+ ┌─────────┐ ┌─────────┐ ┌────────┐
93
+ │ Browser │ │ llms │ │ GitHub │
94
+ └────┬────┘ └────┬────┘ └───┬────┘
95
+ │ │ │
96
+ │ GET /auth/github │ │
97
+ ├───────────────────►│ │
98
+ │ │ │
99
+ │ 302 Redirect │ │
100
+ │◄───────────────────┤ │
101
+ │ │ │
102
+ │ /login/oauth/authorize?... │
103
+ ├────────────────────────────────────────►
104
+ │ │ │
105
+ │ User grants access │
106
+ │◄────────────────────────────────────────
107
+ │ │ │
108
+ │ GET /auth/github/callback?code=... │
109
+ ├───────────────────►│ │
110
+ │ │ │
111
+ │ │ POST /access_token │
112
+ │ ├──────────────────►│
113
+ │ │ │
114
+ │ │ access_token │
115
+ │ │◄──────────────────┤
116
+ │ │ │
117
+ │ │ GET /user │
118
+ │ ├──────────────────►│
119
+ │ │ │
120
+ │ │ user info │
121
+ │ │◄──────────────────┤
122
+ │ │ │
123
+ │ 302 /?session=... │ │
124
+ │ Set-Cookie: token │ │
125
+ │◄───────────────────┤ │
126
+ │ │ │
127
+ ```
128
+
129
+ 1. User clicks "Sign in with GitHub" → redirects to `/auth/github`
130
+ 2. Server generates CSRF state token and redirects to GitHub
131
+ 3. User authorizes the app on GitHub
132
+ 4. GitHub redirects back with authorization code
133
+ 5. Server exchanges code for access token
134
+ 6. Server fetches user info from GitHub API
135
+ 7. Server creates session and sets cookie
136
+
137
+ ## Restricting Access
138
+
139
+ To limit access to specific GitHub users, set `restrict_to` in your config:
140
+
141
+ ```json
142
+ {
143
+ "client_id": "...",
144
+ "client_secret": "...",
145
+ "redirect_uri": "...",
146
+ "restrict_to": "alice bob charlie"
147
+ }
148
+ ```
149
+
150
+ Users not in this list receive a `403 Forbidden` response.
151
+
152
+ ## UI Component
153
+
154
+ The extension provides a custom `SignIn` component that displays a "Sign in with GitHub" button. This component automatically overrides the default sign-in UI when the extension is loaded.
155
+
156
+ ## Session Storage
157
+
158
+ Sessions are stored in memory with:
159
+ - **Token**: Cryptographically secure random string
160
+ - **User data**: GitHub user ID, username, display name, avatar URL, email
161
+ - **Expiry**: Automatic cleanup after 24 hours
162
+ - **Cookie**: `llms-token` with `httponly` flag for security
163
+
164
+ ## Security Notes
165
+
166
+ - **CSRF Protection**: OAuth state tokens prevent cross-site request forgery
167
+ - **State Cleanup**: Expired state tokens (>10 min) are automatically removed
168
+ - **Session Cleanup**: Sessions older than 24 hours are pruned
169
+ - **HttpOnly Cookie**: Session token is not accessible via JavaScript
@@ -0,0 +1,254 @@
1
+ import json
2
+ import os
3
+ import re
4
+ import secrets
5
+ import time
6
+ from urllib.parse import parse_qs, urlencode
7
+
8
+ import aiohttp
9
+ from aiohttp import web
10
+
11
+
12
+ def install(ctx):
13
+ g_app = ctx.app
14
+
15
+ auth_config_file = os.path.join(ctx.get_user_path(), "github_auth", "config.json")
16
+
17
+ auth_config = None
18
+ if os.path.exists(auth_config_file):
19
+ try:
20
+ with open(auth_config_file, encoding="utf-8") as f:
21
+ auth_config = json.load(f)
22
+ if "enabled" in auth_config and not auth_config["enabled"]:
23
+ ctx.log("GitHub Auth is disabled in config")
24
+ auth_config = None
25
+ except Exception as e:
26
+ ctx.err("Failed to load GitHub auth config", e)
27
+ else:
28
+ ctx.dbg(f"GitHub Auth config file '{auth_config_file}' not found")
29
+
30
+ if not auth_config:
31
+ # don't load extension if auth_config is not found or is disabled
32
+ ctx.disabled = True
33
+ return
34
+
35
+ client_id = auth_config.get("client_id", "")
36
+ client_secret = auth_config.get("client_secret", "")
37
+ redirect_uri = auth_config.get("redirect_uri", "")
38
+ restrict_to = auth_config.get("restrict_to", "")
39
+
40
+ # Expand environment variables
41
+ if client_id.startswith("$"):
42
+ client_id = client_id[1:]
43
+ if client_secret.startswith("$"):
44
+ client_secret = client_secret[1:]
45
+ client_secret = os.getenv(client_secret)
46
+ if redirect_uri.startswith("$"):
47
+ redirect_uri = redirect_uri[1:]
48
+ redirect_uri = os.getenv(redirect_uri)
49
+ if restrict_to.startswith("$"):
50
+ restrict_to = restrict_to[1:]
51
+ restrict_to = os.getenv(restrict_to)
52
+
53
+ # check if client_id is set
54
+ if client_id == "GITHUB_CLIENT_ID":
55
+ client_id = os.getenv(client_id)
56
+ if client_secret == "GITHUB_CLIENT_SECRET":
57
+ client_secret = os.getenv(client_secret)
58
+ if restrict_to == "GITHUB_USERS":
59
+ restrict_to = os.getenv(restrict_to)
60
+
61
+ if not client_id or not redirect_uri or not client_secret:
62
+ ctx.disabled = True
63
+ ctx.log("GitHub OAuth client_id, client_secret and redirect_uri are not configured")
64
+ return
65
+
66
+ from llms.main import AuthProvider
67
+
68
+ class GitHubAuthProvider(AuthProvider):
69
+ def __init__(self, app):
70
+ super().__init__(app)
71
+
72
+ # Adding an Auth Provider forces Authentication to be enabled
73
+ auth_provider = GitHubAuthProvider(g_app)
74
+ g_app.auth_providers.append(auth_provider)
75
+
76
+ # OAuth handlers
77
+ async def github_auth_handler(request):
78
+ # Generate CSRF state token
79
+ state = secrets.token_urlsafe(32)
80
+ ctx.oauth_states[state] = {"created": time.time(), "redirect_uri": redirect_uri}
81
+
82
+ # Clean up old states (older than 10 minutes)
83
+ current_time = time.time()
84
+ expired_states = [s for s, data in ctx.oauth_states.items() if current_time - data["created"] > 600]
85
+ for s in expired_states:
86
+ del ctx.oauth_states[s]
87
+
88
+ # Build GitHub authorization URL
89
+ params = {
90
+ "client_id": client_id,
91
+ "redirect_uri": redirect_uri,
92
+ "state": state,
93
+ "scope": "read:user user:email",
94
+ }
95
+ auth_url = f"https://github.com/login/oauth/authorize?{urlencode(params)}"
96
+
97
+ return web.HTTPFound(auth_url)
98
+
99
+ def validate_user(github_username):
100
+ # If restrict_to is configured, validate the user
101
+ if restrict_to:
102
+ # Parse allowed users (comma or space delimited)
103
+ allowed_users = [u.strip() for u in re.split(r"[,\s]+", restrict_to) if u.strip()]
104
+
105
+ # Check if user is in the allowed list
106
+ if not github_username or github_username not in allowed_users:
107
+ ctx.log(f"Access denied for user: {github_username}. Not in allowed list: {allowed_users}")
108
+ return web.Response(
109
+ text=f"Access denied. User '{github_username}' is not authorized to access this application.",
110
+ status=403,
111
+ )
112
+ return None
113
+
114
+ async def github_callback_handler(request):
115
+ """Handle GitHub OAuth callback"""
116
+ code = request.query.get("code")
117
+ state = request.query.get("state")
118
+
119
+ # Handle malformed URLs where query params are appended with & instead of ?
120
+ if not code and "tail" in request.match_info:
121
+ tail = request.match_info["tail"]
122
+ if tail.startswith("&"):
123
+ params = parse_qs(tail[1:])
124
+ code = params.get("code", [None])[0]
125
+ state = params.get("state", [None])[0]
126
+
127
+ if not code or not state:
128
+ return web.Response(text="Missing code or state parameter", status=400)
129
+
130
+ # Verify state token (CSRF protection)
131
+ if state not in ctx.oauth_states:
132
+ return web.Response(text="Invalid state parameter", status=400)
133
+
134
+ ctx.oauth_states.pop(state)
135
+
136
+ # Exchange code for access token
137
+ async with aiohttp.ClientSession() as session:
138
+ token_url = "https://github.com/login/oauth/access_token"
139
+ token_data = {
140
+ "client_id": client_id,
141
+ "client_secret": client_secret,
142
+ "code": code,
143
+ "redirect_uri": redirect_uri,
144
+ }
145
+ headers = {"Accept": "application/json"}
146
+
147
+ async with session.post(token_url, data=token_data, headers=headers) as resp:
148
+ token_response = await resp.json()
149
+ access_token = token_response.get("access_token")
150
+
151
+ if not access_token:
152
+ error = token_response.get("error_description", "Failed to get access token")
153
+ return web.json_response(ctx.create_error_response(f"OAuth error: {error}"), status=400)
154
+
155
+ # Fetch user info
156
+ user_url = "https://api.github.com/user"
157
+ headers = {"Authorization": f"Bearer {access_token}", "Accept": "application/json"}
158
+
159
+ async with session.get(user_url, headers=headers) as resp:
160
+ user_data = await resp.json()
161
+
162
+ # Validate user
163
+ error_response = validate_user(user_data.get("login", ""))
164
+ if error_response:
165
+ return error_response
166
+
167
+ # Create session
168
+ session_token = secrets.token_urlsafe(32)
169
+ ctx.sessions[session_token] = {
170
+ "userId": str(user_data.get("id", "")),
171
+ "userName": user_data.get("login", ""),
172
+ "displayName": user_data.get("name", ""),
173
+ "profileUrl": user_data.get("avatar_url", ""),
174
+ "email": user_data.get("email", ""),
175
+ "created": time.time(),
176
+ }
177
+
178
+ # Redirect to UI with session token
179
+ response = web.HTTPFound(f"/?session={session_token}")
180
+ response.set_cookie("llms-token", session_token, httponly=True, path="/", max_age=86400)
181
+ return response
182
+
183
+ async def session_handler(request):
184
+ """Validate and return session info"""
185
+ session_token = auth_provider.get_session_token(request)
186
+
187
+ if not session_token or session_token not in ctx.sessions:
188
+ return web.json_response(ctx.create_error_response("Invalid or expired session"), status=401)
189
+
190
+ session_data = ctx.sessions[session_token]
191
+
192
+ # Clean up old sessions (older than 24 hours)
193
+ current_time = time.time()
194
+ expired_sessions = [token for token, data in ctx.sessions.items() if current_time - data["created"] > 86400]
195
+ for token in expired_sessions:
196
+ del ctx.sessions[token]
197
+
198
+ return web.json_response({**session_data, "sessionToken": session_token})
199
+
200
+ async def logout_handler(request):
201
+ """End OAuth session"""
202
+ session_token = auth_provider.get_session_token(request)
203
+
204
+ if session_token and session_token in g_app.sessions:
205
+ del g_app.sessions[session_token]
206
+
207
+ response = web.json_response({"success": True})
208
+ response.del_cookie("llms-token")
209
+ return response
210
+
211
+ async def auth_handler(request):
212
+ """Check authentication status and return user info"""
213
+ # Check for OAuth session token
214
+ session_token = auth_provider.get_session_token(request)
215
+
216
+ if session_token and session_token in g_app.sessions:
217
+ session_data = g_app.sessions[session_token]
218
+ return web.json_response(
219
+ {
220
+ "userId": session_data.get("userId", ""),
221
+ "userName": session_data.get("userName", ""),
222
+ "displayName": session_data.get("displayName", ""),
223
+ "profileUrl": session_data.get("profileUrl", ""),
224
+ "authProvider": "github",
225
+ }
226
+ )
227
+
228
+ # Check for API key in Authorization header
229
+ # auth_header = request.headers.get('Authorization', '')
230
+ # if auth_header.startswith('Bearer '):
231
+ # # For API key auth, return a basic response
232
+ # # You can customize this based on your API key validation logic
233
+ # api_key = auth_header[7:]
234
+ # if api_key: # Add your API key validation logic here
235
+ # return web.json_response({
236
+ # "userId": "1",
237
+ # "userName": "apiuser",
238
+ # "displayName": "API User",
239
+ # "profileUrl": "",
240
+ # "authProvider": "apikey"
241
+ # })
242
+
243
+ # Not authenticated - return error in expected format
244
+ return web.json_response(g_app.error_auth_required, status=401)
245
+
246
+ ctx.add_get("/auth", auth_handler)
247
+ ctx.add_get("/auth/github", github_auth_handler)
248
+ ctx.add_get("/auth/github/callback", github_callback_handler)
249
+ ctx.add_get("/auth/github/callback{tail:.*}", github_callback_handler)
250
+ ctx.add_get("/auth/session", session_handler)
251
+ ctx.add_post("/auth/logout", logout_handler)
252
+
253
+
254
+ __install__ = install
@@ -0,0 +1,66 @@
1
+ import { ref } from "vue"
2
+
3
+ const SignIn = {
4
+ template: `
5
+ <div class="min-h-full -mt-36 flex flex-col justify-center sm:px-6 lg:px-8">
6
+ <div class="sm:mx-auto sm:w-full sm:max-w-md text-center">
7
+ <Welcome />
8
+ </div>
9
+ <div class="sm:mx-auto sm:w-full sm:max-w-md">
10
+ <div v-if="errorMessage" class="mb-3 bg-red-50 dark:bg-red-900/30 border border-red-200 dark:border-red-800 text-red-800 dark:text-red-200 rounded-lg px-4 py-3">
11
+ <div class="flex items-start space-x-2">
12
+ <div class="flex-1">
13
+ <div class="text-base font-medium">{{ errorMessage }}</div>
14
+ </div>
15
+ <button type="button"
16
+ @click="errorMessage = null"
17
+ class="text-red-400 dark:text-red-300 hover:text-red-600 dark:hover:text-red-100 flex-shrink-0"
18
+ >
19
+ <svg class="w-4 h-4" fill="currentColor" viewBox="0 0 20 20">
20
+ <path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"></path>
21
+ </svg>
22
+ </button>
23
+ </div>
24
+ </div>
25
+ <div class="py-8 px-4 sm:px-10">
26
+ <div class="space-y-4">
27
+ <button
28
+ type="button"
29
+ @click="signInWithGitHub"
30
+ class="w-full inline-flex items-center justify-center px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm text-base font-medium text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-800 hover:bg-gray-50 dark:hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-500 transition-colors"
31
+ >
32
+ <svg class="w-6 h-6 mr-3" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true">
33
+ <path fill-rule="evenodd" d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z" clip-rule="evenodd" />
34
+ </svg>
35
+ Sign in with GitHub
36
+ </button>
37
+ </div>
38
+ </div>
39
+ </div>
40
+ </div>
41
+ `,
42
+ emits: ['done'],
43
+ setup(props, { emit }) {
44
+ const errorMessage = ref(null)
45
+
46
+ function signInWithGitHub() {
47
+ // Redirect to GitHub OAuth endpoint
48
+ window.location.href = '/auth/github'
49
+ }
50
+
51
+ return {
52
+ signInWithGitHub,
53
+ errorMessage,
54
+ }
55
+ }
56
+ }
57
+
58
+
59
+ export default {
60
+ install(ctx) {
61
+ // Override SignIn component
62
+ ctx.components({
63
+ SignIn,
64
+ })
65
+ }
66
+ }
@@ -1,14 +1,5 @@
1
1
  {
2
2
  "version": 3,
3
- "auth": {
4
- "enabled": false,
5
- "github": {
6
- "client_id": "GITHUB_CLIENT_ID",
7
- "client_secret": "GITHUB_CLIENT_SECRET",
8
- "redirect_uri": "http://localhost:8000/auth/github/callback",
9
- "restrict_to": "GITHUB_USERS"
10
- }
11
- },
12
3
  "disable_extensions": [],
13
4
  "defaults": {
14
5
  "headers": {