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,527 @@
1
+ require 'io/console'
2
+ require 'forwardable'
3
+ require 'reline/version'
4
+ require 'reline/config'
5
+ require 'reline/key_actor'
6
+ require 'reline/key_stroke'
7
+ require 'reline/line_editor'
8
+ require 'reline/history'
9
+ require 'reline/io'
10
+ require 'reline/face'
11
+ require 'rbconfig'
12
+
13
+ module Reline
14
+ # NOTE: For making compatible with the rb-readline gem
15
+ FILENAME_COMPLETION_PROC = nil # :nodoc:
16
+ USERNAME_COMPLETION_PROC = nil # :nodoc:
17
+
18
+ class ConfigEncodingConversionError < StandardError; end # :nodoc:
19
+
20
+ # EOF key: { char: nil, method_symbol: nil }
21
+ # Other key: { char: String, method_symbol: Symbol }
22
+ Key = Struct.new(:char, :method_symbol, :unused_boolean) do
23
+ # For dialog_proc `key.match?(dialog.name)`
24
+ def match?(sym)
25
+ method_symbol && method_symbol == sym
26
+ end
27
+ end # :nodoc:
28
+ CursorPos = Struct.new(:x, :y) # :nodoc:
29
+ DialogRenderInfo = Struct.new(
30
+ :pos,
31
+ :contents,
32
+ :face,
33
+ :bg_color, # For the time being, this line should stay here for the compatibility with IRB.
34
+ :width,
35
+ :height,
36
+ :scrollbar,
37
+ keyword_init: true
38
+ ) # :nodoc:
39
+
40
+ class Core
41
+ ATTR_READER_NAMES = %i(
42
+ completion_append_character
43
+ basic_word_break_characters
44
+ completer_word_break_characters
45
+ basic_quote_characters
46
+ completer_quote_characters
47
+ filename_quote_characters
48
+ special_prefixes
49
+ completion_proc
50
+ output_modifier_proc
51
+ prompt_proc
52
+ auto_indent_proc
53
+ pre_input_hook
54
+ dig_perfect_match_proc
55
+ ).each(&method(:attr_reader))
56
+
57
+ attr_accessor :config
58
+ attr_accessor :key_stroke
59
+ attr_accessor :line_editor
60
+ attr_accessor :last_incremental_search
61
+ attr_reader :output
62
+
63
+ extend Forwardable
64
+ def_delegators :config,
65
+ :autocompletion,
66
+ :autocompletion=
67
+
68
+ def initialize
69
+ self.output = STDOUT
70
+ @mutex = Mutex.new
71
+ @dialog_proc_list = {}
72
+ yield self
73
+ @completion_quote_character = nil
74
+ end
75
+
76
+ def io_gate
77
+ Reline::IOGate
78
+ end
79
+
80
+ def encoding
81
+ io_gate.encoding
82
+ end
83
+
84
+ def completion_append_character=(val)
85
+ if val.nil?
86
+ @completion_append_character = nil
87
+ elsif val.size == 1
88
+ @completion_append_character = val.encode(encoding)
89
+ elsif val.size > 1
90
+ @completion_append_character = val[0].encode(encoding)
91
+ else
92
+ @completion_append_character = nil
93
+ end
94
+ end
95
+
96
+ def basic_word_break_characters=(v)
97
+ @basic_word_break_characters = v.encode(encoding)
98
+ end
99
+
100
+ def completer_word_break_characters=(v)
101
+ @completer_word_break_characters = v.encode(encoding)
102
+ end
103
+
104
+ def basic_quote_characters=(v)
105
+ @basic_quote_characters = v.encode(encoding)
106
+ end
107
+
108
+ def completer_quote_characters=(v)
109
+ @completer_quote_characters = v.encode(encoding)
110
+ end
111
+
112
+ def filename_quote_characters=(v)
113
+ @filename_quote_characters = v.encode(encoding)
114
+ end
115
+
116
+ def special_prefixes=(v)
117
+ @special_prefixes = v.encode(encoding)
118
+ end
119
+
120
+ def completion_case_fold=(v)
121
+ @config.completion_ignore_case = v
122
+ end
123
+
124
+ def completion_case_fold
125
+ @config.completion_ignore_case
126
+ end
127
+
128
+ def completion_quote_character
129
+ @completion_quote_character
130
+ end
131
+
132
+ def completion_proc=(p)
133
+ raise ArgumentError unless p.respond_to?(:call) or p.nil?
134
+ @completion_proc = p
135
+ end
136
+
137
+ def output_modifier_proc=(p)
138
+ raise ArgumentError unless p.respond_to?(:call) or p.nil?
139
+ @output_modifier_proc = p
140
+ end
141
+
142
+ def prompt_proc=(p)
143
+ raise ArgumentError unless p.respond_to?(:call) or p.nil?
144
+ @prompt_proc = p
145
+ end
146
+
147
+ def auto_indent_proc=(p)
148
+ raise ArgumentError unless p.respond_to?(:call) or p.nil?
149
+ @auto_indent_proc = p
150
+ end
151
+
152
+ def pre_input_hook=(p)
153
+ @pre_input_hook = p
154
+ end
155
+
156
+ def dig_perfect_match_proc=(p)
157
+ raise ArgumentError unless p.respond_to?(:call) or p.nil?
158
+ @dig_perfect_match_proc = p
159
+ end
160
+
161
+ DialogProc = Struct.new(:dialog_proc, :context)
162
+ def add_dialog_proc(name_sym, p, context = nil)
163
+ raise ArgumentError unless name_sym.instance_of?(Symbol)
164
+ if p.nil?
165
+ @dialog_proc_list.delete(name_sym)
166
+ else
167
+ raise ArgumentError unless p.respond_to?(:call)
168
+ @dialog_proc_list[name_sym] = DialogProc.new(p, context)
169
+ end
170
+ end
171
+
172
+ def dialog_proc(name_sym)
173
+ @dialog_proc_list[name_sym]
174
+ end
175
+
176
+ def input=(val)
177
+ raise TypeError unless val.respond_to?(:getc) or val.nil?
178
+ if val.respond_to?(:getc) && io_gate.respond_to?(:input=)
179
+ io_gate.input = val
180
+ end
181
+ end
182
+
183
+ def output=(val)
184
+ raise TypeError unless val.respond_to?(:write) or val.nil?
185
+ @output = val
186
+ io_gate.output = val
187
+ end
188
+
189
+ def vi_editing_mode
190
+ config.editing_mode = :vi_insert
191
+ nil
192
+ end
193
+
194
+ def emacs_editing_mode
195
+ config.editing_mode = :emacs
196
+ nil
197
+ end
198
+
199
+ def vi_editing_mode?
200
+ config.editing_mode_is?(:vi_insert, :vi_command)
201
+ end
202
+
203
+ def emacs_editing_mode?
204
+ config.editing_mode_is?(:emacs)
205
+ end
206
+
207
+ def get_screen_size
208
+ io_gate.get_screen_size
209
+ end
210
+
211
+ Reline::DEFAULT_DIALOG_PROC_AUTOCOMPLETE = ->() {
212
+ # autocomplete
213
+ return unless config.autocompletion
214
+
215
+ journey_data = completion_journey_data
216
+ return unless journey_data
217
+
218
+ target = journey_data.list.first
219
+ completed = journey_data.list[journey_data.pointer]
220
+ result = journey_data.list.drop(1)
221
+ pointer = journey_data.pointer - 1
222
+ return if completed.empty? || (result == [completed] && pointer < 0)
223
+
224
+ target_width = Reline::Unicode.calculate_width(target)
225
+ completed_width = Reline::Unicode.calculate_width(completed)
226
+ if cursor_pos.x <= completed_width - target_width
227
+ # When target is rendered on the line above cursor position
228
+ x = screen_width - completed_width
229
+ y = -1
230
+ else
231
+ x = [cursor_pos.x - completed_width, 0].max
232
+ y = 0
233
+ end
234
+ cursor_pos_to_render = Reline::CursorPos.new(x, y)
235
+ if context and context.is_a?(Array)
236
+ context.clear
237
+ context.push(cursor_pos_to_render, result, pointer, dialog)
238
+ end
239
+ dialog.pointer = pointer
240
+ DialogRenderInfo.new(
241
+ pos: cursor_pos_to_render,
242
+ contents: result,
243
+ scrollbar: true,
244
+ height: [15, preferred_dialog_height].min,
245
+ face: :completion_dialog
246
+ )
247
+ } # :nodoc:
248
+ Reline::DEFAULT_DIALOG_CONTEXT = Array.new # :nodoc:
249
+
250
+ def readmultiline(prompt = '', add_hist = false, &confirm_multiline_termination)
251
+ @mutex.synchronize do
252
+ unless confirm_multiline_termination
253
+ raise ArgumentError.new('#readmultiline needs block to confirm multiline termination')
254
+ end
255
+
256
+ io_gate.with_raw_input do
257
+ inner_readline(prompt, add_hist, true, &confirm_multiline_termination)
258
+ end
259
+
260
+ whole_buffer = line_editor.whole_buffer.dup
261
+ whole_buffer.taint if RUBY_VERSION < '2.7'
262
+ if add_hist and whole_buffer and whole_buffer.chomp("\n").size > 0
263
+ Reline::HISTORY << whole_buffer
264
+ end
265
+
266
+ if line_editor.eof?
267
+ line_editor.reset_line
268
+ # Return nil if the input is aborted by C-d.
269
+ nil
270
+ else
271
+ whole_buffer
272
+ end
273
+ end
274
+ end
275
+
276
+ def readline(prompt = '', add_hist = false)
277
+ @mutex.synchronize do
278
+ io_gate.with_raw_input do
279
+ inner_readline(prompt, add_hist, false)
280
+ end
281
+
282
+ line = line_editor.line.dup
283
+ line.taint if RUBY_VERSION < '2.7'
284
+ if add_hist and line and line.chomp("\n").size > 0
285
+ Reline::HISTORY << line.chomp("\n")
286
+ end
287
+
288
+ line_editor.reset_line if line_editor.line.nil?
289
+ line
290
+ end
291
+ end
292
+
293
+ private def inner_readline(prompt, add_hist, multiline, &confirm_multiline_termination)
294
+ if ENV['RELINE_STDERR_TTY']
295
+ if io_gate.win?
296
+ $stderr = File.open(ENV['RELINE_STDERR_TTY'], 'a')
297
+ else
298
+ $stderr.reopen(ENV['RELINE_STDERR_TTY'], 'w')
299
+ end
300
+ $stderr.sync = true
301
+ $stderr.puts "Reline is used by #{Process.pid}"
302
+ end
303
+ unless config.test_mode or config.loaded?
304
+ config.read
305
+ io_gate.set_default_key_bindings(config)
306
+ end
307
+ otio = io_gate.prep
308
+
309
+ may_req_ambiguous_char_width
310
+ key_stroke.encoding = encoding
311
+ line_editor.reset(prompt)
312
+ if multiline
313
+ line_editor.multiline_on
314
+ if block_given?
315
+ line_editor.confirm_multiline_termination_proc = confirm_multiline_termination
316
+ end
317
+ else
318
+ line_editor.multiline_off
319
+ end
320
+ line_editor.completion_proc = completion_proc
321
+ line_editor.completion_append_character = completion_append_character
322
+ line_editor.output_modifier_proc = output_modifier_proc
323
+ line_editor.prompt_proc = prompt_proc
324
+ line_editor.auto_indent_proc = auto_indent_proc
325
+ line_editor.dig_perfect_match_proc = dig_perfect_match_proc
326
+
327
+ pre_input_hook&.call
328
+
329
+ unless Reline::IOGate.dumb?
330
+ @dialog_proc_list.each_pair do |name_sym, d|
331
+ line_editor.add_dialog_proc(name_sym, d.dialog_proc, d.context)
332
+ end
333
+ end
334
+
335
+ line_editor.update_dialogs
336
+ line_editor.rerender
337
+
338
+ begin
339
+ line_editor.set_signal_handlers
340
+ loop do
341
+ read_io(config.keyseq_timeout) { |inputs|
342
+ inputs.each do |key|
343
+ case key.method_symbol
344
+ when :bracketed_paste_start
345
+ # io_gate is Reline::ANSI because the key :bracketed_paste_start is only assigned in Reline::ANSI
346
+ key = Reline::Key.new(io_gate.read_bracketed_paste, :insert_multiline_text)
347
+ when :quoted_insert, :ed_quoted_insert
348
+ char = io_gate.read_single_char(config.keyseq_timeout.fdiv(1000))
349
+ key = Reline::Key.new(char || '', :insert_raw_char)
350
+ end
351
+ line_editor.set_pasting_state(io_gate.in_pasting?)
352
+ line_editor.update(key)
353
+ end
354
+ }
355
+ if line_editor.finished?
356
+ line_editor.render_finished
357
+ break
358
+ else
359
+ line_editor.rerender
360
+ end
361
+ end
362
+ io_gate.move_cursor_column(0)
363
+ rescue Errno::EIO
364
+ # Maybe the I/O has been closed.
365
+ ensure
366
+ line_editor.finalize
367
+ io_gate.deprep(otio)
368
+ end
369
+ end
370
+
371
+ # GNU Readline watis for "keyseq-timeout" milliseconds when the input is
372
+ # ambiguous whether it is matching or matched.
373
+ # If the next character does not arrive within the specified timeout, input
374
+ # is considered as matched.
375
+ # `ESC` is ambiguous because it can be a standalone ESC (matched) or part of
376
+ # `ESC char` or part of CSI sequence (matching).
377
+ private def read_io(keyseq_timeout, &block)
378
+ buffer = []
379
+ status = KeyStroke::MATCHING
380
+ loop do
381
+ timeout = status == KeyStroke::MATCHING_MATCHED ? keyseq_timeout.fdiv(1000) : Float::INFINITY
382
+ c = io_gate.getc(timeout)
383
+ if c.nil? || c == -1
384
+ if status == KeyStroke::MATCHING_MATCHED
385
+ status = KeyStroke::MATCHED
386
+ elsif buffer.empty?
387
+ # io_gate is closed and reached EOF
388
+ block.call([Key.new(nil, nil, false)])
389
+ return
390
+ else
391
+ status = KeyStroke::UNMATCHED
392
+ end
393
+ else
394
+ buffer << c
395
+ status = key_stroke.match_status(buffer)
396
+ end
397
+
398
+ if status == KeyStroke::MATCHED || status == KeyStroke::UNMATCHED
399
+ expanded, rest_bytes = key_stroke.expand(buffer)
400
+ rest_bytes.reverse_each { |c| io_gate.ungetc(c) }
401
+ block.call(expanded)
402
+ return
403
+ end
404
+ end
405
+ end
406
+
407
+ def ambiguous_width
408
+ may_req_ambiguous_char_width unless defined? @ambiguous_width
409
+ @ambiguous_width
410
+ end
411
+
412
+ private def may_req_ambiguous_char_width
413
+ @ambiguous_width = 1 if io_gate.dumb? || !STDIN.tty? || !STDOUT.tty?
414
+ return if defined? @ambiguous_width
415
+ io_gate.move_cursor_column(0)
416
+ begin
417
+ output.write "\u{25bd}"
418
+ rescue Encoding::UndefinedConversionError
419
+ # LANG=C
420
+ @ambiguous_width = 1
421
+ else
422
+ @ambiguous_width = io_gate.cursor_pos.x == 2 ? 2 : 1
423
+ end
424
+ io_gate.move_cursor_column(0)
425
+ io_gate.erase_after_cursor
426
+ end
427
+ end
428
+
429
+ extend Forwardable
430
+ extend SingleForwardable
431
+
432
+ #--------------------------------------------------------
433
+ # Documented API
434
+ #--------------------------------------------------------
435
+
436
+ (Core::ATTR_READER_NAMES).each { |name|
437
+ def_single_delegators :core, :"#{name}", :"#{name}="
438
+ }
439
+ def_single_delegators :core, :input=, :output=
440
+ def_single_delegators :core, :vi_editing_mode, :emacs_editing_mode
441
+
442
+ ##
443
+ # :singleton-method: readmultiline
444
+ # :call-seq:
445
+ # readmultiline(prompt = '', add_hist = false, &confirm_multiline_termination) -> string or nil
446
+ def_single_delegators :core, :readmultiline
447
+
448
+ ##
449
+ # :singleton-method: readline
450
+ # :call-seq:
451
+ # readline(prompt = '', add_hist = false) -> string or nil
452
+ def_single_delegators :core, :readline
453
+ def_single_delegators :core, :completion_case_fold, :completion_case_fold=
454
+ def_single_delegators :core, :completion_quote_character
455
+ def_instance_delegators self, :readline
456
+ private :readline
457
+
458
+
459
+ #--------------------------------------------------------
460
+ # Undocumented API
461
+ #--------------------------------------------------------
462
+
463
+ # Testable in original
464
+ def_single_delegators :core, :get_screen_size
465
+ def_single_delegators :line_editor, :eof?
466
+ def_instance_delegators self, :eof?
467
+ def_single_delegators :line_editor, :delete_text
468
+ def_single_delegator :line_editor, :line, :line_buffer
469
+ def_single_delegator :line_editor, :byte_pointer, :point
470
+ def_single_delegator :line_editor, :byte_pointer=, :point=
471
+
472
+ def self.insert_text(text)
473
+ line_editor.insert_multiline_text(text)
474
+ self
475
+ end
476
+
477
+ # Untestable in original
478
+ def_single_delegator :line_editor, :rerender, :redisplay
479
+ def_single_delegators :core, :vi_editing_mode?, :emacs_editing_mode?
480
+ def_single_delegators :core, :ambiguous_width
481
+ def_single_delegators :core, :last_incremental_search
482
+ def_single_delegators :core, :last_incremental_search=
483
+ def_single_delegators :core, :add_dialog_proc
484
+ def_single_delegators :core, :dialog_proc
485
+ def_single_delegators :core, :autocompletion, :autocompletion=
486
+
487
+ def_instance_delegators self, :readmultiline
488
+ private :readmultiline
489
+
490
+ def self.encoding_system_needs # :nodoc:
491
+ self.core.encoding
492
+ end
493
+
494
+ def self.core
495
+ @core ||= Core.new { |core|
496
+ core.config = Reline::Config.new
497
+ core.key_stroke = Reline::KeyStroke.new(core.config, core.encoding)
498
+ core.line_editor = Reline::LineEditor.new(core.config)
499
+
500
+ core.basic_word_break_characters = " \t\n`><=;|&{("
501
+ core.completer_word_break_characters = " \t\n`><=;|&{("
502
+ core.basic_quote_characters = '"\''
503
+ core.completer_quote_characters = '"\''
504
+ core.filename_quote_characters = ""
505
+ core.special_prefixes = ""
506
+ core.add_dialog_proc(:autocomplete, Reline::DEFAULT_DIALOG_PROC_AUTOCOMPLETE, Reline::DEFAULT_DIALOG_CONTEXT)
507
+ }
508
+ end
509
+
510
+ def self.ungetc(c)
511
+ core.io_gate.ungetc(c)
512
+ end
513
+
514
+ def self.line_editor
515
+ core.line_editor
516
+ end
517
+ end
518
+
519
+
520
+ Reline::IOGate = Reline::IO.decide_io_gate
521
+
522
+ # Deprecated
523
+ Reline::GeneralIO = Reline::Dumb.new # :nodoc:
524
+
525
+ Reline::Face.load_initial_configs
526
+
527
+ Reline::HISTORY = Reline::History.new(Reline.core.config)