elelem 0.9.2 → 0.11.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 (43) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +8 -118
  3. data/Rakefile +0 -11
  4. data/exe/elelem +8 -79
  5. data/lib/elelem/agent.rb +51 -142
  6. data/lib/elelem/cli.rb +76 -0
  7. data/lib/elelem/commands.rb +49 -0
  8. data/lib/elelem/config.rb +17 -0
  9. data/lib/elelem/conversation.rb +25 -0
  10. data/lib/elelem/input.rb +53 -0
  11. data/lib/elelem/null_input.rb +8 -0
  12. data/lib/elelem/null_output.rb +7 -0
  13. data/lib/elelem/null_tool.rb +18 -0
  14. data/lib/elelem/output.rb +57 -0
  15. data/lib/elelem/plugins.rb +10 -21
  16. data/lib/elelem/prompts/default.erb +3 -0
  17. data/lib/elelem/registration.rb +37 -0
  18. data/lib/elelem/registry.rb +69 -0
  19. data/lib/elelem/result.rb +26 -0
  20. data/lib/elelem/slash_command.rb +18 -0
  21. data/lib/elelem/stub_provider.rb +15 -0
  22. data/lib/elelem/system_prompt.rb +4 -42
  23. data/lib/elelem/tool.rb +6 -14
  24. data/lib/elelem/toolbox.rb +23 -23
  25. data/lib/elelem/version.rb +2 -2
  26. data/lib/elelem.rb +29 -27
  27. metadata +49 -65
  28. data/CHANGELOG.md +0 -280
  29. data/lib/elelem/mcp.rb +0 -96
  30. data/lib/elelem/net/claude.rb +0 -200
  31. data/lib/elelem/net/ollama.rb +0 -78
  32. data/lib/elelem/net/openai.rb +0 -86
  33. data/lib/elelem/net.rb +0 -16
  34. data/lib/elelem/plugins/confirm.rb +0 -12
  35. data/lib/elelem/plugins/edit.rb +0 -15
  36. data/lib/elelem/plugins/eval.rb +0 -20
  37. data/lib/elelem/plugins/execute.rb +0 -18
  38. data/lib/elelem/plugins/mcp.rb +0 -14
  39. data/lib/elelem/plugins/read.rb +0 -21
  40. data/lib/elelem/plugins/verify.rb +0 -47
  41. data/lib/elelem/plugins/write.rb +0 -23
  42. data/lib/elelem/templates/system_prompt.erb +0 -53
  43. data/lib/elelem/terminal.rb +0 -97
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: elelem
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.2
4
+ version: 0.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - mo khan
@@ -10,173 +10,159 @@ cert_chain: []
10
10
  date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
- name: date
13
+ name: erb
14
14
  requirement: !ruby/object:Gem::Requirement
15
15
  requirements:
16
16
  - - "~>"
17
17
  - !ruby/object:Gem::Version
18
- version: '3.0'
18
+ version: '6.0'
19
19
  type: :runtime
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
23
  - - "~>"
24
24
  - !ruby/object:Gem::Version
25
- version: '3.0'
25
+ version: '6.0'
26
26
  - !ruby/object:Gem::Dependency
27
- name: erb
27
+ name: forwardable
28
28
  requirement: !ruby/object:Gem::Requirement
29
29
  requirements:
30
30
  - - "~>"
31
31
  - !ruby/object:Gem::Version
32
- version: '6.0'
32
+ version: '1.4'
33
33
  type: :runtime
34
34
  prerelease: false
35
35
  version_requirements: !ruby/object:Gem::Requirement
36
36
  requirements:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
- version: '6.0'
39
+ version: '1.4'
40
40
  - !ruby/object:Gem::Dependency
41
- name: fileutils
41
+ name: io-console
42
42
  requirement: !ruby/object:Gem::Requirement
43
43
  requirements:
44
44
  - - "~>"
