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
@@ -0,0 +1,284 @@
1
+ # encoding: utf-8
2
+ # Encoding.default_internal = 'UTF-8'
3
+
4
+ # = CodeRay Library
5
+ #
6
+ # CodeRay is a Ruby library for syntax highlighting.
7
+ #
8
+ # I try to make CodeRay easy to use and intuitive, but at the same time fully
9
+ # featured, complete, fast and efficient.
10
+ #
11
+ # See README.
12
+ #
13
+ # It consists mainly of
14
+ # * the main engine: CodeRay (Scanners::Scanner, Tokens, Encoders::Encoder)
15
+ # * the plugin system: PluginHost, Plugin
16
+ # * the scanners in CodeRay::Scanners
17
+ # * the encoders in CodeRay::Encoders
18
+ # * the styles in CodeRay::Styles
19
+ #
20
+ # Here's a fancy graphic to light up this gray docu:
21
+ #
22
+ # http://cycnus.de/raindark/coderay/scheme.png
23
+ #
24
+ # == Documentation
25
+ #
26
+ # See CodeRay, Encoders, Scanners, Tokens.
27
+ #
28
+ # == Usage
29
+ #
30
+ # Remember you need RubyGems to use CodeRay, unless you have it in your load
31
+ # path. Run Ruby with -rubygems option if required.
32
+ #
33
+ # === Highlight Ruby code in a string as html
34
+ #
35
+ # require 'coderay'
36
+ # print CodeRay.scan('puts "Hello, world!"', :ruby).html
37
+ #
38
+ # # prints something like this:
39
+ # puts <span class="s">&quot;Hello, world!&quot;</span>
40
+ #
41
+ #
42
+ # === Highlight C code from a file in a html div
43
+ #
44
+ # require 'coderay'
45
+ # print CodeRay.scan(File.read('ruby.h'), :c).div
46
+ # print CodeRay.scan_file('ruby.h').html.div
47
+ #
48
+ # You can include this div in your page. The used CSS styles can be printed with
49
+ #
50
+ # % coderay_stylesheet
51
+ #
52
+ # === Highlight without typing too much
53
+ #
54
+ # If you are one of the hasty (or lazy, or extremely curious) people, just run this file:
55
+ #
56
+ # % ruby -rubygems /path/to/coderay/coderay.rb > example.html
57
+ #
58
+ # and look at the file it created in your browser.
59
+ #
60
+ # = CodeRay Module
61
+ #
62
+ # The CodeRay module provides convenience methods for the engine.
63
+ #
64
+ # * The +lang+ and +format+ arguments select Scanner and Encoder to use. These are
65
+ # simply lower-case symbols, like <tt>:python</tt> or <tt>:html</tt>.
66
+ # * All methods take an optional hash as last parameter, +options+, that is send to
67
+ # the Encoder / Scanner.
68
+ # * Input and language are always sorted in this order: +code+, +lang+.
69
+ # (This is in alphabetical order, if you need a mnemonic ;)
70
+ #
71
+ # You should be able to highlight everything you want just using these methods;
72
+ # so there is no need to dive into CodeRay's deep class hierarchy.
73
+ #
74
+ # The examples in the demo directory demonstrate common cases using this interface.
75
+ #
76
+ # = Basic Access Ways
77
+ #
78
+ # Read this to get a general view what CodeRay provides.
79
+ #
80
+ # == Scanning
81
+ #
82
+ # Scanning means analysing an input string, splitting it up into Tokens.
83
+ # Each Token knows about what type it is: string, comment, class name, etc.
84
+ #
85
+ # Each +lang+ (language) has its own Scanner; for example, <tt>:ruby</tt> code is
86
+ # handled by CodeRay::Scanners::Ruby.
87
+ #
88
+ # CodeRay.scan:: Scan a string in a given language into Tokens.
89
+ # This is the most common method to use.
90
+ # CodeRay.scan_file:: Scan a file and guess the language using FileType.
91
+ #
92
+ # The Tokens object you get from these methods can encode itself; see Tokens.
93
+ #
94
+ # == Encoding
95
+ #
96
+ # Encoding means compiling Tokens into an output. This can be colored HTML or
97
+ # LaTeX, a textual statistic or just the number of non-whitespace tokens.
98
+ #
99
+ # Each Encoder provides output in a specific +format+, so you select Encoders via
100
+ # formats like <tt>:html</tt> or <tt>:statistic</tt>.
101
+ #
102
+ # CodeRay.encode:: Scan and encode a string in a given language.
103
+ # CodeRay.encode_tokens:: Encode the given tokens.
104
+ # CodeRay.encode_file:: Scan a file, guess the language using FileType and encode it.
105
+ #
106
+ # == All-in-One Encoding
107
+ #
108
+ # CodeRay.encode:: Highlight a string with a given input and output format.
109
+ #
110
+ # == Instanciating
111
+ #
112
+ # You can use an Encoder instance to highlight multiple inputs. This way, the setup
113
+ # for this Encoder must only be done once.
114
+ #
115
+ # CodeRay.encoder:: Create an Encoder instance with format and options.
116
+ # CodeRay.scanner:: Create an Scanner instance for lang, with '' as default code.
117
+ #
118
+ # To make use of CodeRay.scanner, use CodeRay::Scanner::code=.
119
+ #
120
+ # The scanning methods provide more flexibility; we recommend to use these.
121
+ #
122
+ # == Reusing Scanners and Encoders
123
+ #
124
+ # If you want to re-use scanners and encoders (because that is faster), see
125
+ # CodeRay::Duo for the most convenient (and recommended) interface.
126
+ module CodeRay
127
+
128
+ $CODERAY_DEBUG ||= false
129
+
130
+ CODERAY_PATH = File.expand_path('../coderay', __FILE__)
131
+
132
+ # Assuming the path is a subpath of lib/coderay/
133
+ def self.coderay_path *path
134
+ File.join CODERAY_PATH, *path
135
+ end
136
+
137
+ autoload :VERSION, 'coderay/version'
138
+
139
+ # helpers
140
+ autoload :FileType, coderay_path('helpers', 'file_type')
141
+
142
+ # Tokens
143
+ autoload :Tokens, coderay_path('tokens')
144
+ autoload :TokensProxy, coderay_path('tokens_proxy')
145
+ autoload :TokenKinds, coderay_path('token_kinds')
146
+
147
+ # Plugin system
148
+ autoload :PluginHost, coderay_path('helpers', 'plugin_host')
149
+ autoload :Plugin, coderay_path('helpers', 'plugin')
150
+
151
+ # Plugins
152
+ autoload :Scanners, coderay_path('scanners')
153
+ autoload :Encoders, coderay_path('encoders')
154
+ autoload :Styles, coderay_path('styles')
155
+
156
+ # convenience access and reusable Encoder/Scanner pair
157
+ autoload :Duo, coderay_path('duo')
158
+
159
+ class << self
160
+
161
+ # Scans the given +code+ (a String) with the Scanner for +lang+.
162
+ #
163
+ # This is a simple way to use CodeRay. Example:
164
+ # require 'coderay'
165
+ # page = CodeRay.scan("puts 'Hello, world!'", :ruby).html
166
+ #
167
+ # See also demo/demo_simple.
168
+ def scan code, lang, options = {}, &block
169
+ CodeRay::TokensProxy.new code, lang, options, block
170
+ end
171
+
172
+ # Scans +filename+ (a path to a code file) with the Scanner for +lang+.
173
+ #
174
+ # If +lang+ is :auto or omitted, the CodeRay::FileType module is used to
175
+ # determine it. If it cannot find out what type it is, it uses
176
+ # CodeRay::Scanners::Text.
177
+ #
178
+ # Calls CodeRay.scan.
179
+ #
180
+ # Example:
181
+ # require 'coderay'
182
+ # page = CodeRay.scan_file('some_c_code.c').html
183
+ def scan_file filename, lang = :auto, options = {}, &block
184
+ lang = CodeRay::FileType.fetch filename, :text, true if lang == :auto
185
+ code = File.read filename
186
+ scan code, lang, options, &block
187
+ end
188
+
189
+ # Encode a string.
190
+ #
191
+ # This scans +code+ with the the Scanner for +lang+ and then
192
+ # encodes it with the Encoder for +format+.
193
+ # +options+ will be passed to the Encoder.
194
+ #
195
+ # See CodeRay::Encoder.encode.
196
+ def encode code, lang, format, options = {}
197
+ encoder(format, options).encode code, lang, options
198
+ end
199
+
200
+ # Encode pre-scanned Tokens.
201
+ # Use this together with CodeRay.scan:
202
+ #
203
+ # require 'coderay'
204
+ #
205
+ # # Highlight a short Ruby code example in a HTML span
206
+ # tokens = CodeRay.scan '1 + 2', :ruby
207
+ # puts CodeRay.encode_tokens(tokens, :span)
208
+ #
209
+ def encode_tokens tokens, format, options = {}
210
+ encoder(format, options).encode_tokens tokens, options
211
+ end
212
+
213
+ # Encodes +filename+ (a path to a code file) with the Scanner for +lang+.
214
+ #
215
+ # See CodeRay.scan_file.
216
+ # Notice that the second argument is the output +format+, not the input language.
217
+ #
218
+ # Example:
219
+ # require 'coderay'
220
+ # page = CodeRay.encode_file 'some_c_code.c', :html
221
+ def encode_file filename, format, options = {}
222
+ tokens = scan_file filename, :auto, get_scanner_options(options)
223
+ encode_tokens tokens, format, options
224
+ end
225
+
226
+ # Highlight a string into a HTML <div>.
227
+ #
228
+ # CSS styles use classes, so you have to include a stylesheet
229
+ # in your output.
230
+ #
231
+ # See encode.
232
+ def highlight code, lang, options = { :css => :class }, format = :div
233
+ encode code, lang, format, options
234
+ end
235
+
236
+ # Highlight a file into a HTML <div>.
237
+ #
238
+ # CSS styles use classes, so you have to include a stylesheet
239
+ # in your output.
240
+ #
241
+ # See encode.
242
+ def highlight_file filename, options = { :css => :class }, format = :div
243
+ encode_file filename, format, options
244
+ end
245
+
246
+ # Finds the Encoder class for +format+ and creates an instance, passing
247
+ # +options+ to it.
248
+ #
249
+ # Example:
250
+ # require 'coderay'
251
+ #
252
+ # stats = CodeRay.encoder(:statistic)
253
+ # stats.encode("puts 17 + 4\n", :ruby)
254
+ #
255
+ # puts '%d out of %d tokens have the kind :integer.' % [
256
+ # stats.type_stats[:integer].count,
257
+ # stats.real_token_count
258
+ # ]
259
+ # #-> 2 out of 4 tokens have the kind :integer.
260
+ def encoder format, options = {}
261
+ CodeRay::Encoders[format].new options
262
+ end
263
+
264
+ # Finds the Scanner class for +lang+ and creates an instance, passing
265
+ # +options+ to it.
266
+ #
267
+ # See Scanner.new.
268
+ def scanner lang, options = {}, &block
269
+ CodeRay::Scanners[lang].new '', options, &block
270
+ end
271
+
272
+ # Extract the options for the scanner from the +options+ hash.
273
+ #
274
+ # Returns an empty Hash if <tt>:scanner_options</tt> is not set.
275
+ #
276
+ # This is used if a method like CodeRay.encode has to provide options
277
+ # for Encoder _and_ scanner.
278
+ def get_scanner_options options
279
+ options.fetch :scanner_options, {}
280
+ end
281
+
282
+ end
283
+
284
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ class IO::Line::Multiple
4
+ def initialize(lines, cursor)
5
+ @lines = lines
6
+ @cursor = cursor
7
+ end
8
+
9
+ def print(*strs, lineno:)
10
+ line = @lines[lineno]
11
+ if lineno > @cursor
12
+ line.io.cursor_down(lineno - @cursor)
13
+ elsif lineno < @cursor
14
+ line.io.cursor_up(lineno + @cursor)
15
+ end
16
+ @cursor = lineno
17
+ line.rewind.print(*strs)
18
+ end
19
+ end
@@ -2,7 +2,9 @@
2
2
 
