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,421 @@
1
+ class Reline::Unicode
2
+ EscapedPairs = {
3
+ 0x00 => '^@',
4
+ 0x01 => '^A', # C-a
5
+ 0x02 => '^B',
6
+ 0x03 => '^C',
7
+ 0x04 => '^D',
8
+ 0x05 => '^E',
9
+ 0x06 => '^F',
10
+ 0x07 => '^G',
11
+ 0x08 => '^H', # Backspace
12
+ 0x09 => '^I',
13
+ 0x0A => '^J',
14
+ 0x0B => '^K',
15
+ 0x0C => '^L',
16
+ 0x0D => '^M', # Enter
17
+ 0x0E => '^N',
18
+ 0x0F => '^O',
19
+ 0x10 => '^P',
20
+ 0x11 => '^Q',
21
+ 0x12 => '^R',
22
+ 0x13 => '^S',
23
+ 0x14 => '^T',
24
+ 0x15 => '^U',
25
+ 0x16 => '^V',
26
+ 0x17 => '^W',
27
+ 0x18 => '^X',
28
+ 0x19 => '^Y',
29
+ 0x1A => '^Z', # C-z
30
+ 0x1B => '^[', # C-[ C-3
31
+ 0x1C => '^\\', # C-\
32
+ 0x1D => '^]', # C-]
33
+ 0x1E => '^^', # C-~ C-6
34
+ 0x1F => '^_', # C-_ C-7
35
+ 0x7F => '^?', # C-? C-8
36
+ }
37
+
38
+ NON_PRINTING_START = "\1"
39
+ NON_PRINTING_END = "\2"
40
+ CSI_REGEXP = /\e\[[\d;]*[ABCDEFGHJKSTfminsuhl]/
41
+ OSC_REGEXP = /\e\]\d+(?:;[^;\a\e]+)*(?:\a|\e\\)/
42
+ WIDTH_SCANNER = /\G(?:(#{NON_PRINTING_START})|(#{NON_PRINTING_END})|(#{CSI_REGEXP})|(#{OSC_REGEXP})|(\X))/o
43
+
44
+ def self.escape_for_print(str)
45
+ str.chars.map! { |gr|
46
+ case gr
47
+ when -"\n"
48
+ gr
49
+ when -"\t"
50
+ -' '
51
+ else
52
+ EscapedPairs[gr.ord] || gr
53
+ end
54
+ }.join
55
+ end
56
+
57
+ def self.safe_encode(str, encoding)
58
+ # Reline only supports utf-8 convertible string.
59
+ converted = str.encode(encoding, invalid: :replace, undef: :replace)
60
+ return converted if str.encoding == Encoding::UTF_8 || converted.encoding == Encoding::UTF_8 || converted.ascii_only?
61
+
62
+ # This code is essentially doing the same thing as
63
+ # `str.encode(utf8, **replace_options).encode(encoding, **replace_options)`
64
+ # but also avoids unnecessary irreversible encoding conversion.
65
+ converted.gsub(/\X/) do |c|
66
+ c.encode(Encoding::UTF_8)
67
+ c
68
+ rescue Encoding::UndefinedConversionError
69
+ '?'
70
+ end
71
+ end
72
+
73
+ require 'reline/unicode/east_asian_width'
74
+
75
+ def self.east_asian_width(ord)
76
+ chunk_index = EastAsianWidth::CHUNK_LAST.bsearch_index { |o| ord <= o }
77
+ size = EastAsianWidth::CHUNK_WIDTH[chunk_index]
78
+ size == -1 ? Reline.ambiguous_width : size
79
+ end
80
+
81
+ def self.get_mbchar_width(mbchar)
82
+ ord = mbchar.ord
83
+ if ord <= 0x1F # in EscapedPairs
84
+ return 2
85
+ elsif mbchar.length == 1 && ord <= 0x7E # printable ASCII chars
86
+ return 1
87
+ end
88
+
89
+ utf8_mbchar = mbchar.encode(Encoding::UTF_8)
90
+ zwj = false
91
+ utf8_mbchar.chars.sum do |c|
92
+ if zwj
93
+ zwj = false
94
+ 0
95
+ elsif c.ord == 0x200D # Zero Width Joiner
96
+ zwj = true
97
+ 0
98
+ else
99
+ east_asian_width(c.ord)
100
+ end
101
+ end
102
+ end
103
+
104
+ def self.calculate_width(str, allow_escape_code = false)
105
+ if allow_escape_code
106
+ width = 0
107
+ rest = str.encode(Encoding::UTF_8)
108
+ in_zero_width = false
109
+ rest.scan(WIDTH_SCANNER) do |non_printing_start, non_printing_end, csi, osc, gc|
110
+ case
111
+ when non_printing_start
112
+ in_zero_width = true
113
+ when non_printing_end
114
+ in_zero_width = false
115
+ when csi, osc
116
+ when gc
117
+ unless in_zero_width
118
+ width += get_mbchar_width(gc)
119
+ end
120
+ end
121
+ end
122
+ width
123
+ else
124
+ str.encode(Encoding::UTF_8).grapheme_clusters.inject(0) { |w, gc|
125
+ w + get_mbchar_width(gc)
126
+ }
127
+ end
128
+ end
129
+
130
+ # This method is used by IRB
131
+ def self.split_by_width(str, max_width)
132
+ lines = split_line_by_width(str, max_width)
133
+ [lines, lines.size]
134
+ end
135
+
136
+ def self.split_line_by_width(str, max_width, encoding = str.encoding, offset: 0)
137
+ lines = [String.new(encoding: encoding)]
138
+ width = offset
139
+ rest = str.encode(Encoding::UTF_8)
140
+ in_zero_width = false
141
+ seq = String.new(encoding: encoding)
142
+ rest.scan(WIDTH_SCANNER) do |non_printing_start, non_printing_end, csi, osc, gc|
143
+ case
144
+ when non_printing_start
145
+ in_zero_width = true
146
+ when non_printing_end
147
+ in_zero_width = false
148
+ when csi
149
+ lines.last << csi
150
+ unless in_zero_width
151
+ if csi == -"\e[m" || csi == -"\e[0m"
152
+ seq.clear
153
+ else
154
+ seq << csi
155
+ end
156
+ end
157
+ when osc
158
+ lines.last << osc
159
+ seq << osc unless in_zero_width
160
+ when gc
161
+ unless in_zero_width
162
+ mbchar_width = get_mbchar_width(gc)
163
+ if (width += mbchar_width) > max_width
164
+ width = mbchar_width
165
+ lines << seq.dup
166
+ end
167
+ end
168
+ lines.last << gc
169
+ end
170
+ end
171
+ # The cursor moves to next line in first
172
+ if width == max_width
173
+ lines << String.new(encoding: encoding)
174
+ end
175
+ lines
176
+ end
177
+
178
+ def self.strip_non_printing_start_end(prompt)
179
+ prompt.gsub(/\x01([^\x02]*)(?:\x02|\z)/) { $1 }
180
+ end
181
+
182
+ # Take a chunk of a String cut by width with escape sequences.
183
+ def self.take_range(str, start_col, max_width)
184
+ take_mbchar_range(str, start_col, max_width).first
185
+ end
186
+
187
+ def self.take_mbchar_range(str, start_col, width, cover_begin: false, cover_end: false, padding: false)
188
+ chunk = String.new(encoding: str.encoding)
189
+
190
+ end_col = start_col + width
191
+ total_width = 0
192
+ rest = str.encode(Encoding::UTF_8)
193
+ in_zero_width = false
194
+ chunk_start_col = nil
195
+ chunk_end_col = nil
196
+ has_csi = false
197
+ rest.scan(WIDTH_SCANNER) do |non_printing_start, non_printing_end, csi, osc, gc|
198
+ case
199
+ when non_printing_start
200
+ in_zero_width = true
201
+ when non_printing_end
202
+ in_zero_width = false
203
+ when csi
204
+ has_csi = true
205
+ chunk << csi
206
+ when osc
207
+ chunk << osc
208
+ when gc
209
+ if in_zero_width
210
+ chunk << gc
211
+ next
212
+ end
213
+
214
+ mbchar_width = get_mbchar_width(gc)
215
+ prev_width = total_width
216
+ total_width += mbchar_width
217
+
218
+ if (cover_begin || padding ? total_width <= start_col : prev_width < start_col)
219
+ # Current character haven't reached start_col yet
220
+ next
221
+ elsif padding && !cover_begin && prev_width < start_col && start_col < total_width
222
+ # Add preceding padding. This padding might have background color.
223
+ chunk << ' ' * (total_width - start_col)
224
+ chunk_start_col ||= start_col
225
+ chunk_end_col = total_width
226
+ next
227
+ elsif (cover_end ? prev_width < end_col : total_width <= end_col)
228
+ # Current character is in the range
229
+ chunk << gc
230
+ chunk_start_col ||= prev_width
231
+ chunk_end_col = total_width
232
+ break if total_width >= end_col
233
+ else
234
+ # Current character exceeds end_col
235
+ if padding && end_col < total_width
236
+ # Add succeeding padding. This padding might have background color.
237
+ chunk << ' ' * (end_col - prev_width)
238
+ chunk_start_col ||= prev_width
239
+ chunk_end_col = end_col
240
+ end
241
+ break
242
+ end
243
+ end
244
+ end
245
+ chunk_start_col ||= start_col
246
+ chunk_end_col ||= start_col
247
+ if padding && chunk_end_col < end_col
248
+ # Append padding. This padding should not include background color.
249
+ chunk << "\e[0m" if has_csi
250
+ chunk << ' ' * (end_col - chunk_end_col)
251
+ chunk_end_col = end_col
252
+ end
253
+ [chunk, chunk_start_col, chunk_end_col - chunk_start_col]
254
+ end
255
+
256
+ def self.get_next_mbchar_size(line, byte_pointer)
257
+ grapheme = line.byteslice(byte_pointer..-1).grapheme_clusters.first
258
+ grapheme ? grapheme.bytesize : 0
259
+ end
260
+
261
+ def self.get_prev_mbchar_size(line, byte_pointer)
262
+ if byte_pointer.zero?
263
+ 0
264
+ else
265
+ grapheme = line.byteslice(0..(byte_pointer - 1)).grapheme_clusters.last
266
+ grapheme ? grapheme.bytesize : 0
267
+ end
268
+ end
269
+
270
+ def self.em_forward_word(line, byte_pointer)
271
+ gcs = line.byteslice(byte_pointer..).grapheme_clusters
272
+ nonwords = gcs.take_while { |c| !word_character?(c) }
273
+ words = gcs.drop(nonwords.size).take_while { |c| word_character?(c) }
274
+ nonwords.sum(&:bytesize) + words.sum(&:bytesize)
275
+ end
276
+
277
+ def self.em_forward_word_with_capitalization(line, byte_pointer)
278
+ gcs = line.byteslice(byte_pointer..).grapheme_clusters
279
+ nonwords = gcs.take_while { |c| !word_character?(c) }
280
+ words = gcs.drop(nonwords.size).take_while { |c| word_character?(c) }
281
+ [nonwords.sum(&:bytesize) + words.sum(&:bytesize), nonwords.join + words.join.capitalize]
282
+ end
283
+
284
+ def self.em_backward_word(line, byte_pointer)
285
+ gcs = line.byteslice(0, byte_pointer).grapheme_clusters.reverse
286
+ nonwords = gcs.take_while { |c| !word_character?(c) }
287
+ words = gcs.drop(nonwords.size).take_while { |c| word_character?(c) }
288
+ nonwords.sum(&:bytesize) + words.sum(&:bytesize)
289
+ end
290
+
291
+ def self.em_big_backward_word(line, byte_pointer)
292
+ gcs = line.byteslice(0, byte_pointer).grapheme_clusters.reverse
293
+ spaces = gcs.take_while { |c| space_character?(c) }
294
+ nonspaces = gcs.drop(spaces.size).take_while { |c| !space_character?(c) }
295
+ spaces.sum(&:bytesize) + nonspaces.sum(&:bytesize)
296
+ end
297
+
298
+ def self.ed_transpose_words(line, byte_pointer)
299
+ gcs = line.byteslice(0, byte_pointer).grapheme_clusters
300
+ pos = gcs.size
301
+ gcs += line.byteslice(byte_pointer..).grapheme_clusters
302
+ pos += 1 while pos < gcs.size && !word_character?(gcs[pos])
303
+ if pos == gcs.size # 'aaa bbb [cursor] '
304
+ pos -= 1 while pos > 0 && !word_character?(gcs[pos - 1])
305
+ second_word_end = gcs.size
306
+ else # 'aaa [cursor]bbb'
307
+ pos += 1 while pos < gcs.size && word_character?(gcs[pos])
308
+ second_word_end = pos
309
+ end
310
+ pos -= 1 while pos > 0 && word_character?(gcs[pos - 1])
311
+ second_word_start = pos
312
+ pos -= 1 while pos > 0 && !word_character?(gcs[pos - 1])
313
+ first_word_end = pos
314
+ pos -= 1 while pos > 0 && word_character?(gcs[pos - 1])
315
+ first_word_start = pos
316
+
317
+ [first_word_start, first_word_end, second_word_start, second_word_end].map do |idx|
318
+ gcs.take(idx).sum(&:bytesize)
319
+ end
320
+ end
321
+
322
+ def self.vi_big_forward_word(line, byte_pointer)
323
+ gcs = line.byteslice(byte_pointer..).grapheme_clusters
324
+ nonspaces = gcs.take_while { |c| !space_character?(c) }
325
+ spaces = gcs.drop(nonspaces.size).take_while { |c| space_character?(c) }
326
+ nonspaces.sum(&:bytesize) + spaces.sum(&:bytesize)
327
+ end
328
+
329
+ def self.vi_big_forward_end_word(line, byte_pointer)
330
+ gcs = line.byteslice(byte_pointer..).grapheme_clusters
331
+ first = gcs.shift(1)
332
+ spaces = gcs.take_while { |c| space_character?(c) }
333
+ nonspaces = gcs.drop(spaces.size).take_while { |c| !space_character?(c) }
334
+ matched = spaces + nonspaces
335
+ matched.pop
336
+ first.sum(&:bytesize) + matched.sum(&:bytesize)
337
+ end
338
+
339
+ def self.vi_big_backward_word(line, byte_pointer)
340
+ gcs = line.byteslice(0, byte_pointer).grapheme_clusters.reverse
341
+ spaces = gcs.take_while { |c| space_character?(c) }
342
+ nonspaces = gcs.drop(spaces.size).take_while { |c| !space_character?(c) }
343
+ spaces.sum(&:bytesize) + nonspaces.sum(&:bytesize)
344
+ end
345
+
346
+ def self.vi_forward_word(line, byte_pointer, drop_terminate_spaces = false)
347
+ gcs = line.byteslice(byte_pointer..).grapheme_clusters
348
+ return 0 if gcs.empty?
349
+
350
+ c = gcs.first
351
+ matched =
352
+ if word_character?(c)
353
+ gcs.take_while { |c| word_character?(c) }
354
+ elsif space_character?(c)
355
+ gcs.take_while { |c| space_character?(c) }
356
+ else
357
+ gcs.take_while { |c| !word_character?(c) && !space_character?(c) }
358
+ end
359
+
360
+ return matched.sum(&:bytesize) if drop_terminate_spaces
361
+
362
+ spaces = gcs.drop(matched.size).take_while { |c| space_character?(c) }
363
+ matched.sum(&:bytesize) + spaces.sum(&:bytesize)
364
+ end
365
+
366
+ def self.vi_forward_end_word(line, byte_pointer)
367
+ gcs = line.byteslice(byte_pointer..).grapheme_clusters
368
+ return 0 if gcs.empty?
369
+ return gcs.first.bytesize if gcs.size == 1
370
+
371
+ start = gcs.shift
372
+ skips = [start]
373
+ if space_character?(start) || space_character?(gcs.first)
374
+ spaces = gcs.take_while { |c| space_character?(c) }
375
+ skips += spaces
376
+ gcs.shift(spaces.size)
377
+ end
378
+ start_with_word = word_character?(gcs.first)
379
+ matched = gcs.take_while { |c| start_with_word ? word_character?(c) : !word_character?(c) && !space_character?(c) }
380
+ matched.pop
381
+ skips.sum(&:bytesize) + matched.sum(&:bytesize)
382
+ end
383
+
384
+ def self.vi_backward_word(line, byte_pointer)
385
+ gcs = line.byteslice(0, byte_pointer).grapheme_clusters.reverse
386
+ spaces = gcs.take_while { |c| space_character?(c) }
387
+ gcs.shift(spaces.size)
388
+ start_with_word = word_character?(gcs.first)
389
+ matched = gcs.take_while { |c| start_with_word ? word_character?(c) : !word_character?(c) && !space_character?(c) }
390
+ spaces.sum(&:bytesize) + matched.sum(&:bytesize)
391
+ end
392
+
393
+ def self.common_prefix(list, ignore_case: false)
394
+ return '' if list.empty?
395
+
396
+ common_prefix_gcs = list.first.grapheme_clusters
397
+ list.each do |item|
398
+ gcs = item.grapheme_clusters
399
+ common_prefix_gcs = common_prefix_gcs.take_while.with_index do |gc, i|
400
+ ignore_case ? gc.casecmp?(gcs[i]) : gc == gcs[i]
401
+ end
402
+ end
403
+ common_prefix_gcs.join
404
+ end
405
+
406
+ def self.vi_first_print(line)
407
+ gcs = line.grapheme_clusters
408
+ spaces = gcs.take_while { |c| space_character?(c) }
409
+ spaces.sum(&:bytesize)
410
+ end
411
+
412
+ def self.word_character?(s)
413
+ s.encode(Encoding::UTF_8).match?(/\p{Word}/) if s
414
+ rescue Encoding::UndefinedConversionError
415
+ false
416
+ end
417
+
418
+ def self.space_character?(s)
419
+ s.match?(/\s/) if s
420
+ end
421
+ end
@@ -0,0 +1,3 @@
1
+ module Reline
2
+ VERSION = '0.6.2'
3
+ end