Commit 481194e
Changed files (2)
CHANGELOG.md
@@ -2,18 +2,30 @@
### Added
- **Async MCP loading** for faster startup - tools load in background thread
+- **HTTP MCP servers** with SSE support and session management
+- **OAuth authentication** for MCP servers with PKCE, automatic token refresh
+- **Global hooks** - `toolbox.before`/`toolbox.after` without tool name applies to all tools
- **`/context` improvements**: `/context <n>` to view entry, `/context json` for full dump
- **ast-grep (`sg`) support** for building repo maps - faster and more accurate than ctags
-- **OAuth authentication** for MCP servers with automatic token refresh
-- **New tools**: `glob`, `grep`, `list`, `git` for structured file operations
+- **New tools**: `glob`, `grep`, `list`, `git`, `task`, `/tools` command
- **Permissions system** (`lib/elelem/permissions.rb`) for tool access control
- **OpenAI reasoning mode** - enables `Reasoning: high` for o-series models
+- **Test coverage** for OAuth, token storage, HTTP MCP, SSE parsing, global hooks
### Changed
+- **BREAKING: Plugin API** - plugins now receive `agent` instead of `toolbox`
+ - Old: `Elelem::Plugins.register(:name) { |toolbox| toolbox.add(...) }`
+ - New: `Elelem::Plugins.register(:name) { |agent| agent.toolbox.add(...) }`
+ - Plugins can now access `agent.terminal`, `agent.commands`, `agent.conversation`
- Extracted `Conversation` class from `Agent` for better separation of concerns
+- Extracted `Commands` class for slash command handling
- Refactored LLM fetch interface to emit separate events for thinking/content/tool_calls
- Simplified system prompt with inline ERB template
- Renamed confirm plugin to `zz_confirm` to ensure it loads last
+- MCP logs now write to `~/.elelem/mcp.log` instead of working directory
+- Tool schema now frozen to prevent mutation
+- Uses `Open3.capture2` instead of backticks for thread safety
+- Improved ANSI escape sequence stripping in `/shell` transcripts
## [0.9.2] - 2026-01-22
README.md
@@ -129,18 +129,94 @@ Each provider reads its configuration from environment variables:
* **Conversation History** – persists across turns; can be cleared.
* **Context Dump** – `/context` shows the current conversation state.
-## Toolbox Overview
-
-The `Toolbox` class is defined in `lib/elelem/toolbox.rb`. It supplies
-three tools, each represented by a JSON schema that the LLM can call.
+## Tools
+
+Built-in tools available to the LLM:
+
+| Tool | Purpose | Parameters |
+| --------- | -------------------------- | ------------------------- |
+| `read` | Read file contents | `path` |
+| `write` | Write file | `path`, `content` |
+| `edit` | Replace text in file | `path`, `old`, `new` |
+| `execute` | Run shell command | `command` |
+| `eval` | Execute Ruby code | `ruby` |
+| `glob` | Find files by pattern | `pattern`, `path` |
+| `grep` | Search file contents | `pattern`, `path`, `glob` |
+| `list` | List directory | `path`, `recursive` |
+| `git` | Run git command | `command`, `args` |
+| `task` | Delegate to sub-agent | `prompt` |
+| `verify` | Check syntax and run tests | `path` |
+
+Aliases: `bash`, `sh`, `exec` → `execute`; `open` → `read`; `ls` → `list`
+
+## Plugins
+
+Plugins extend elelem with custom tools and commands. They are loaded from:
+- `lib/elelem/plugins/` (built-in)
+- `~/.elelem/plugins/` (user global)
+- `.elelem/plugins/` (project local)
+
+### Writing a Plugin
+
+```ruby
+# ~/.elelem/plugins/hello.rb
+Elelem::Plugins.register(:hello) do |agent|
+ # Add a tool
+ agent.toolbox.add("hello",
+ description: "Say hello",
+ params: { name: { type: "string" } },
+ required: ["name"]
+ ) do |args|
+ { message: "Hello, #{args["name"]}!" }
+ end
+
+ # Add a command
+ agent.commands.register("greet", description: "Greet the user") do
+ agent.terminal.say "Hello!"
+ end
+
+ # Add hooks
+ agent.toolbox.before("execute") { |args| puts "Running: #{args["command"]}" }
+ agent.toolbox.after("execute") { |args, result| puts "Exit: #{result[:exit_status]}" }
+
+ # Global hook (runs for all tools)
+ agent.toolbox.before { |args, tool_name:| puts "Calling #{tool_name}" }
+end
+```
-| Tool | Purpose | Parameters |
-| --------- | ------------------ | ------------------ |
-| `read` | Read file contents | `path` |
-| `write` | Write file | `path`, `content` |
-| `execute` | Run shell command | `command` |
+### Plugin API
+
+Plugins receive an `agent` object with access to:
+- `agent.toolbox` - add tools, register hooks
+- `agent.terminal` - output to the user (`say`, `ask`, `markdown`)
+- `agent.commands` - register slash commands
+- `agent.conversation` - access message history
+- `agent.client` - the LLM client
+- `agent.fork(system_prompt:)` - create a sub-agent
+
+## MCP Configuration
+
+Configure MCP servers in `~/.elelem/mcp.json` or `.elelem/mcp.json`:
+
+```json
+{
+ "mcpServers": {
+ "gitlab": {
+ "command": "npx",
+ "args": ["-y", "@anthropics/gitlab-mcp"],
+ "env": {
+ "GITLAB_TOKEN": "${GITLAB_TOKEN}"
+ }
+ },
+ "remote": {
+ "type": "http",
+ "url": "https://mcp.example.com/sse"
+ }
+ }
+}
+```
-Aliases: `bash`, `sh`, `exec` → `execute`; `open` → `read`
+HTTP servers support OAuth authentication automatically.
## Known Limitations