45
45
  - !ruby/object:Gem::Version
46
- version: '1.0'
46
+ version: '0.9'
47
47
  type: :runtime
48
48
  prerelease: false
49
49
  version_requirements: !ruby/object:Gem::Requirement
50
50
  requirements:
51
51
  - - "~>"
52
52
  - !ruby/object:Gem::Version
53
- version: '1.0'
53
+ version: '0.9'
54
54
  - !ruby/object:Gem::Dependency
55
55
  name: json
56
56
  requirement: !ruby/object:Gem::Requirement
57
57
  requirements:
58
58
  - - "~>"
59
59
  - !ruby/object:Gem::Version
60
- version: '2.0'
60
+ version: '3.0'
61
61
  type: :runtime
62
62
  prerelease: false
63
63
  version_requirements: !ruby/object:Gem::Requirement
64
64
  requirements:
65
65
  - - "~>"
66
66
  - !ruby/object:Gem::Version
67
- version: '2.0'
67
+ version: '3.0'
68
68
  - !ruby/object:Gem::Dependency
69
69
  name: json_schemer
70
70
  requirement: !ruby/object:Gem::Requirement
71
71
  requirements:
72
72
  - - "~>"
73
73
  - !ruby/object:Gem::Version
74
- version: '2.0'
74
+ version: '2.5'
75
75
  type: :runtime
76
76
  prerelease: false
77
77
  version_requirements: !ruby/object:Gem::Requirement
78
78
  requirements:
79
79
  - - "~>"
80
80
  - !ruby/object:Gem::Version
81
- version: '2.0'
81
+ version: '2.5'
82
82
  - !ruby/object:Gem::Dependency
83
- name: net-hippie
83
+ name: logger
84
84
  requirement: !ruby/object:Gem::Requirement
85
85
  requirements:
86
86
  - - "~>"
87
87
  - !ruby/object:Gem::Version
88
- version: '1.0'
88
+ version: '1.7'
89
89
  type: :runtime
90
90
  prerelease: false
91
91
  version_requirements: !ruby/object:Gem::Requirement
92
92
  requirements:
93
93
  - - "~>"
94
94
  - !ruby/object:Gem::Version
95
- version: '1.0'
95
+ version: '1.7'
96
96
  - !ruby/object:Gem::Dependency
97
97
  name: open3
98
98
  requirement: !ruby/object:Gem::Requirement
99
99
  requirements:
100
100
  - - "~>"
101
101
  - !ruby/object:Gem::Version
102
- version: '0.1'
102
+ version: '0.2'
103
103
  type: :runtime
104
104
  prerelease: false
105
105
  version_requirements: !ruby/object:Gem::Requirement
106
106
  requirements:
107
107
  - - "~>"
108
108
  - !ruby/object:Gem::Version
109
- version: '0.1'
109
+ version: '0.2'
110
110
  - !ruby/object:Gem::Dependency
111
111
  name: optparse
112
112
  requirement: !ruby/object:Gem::Requirement
113
113
  requirements:
114
114
  - - "~>"
115
115
  - !ruby/object:Gem::Version
116
- version: '0.1'
116
+ version: '0.8'
117
117
  type: :runtime
118
118
  prerelease: false
119
119
  version_requirements: !ruby/object:Gem::Requirement
120
120
  requirements:
121
121
  - - "~>"
122
122
  - !ruby/object:Gem::Version
123
- version: '0.1'
123
+ version: '0.8'
124
124
  - !ruby/object:Gem::Dependency
125
125
  name: pathname
126
126
  requirement: !ruby/object:Gem::Requirement
127
127
  requirements:
128
128
  - - "~>"
129
129
  - !ruby/object:Gem::Version
130
- version: '0.1'
130
+ version: '0.5'
131
131
  type: :runtime
132
132
  prerelease: false
133
133
  version_requirements: !ruby/object:Gem::Requirement
