llm-shell 0.9.2 → 0.10.0

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 (258) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +61 -66
  3. data/lib/llm/shell/command.rb +40 -40
  4. data/lib/llm/shell/commands/clear_screen.rb +4 -18
  5. data/lib/llm/shell/commands/debug_mode.rb +12 -0
  6. data/lib/llm/shell/commands/dir_import.rb +4 -20
  7. data/lib/llm/shell/commands/disable_tool.rb +33 -0
  8. data/lib/llm/shell/commands/enable_tool.rb +33 -0
  9. data/lib/llm/shell/commands/file_import.rb +4 -20
  10. data/lib/llm/shell/commands/help.rb +23 -36
  11. data/lib/llm/shell/commands/show_chat.rb +4 -19
  12. data/lib/llm/shell/commands/show_version.rb +4 -20
  13. data/lib/llm/shell/commands/system_prompt.rb +4 -18
  14. data/lib/llm/shell/completion.rb +5 -5
  15. data/lib/llm/shell/config.rb +4 -5
  16. data/lib/llm/shell/formatter.rb +1 -2
  17. data/lib/llm/shell/internal/coderay/lib/coderay/duo.rb +81 -0
  18. data/lib/llm/shell/internal/coderay/lib/coderay/encoders/_map.rb +17 -0
  19. data/lib/llm/shell/internal/coderay/lib/coderay/encoders/comment_filter.rb +25 -0
  20. data/lib/llm/shell/internal/coderay/lib/coderay/encoders/count.rb +39 -0
  21. data/lib/llm/shell/internal/coderay/lib/coderay/encoders/debug.rb +49 -0
  22. data/lib/llm/shell/internal/coderay/lib/coderay/encoders/debug_lint.rb +63 -0
  23. data/lib/llm/shell/internal/coderay/lib/coderay/encoders/div.rb +23 -0
  24. data/lib/llm/shell/internal/coderay/lib/coderay/encoders/encoder.rb +190 -0
  25. data/lib/llm/shell/internal/coderay/lib/coderay/encoders/filter.rb +58 -0
  26. data/lib/llm/shell/internal/coderay/lib/coderay/encoders/html/css.rb +65 -0
  27. data/lib/llm/shell/internal/coderay/lib/coderay/encoders/html/numbering.rb +108 -0
  28. data/lib/llm/shell/internal/coderay/lib/coderay/encoders/html/output.rb +164 -0
  29. data/lib/llm/shell/internal/coderay/lib/coderay/encoders/html.rb +333 -0
  30. data/lib/llm/shell/internal/coderay/lib/coderay/encoders/json.rb +83 -0
  31. data/lib/llm/shell/internal/coderay/lib/coderay/encoders/lines_of_code.rb +45 -0
  32. data/lib/llm/shell/internal/coderay/lib/coderay/encoders/lint.rb +59 -0
  33. data/lib/llm/shell/internal/coderay/lib/coderay/encoders/null.rb +18 -0
  34. data/lib/llm/shell/internal/coderay/lib/coderay/encoders/page.rb +24 -0
  35. data/lib/llm/shell/internal/coderay/lib/coderay/encoders/span.rb +23 -0
  36. data/lib/llm/shell/internal/coderay/lib/coderay/encoders/statistic.rb +95 -0
  37. data/lib/llm/shell/internal/coderay/lib/coderay/encoders/terminal.rb +195 -0
  38. data/lib/llm/shell/internal/coderay/lib/coderay/encoders/text.rb +46 -0
  39. data/lib/llm/shell/internal/coderay/lib/coderay/encoders/token_kind_filter.rb +111 -0
  40. data/lib/llm/shell/internal/coderay/lib/coderay/encoders/xml.rb +72 -0
  41. data/lib/llm/shell/internal/coderay/lib/coderay/encoders/yaml.rb +50 -0
  42. data/lib/llm/shell/internal/coderay/lib/coderay/encoders.rb +18 -0
  43. data/lib/llm/shell/internal/coderay/lib/coderay/for_redcloth.rb +95 -0
  44. data/lib/llm/shell/internal/coderay/lib/coderay/helpers/file_type.rb +151 -0
  45. data/lib/llm/shell/internal/coderay/lib/coderay/helpers/plugin.rb +55 -0
  46. data/lib/llm/shell/internal/coderay/lib/coderay/helpers/plugin_host.rb +221 -0
  47. data/lib/llm/shell/internal/coderay/lib/coderay/helpers/word_list.rb +72 -0
  48. data/lib/llm/shell/internal/coderay/lib/coderay/scanners/_map.rb +24 -0
  49. data/lib/llm/shell/internal/coderay/lib/coderay/scanners/c.rb +189 -0
  50. data/lib/llm/shell/internal/coderay/lib/coderay/scanners/clojure.rb +217 -0
  51. data/lib/llm/shell/internal/coderay/lib/coderay/scanners/cpp.rb +217 -0
  52. data/lib/llm/shell/internal/coderay/lib/coderay/scanners/css.rb +196 -0
  53. data/lib/llm/shell/internal/coderay/lib/coderay/scanners/debug.rb +75 -0
  54. data/lib/llm/shell/internal/coderay/lib/coderay/scanners/delphi.rb +144 -0
  55. data/lib/llm/shell/internal/coderay/lib/coderay/scanners/diff.rb +221 -0
  56. data/lib/llm/shell/internal/coderay/lib/coderay/scanners/erb.rb +81 -0
  57. data/lib/llm/shell/internal/coderay/lib/coderay/scanners/go.rb +208 -0
  58. data/lib/llm/shell/internal/coderay/lib/coderay/scanners/groovy.rb +268 -0
  59. data/lib/llm/shell/internal/coderay/lib/coderay/scanners/haml.rb +168 -0
  60. data/lib/llm/shell/internal/coderay/lib/coderay/scanners/html.rb +275 -0
  61. data/lib/llm/shell/internal/coderay/lib/coderay/scanners/java/builtin_types.rb +421 -0
  62. data/lib/llm/shell/internal/coderay/lib/coderay/scanners/java.rb +174 -0
  63. data/lib/llm/shell/internal/coderay/lib/coderay/scanners/java_script.rb +236 -0
  64. data/lib/llm/shell/internal/coderay/lib/coderay/scanners/json.rb +98 -0
  65. data/lib/llm/shell/internal/coderay/lib/coderay/scanners/lua.rb +280 -0
  66. data/lib/llm/shell/internal/coderay/lib/coderay/scanners/php.rb +527 -0
  67. data/lib/llm/shell/internal/coderay/lib/coderay/scanners/python.rb +287 -0
  68. data/lib/llm/shell/internal/coderay/lib/coderay/scanners/raydebug.rb +75 -0
  69. data/lib/llm/shell/internal/coderay/lib/coderay/scanners/ruby/patterns.rb +178 -0
  70. data/lib/llm/shell/internal/coderay/lib/coderay/scanners/ruby/string_state.rb +79 -0
  71. data/lib/llm/shell/internal/coderay/lib/coderay/scanners/ruby.rb +477 -0
  72. data/lib/llm/shell/internal/coderay/lib/coderay/scanners/sass.rb +232 -0
  73. data/lib/llm/shell/internal/coderay/lib/coderay/scanners/scanner.rb +337 -0
  74. data/lib/llm/shell/internal/coderay/lib/coderay/scanners/sql.rb +169 -0
  75. data/lib/llm/shell/internal/coderay/lib/coderay/scanners/taskpaper.rb +36 -0
  76. data/lib/llm/shell/internal/coderay/lib/coderay/scanners/text.rb +26 -0
  77. data/lib/llm/shell/internal/coderay/lib/coderay/scanners/xml.rb +17 -0
  78. data/lib/llm/shell/internal/coderay/lib/coderay/scanners/yaml.rb +140 -0
  79. data/lib/llm/shell/internal/coderay/lib/coderay/scanners.rb +27 -0
  80. data/lib/llm/shell/internal/coderay/lib/coderay/styles/_map.rb +7 -0
  81. data/lib/llm/shell/internal/coderay/lib/coderay/styles/alpha.rb +153 -0
  82. data/lib/llm/shell/internal/coderay/lib/coderay/styles/style.rb +18 -0
  83. data/lib/llm/shell/internal/coderay/lib/coderay/styles.rb +15 -0
  84. data/lib/llm/shell/internal/coderay/lib/coderay/token_kinds.rb +85 -0
  85. data/lib/llm/shell/internal/coderay/lib/coderay/tokens.rb +164 -0
  86. data/lib/llm/shell/internal/coderay/lib/coderay/tokens_proxy.rb +55 -0
  87. data/lib/llm/shell/internal/coderay/lib/coderay/version.rb +3 -0
  88. data/lib/llm/shell/internal/coderay/lib/coderay.rb +284 -0
  89. data/lib/llm/shell/internal/io-line/lib/io/line/multiple.rb +19 -0
  90. data/lib/{io → llm/shell/internal/io-line/lib/io}/line.rb +2 -0
  91. data/lib/llm/shell/internal/llm.rb/lib/llm/bot/builder.rb +31 -0
  92. data/lib/llm/shell/internal/llm.rb/lib/llm/bot/conversable.rb +37 -0
  93. data/lib/llm/shell/internal/llm.rb/lib/llm/bot/prompt/completion.rb +49 -0
  94. data/lib/llm/shell/internal/llm.rb/lib/llm/bot/prompt/respond.rb +49 -0
  95. data/lib/llm/shell/internal/llm.rb/lib/llm/bot.rb +150 -0
  96. data/lib/llm/shell/internal/llm.rb/lib/llm/buffer.rb +162 -0
  97. data/lib/llm/shell/internal/llm.rb/lib/llm/client.rb +36 -0
  98. data/lib/llm/shell/internal/llm.rb/lib/llm/error.rb +49 -0
  99. data/lib/llm/shell/internal/llm.rb/lib/llm/eventhandler.rb +44 -0
  100. data/lib/llm/shell/internal/llm.rb/lib/llm/eventstream/event.rb +69 -0
  101. data/lib/llm/shell/internal/llm.rb/lib/llm/eventstream/parser.rb +88 -0
  102. data/lib/llm/shell/internal/llm.rb/lib/llm/eventstream.rb +8 -0
  103. data/lib/llm/shell/internal/llm.rb/lib/llm/file.rb +91 -0
  104. data/lib/llm/shell/internal/llm.rb/lib/llm/function.rb +177 -0
  105. data/lib/llm/shell/internal/llm.rb/lib/llm/message.rb +178 -0
  106. data/lib/llm/shell/internal/llm.rb/lib/llm/mime.rb +140 -0
  107. data/lib/llm/shell/internal/llm.rb/lib/llm/multipart.rb +101 -0
  108. data/lib/llm/shell/internal/llm.rb/lib/llm/object/builder.rb +38 -0
  109. data/lib/llm/shell/internal/llm.rb/lib/llm/object/kernel.rb +53 -0
  110. data/lib/llm/shell/internal/llm.rb/lib/llm/object.rb +89 -0
  111. data/lib/llm/shell/internal/llm.rb/lib/llm/provider.rb +352 -0
  112. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/anthropic/error_handler.rb +36 -0
  113. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/anthropic/files.rb +155 -0
  114. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/anthropic/format/completion_format.rb +88 -0
  115. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/anthropic/format.rb +29 -0
  116. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/anthropic/models.rb +54 -0
  117. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/anthropic/response/completion.rb +39 -0
  118. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/anthropic/response/enumerable.rb +11 -0
  119. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/anthropic/response/file.rb +23 -0
  120. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/anthropic/response/web_search.rb +21 -0
  121. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/anthropic/stream_parser.rb +66 -0
  122. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/anthropic.rb +138 -0
  123. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/deepseek/format/completion_format.rb +68 -0
  124. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/deepseek/format.rb +27 -0
  125. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/deepseek.rb +75 -0
  126. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/gemini/audio.rb +73 -0
  127. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/gemini/error_handler.rb +47 -0
  128. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/gemini/files.rb +146 -0
  129. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/gemini/format/completion_format.rb +69 -0
  130. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/gemini/format.rb +39 -0
  131. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/gemini/images.rb +133 -0
  132. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/gemini/models.rb +60 -0
  133. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/gemini/response/completion.rb +35 -0
  134. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/gemini/response/embedding.rb +8 -0
  135. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/gemini/response/file.rb +11 -0
  136. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/gemini/response/files.rb +15 -0
  137. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/gemini/response/image.rb +31 -0
  138. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/gemini/response/models.rb +15 -0
  139. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/gemini/response/web_search.rb +22 -0
  140. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/gemini/stream_parser.rb +86 -0
  141. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/gemini.rb +173 -0
  142. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/llamacpp.rb +74 -0
  143. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/ollama/error_handler.rb +36 -0
  144. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/ollama/format/completion_format.rb +77 -0
  145. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/ollama/format.rb +29 -0
  146. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/ollama/models.rb +56 -0
  147. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/ollama/response/completion.rb +28 -0
  148. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/ollama/response/embedding.rb +9 -0
  149. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/ollama/stream_parser.rb +44 -0
  150. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/ollama.rb +116 -0
  151. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/openai/audio.rb +91 -0
  152. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/openai/error_handler.rb +46 -0
  153. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/openai/files.rb +134 -0
  154. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/openai/format/completion_format.rb +90 -0
  155. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/openai/format/moderation_format.rb +35 -0
  156. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/openai/format/respond_format.rb +72 -0
  157. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/openai/format.rb +54 -0
  158. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/openai/images.rb +109 -0
  159. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/openai/models.rb +55 -0
  160. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/openai/moderations.rb +65 -0
  161. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/openai/response/audio.rb +7 -0
  162. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/openai/response/completion.rb +40 -0
  163. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/openai/response/embedding.rb +9 -0
  164. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/openai/response/enumerable.rb +23 -0
  165. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/openai/response/file.rb +7 -0
  166. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/openai/response/image.rb +16 -0
  167. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/openai/response/moderations.rb +34 -0
  168. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/openai/response/responds.rb +48 -0
  169. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/openai/response/web_search.rb +21 -0
  170. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/openai/responses/stream_parser.rb +76 -0
  171. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/openai/responses.rb +99 -0
  172. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/openai/stream_parser.rb +86 -0
  173. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/openai/vector_stores.rb +228 -0
  174. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/openai.rb +206 -0
  175. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/xai/images.rb +58 -0
  176. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/xai.rb +72 -0
  177. data/lib/llm/shell/internal/llm.rb/lib/llm/providers/zai.rb +74 -0
  178. data/lib/llm/shell/internal/llm.rb/lib/llm/response.rb +67 -0
  179. data/lib/llm/shell/internal/llm.rb/lib/llm/schema/array.rb +26 -0
  180. data/lib/llm/shell/internal/llm.rb/lib/llm/schema/boolean.rb +13 -0
  181. data/lib/llm/shell/internal/llm.rb/lib/llm/schema/integer.rb +43 -0
  182. data/lib/llm/shell/internal/llm.rb/lib/llm/schema/leaf.rb +78 -0
  183. data/lib/llm/shell/internal/llm.rb/lib/llm/schema/null.rb +13 -0
  184. data/lib/llm/shell/internal/llm.rb/lib/llm/schema/number.rb +43 -0
  185. data/lib/llm/shell/internal/llm.rb/lib/llm/schema/object.rb +41 -0
  186. data/lib/llm/shell/internal/llm.rb/lib/llm/schema/string.rb +34 -0
  187. data/lib/llm/shell/internal/llm.rb/lib/llm/schema/version.rb +8 -0
  188. data/lib/llm/shell/internal/llm.rb/lib/llm/schema.rb +81 -0
  189. data/lib/llm/shell/internal/llm.rb/lib/llm/server_tool.rb +32 -0
  190. data/lib/llm/shell/internal/llm.rb/lib/llm/tool/param.rb +75 -0
  191. data/lib/llm/shell/internal/llm.rb/lib/llm/tool.rb +78 -0
  192. data/lib/llm/shell/internal/llm.rb/lib/llm/utils.rb +19 -0
  193. data/lib/llm/shell/internal/llm.rb/lib/llm/version.rb +5 -0
  194. data/lib/llm/shell/internal/llm.rb/lib/llm.rb +121 -0
  195. data/lib/llm/shell/internal/optparse/lib/optionparser.rb +2 -0
  196. data/lib/llm/shell/internal/optparse/lib/optparse/ac.rb +70 -0
  197. data/lib/llm/shell/internal/optparse/lib/optparse/date.rb +18 -0
  198. data/lib/llm/shell/internal/optparse/lib/optparse/kwargs.rb +27 -0
  199. data/lib/llm/shell/internal/optparse/lib/optparse/shellwords.rb +7 -0
  200. data/lib/llm/shell/internal/optparse/lib/optparse/time.rb +11 -0
  201. data/lib/llm/shell/internal/optparse/lib/optparse/uri.rb +7 -0
  202. data/lib/llm/shell/internal/optparse/lib/optparse/version.rb +80 -0
  203. data/lib/llm/shell/internal/optparse/lib/optparse.rb +2469 -0
  204. data/lib/llm/shell/internal/paint/lib/paint/constants.rb +104 -0
  205. data/lib/llm/shell/internal/paint/lib/paint/pa.rb +13 -0
  206. data/lib/llm/shell/internal/paint/lib/paint/rgb_colors.rb +14 -0
  207. data/lib/llm/shell/internal/paint/lib/paint/shortcuts.rb +100 -0
  208. data/lib/llm/shell/internal/paint/lib/paint/shortcuts_version.rb +5 -0
  209. data/lib/llm/shell/internal/paint/lib/paint/util.rb +16 -0
  210. data/lib/llm/shell/internal/paint/lib/paint/version.rb +5 -0
  211. data/lib/llm/shell/internal/paint/lib/paint.rb +261 -0
  212. data/lib/llm/shell/internal/reline/lib/reline/config.rb +378 -0
  213. data/lib/llm/shell/internal/reline/lib/reline/face.rb +199 -0
  214. data/lib/llm/shell/internal/reline/lib/reline/history.rb +76 -0
  215. data/lib/llm/shell/internal/reline/lib/reline/io/ansi.rb +322 -0
  216. data/lib/llm/shell/internal/reline/lib/reline/io/dumb.rb +120 -0
  217. data/lib/llm/shell/internal/reline/lib/reline/io/windows.rb +530 -0
  218. data/lib/llm/shell/internal/reline/lib/reline/io.rb +55 -0
  219. data/lib/llm/shell/internal/reline/lib/reline/key_actor/base.rb +37 -0
  220. data/lib/llm/shell/internal/reline/lib/reline/key_actor/composite.rb +17 -0
  221. data/lib/llm/shell/internal/reline/lib/reline/key_actor/emacs.rb +517 -0
  222. data/lib/llm/shell/internal/reline/lib/reline/key_actor/vi_command.rb +518 -0
  223. data/lib/llm/shell/internal/reline/lib/reline/key_actor/vi_insert.rb +517 -0
  224. data/lib/llm/shell/internal/reline/lib/reline/key_actor.rb +8 -0
  225. data/lib/llm/shell/internal/reline/lib/reline/key_stroke.rb +119 -0
  226. data/lib/llm/shell/internal/reline/lib/reline/kill_ring.rb +125 -0
  227. data/lib/llm/shell/internal/reline/lib/reline/line_editor.rb +2356 -0
  228. data/lib/llm/shell/internal/reline/lib/reline/unicode/east_asian_width.rb +1292 -0
  229. data/lib/llm/shell/internal/reline/lib/reline/unicode.rb +421 -0
  230. data/lib/llm/shell/internal/reline/lib/reline/version.rb +3 -0
  231. data/lib/llm/shell/internal/reline/lib/reline.rb +527 -0
  232. data/lib/llm/shell/internal/tomlrb/lib/tomlrb/generated_parser.rb +712 -0
  233. data/lib/llm/shell/internal/tomlrb/lib/tomlrb/handler.rb +268 -0
  234. data/lib/llm/shell/internal/tomlrb/lib/tomlrb/local_date.rb +35 -0
  235. data/lib/llm/shell/internal/tomlrb/lib/tomlrb/local_date_time.rb +42 -0
  236. data/lib/llm/shell/internal/tomlrb/lib/tomlrb/local_time.rb +40 -0
  237. data/lib/llm/shell/internal/tomlrb/lib/tomlrb/parser.rb +21 -0
  238. data/lib/llm/shell/internal/tomlrb/lib/tomlrb/scanner.rb +92 -0
  239. data/lib/llm/shell/internal/tomlrb/lib/tomlrb/string_utils.rb +40 -0
  240. data/lib/llm/shell/internal/tomlrb/lib/tomlrb/version.rb +5 -0
  241. data/lib/llm/shell/internal/tomlrb/lib/tomlrb.rb +49 -0
  242. data/lib/llm/shell/options.rb +1 -1
  243. data/lib/llm/shell/renderer.rb +2 -3
  244. data/lib/llm/shell/repl.rb +21 -16
  245. data/lib/llm/shell/tool.rb +42 -0
  246. data/lib/llm/shell/tools/read_file.rb +15 -0
  247. data/lib/llm/shell/tools/system.rb +17 -0
  248. data/lib/llm/shell/tools/write_file.rb +16 -0
  249. data/lib/llm/shell/version.rb +1 -1
  250. data/lib/llm/shell.rb +83 -39
  251. data/libexec/llm-shell/shell +4 -6
  252. data/llm-shell.gemspec +0 -4
  253. metadata +233 -63
  254. data/lib/llm/function.rb +0 -17
  255. data/lib/llm/shell/command/extension.rb +0 -42
  256. data/lib/llm/shell/commands/utils.rb +0 -21
  257. data/lib/llm/shell/functions/read_file.rb +0 -22
  258. data/lib/llm/shell/functions/write_file.rb +0 -22
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4ec2b8025a69a836d633b92ae23c86e8e6d8c6ce42ed6d2da08194909ade1de8
4
- data.tar.gz: 8a29bfddd6bfef7973483d8efca2e182d3aced3b82bf771beb73f673fc7861a2
3
+ metadata.gz: f967ca0697d19fdbdedad92516bc0ef92da47b29c4170791a8fac55fc5689ecb
4
+ data.tar.gz: e208bc99728251c53027f74cf7e77aa036ffd4cee0beab530685db262e0f229d
5
5
  SHA512:
