elelem 0.8.0 → 0.9.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +71 -3
- data/README.md +31 -46
- data/exe/elelem +78 -3
- data/lib/elelem/agent.rb +135 -228
- data/lib/elelem/mcp.rb +96 -0
- data/lib/elelem/net/claude.rb +200 -0
- data/lib/elelem/net/ollama.rb +78 -0
- data/lib/elelem/net/openai.rb +86 -0
- data/lib/elelem/net.rb +16 -0
- data/lib/elelem/plugins/confirm.rb +12 -0
- data/lib/elelem/plugins/edit.rb +15 -0
- data/lib/elelem/plugins/eval.rb +20 -0
- data/lib/elelem/plugins/execute.rb +18 -0
- data/lib/elelem/plugins/mcp.rb +14 -0
- data/lib/elelem/plugins/read.rb +21 -0
- data/lib/elelem/plugins/verify.rb +47 -0
- data/lib/elelem/plugins/write.rb +23 -0
- data/lib/elelem/plugins.rb +43 -0
- data/lib/elelem/system_prompt.rb +65 -0
- data/lib/elelem/templates/system_prompt.erb +53 -0
- data/lib/elelem/terminal.rb +55 -65
- data/lib/elelem/tool.rb +30 -32
- data/lib/elelem/toolbox.rb +36 -94
- data/lib/elelem/version.rb +1 -1
- data/lib/elelem.rb +28 -36
- metadata +39 -61
- data/lib/elelem/application.rb +0 -45
- data/lib/elelem/conversation.rb +0 -78
- data/lib/elelem/git_context.rb +0 -79
- data/lib/elelem/system_prompt.erb +0 -16
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c88aa14330442939c8d62db38adcb229c860059888567b21fb309b760da18b7e
|
|
4
|
+
data.tar.gz: 7829340c692a3b025d95f47be9908c8d5ca0ab7988454b29e73af783d0e7d3ab
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a3254b0655057dbaf8871ef6e6782bb962b588525a69a6d9f0746368f4c38d92c3ad41790104bb2cedfb25c16df2d77d07f236cfdde23805bee3be21d515cf99
|
|
7
|
+
data.tar.gz: f6d43cbe0659d37b6c6249bad2dc5c3dd04b6e4e2bb0a2a7201b4a479a9c1c52cc8e0516ffeb6b050098537e5c10b4d7887c80c8870ac01334599ab49100dc06
|
data/CHANGELOG.md
CHANGED
|
@@ -1,4 +1,73 @@
|
|
|
1
|
-
## [
|
|
1
|
+
## [0.9.0] - 2026-01-21
|
|
2
|
+
|
|
3
|
+
### Added
|
|
4
|
+
- **Plugin system** with support for custom tool definitions
|
|
5
|
+
- Load plugins from `lib/elelem/plugins/`, `~/.elelem/plugins/`, and `.elelem/plugins/`
|
|
6
|
+
- `Elelem::Plugins.register(name) { |toolbox| ... }` API
|
|
7
|
+
- Built-in plugins: `read`, `write`, `edit`, `execute`, `eval`, `verify`, `confirm`, `mcp`
|
|
8
|
+
- **MCP (Model Context Protocol)** server support via `.mcp.json` configuration
|
|
9
|
+
- **AGENTS.md** file support - searches up directory tree for project instructions
|
|
10
|
+
- **`/init` command** to generate an AGENTS.md file for the current project
|
|
11
|
+
- **`/shell` command** to drop into a shell session and capture the transcript to context
|
|
12
|
+
- **`/reload` command** to hot-reload source code without restarting the process
|
|
13
|
+
- **`task` tool** for delegating subtasks to focused sub-agents
|
|
14
|
+
- **`edit` tool** for replacing first occurrence of text in a file
|
|
15
|
+
- **`eval` tool** for executing Ruby code and dynamically registering new tools
|
|
16
|
+
- **`verify` tool** for syntax checking and running project tests
|
|
17
|
+
- **Pre/post tool hooks** (`toolbox.before`/`toolbox.after`) for extensibility
|
|
18
|
+
- **Confirmation prompt** before executing shell commands (when TTY)
|
|
19
|
+
- **Context compaction** for long conversations (summarizes old messages)
|
|
20
|
+
- **Repo map** via ctags included in system prompt
|
|
21
|
+
- **Markdown rendering** with [glow](https://github.com/charmbracelet/glow) for LLM responses
|
|
22
|
+
- **CLI improvements**: optparse-based interface with `-p`/`-m` flags
|
|
23
|
+
- `elelem chat` - Interactive REPL (default)
|
|
24
|
+
- `elelem ask <prompt>` - One-shot query (reads stdin if piped)
|
|
25
|
+
- `elelem files` - Output files as XML
|
|
26
|
+
- JSON Schema validation for tool call arguments (via `json_schemer`)
|
|
27
|
+
- Tool aliases support (e.g., `bash`, `sh`, `exec` → `execute`)
|
|
28
|
+
- **Dependencies documentation** in README with installation links
|
|
29
|
+
|
|
30
|
+
### Changed
|
|
31
|
+
- **Breaking**: Requires Ruby >= 4.0.0 (was 3.4.0)
|
|
32
|
+
- **Breaking**: Removed `net-llm` dependency - LLM clients now inline in `lib/elelem/net/`
|
|
33
|
+
- `Elelem::Net::Claude` (Anthropic and Vertex AI)
|
|
34
|
+
- `Elelem::Net::OpenAI`
|
|
35
|
+
- `Elelem::Net::Ollama`
|
|
36
|
+
- **Breaking**: Simplified LLM client `fetch` contract
|
|
37
|
+
- Yields `{content:, thinking:}` deltas
|
|
38
|
+
- Returns `tool_calls` array directly
|
|
39
|
+
- **Breaking**: Tool schema uses OpenAI format (`{type: "function", function: {...}}`)
|
|
40
|
+
- **Breaking**: Tool definitions use `description:` key (was `desc:`)
|
|
41
|
+
- **Breaking**: Removed modes and permissions system entirely
|
|
42
|
+
- **Breaking**: Removed slash commands (`/mode`, `/env`, `/provider`, `/model`)
|
|
43
|
+
- Remaining: `/clear`, `/context`, `/init`, `/reload`, `/shell`, `/exit`, `/help`
|
|
44
|
+
- **Breaking**: Removed many dependencies
|
|
45
|
+
- Removed: `thor`, `cli-ui`, `erb`, `cgi`, `set`, `timeout`, `logger`, `net-llm`, `json-schema`
|
|
46
|
+
- Added: `json_schemer`, `optparse`, `tempfile`, `stringio`, `uri`
|
|
47
|
+
- Consolidated multiple exe files into single `exe/elelem` entry point
|
|
48
|
+
- Tools are now defined via plugins instead of hardcoded in Toolbox
|
|
49
|
+
- System prompt includes hints for `rg`, `fd`, `sg` (ast-grep), `sed`, `patch`
|
|
50
|
+
- System prompt regenerated on each fetch (includes dynamic repo map)
|
|
51
|
+
- Default tool set: `read`, `write`, `edit`, `execute`, `eval`, `verify`, `task`
|
|
52
|
+
- System prompt encourages using `eval` to create tools for repetitive tasks
|
|
53
|
+
|
|
54
|
+
### Removed
|
|
55
|
+
- `lib/elelem/application.rb` - CLI now in `exe/elelem`
|
|
56
|
+
- `lib/elelem/conversation.rb` - simplified into Agent
|
|
57
|
+
- `lib/elelem/git_context.rb` - inlined into Agent
|
|
58
|
+
- `lib/elelem/system_prompt.erb` - now generated in Agent
|
|
59
|
+
- `web_fetch`, `web_search`, `fetch`, `search_engine` tools
|
|
60
|
+
- `patch` tool (use `edit` or `execute` with `sed`/`patch`)
|
|
61
|
+
- `grep`, `list` tools (use `execute` with `rg`, `fd`)
|
|
62
|
+
- Modes and permissions system
|
|
63
|
+
- Events module
|
|
64
|
+
- GitHub Actions CI workflow
|
|
65
|
+
|
|
66
|
+
### Fixed
|
|
67
|
+
- Handle missing args in Claude provider
|
|
68
|
+
- Tool alias resolution (use canonical tool name, not alias)
|
|
69
|
+
- Unknown tool error now suggests using `execute` and lists available tools
|
|
70
|
+
- Duplicate write operations in edit flow
|
|
2
71
|
|
|
3
72
|
## [0.8.0] - 2026-01-14
|
|
4
73
|
|
|
@@ -48,7 +117,7 @@
|
|
|
48
117
|
- Tab completion for `pass` entries without requiring `show` subcommand
|
|
49
118
|
- Password store symlink support in tab completion
|
|
50
119
|
|
|
51
|
-
## [0.5.0] -
|
|
120
|
+
## [0.5.0] - 2026-01-07
|
|
52
121
|
|
|
53
122
|
### Added
|
|
54
123
|
- Multi-provider support: Ollama, Anthropic, OpenAI, and VertexAI
|
|
@@ -198,4 +267,3 @@
|
|
|
198
267
|
## [0.1.0] - 2025-08-08
|
|
199
268
|
|
|
200
269
|
- Initial release
|
|
201
|
-
|
data/README.md
CHANGED
|
@@ -7,8 +7,7 @@ Fast, correct, autonomous – pick two.
|
|
|
7
7
|
Elelem is a minimal coding agent written in Ruby. It is designed to help
|
|
8
8
|
you write, edit, and manage code and plain-text files from the command line
|
|
9
9
|
by delegating work to an LLM. The agent exposes a simple text-based UI and a
|
|
10
|
-
set of built-in tools that give the LLM access to the local file system
|
|
11
|
-
and Git.
|
|
10
|
+
set of built-in tools that give the LLM access to the local file system.
|
|
12
11
|
|
|
13
12
|
## Design Principles
|
|
14
13
|
|
|
@@ -26,6 +25,26 @@ and Git.
|
|
|
26
25
|
* Runs inside a Git repository.
|
|
27
26
|
* Git is available and functional.
|
|
28
27
|
|
|
28
|
+
## Dependencies
|
|
29
|
+
|
|
30
|
+
Elelem relies on several external tools. Install the ones you need:
|
|
31
|
+
|
|
32
|
+
| Tool | Purpose | Install |
|
|
33
|
+
|------|---------|---------|
|
|
34
|
+
| [Ollama](https://ollama.ai/) | Default LLM provider | https://ollama.ai/download |
|
|
35
|
+
| [glow](https://github.com/charmbracelet/glow) | Markdown rendering | `brew install glow` / `go install github.com/charmbracelet/glow@latest` |
|
|
36
|
+
| [ctags](https://ctags.io/) | Repo map generation | `brew install universal-ctags` / `apt install universal-ctags` |
|
|
37
|
+
| [ripgrep](https://github.com/BurntSushi/ripgrep) | Text search (`rg`) | `brew install ripgrep` / `apt install ripgrep` |
|
|
38
|
+
| [fd](https://github.com/sharkdp/fd) | File discovery | `brew install fd` / `apt install fd-find` |
|
|
39
|
+
| [ast-grep](https://ast-grep.github.io/) | Structural search (`sg`) | `brew install ast-grep` / `cargo install ast-grep` |
|
|
40
|
+
| [Git](https://git-scm.com/) | Version control | `brew install git` / `apt install git` |
|
|
41
|
+
|
|
42
|
+
**Required:** Git, Ollama (or another LLM provider)
|
|
43
|
+
|
|
44
|
+
**Recommended:** glow, ctags, ripgrep, fd
|
|
45
|
+
|
|
46
|
+
**Optional:** ast-grep (for structural code search)
|
|
47
|
+
|
|
29
48
|
## Scope
|
|
30
49
|
|
|
31
50
|
Only plain-text and source-code files are supported. No binary handling,
|
|
@@ -101,35 +120,10 @@ Each provider reads its configuration from environment variables:
|
|
|
101
120
|
| openai | `OPENAI_API_KEY`, `OPENAI_BASE_URL` |
|
|
102
121
|
| vertex-ai | `GOOGLE_CLOUD_PROJECT`, `GOOGLE_CLOUD_REGION` |
|
|
103
122
|
|
|
104
|
-
## Mode System
|
|
105
|
-
|
|
106
|
-
The agent exposes seven built‑in tools. You can switch which ones are
|
|
107
|
-
available by changing the *mode*:
|
|
108
|
-
|
|
109
|
-
| Mode | Enabled Tools |
|
|
110
|
-
|---------|------------------------------------------|
|
|
111
|
-
| plan | `grep`, `list`, `read` |
|
|
112
|
-
| build | `grep`, `list`, `read`, `patch`, `write` |
|
|
113
|
-
| verify | `grep`, `list`, `read`, `execute` |
|
|
114
|
-
| auto | All tools |
|
|
115
|
-
|
|
116
|
-
Use the following commands inside the REPL:
|
|
117
|
-
|
|
118
|
-
```text
|
|
119
|
-
/mode plan # Read‑only
|
|
120
|
-
/mode build # Read + Write
|
|
121
|
-
/mode verify # Read + Execute
|
|
122
|
-
/mode auto # All tools
|
|
123
|
-
/mode # Show current mode
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
The system prompt is adjusted per mode so the LLM knows which actions
|
|
127
|
-
are permissible.
|
|
128
|
-
|
|
129
123
|
## Features
|
|
130
124
|
|
|
131
125
|
* **Interactive REPL** – clean, streaming chat.
|
|
132
|
-
* **Toolbox** – file I/O
|
|
126
|
+
* **Toolbox** – file I/O and shell execution.
|
|
133
127
|
* **Streaming Responses** – output appears in real time.
|
|
134
128
|
* **Conversation History** – persists across turns; can be cleared.
|
|
135
129
|
* **Context Dump** – `/context` shows the current conversation state.
|
|
@@ -137,24 +131,15 @@ are permissible.
|
|
|
137
131
|
## Toolbox Overview
|
|
138
132
|
|
|
139
133
|
The `Toolbox` class is defined in `lib/elelem/toolbox.rb`. It supplies
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
| Tool | Purpose
|
|
143
|
-
|
|
|
144
|
-
| `
|
|
145
|
-
| `
|
|
146
|
-
| `
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
| `read` | Read file contents | `path` |
|
|
150
|
-
| `write` | Overwrite a file | `path`, `content` |
|
|
151
|
-
|
|
152
|
-
## Tool Definition
|
|
153
|
-
|
|
154
|
-
The core `Tool` wrapper is defined in `lib/elelem/tool.rb`. Each tool is
|
|
155
|
-
created with a name, description, JSON schema for arguments, and a block
|
|
156
|
-
that performs the operation. The LLM calls a tool by name and passes the
|
|
157
|
-
arguments as a hash.
|
|
134
|
+
three tools, each represented by a JSON schema that the LLM can call.
|
|
135
|
+
|
|
136
|
+
| Tool | Purpose | Parameters |
|
|
137
|
+
| --------- | ------------------ | ------------------ |
|
|
138
|
+
| `read` | Read file contents | `path` |
|
|
139
|
+
| `write` | Write file | `path`, `content` |
|
|
140
|
+
| `execute` | Run shell command | `command` |
|
|
141
|
+
|
|
142
|
+
Aliases: `bash`, `sh`, `exec` → `execute`; `open` → `read`
|
|
158
143
|
|
|
159
144
|
## Known Limitations
|
|
160
145
|
|
data/exe/elelem
CHANGED
|
@@ -2,9 +2,84 @@
|
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
require "elelem"
|
|
5
|
+
require "optparse"
|
|
5
6
|
|
|
6
|
-
Signal.trap("INT")
|
|
7
|
-
|
|
7
|
+
Signal.trap("INT") { exit 1 }
|
|
8
|
+
|
|
9
|
+
class App
|
|
10
|
+
MODELS = {
|
|
11
|
+
"ollama" => "gpt-oss:latest",
|
|
12
|
+
"anthropic" => "claude-opus-4-5-20250514",
|
|
13
|
+
"vertex" => "claude-opus-4-5@20251101",
|
|
14
|
+
"openai" => "gpt-4o"
|
|
15
|
+
}.freeze
|
|
16
|
+
|
|
17
|
+
PROVIDERS = {
|
|
18
|
+
"ollama" => ->(model) { Elelem::Net::Ollama.new(model: model, host: ENV.fetch("OLLAMA_HOST", "localhost:11434")) },
|
|
19
|
+
"anthropic" => ->(model) { Elelem::Net::Claude.anthropic(model: model, api_key: ENV.fetch("ANTHROPIC_API_KEY")) },
|
|
20
|
+
"vertex" => ->(model) { Elelem::Net::Claude.vertex(model: model, project: ENV.fetch("GOOGLE_CLOUD_PROJECT"), region: ENV.fetch("GOOGLE_CLOUD_REGION", "us-east5")) },
|
|
21
|
+
"openai" => ->(model) { Elelem::Net::OpenAI.new(model: model, api_key: ENV.fetch("OPENAI_API_KEY")) }
|
|
22
|
+
}.freeze
|
|
23
|
+
|
|
24
|
+
def initialize(args)
|
|
25
|
+
@provider = "ollama"
|
|
26
|
+
@model = nil
|
|
27
|
+
@args = parse(args)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def run
|
|
31
|
+
command = @args.shift || "chat"
|
|
32
|
+
send(command.tr("-", "_"))
|
|
33
|
+
rescue NoMethodError
|
|
34
|
+
abort "Unknown command: #{command}"
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
private
|
|
38
|
+
|
|
39
|
+
def parse(args)
|
|
40
|
+
@parser = OptionParser.new do |o|
|
|
41
|
+
o.banner = "Usage: elelem [command] [options] [args]"
|
|
42
|
+
o.separator "\nCommands:"
|
|
43
|
+
o.separator " chat Interactive REPL (default)"
|
|
44
|
+
o.separator " ask <prompt> One-shot query (reads stdin if piped)"
|
|
45
|
+
o.separator " files Output files as XML (no options)"
|
|
46
|
+
o.separator " help Show this help"
|
|
47
|
+
o.separator "\nOptions:"
|
|
48
|
+
o.on("-p", "--provider NAME", "ollama, anthropic, vertex, openai") { |p| @provider = p }
|
|
49
|
+
o.on("-m", "--model NAME", "Override default model") { |m| @model = m }
|
|
50
|
+
o.on("-h", "--help") { puts o; exit }
|
|
51
|
+
end
|
|
52
|
+
@parser.parse!(args)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def help
|
|
56
|
+
puts @parser
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def client
|
|
60
|
+
model = @model || MODELS.fetch(@provider)
|
|
61
|
+
PROVIDERS.fetch(@provider).call(model)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def chat = Elelem.start(client)
|
|
65
|
+
|
|
66
|
+
def ask
|
|
67
|
+
abort "Usage: elelem ask <prompt>" if @args.empty?
|
|
68
|
+
prompt = @args.join(" ")
|
|
69
|
+
prompt = "#{prompt}\n\n```\n#{$stdin.read}\n```" if $stdin.stat.pipe?
|
|
70
|
+
Elelem::Terminal.new.markdown Elelem.ask(client, prompt)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def files
|
|
74
|
+
files = $stdin.stat.pipe? ? $stdin.readlines : `git ls-files`.lines
|
|
75
|
+
puts "<documents>"
|
|
76
|
+
files.each_with_index do |line, i|
|
|
77
|
+
path = line.strip
|
|
78
|
+
next if path.empty? || !File.file?(path)
|
|
79
|
+
puts %Q{<document index="#{i + 1}"><source>#{path}</source><content><![CDATA[#{File.read(path)}]]></content></document>}
|
|
80
|
+
end
|
|
81
|
+
puts "</documents>"
|
|
82
|
+
end
|
|
8
83
|
end
|
|
9
84
|
|
|
10
|
-
|
|
85
|
+
App.new(ARGV).run
|