134
134
  requirements:
135
135
  - - "~>"
136
136
  - !ruby/object:Gem::Version
137
- version: '0.1'
137
+ version: '0.5'
138
138
  - !ruby/object:Gem::Dependency
139
139
  name: reline
140
140
  requirement: !ruby/object:Gem::Requirement
141
141
  requirements:
142
142
  - - "~>"
143
143
  - !ruby/object:Gem::Version
144
- version: '0.6'
144
+ version: '0.7'
145
145
  type: :runtime
146
146
  prerelease: false
147
147
  version_requirements: !ruby/object:Gem::Requirement
148
148
  requirements:
149
149
  - - "~>"
150
150
  - !ruby/object:Gem::Version
151
- version: '0.6'
152
- - !ruby/object:Gem::Dependency
153
- name: stringio
154
- requirement: !ruby/object:Gem::Requirement
155
- requirements:
156
- - - "~>"
157
- - !ruby/object:Gem::Version
158
- version: '3.0'
159
- type: :runtime
160
- prerelease: false
161
- version_requirements: !ruby/object:Gem::Requirement
162
- requirements:
163
- - - "~>"
164
- - !ruby/object:Gem::Version
165
- version: '3.0'
151
+ version: '0.7'
166
152
  - !ruby/object:Gem::Dependency
167
- name: tempfile
153
+ name: shellwords
168
154
  requirement: !ruby/object:Gem::Requirement
169
155
  requirements:
170
156
  - - "~>"
171
157
  - !ruby/object:Gem::Version
172
- version: '0.3'
158
+ version: '0.2'
173
159
  type: :runtime
174
160
  prerelease: false
175
161
  version_requirements: !ruby/object:Gem::Requirement
176
162
  requirements:
177
163
  - - "~>"
178
164
  - !ruby/object:Gem::Version
179
- version: '0.3'
165
+ version: '0.2'
180
166
  - !ruby/object:Gem::Dependency
181
167
  name: uri
182
168
  requirement: !ruby/object:Gem::Requirement
@@ -191,7 +177,7 @@ dependencies:
191
177
  - - "~>"
192
178
  - !ruby/object:Gem::Version
193
179
  version: '1.0'
194
- description: A minimal coding agent supporting Ollama, Anthropic, OpenAI, and VertexAI.
180
+ description: A minimal coding harness.
195
181
  email:
196
182
  - mo@mokhan.ca
197
183
  executables:
@@ -199,41 +185,39 @@ executables:
199
185
  extensions: []
200
186
  extra_rdoc_files: []
201
187
  files:
202
- - CHANGELOG.md
203
188
  - LICENSE.txt
204
189
  - README.md
205
190
  - Rakefile
206
191
  - exe/elelem
207
192
  - lib/elelem.rb
208
193
  - lib/elelem/agent.rb
209
- - lib/elelem/mcp.rb
210
- - lib/elelem/net.rb
211
- - lib/elelem/net/claude.rb
212
- - lib/elelem/net/ollama.rb
213
- - lib/elelem/net/openai.rb
194
+ - lib/elelem/cli.rb
195
+ - lib/elelem/commands.rb
196
+ - lib/elelem/config.rb
197
+ - lib/elelem/conversation.rb
198
+ - lib/elelem/input.rb
199
+ - lib/elelem/null_input.rb
200
+ - lib/elelem/null_output.rb
201
+ - lib/elelem/null_tool.rb
202
+ - lib/elelem/output.rb
214
203
  - lib/elelem/plugins.rb
215
- - lib/elelem/plugins/confirm.rb
216
- - lib/elelem/plugins/edit.rb
217
- - lib/elelem/plugins/eval.rb
218
- - lib/elelem/plugins/execute.rb
219
- - lib/elelem/plugins/mcp.rb
220
- - lib/elelem/plugins/read.rb
221
- - lib/elelem/plugins/verify.rb
222
- - lib/elelem/plugins/write.rb
204
+ - lib/elelem/prompts/default.erb
205
+ - lib/elelem/registration.rb
206
+ - lib/elelem/registry.rb
207
+ - lib/elelem/result.rb
208
+ - lib/elelem/slash_command.rb
209
+ - lib/elelem/stub_provider.rb
223
210
  - lib/elelem/system_prompt.rb