6
- metadata.gz: 6595412e81ab721f64ab2275ed087e8d01321a8d56c5d4b2566d31f1c0fa0a59c01ddd8981c6c4771c0896481586244bffa642ed8275416c8b2e93010a43956c
7
- data.tar.gz: 3ad0f23e6fabc847984b750d86e4adcefb46f2f0748416bcabd91ad5664b4745acb04d80e4faf0e63cd7e2b3747d555e0fe921d961ef611f886a6ba0c34bfa0a
6
+ metadata.gz: 1210291c52e97bc62c00bbc7da2c13bd45c6837c2b2ffc2e6d6764c5599864b75f97e9e0a6ef8ff99999ae59432ce04c00a4f360f54685e453b6ab561448c6f3
7
+ data.tar.gz: 0306b40c3877bbf7f2203da41a82f20731c8cc4ca863e10582fe2658e6532eb17c5d2031c757b43b28270e61f49c3d9258cbc9e5b2b43c95104d0a896dd0a2f1
data/README.md CHANGED
@@ -6,6 +6,13 @@ console that can interact with multiple Large Language Models
6
6
  library and a tool to help improve the library through real-world
7
7
  usage and feedback.
8
8
 
9
+ ## Demo
10
+
11
+ <details>
12
+ <summary>Show</summary>
13
+ <img src="share/llm-shell/examples/demo.gif/">
14
+ </details>
15
+
9
16
  ## Features