3
3
  class IO::Line
4
4
  require "io/console"
5
+ require_relative "line/multiple"
5
6
 
7
+ VERSION = "0.1.0"
6
8
  attr_reader :io
7
9
 
8
10
  def initialize(io)
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ class LLM::Bot
4
+ ##
5
+ # @private
6
+ module Builder
7
+ private
8
+
9
+ ##
10
+ # @param [String] prompt The prompt
11
+ # @param [Hash] params
12
+ # @return [LLM::Response]
13
+ def create_response!(prompt, params)
14
+ @provider.responses.create(
15
+ prompt,
16
+ @params.merge(params.merge(@response ? {previous_response_id: @response.id} : {}))
17
+ )
18
+ end
19
+
20
+ ##
21
+ # @param [String] prompt The prompt
22
+ # @param [Hash] params
23
+ # @return [LLM::Response]
24
+ def create_completion!(prompt, params)
25
+ @provider.complete(
26
+ prompt,
27
+ @params.merge(params.merge(messages:))
28
+ )
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ class LLM::Bot
4
+ ##
5
+ # @private
6
+ module Conversable
7
+ private
8
+
9
+ ##
10
+ # Queues a response to be sent to the provider.
11
+ # @param [String] prompt The prompt
12
+ # @param [Hash] params
13
+ # @return [void]
14
+ def async_response(prompt, params = {})
15
+ if Array === prompt and prompt.empty?
16
+ @messages
17
+ else
18
+ role = params.delete(:role)
19
+ @messages << [LLM::Message.new(role, prompt), @params.merge(params), :respond]
20
+ end
21
+ end
22
+
23
+ ##
24
+ # Queues a completion to be sent to the provider.
25
+ # @param [String] prompt The prompt
26
+ # @param [Hash] params
27
+ # @return [void]
28
+ def async_completion(prompt, params = {})
29
+ if Array === prompt and prompt.empty?
30
+ @messages
31
+ else
32
+ role = params.delete(:role)
33
+ @messages << [LLM::Message.new(role, prompt), @params.merge(params), :complete]
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LLM::Bot::Prompt
4
+ class Completion < Struct.new(:bot, :defaults)
5
+ ##
6
+ # @param [LLM::Bot] bot
7
+ # @param [Hash] defaults
8
+ # @return [LLM::Bot::Prompt::Completion]
9
+ def initialize(bot, defaults)
10
+ super(bot, defaults || {})
11
+ end
12
+
13
+ ##
14
+ # @param [String] prompt
15
+ # @param [Hash] params (see LLM::Provider#complete)
16
+ # @return [LLM::Bot]
17
+ def system(prompt, params = {})
18
+ params = defaults.merge(params)
19
+ bot.chat prompt, params.merge(role: :system)
20
+ end
21
+
22
+ ##
23
+ # @param [String] prompt
24
+ # @param [Hash] params (see LLM::Provider#complete)
25
+ # @return [LLM::Bot]
26
+ def user(prompt, params = {})
27
+ params = defaults.merge(params)
28
+ bot.chat prompt, params.merge(role: :user)
29
+ end
30
+
31
+ ##
32
+ # @param [String] prompt
33
+ # @param [Hash] params (see LLM::Provider#complete)
34
+ # @return [LLM::Bot]
35
+ def assistant(prompt, params = {})
36
+ params = defaults.merge(params)
37
+ bot.chat prompt, params.merge(role: :assistant)
38
+ end
39
+
40
+ ##
41
+ # @param [String] prompt
42
+ # @param [Hash] params (see LLM::Provider#complete)
43
+ # @return [LLM::Bot]
44
+ def model(prompt, params = {})
45
+ params = defaults.merge(params)
46
+ bot.chat prompt, params.merge(role: :model)
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LLM::Bot::Prompt
4
+ class Respond < Struct.new(:bot, :defaults)
5
+ ##
6
+ # @param [LLM::Bot] bot
7
+ # @param [Hash] defaults
8
+ # @return [LLM::Bot::Prompt::Completion]
9
+ def initialize(bot, defaults)
10
+ super(bot, defaults || {})
11
+ end
12
+
13
+ ##
14
+ # @param [String] prompt
15
+ # @param [Hash] params (see LLM::Provider#complete)
16
+ # @return [LLM::Bot]
17
+ def system(prompt, params = {})
18
+ params = defaults.merge(params)
19
+ bot.respond prompt, params.merge(role: :system)
20
+ end
21
+
22
+ ##
23
+ # @param [String] prompt
24
+ # @param [Hash] params (see LLM::Provider#complete)
25
+ # @return [LLM::Bot]
26
+ def developer(prompt, params = {})
27
+ params = defaults.merge(params)
28
+ bot.respond prompt, params.merge(role: :developer)
29
+ end
30
+
31
+ ##
32
+ # @param [String] prompt
33
+ # @param [Hash] params (see LLM::Provider#complete)
34
+ # @return [LLM::Bot]
35
+ def user(prompt, params = {})
36
+ params = defaults.merge(params)
37
+ bot.respond prompt, params.merge(role: :user)
38
+ end
39
+
40
+ ##
41
+ # @param [String] prompt
42
+ # @param [Hash] params (see LLM::Provider#complete)
43
+ # @return [LLM::Bot]
44
+ def assistant(prompt, params = {})
45
+ params = defaults.merge(params)
46
+ bot.chat prompt, params.merge(role: :assistant)
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,150 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LLM
4
+ ##
5
+ # {LLM::Bot LLM::Bot} provides an object that can maintain a
6
+ # conversation. A conversation can use the chat completions API
7
+ # that all LLM providers support or the responses API that currently
8
+ # only OpenAI supports.
9
+ #
10
+ # @example
11
+ # #!/usr/bin/env ruby
12
+ # require "llm"
13
+ #
14
+ # llm = LLM.openai(key: ENV["KEY"])
15
+ # bot = LLM::Bot.new(llm)
16
+ # url = "https://en.wikipedia.org/wiki/Special:FilePath/Cognac_glass.jpg"
17
+ # msgs = bot.chat do |prompt|
18
+ # prompt.system "Your task is to answer all user queries"
19
+ # prompt.user ["Tell me about this URL", URI(url)]
20
+ # prompt.user ["Tell me about this PDF", File.open("handbook.pdf", "rb")]
21
+ # prompt.user "Are the URL and PDF similar to each other?"
22
+ # end
23
+ #
24
+ # # At this point, we execute a single request
25
+ # msgs.each { print "[#{_1.role}] ", _1.content, "\n" }
26
+ class Bot
27
+ require_relative "bot/prompt/completion"
28
+ require_relative "bot/prompt/respond"
29
+ require_relative "bot/conversable"
30
+ require_relative "bot/builder"
31
+
32
+ include Conversable
33
+ include Builder
34
+
35
+ ##
36
+ # Returns an Enumerable for the messages in a conversation
37
+ # @return [LLM::Buffer<LLM::Message>]
38
+ attr_reader :messages
39
+
40
+ ##
41
+ # @param [LLM::Provider] provider
42
+ # A provider
43
+ # @param [Hash] params
44
+ # The parameters to maintain throughout the conversation.
45
+ # Any parameter the provider supports can be included and
46
+ # not only those listed here.
47
+ # @option params [String] :model Defaults to the provider's default model
48
+ # @option params [#to_json, nil] :schema Defaults to nil
49
+ # @option params [Array<LLM::Function>, nil] :tools Defaults to nil
50
+ def initialize(provider, params = {})
51
+ @provider = provider
52
+ @params = {model: provider.default_model, schema: nil}.compact.merge!(params)
53
+ @messages = LLM::Buffer.new(provider)
54
+ end
55
+
56
+ ##
57
+ # Maintain a conversation via the chat completions API
58
+ # @overload def chat(prompt, params = {})
59
+ # @param prompt (see LLM::Provider#complete)
60
+ # @param params The params
61
+ # @return [LLM::Bot]
62
+ # Returns self
63
+ # @overload def chat(prompt, params, &block)
64
+ # @param prompt (see LLM::Provider#complete)
65
+ # @param params The params
66
+ # @yield prompt Yields a prompt
67
+ # @return [LLM::Buffer]
68
+ # Returns messages
69
+ def chat(prompt = nil, params = {})
70
+ if block_given?
71
+ params = prompt
72
+ yield Prompt::Completion.new(self, params)
73
+ messages
74
+ elsif prompt.nil?
75
+ raise ArgumentError, "wrong number of arguments (given 0, expected 1)"
76
+ else
77
+ params = {role: :user}.merge!(params)
78
+ tap { async_completion(prompt, params) }
79
+ end
80
+ end
81
+
82
+ ##
83
+ # Maintain a conversation via the responses API
84
+ # @overload def respond(prompt, params = {})
85
+ # @param prompt (see LLM::Provider#complete)
86
+ # @param params The params
87
+ # @return [LLM::Bot]
88
+ # Returns self
89
+ # @overload def respond(prompt, params, &block)
90
+ # @note Not all LLM providers support this API
91
+ # @param prompt (see LLM::Provider#complete)
92
+ # @param params The params
93
+ # @yield prompt Yields a prompt
94
+ # @return [LLM::Buffer]
95
+ # Returns messages
96
+ def respond(prompt = nil, params = {})
97
+ if block_given?
98
+ params = prompt
99
+ yield Prompt::Respond.new(self, params)
100
+ messages
101
+ elsif prompt.nil?
102
+ raise ArgumentError, "wrong number of arguments (given 0, expected 1)"
103
+ else
104
+ params = {role: :user}.merge!(params)
105
+ tap { async_response(prompt, params) }
106
+ end
107
+ end
108
+
109
+ ##
110
+ # @return [String]
111
+ def inspect
112
+ "#<#{self.class.name}:0x#{object_id.to_s(16)} " \
113
+ "@provider=#{@provider.class}, @params=#{@params.inspect}, " \
114
+ "@messages=#{@messages.inspect}>"
115
+ end
116
+
117
+ ##
118
+ # Returns an array of functions that can be called
119
+ # @return [Array<LLM::Function>]
120
+ def functions
121
+ messages
122
+ .select(&:assistant?)
123
+ .flat_map(&:functions)
124
+ .select(&:pending?)
125
+ end
126
+
127
+ ##
128
+ # @example
129
+ # llm = LLM.openai(key: ENV["KEY"])
130
+ # bot = LLM::Bot.new(llm, stream: $stdout)
131
+ # bot.chat("Hello", role: :user).flush
132
+ # Drains the buffer and returns all messages as an array
133
+ # @return [Array<LLM::Message>]
134
+ def drain
135
+ messages.drain
136
+ end
137
+ alias_method :flush, :drain
138
+
139
+ ##
140
+ # Returns token usage for the conversation
141
+ # @note
142
+ # This method returns token usage for the latest
143
+ # assistant message, and it returns an empty object
144
+ # if there are no assistant messages
145
+ # @return [LLM::Object]
146
+ def usage
147
+ messages.find(&:assistant?)&.usage || LLM::Object.from_hash({})
148
+ end
149
+ end
150
+ end