llm.rb 12.3.0 → 12.4.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.
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ class LLM::Tool
4
+ ##
5
+ # The {LLM::Tool::Which LLM::Tool::Which} class implements
6
+ # a tool that locates an executable on the system PATH.
7
+ #
8
+ # This lets an agent discover whether a command it intends
9
+ # to use is actually available before attempting to run it.
10
+ # For example, checking `which("rg")` before a search, or
11
+ # `which("git")` before a version control operation, avoids
12
+ # a failed subprocess and lets the agent adapt its strategy
13
+ # when a tool is missing.
14
+ class Which < self
15
+ name "which"
16
+ description "locate an executable on the system PATH"
17
+ parameter :name, String, "the name of the executable to find"
18
+ required %i[name]
19
+
20
+ ##
21
+ # @param [String] name
22
+ # @return [Hash]
23
+ def call(name:)
24
+ path = paths.find { File.executable? File.join(_1, name) }
25
+ {ok: !!path, path:}
26
+ end
27
+
28
+ private
29
+
30
+ ##
31
+ # @return [Array<String>]
32
+ def paths
33
+ ENV["PATH"]
34
+ .to_s
35
+ .split(File::PATH_SEPARATOR)
36
+ end
37
+ end
38
+ end
data/lib/llm/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module LLM
4
- VERSION = "12.3.0"
4
+ VERSION = "12.4.0"
5
5
  end
@@ -92,9 +92,12 @@ features that didn't make it into the homepage documentation.
92
92
  <summary>REPL</summary>
93
93
 
94
94
  - [LLM::Agent](#llmagent)
95
+ - [State](#state)
95
96
  - [Tools](#tools)
96
97
  - [Skills](#skills-1)
97
98
  - [Tracer](#tracer-1)
99
+ - [Input](#input)
100
+ - [Commands](#commands)
98
101
  </details>
99
102
 
100
103
  **Persistence**
@@ -894,6 +897,12 @@ you a way to confirm the work was successful, inspect
894
897
  anything that went wrong, and keep talking to the same
895
898
  agent while its state is still intact.
896
899
 
900
+ The REPL is a curses-based TUI with a status line showing
901
+ a context-usage bar and cost counter, a scrollable transcript
902
+ that renders markdown, and a multi-line input area. The UI
903
+ thread stays responsive while a second thread communicates
904
+ with the model.
905
+
897
906
  #### LLM::Agent
898
907
 
899
908
  The [LLM::Agent#repl](https://r.uby.dev/api-docs/llm.rb/LLM/Agent.html#repl-instance_method)
@@ -915,6 +924,20 @@ agent = LLM::Agent.new(llm)
915
924
  agent.repl
916
925
  ```
917
926
 
927
+ #### State
928
+
929
+ The `path:` option accepts a file path where runtime state
930
+ is read from and written to. This lets you resume a
931
+ conversation across REPL sessions. When the file does not
932
+ exist the agent starts fresh; when it does, the agent
933
+ restores its previous state.
934
+
935
+ ```ruby
936
+ llm = LLM.deepseek(key: ENV["KEY"])
937
+ agent = LLM::Agent.new(llm)
938
+ agent.repl(path: "session.json")
939
+ ```
940
+
918
941
  #### Tools
919
942
 
920
943
  The read-eval-print loop accepts a `tools` option that lets
@@ -952,6 +975,49 @@ agent = LLM::Agent.new(llm, tracer: LLM.logger(llm, path: "agent.log"))
952
975
  agent.repl(tracer: true, tools: [Debugger])
953
976
  ```
954
977
 
978
+ #### Input
979
+
980
+ The input area supports several keyboard shortcuts:
981
+
982
+ | Key | Action |
983
+ |---|---|
984
+ | `Enter` | Submit the current prompt |
985
+ | `Ctrl+A` | Jump to the start of the line |
986
+ | `Ctrl+E` | Jump to the end of the line |
987
+ | `Ctrl+F` | Move the cursor forward |
988
+ | `Ctrl+K` | Erase from cursor to the end of the line |
989
+ | `Ctrl+Y` | Paste previously killed text |
990
+ | `Ctrl+D` | Delete the character at the cursor |
991
+ | `Left / Right` | Move the cursor |
992
+ | `Up / Down` | Scroll the transcript |
993
+
994
+ When characters arrive faster than a threshold the REPL
995
+ detects that text is being pasted rather than typed. In
996
+ paste mode pressing `Enter` inserts a newline instead of
997
+ submitting, allowing multi-line prompts.
998
+
999
+ #### Commands
1000
+
1001
+ Commands are recognized by a `/` prefix on the input line.
1002
+ The built-in command is `/exit`, which leaves the REPL.
1003
+ The [`LLM::Repl::Command`](https://r.uby.dev/api-docs/llm.rb/LLM/Repl/Command.html)
1004
+ class can be subclassed to add custom commands &ndash;
1005
+ any subclass that defines a `name`, `description`, and
1006
+ `call` method is automatically registered and available.
1007
+
1008
+ ```ruby
1009
+ class LLM::Repl::Command
1010
+ class Clear < self
1011
+ name "clear"
1012
+ description "clears the transcript"
1013
+
1014
+ def call
1015
+ system("clear") || system("cls")
1016
+ end
1017
+ end
1018
+ end
1019
+ ```
1020
+
955
1021
  [Back to top](#table-of-contents)
956
1022
 
957
1023
  ## Images
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: llm.rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 12.3.0
4
+ version: 12.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - robert
@@ -468,6 +468,8 @@ files:
468
468
  - lib/llm/registry.rb
469
469
  - lib/llm/repl.rb
470
470
  - lib/llm/repl/bar.rb
471
+ - lib/llm/repl/command.rb
472
+ - lib/llm/repl/commands/exit.rb
471
473
  - lib/llm/repl/input.rb
472
474
  - lib/llm/repl/markdown.rb
473
475
  - lib/llm/repl/status.rb
@@ -505,12 +507,14 @@ files:
505
507
  - lib/llm/tools.rb
506
508
  - lib/llm/tools/chdir.rb
507
509
  - lib/llm/tools/git.rb
510
+ - lib/llm/tools/ls.rb
508
511
  - lib/llm/tools/mkdir.rb
509
512
  - lib/llm/tools/pwd.rb
510
513
  - lib/llm/tools/read_file.rb
511
514
  - lib/llm/tools/rg.rb
512
515
  - lib/llm/tools/shell.rb
513
516
  - lib/llm/tools/swap_text.rb
517
+ - lib/llm/tools/which.rb
514
518
  - lib/llm/tools/write_file.rb
515
519
  - lib/llm/tracer.rb
516
520
  - lib/llm/tracer/logger.rb