10
17
 
11
18
  #### General
@@ -26,44 +33,32 @@ usage and feedback.
26
33
  - 📄 Deploys the less pager for long outputs
27
34
  - 📝 Advanced Markdown formatting and output
28
35
 
29
- ## Demo
30
-
31
- <details>
32
- <summary>Reveal demo</summary>
33
- <img src="share/llm-shell/examples/demo.gif/">
34
- </details>
35
-
36
- <details>
37
- <summary>Reveal demo</summary>
38
- <img src="share/llm-shell/examples/demo.png/">
39
- </details>
40
36
 
41
37
  ## Customization
42
38
 
43
- #### Functions
39
+ #### Tools
44
40
 
45
41
  > For security and safety reasons, a user must confirm the execution of
46
42
  > all function calls before they happen
47
43
 
48
- llm-shell can be extended with your own functions (also known as tool calls).
49
- This can be done by creating a Ruby file in the `~/.llm-shell/functions/`
50
- directory &ndash; with one file per function.
51
44
 
52
- The functions are loaded at boot time. The functions are shared with
53
- the LLM and the LLM can request their execution. The LLM is also made
54
- aware of a function's return value after it has been called.
45
+ Tools are loaded at boot time. Custom tools can be added to the
46
+ `${HOME}/.local/share/llm-shell/tools/` directory. The tools are
47
+ shared with the LLM and the LLM can request their execution.
48
+ The LLM is also made aware of a tool's return value after
49
+ it has been called.
55
50
  See the