224
- - lib/elelem/templates/system_prompt.erb
225
- - lib/elelem/terminal.rb
226
211
  - lib/elelem/tool.rb
227
212
  - lib/elelem/toolbox.rb
228
213
  - lib/elelem/version.rb
229
- homepage: https://src.mokhan.ca/xlgmokha/elelem
214
+ homepage: https://src.mokhan.ca/elelem/elelem
230
215
  licenses:
231
216
  - MIT
232
217
  metadata:
233
218
  allowed_push_host: https://rubygems.org
234
- homepage_uri: https://src.mokhan.ca/xlgmokha/elelem
235
- source_code_uri: https://src.mokhan.ca/xlgmokha/elelem
236
- changelog_uri: https://src.mokhan.ca/xlgmokha/elelem/blob/main/CHANGELOG.md.html
219
+ homepage_uri: https://src.mokhan.ca/elelem/elelem
220
+ source_code_uri: https://src.mokhan.ca/elelem/elelem
237
221
  rdoc_options: []
238
222
  require_paths:
239
223
  - lib
@@ -248,7 +232,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
248
232
  - !ruby/object:Gem::Version
249
233
  version: 4.0.0
250
234
  requirements: []
251
- rubygems_version: 4.0.4
235
+ rubygems_version: 4.0.20
252
236
  specification_version: 4
253
- summary: A minimal coding agent for LLMs.
237
+ summary: A minimal coding harness for LLMs.
254
238
  test_files: []