56
- [functions/](lib/llm/shell/functions/)
51
+ [tools/](lib/llm/shell/tools/)
57
52
  directory for more examples:
58
53
 
59
54
 
60
55
  ```ruby
61
- LLM.function(:system) do |fn|
62
- fn.description "Run a shell command"
63
- fn.params do |schema|
64
- schema.object(command: schema.string.required)
65
- end
66
- fn.define do |command:|
56
+ class System < LLM::Tool
57
+ name "system"
58
+ description "Run a system command"
59
+ param :command, String, "The command to execute", required: true
60
+
61
+ def call(command:)
67
62
  ro, wo = IO.pipe
68
63
  re, we = IO.pipe
69
64
  Process.wait Process.spawn(command, out: wo, err: we)
@@ -75,18 +70,20 @@ end
75
70
 
76
71
  #### Commands
77
72
 
78
- llm-shell can be extended with your own console commands. This can be
79
- done by creating a Ruby file in the `~/.llm-shell/commands/` directory &ndash;
80
- with one file per command. The commands are loaded at boot time.
73
+ llm-shell can be extended with your own console commands that take
74
+ precendence over messages sent to the LLM. Custom commands can be
75
+ added to the `${HOME}/.local/share/llm-shell/commands/` directory.
81
76
  See the
82
77
  [commands/](lib/llm/shell/commands/)
83
78
  directory for more examples:
84
79
 
85
80
  ```ruby
86
- LLM.command "say-hello" do |cmd|
87
- cmd.description "Say hello to somebody"
88
- cmd.define do |name|
89
- io.rewind.print "Hello #{name}!"
81
+ class SayHello < LLM::Command
82
+ name "say-hello"
83
+ description "Say hello to somebody"
84
+
85
+ def call(name)
86
+ io.rewind.print "Hello, #{name}!"
90
87
  end
91
88
  end
92
89
  ```
@@ -97,47 +94,46 @@ end
97
94
  > otherwise you might see unexpected results because llm-shell assumes the LLM
98
95
  > will emit markdown.
99
96
 
100
- The first message in a conversation is sometimes known as a "system prompt",
101
- and it defines the expectations and rules to be followed by an LLM throughout
102
- a conversation. The default prompt used by llm-shell can be found at
103
- [default.txt](share/llm-shell/prompts/default.txt).
104
-
105
- The prompt can be changed by adding a file to the `~/.llm-shell/prompts/` directory,
106
- and then choosing it at boot time with the `-r PROMPT`, `--prompt PROMPT` options.
107
- Generally you probably want to fork [default.txt](share/llm-shell/prompts/default.txt)
97
+ The prompt can be changed by adding a file to the `${HOME}/.local/share/llm-shell/prompts/`
98
+ directory, and then choosing it at boot time with the `-r PROMPT`, `--prompt PROMPT`
99
+ options. Generally you probably want to fork [default.txt](share/llm-shell/prompts/default.txt)
108
100
  to conserve the original prompt rules around markdown and files, then modify it to
109
101
  suit your own needs and preferences.
110
102
 
111
103
  ## Settings
112
104
 
113
- #### YAML
114
105
 
115
106
  The console client can be configured at the command line through option switches,
116
- or through a YAML file. The YAML file can contain the same options that could be
107
+ or through a TOML file. The TOML file can contain the same options that could be
117
108
  specified at the command line. For cloud providers the key option is the only
118
- required parameter, everything else has defaults. The YAML file is read from the
119
- path `${HOME}/.llm-shell/config.yml` and it has the following format:
120
-
121
- ```yaml
122
- # ~/.config/llm-shell.yml
123
- openai:
124
- key: YOURKEY
125
- gemini:
126
- key: YOURKEY
127
- anthropic:
128
- key: YOURKEY
129
- xai:
130
- key: YOURKEY
131
- deepseek:
132
- key: YOURKEY
133
- ollama:
134
- host: localhost
135
- model: deepseek-coder:6.7b
136
- llamacpp:
137
- host: localhost
138
- model: qwen3
139
- tools:
140
- - system
109
+ required parameter, everything else has defaults. The TOML file is read from the
110
+ path `${HOME}/.llm-shell/config.toml` and it has the following format:
111
+
112
+ ```toml
113
+ # ~/.config/llm-shell.toml
114
+
115
+ [openai]
116
+ key = "YOURKEY"
117
+
118
+ [gemini]
119
+ key = "YOURKEY"
120
+
121
+ [anthropic]
122
+ key = "YOURKEY"
123
+
124
+ [xai]
125
+ key = "YOURKEY"
126
+
127
+ [deepseek]
128
+ key = "YOURKEY"
129
+
130
+ [ollama]
131
+ host = "localhost"
132
+ model = "deepseek-coder:6.7b"
133
+
134
+ [llamacpp]
135
+ host = "localhost"
136
+ model = "qwen3"
141
137
  ```