data/CHANGELOG.md DELETED
@@ -1,280 +0,0 @@
1
- ## [0.9.2] - 2026-01-22
2
-
3
- ### Fixed
4
- - Suppress pathname gem constant redefinition warnings on Ruby 4.0
5
-
6
- ## [0.9.1] - 2026-01-22
7
-
8
- ### Fixed
9
- - Use `next` instead of `return` to exit block in execute plugin after-hook
10
- - Use `break` instead of `return` to exit `inject` block in verify plugin
11
-
12
- ## [0.9.0] - 2026-01-21
13
-
14
- ### Added
15
- - **Plugin system** with support for custom tool definitions
16
- - Load plugins from `lib/elelem/plugins/`, `~/.elelem/plugins/`, and `.elelem/plugins/`
17
- - `Elelem::Plugins.register(name) { |toolbox| ... }` API
18
- - Built-in plugins: `read`, `write`, `edit`, `execute`, `eval`, `verify`, `confirm`, `mcp`
19
- - **MCP (Model Context Protocol)** server support via `.mcp.json` configuration
20
- - **AGENTS.md** file support - searches up directory tree for project instructions
21
- - **`/init` command** to generate an AGENTS.md file for the current project
22
- - **`/shell` command** to drop into a shell session and capture the transcript to context
23
- - **`/reload` command** to hot-reload source code without restarting the process
24
- - **`task` tool** for delegating subtasks to focused sub-agents
25
- - **`edit` tool** for replacing first occurrence of text in a file
26
- - **`eval` tool** for executing Ruby code and dynamically registering new tools
27
- - **`verify` tool** for syntax checking and running project tests
28
- - **Pre/post tool hooks** (`toolbox.before`/`toolbox.after`) for extensibility
29
- - **Confirmation prompt** before executing shell commands (when TTY)
30
- - **Context compaction** for long conversations (summarizes old messages)
31
- - **Repo map** via ctags included in system prompt
32
- - **Markdown rendering** with [glow](https://github.com/charmbracelet/glow) for LLM responses
33
- - **CLI improvements**: optparse-based interface with `-p`/`-m` flags
34
- - `elelem chat` - Interactive REPL (default)
35
- - `elelem ask <prompt>` - One-shot query (reads stdin if piped)
36
- - `elelem files` - Output files as XML
37
- - JSON Schema validation for tool call arguments (via `json_schemer`)
38
- - Tool aliases support (e.g., `bash`, `sh`, `exec` → `execute`)
39
- - **Dependencies documentation** in README with installation links
40
-
41
- ### Changed
42
- - **Breaking**: Requires Ruby >= 4.0.0 (was 3.4.0)
43
- - **Breaking**: Removed `net-llm` dependency - LLM clients now inline in `lib/elelem/net/`
44
- - `Elelem::Net::Claude` (Anthropic and Vertex AI)
45
- - `Elelem::Net::OpenAI`
46
- - `Elelem::Net::Ollama`
47
- - **Breaking**: Simplified LLM client `fetch` contract
48
- - Yields `{content:, thinking:}` deltas
49
- - Returns `tool_calls` array directly
50
- - **Breaking**: Tool schema uses OpenAI format (`{type: "function", function: {...}}`)
51
- - **Breaking**: Tool definitions use `description:` key (was `desc:`)
52
- - **Breaking**: Removed modes and permissions system entirely
53
- - **Breaking**: Removed slash commands (`/mode`, `/env`, `/provider`, `/model`)
54
- - Remaining: `/clear`, `/context`, `/init`, `/reload`, `/shell`, `/exit`, `/help`
55
- - **Breaking**: Removed many dependencies
56
- - Removed: `thor`, `cli-ui`, `erb`, `cgi`, `set`, `timeout`, `logger`, `net-llm`, `json-schema`
57
- - Added: `json_schemer`, `optparse`, `tempfile`, `stringio`, `uri`
58
- - Consolidated multiple exe files into single `exe/elelem` entry point
59
- - Tools are now defined via plugins instead of hardcoded in Toolbox
60
- - System prompt includes hints for `rg`, `fd`, `sg` (ast-grep), `sed`, `patch`
61
- - System prompt regenerated on each fetch (includes dynamic repo map)
62
- - Default tool set: `read`, `write`, `edit`, `execute`, `eval`, `verify`, `task`
63
- - System prompt encourages using `eval` to create tools for repetitive tasks
64
-
65
- ### Removed
66
- - `lib/elelem/application.rb` - CLI now in `exe/elelem`
67
- - `lib/elelem/conversation.rb` - simplified into Agent
68
- - `lib/elelem/git_context.rb` - inlined into Agent
69
- - `lib/elelem/system_prompt.erb` - now generated in Agent
70
- - `web_fetch`, `web_search`, `fetch`, `search_engine` tools
71
- - `patch` tool (use `edit` or `execute` with `sed`/`patch`)
72
- - `grep`, `list` tools (use `execute` with `rg`, `fd`)
73
- - Modes and permissions system
74
- - Events module
75
- - GitHub Actions CI workflow
76
-
77
- ### Fixed
78
- - Handle missing args in Claude provider
79
- - Tool alias resolution (use canonical tool name, not alias)
80
- - Unknown tool error now suggests using `execute` and lists available tools
81
- - Duplicate write operations in edit flow
82
-
83
- ## [0.8.0] - 2026-01-14
84
-
85
- ### Added
86
- - `fetch` tool for HTTP GET requests (returns status and body)
87
- - `search_engine` tool for DuckDuckGo Instant Answer API searches
88
- - Tool aliases: `get`/`web` → `fetch`, `ddg`/`duckduckgo` → `search_engine`
89
- - `net-hippie` and `cgi` dependencies for HTTP requests
90
-
91
- ## [0.7.0] - 2026-01-14
92
-
93
- ### Added
94
- - ASCII spinner animation while waiting for LLM responses
95
- - `Terminal#waiting` method with automatic cleanup on next output
96
- - Decision-making principles in system prompt (prefer reversible actions, ask when uncertain)
97
- - Mode enforcement tests
98
-
99
- ### Changed
100
- - Renamed internal `mode` concept to `permissions` for clarity (read/write/execute are permissions, plan/build/verify are modes)
101
- - Refactored `Toolbox#run_tool` to accept `permissions:` parameter
102
-
103
- ### Fixed
104
- - **Security**: Mode restrictions now enforced at execution time, not just schema time
105
- - Previously, LLMs could call tools outside their mode by guessing tool names
106
- - Now `run_tool` validates the tool is allowed for the current permission set
107
-
108
- ## [0.6.0] - 2026-01-12
109
-
110
- ### Added
111
- - `/env` slash command to capture environment variables for provider connections
112
- - `/shell` slash command
113
- - `/provider` and `/model` slash commands
114
- - Tab completion for commands
115
- - Help output for `/mode` and `/env` commands
116
-
117
- ### Changed
118
- - Renamed `bash` tool to `exec`
119
- - Tuned system prompt
120
- - Changed thinking prompt to ellipsis
121
- - Removed username from system prompt
122
- - Use pessimistic constraint on net-llm dependency
123
- - Extracted Terminal class for IO abstraction (enables E2E testing)
124
-
125
- ### Fixed
126
- - Prevent infinite looping errors
127
- - Provide function schema when tool is called with invalid arguments
128
- - Tab completion for `pass` entries without requiring `show` subcommand
129
- - Password store symlink support in tab completion
130
-
131
- ## [0.5.0] - 2026-01-07
132
-
133
- ### Added
134
- - Multi-provider support: Ollama, Anthropic, OpenAI, and VertexAI
135
- - `--provider` CLI option to select LLM provider (default: ollama)
136
- - `--model` CLI option to override default model
137
- - Tool aliases (`bash` also accepts `exec`, `shell`, `command`, `terminal`, `run`)
138
- - Thinking text output for models that support extended thinking
139
-
140
- ### Changed
141
- - Requires net-llm >= 0.5.0 with unified fetch interface
142
- - Updated gem description to reflect multi-provider support
143
-
144
- ## [0.4.2] - 2025-12-01
145
-
146
- ### Changed
147
- - Renamed `exec` tool to `bash` for clarity
148
- - Improved system prompt with iterative refinements
149
- - Added environment context variables to system prompt
150
-
151
- ## [0.4.1] - 2025-11-26
152
-
153
- ### Added
154
- - `elelem files` subcommand: generates Claude‑compatible XML file listings.
155
- - Rake task `files:prompt` to output a ready‑to‑copy list of files for prompts.
156
-
157
- ### Changed
158
- - Refactor tool‑call formatting to a more compact JSON payload for better LLM parsing.
159
- - Updated CI and documentation to use GitHub instead of previous hosting.
160
- - Runtime validation of command‑line parameters against a JSON schema.
161
-
162
- ### Fixed
163
- - Minor documentation and CI workflow adjustments.
164
-
165
- ## [0.4.0] - 2025-11-10
166
-
167
- ### Added
168
- - **Eval Tool**: Meta-programming tool that allows the LLM to dynamically create and register new tools at runtime
169
- - Eval tool has access to the toolbox for enhanced capabilities
170
- - Comprehensive test coverage with RSpec
171
- - Agent specs
172
- - Conversation specs
173
- - Toolbox specs
174
-
175
- ### Changed
176
- - **Architecture Improvements**: Significant refactoring for better separation of concerns
177
- - Extracted Tool class to separate file (`lib/elelem/tool.rb`)
178
- - Extracted Toolbox class to separate file (`lib/elelem/toolbox.rb`)
179
- - Extracted Shell class for command execution
180
- - Improved tool registration through `#add_tool` method
181
- - Tool constants moved to Toolbox for better organization
182
- - Agent class simplified by delegating to Tool instances
183
-
184
- ### Fixed
185
- - `/context` command now correctly accounts for the current mode
186
-
187
- ## [0.3.0] - 2025-11-05
188
-
189
- ### Added
190
- - **Mode System**: Control agent capabilities with workflow modes
191
- - `/mode plan` - Read-only mode (grep, list, read)
192
- - `/mode build` - Read + Write mode (grep, list, read, patch, write)
193
- - `/mode verify` - Read + Execute mode (grep, list, read, execute)
194
- - `/mode auto` - All tools enabled
195
- - Each mode adapts system prompt to guide appropriate behavior
196
- - Improved output formatting
197
- - Suppressed verbose thinking/reasoning output
198
- - Clean tool call display (e.g., `date` instead of full JSON hash)
199
- - Mode switch confirmation messages
200
- - Clear command feedback
201
- - Design philosophy documentation in README
202
- - Mode system documentation
203
-
204
- ### Changed
205
- - **BREAKING**: Removed `llm-ollama` and `llm-openai` standalone executables (use main `elelem chat` command)
206
- - **BREAKING**: Simplified architecture - consolidated all logic into Agent class
207
- - Removed Configuration class
208
- - Removed Toolbox system
209
- - Removed MCP client infrastructure
210
- - Removed Tool and Tools classes
211
- - Removed TUI abstraction layer (direct puts/Reline usage)
212
- - Removed API wrapper class
213
- - Removed state machine
214
- - Improved execute tool description to guide LLM toward direct command execution
215
- - Extracted tool definitions from long inline strings to readable private methods
216
- - Updated README with clear philosophy and usage examples
217
- - Reduced total codebase from 417 to 395 lines (-5%)
218
-
219
- ### Fixed
220
- - Working directory handling for execute tool (handles empty string cwd)
221
- - REPL EOF handling (graceful exit when input stream ends)
222
- - Tool call formatting now shows clean, readable commands
223
-
224
- ### Removed
225
- - `exe/llm-ollama` (359 lines)
226
- - `exe/llm-openai` (340 lines)
227
- - `lib/elelem/configuration.rb`
228
- - `lib/elelem/toolbox.rb` and toolbox/* files
229
- - `lib/elelem/mcp_client.rb`
230
- - `lib/elelem/tool.rb` and `lib/elelem/tools.rb`
231
- - `lib/elelem/tui.rb`
232
- - `lib/elelem/api.rb`
233
- - `lib/elelem/states/*` (state machine infrastructure)
234
- - Removed ~750 lines of unused/redundant code
235
-
236
- ## [0.2.1] - 2025-10-15
237
-
238
- ### Fixed
239
- - Added missing `exe/llm-ollama` and `exe/llm-openai` files to gemspec
240
- - These executables were added in 0.2.0 but not included in the packaged gem
241
-
242
- ## [0.2.0] - 2025-10-15
243
-
244
- ### Added
245
- - New `llm-ollama` executable - minimal coding agent with streaming support for Ollama
246
- - New `llm-openai` executable - minimal coding agent for OpenAI/compatible APIs
247
- - Memory feature for persistent context storage and retrieval
248
- - Web fetch tool for retrieving and analyzing web content
249
- - Streaming responses with real-time token display
250
- - Visual "thinking" progress indicators with dots during reasoning phase
251
-
252
- ### Changed
253
- - **BREAKING**: Migrated from custom Net::HTTP implementation to `net-llm` gem
254
- - API client now uses `Net::Llm::Ollama` for better reliability and maintainability
255
- - Removed direct dependencies on `net-http` and `uri` (now transitive through net-llm)
256
- - Maps Ollama's `thinking` field to internal `reasoning` field
257
- - Maps Ollama's `done_reason` to internal `finish_reason`
258
- - Improved system prompt for better agent behavior
259
- - Enhanced error handling and logging
260
-
261
- ### Fixed
262
- - Response processing for Ollama's native message format
263
- - Tool argument parsing to handle both string and object formats
264
- - Safe navigation operator usage to prevent nil errors
265
-
266
- ## [0.1.2] - 2025-08-14
267
-
268
- ### Fixed
269
- - Fixed critical bug where bash tool had nested parameters schema causing tool calls to fail with "no implicit conversion of nil into String" error
270
-
271
- ## [0.1.1] - 2025-08-12
272
-
273
- ### Fixed
274
- - Fixed infinite loop bug after tool execution - loop now continues until assistant provides final response
275
- - Fixed conversation history accumulating streaming chunks as separate entries - now properly combines same-role consecutive messages
276
- - Improved state machine logging with better debug output
277
-
278
- ## [0.1.0] - 2025-08-08
279
-
280
- - Initial release
data/lib/elelem/mcp.rb DELETED
@@ -1,96 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Elelem
4
- class MCP
5
- def initialize(config_path = ".mcp.json")
6
- @config = File.exist?(config_path) ? JSON.parse(IO.read(config_path)) : {}
7
- @servers = {}
8
- end
9
-
10
- def tools
11
- @config.fetch("mcpServers", {}).flat_map do |name, _|
12
- server(name).tools.map do |tool|
13
- [
14
- "#{name}_#{tool["name"]}",
15
- {
16
- description: tool["description"],
17
- params: tool.dig("inputSchema", "properties") || {},
18
- required: tool.dig("inputSchema", "required") || [],
19
- fn: ->(a) { server(name).call(tool["name"], a) }
20
- }
21
- ]
22
- end
23
- end.to_h
24
- end
25
-
26
- def close
27
- @servers.each_value(&:close)
28
- end
29
-
30
- private
31
-
32
- def server(name)
33
- @servers[name] ||= Server.new(**@config.dig("mcpServers", name).transform_keys(&:to_sym))
34
- end
35
-
36
- class Server
37
- def initialize(command:, args: [], env: {})
38
- resolved_env = env.transform_values { |v| v.gsub(/\$\{(\w+)\}/) { ENV[$1] } }
39
- @stdin, @stdout, @stderr, @wait = Open3.popen3(resolved_env, command, *args)
40
- @id = 0
41
- initialize!
42
- end
43
-
44
- def tools
45
- request("tools/list")["tools"]
46
- end
47
-
48
- def call(name, args)
49
- result = request("tools/call", { name: name, arguments: args })
50
- { content: result["content"]&.map { |c| c["text"] }&.join("\n") }
51
- end
52
-
53
- def close
54
- @stdin.close rescue nil
55
- @stdout.close rescue nil
56
- @stderr.close rescue nil
57
- @wait.kill rescue nil
58
- end
59
-
60
- private
61
-
62
- def initialize!
63
- request("initialize", {
64
- protocolVersion: "2024-11-05",
65
- capabilities: {},
66
- clientInfo: { name: "elelem", version: VERSION }
67
- })
68
- notify("notifications/initialized")
69
- end
70
-
71
- def request(method, params = {})
72
- send_msg(id: @id += 1, method: method, params: params)
73
- read_response(@id)
74
- end
75
-
76
- def notify(method, params = {})
77
- send_msg(method: method, params: params)
78
- end
79
-
80
- def send_msg(msg)
81
- @stdin.puts({ jsonrpc: "2.0", **msg }.to_json)
82
- @stdin.flush
83
- end
84
-
85
- def read_response(id)
86
- loop do
87
- line = @stdout.gets
88
- raise "Server closed" unless line
89
- msg = JSON.parse(line)
90
- return msg["result"] if msg["id"] == id
91
- raise msg["error"]["message"] if msg["error"]
92
- end
93
- end
94
- end
95
- end
96
- end