142
138
 
143
139
  ## Usage
@@ -151,7 +147,6 @@ Usage: llm-shell [OPTIONS]
151
147
  -m, --model [MODEL] Optional. The name of a model.
152
148
  -h, --host [HOST] Optional. Sometimes required by ollama.
153
149
  -o, --port [PORT] Optional. Sometimes required by ollama.
154
- -f, --files [GLOB] Optional. Glob pattern(s) separated by a comma.
155
150
  -r, --prompt [PROMPT] Optional. The prompt to use.
156
151
  -v, --version Optional. Print the version and exit
157
152
  ```
@@ -2,27 +2,35 @@
2
2
 
3
3
  class LLM::Shell
4
4
  class Command
5
- require_relative "commands/utils"
5
+ ##
6
+ # Returns true for builtin commands
7
+ # @return [Boolean]
8
+ def self.builtin?
9
+ path, _ = instance_method(:call).source_location
10
+ path&.include?(LLM::Shell.root)
11
+ end
6
12
 
7
13
  ##
8
- # @api private
9
- class Context < Struct.new(:bot, :io)
10
- def pager(...)
11
- LLM::Shell.pager(...)
12
- end
14
+ # Always returns true
15
+ # @return [Boolean]
16
+ def self.enabled?
17
+ true
13
18
  end
14
19
 
15
20
  ##
16
- # Returns the underlying command object
17
- # @return [Class, #call]
18
- attr_reader :object
21
+ # @param [Class] klass
22
+ # A subclass
23
+ # @return [void]
24
+ def self.inherited(klass)
25
+ LLM::Shell.commands << klass
26
+ end
19
27
 
20
28
  ##
21
29
  # Set or get the command name
22
30
  # @param [String, nil] name
23
31
  # The name of the command
24
32
  # @return [String]
25
- def name(name = nil)
33
+ def self.name(name = nil)
26
34
  if name
27
35
  @name = name
28
36
  else
@@ -35,7 +43,7 @@ class LLM::Shell
35
43
  # @param [String, nil] desc
36
44
  # The description of the command
37
45
  # @return [String]
38
- def description(desc = nil)
46
+ def self.description(desc = nil)
39
47
  if desc
40
48
  @description = desc
41
49
  else
@@ -44,45 +52,37 @@ class LLM::Shell
44
52
  end
45
53
 
46
54
  ##
47
- # Setup the command context
48
- # @return [void]
49
- def setup(bot, io)
50
- @context = Context.new(bot, io)
51
- end
52
-
53
- ##
54
- # Define the command
55
- # @return [void]
56
- def define(klass = nil, &b)
57
- @object = klass || b
55
+ # @param [LLM::Bot] bot
56
+ # An instance of {LLM::Bot LLM::Bot}
57
+ # @param [IO::Line] io
58
+ # An IO object
59
+ def initialize(bot, io)
60
+ @bot = bot
61
+ @io = io
58
62
  end
59
- alias_method :register, :define
60
63
 
61
64
  ##
62
65
  # Call the command
63
66
  # @reurn [void]
64
67
  def call(*argv)
65
- if @context.nil?
66
- raise "context has not been setup"
67
- elsif Class === @object
68
- @object.new(@context).call(*argv)
69
- else
70
- @context.instance_exec(*argv, &@object)
71
- end
68
+ raise NotImplementedError
72
69
  end
73
70
 
74
- ##
75
- # @return [Boolean]
76
- # Returns true if this is a builtin command
77
- def builtin?
78
- @builtin
71
+ private
72
+
73
+ attr_reader :bot, :io
74
+
75
+ def import(file)
76
+ return unless File.file?(file)
77
+ bot.chat [
78
+ "<file path=\"#{file}\">",
79
+ File.read(file),
80
+ "</file>"
81
+ ].join("\n")
79
82
  end
80
83
 
81
- ##
82
- # Mark this command as builtin command
83
- # @return [void]
84
- def builtin!
85
- @builtin = true
84
+ def pager(...)
85
+ LLM::Shell.pager(...)
86
86
  end
87
87
  end
88
88
  end
@@ -1,17 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class LLM::Shell::Command
4
- class ClearScreen
5
- require_relative "utils"
6
- include Utils
7
-
8
- ##
9
- # @param [LLM::Shell::Context] context
10
- # The context of the command
11
- # @return [LLM::Shell::Command::ClearScreen]
12
- def initialize(context)
13
- @context = context
14
- end
3
+ class LLM::Shell
4
+ class Command::ClearScreen < Command
5
+ name "clear-screen"
6
+ description "Clears the screen"
15
7
 
16
8
  ##
17
9
  # Clears the screen
@@ -22,11 +14,5 @@ class LLM::Shell::Command
22
14
 
23
15
  def console = IO.console
24
16
  def clear_screen = console.clear_screen
25
-
26
- LLM.command "clear-screen" do |cmd|
27
- cmd.description "Clear the screen"
28
- cmd.register(self)
29
- cmd.builtin!
30
- end
31
17
  end
32
18
  end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ class LLM::Shell
4
+ class Command::DebugMode < Command
5
+ name 'debug-mode'
6
+ description 'Enter into debug mode'
7
+
8
+ def call
9
+ binding.irb
10
+ end
11
+ end
12
+ end
@@ -1,9 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class LLM::Shell::Command
4
- class DirImport
5
- require_relative "utils"
6
- include Utils
3
+ class LLM::Shell
4
+ class Command::DirImport < Command
5
+ name "dir-import"
6
+ description "Import the contents of a directory"
7
7
 
8
8
  ##
9
9
  # Completes a path with a wildcard.
@@ -15,14 +15,6 @@ class LLM::Shell::Command
15
15
  Dir["#{path}*"]
16
16
  end
17
17
 
18
- ##
19
- # @param [LLM::Shell::Context] context
20
- # The context of the command
21
- # @return [LLM::Shell::Command::DirImport]
22
- def initialize(context)
23
- @context = context
24
- end
25
-
26
18
  ##
27
19
  # Recursively imports all files in a directory.
28
20
  # @return [void]
@@ -37,13 +29,5 @@ class LLM::Shell::Command
37
29
  end
38
30
  end
39
31
  end
40
-
41
- private
42
-
43
- LLM.command "dir-import" do |cmd|
44
- cmd.description "Share a directory with the LLM"
45
- cmd.register(self)
46
- cmd.builtin!
47
- end
48
32
  end
49
33
  end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ class LLM::Shell
4
+ class Command::DisableTool < Command
5
+ Error = Class.new(RuntimeError)
6
+
7
+ name "disable-tool"
8
+ description "Disable a tool"
9
+
10
+ ##
11
+ # Completes a tool name.
12
+ # @param name [String]
13
+ # The tool name to complete.
14
+ # @return [Array<String>]
15
+ # Returns the completed tool name(s)
16
+ def self.complete(name)
17
+ LLM::Shell.tools.map(&:name).select { _1.start_with?(name) }
18
+ end
19
+
20
+ ##
21
+ # Disables the given tool.
22
+ # @return [void]
23
+ def call(name)
24
+ tool = LLM::Shell.tools.find { _1.name == name }
25
+ if tool
26
+ tool.disable!
27
+ io.rewind.print("tool disabled").end
28
+ else
29
+ raise Error, "unknown tool: #{name}"
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ class LLM::Shell
4
+ class Command::EnableTool < Command
5
+ Error = Class.new(RuntimeError)
6
+
7
+ name "enable-tool"
8
+ description "Enable a tool"
9
+
10
+ ##
11
+ # Completes a tool name.
12
+ # @param name [String]
13
+ # The tool name to complete.
14
+ # @return [Array<String>]
15
+ # Returns the completed tool name(s)
16
+ def self.complete(name)
17
+ LLM::Shell.tools.map(&:name).select { _1.start_with?(name) }
18
+ end
19
+
20
+ ##
21
+ # Enables the given tool.
22
+ # @return [void]
23
+ def call(name)
24
+ tool = LLM::Shell.tools.find { _1.name == name }
25
+ if tool
26
+ tool.enable!
27
+ io.rewind.print("tool enabled").end
28
+ else
29
+ raise Error, "unknown tool: #{name}"
30
+ end
31
+ end
32
+ end
33
+ end
@@ -1,9 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class LLM::Shell::Command
4
- class FileImport
5
- require_relative "utils"
6
- include Utils
3
+ class LLM::Shell
4
+ class Command::FileImport < Command
5
+ name "file-import"
6
+ description "Import a file"
7
7
 
8
8
  ##
9
9
  # Completes a path with a wildcard.
@@ -15,27 +15,11 @@ class LLM::Shell::Command
15
15
  Dir["#{path}*"]
16
16
  end
17
17
 
18
- ##
19
- # @param [LLM::Shell::Context] context
20
- # The context of the command
21
- # @return [LLM::Shell::Command::FileImport]
22
- def initialize(context)
23
- @context = context
24
- end
25
-
26
18
  ##
27
19
  # Imports one or more globbed files.
28
20
  # @return [void]
29
21
  def call(*files)
30
22
  Dir[*files].each { import(_1) }
31
23
  end
32
-
33
- private
34
-
35
- LLM.command "file-import" do |cmd|
36
- cmd.description "Share a file with the LLM"
37
- cmd.register(self)
38
- cmd.builtin!
39
- end
40
24
  end
41
25
  end
@@ -1,24 +1,18 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class LLM::Shell::Command
4
- class Help
5
- require_relative "utils"
6
- include Utils
7
-
8
- ##
9
- # @param [LLM::Shell::Context] context
10
- # The context of the command
11
- # @return [LLM::Shell::Command::Help]
12
- def initialize(context)
13
- @context = context
14
- end
3
+ class LLM::Shell
4
+ class Command::Help < Command
5
+ name "help"
6
+ description "Show help"
15
7
 
16
8
  ##
17
9
  # Prints help
18
10
  # @return [void]
19
11
  def call
20
12
  pager do |io|
13
+ io.print(Paint["Help", :bold, :underline], "\n\n")
21
14
  render_commands(io)
15
+ io.print("\n")
22
16
  render_functions(io)
23
17
  end
24
18
  end
@@ -27,40 +21,33 @@ class LLM::Shell::Command
27
21
 
28
22
  def render_commands(io)
29
23
  io.print(Paint["Commands", :bold, :underline], "\n\n")
30
- io.print(Paint["Builtin", :bold], "\n\n")
31
- render_group commands.select(&:builtin?), io, :cyan
32
- io.print(Paint["User", :bold], "\n\n")
33
- render_group commands.reject(&:builtin?), io, :cyan
24
+ render_group(io, "Builtin", commands.select(&:builtin?), :cyan)
25
+ io.print("\n")
26
+ render_group(io, "User", commands.reject(&:builtin?), :cyan)
34
27
  end
35
28
 
36
29
  def render_functions(io)
37
30
  io.print(Paint["Functions", :bold, :underline], "\n\n")
38
- io.print(Paint["Builtin", :bold], "\n\n")
39
- render_group functions.select(&:builtin?), io, :blue
40
- io.print(Paint["User", :bold], "\n\n")
41
- render_group functions.reject(&:builtin?), io, :blue
31
+ render_group(io, "Builtin (Enabled)", functions.select { |f| f.builtin? && f.enabled? }, :blue)
32
+ render_group(io, "Builtin (Disabled)", functions.select { |f| f.builtin? && !f.enabled? }, :blue)
33
+ io.print("\n")
34
+ render_group(io, "User (Enabled)", functions.select { |f| !f.builtin? && f.enabled? }, :blue)
35
+ render_group(io, "User (Disabled)", functions.select { |f| !f.builtin? && !f.enabled? }, :blue)
42
36
  end
43
37
 
44
- def render_group(commands, io, bgcolor)
45
- if commands.empty?
46
- io.print(Paint["None available", :yellow], "\n\n")
38
+ def render_group(io, title, items, color)
39
+ io.print(Paint[title, :bold], "\n")
40
+ if items.empty?
41
+ io.print(Paint[" None available", :yellow], "\n")
47
42
  else
48
- commands.each.with_index(1) do |command, index|
49
- io.print(name(command, index, bgcolor), "\n")
50
- io.print(desc(command), "\n\n")
43
+ items.each do |item|
44
+ status = item.enabled? ? Paint["enabled", :green] : Paint["disabled", :red]
45
+ io.print(" ", Paint[item.name, color, :bold], " - ", item.description || "No description", " (", status, ")\n")
51
46
  end
52
47
  end
53
48
  end
54
49
 
55
- def commands = LLM.commands.values.sort_by(&:name)
56
- def functions = LLM.functions.values.sort_by(&:name)
57
- def name(command, index, bgcolor) = [Paint[" #{index} ", :white, bgcolor, :bold], " ", Paint[command.name, :bold]].join
58
- def desc(command) = command.description || "No description"
59
-
60
- LLM.command "help" do |cmd|
61
- cmd.description "Show the help menu"
62
- cmd.register(self)
63
- cmd.builtin!
64
- end
50
+ def commands = LLM::Shell.commands.sort_by(&:name)
51
+ def functions = LLM::Shell.tools.sort_by(&:name)
65
52
  end
66
53
  end
@@ -1,17 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class LLM::Shell::Command
4
- class ShowChat
5
- require_relative "utils"
6
- include Utils
7
-
8
- ##
9
- # @param [LLM::Shell::Context] context
10
- # The context of the command
11
- # @return [LLM::Shell::Command::ShowChat]
12
- def initialize(context)
13
- @context = context
14
- end
3
+ class LLM::Shell
4
+ class Command::ShowChat < Command
5
+ name "show-chat"
6
+ description "Show the chat"
15
7
 
16
8
  ##
17
9
  # Emits the full chat history to standard output
@@ -26,7 +18,6 @@ class LLM::Shell::Command
26
18
  def emit
27
19
  pager do |io|
28
20
  messages.each.with_index do |message, index|
29
- next if index <= 1
30
21
  io << render(message) << "\n"
31
22
  end
32
23
  end
@@ -36,11 +27,5 @@ class LLM::Shell::Command
36
27
  def clear_screen = console.clear_screen
37
28
  def messages = bot.messages
38
29
  def render(message) = LLM::Shell::Renderer.new(message).render
39
-
40
- LLM.command "show-chat" do |cmd|
41
- cmd.description "Show the chat"
42
- cmd.register(self)
43
- cmd.builtin!
44
- end
45
30
  end
46
31
  end