elelem 0.2.1 → 0.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7d165866e64423e182a5497407deba0249b4c73ca4fc5c3af36a979925aade9f
4
- data.tar.gz: 4b8f6b384a901781514bd085c106672489676b065eab7c2c6057ffff49842b71
3
+ metadata.gz: bcd68905e2c0dd4aa7e6c22865d0353ab2fa0dff0ce8bfde3e319b10b7d4e548
4
+ data.tar.gz: ed59f2ca17e210adbd7b371556d7994589e75e7a515d688bb6751d8bbd3380c5
5
5
  SHA512:
6
- metadata.gz: 356ff6e3bbadda54bc3ae9663d67879ea3fc1cd52418eaaa228f8aa1b7a6bf2a9db847dfa482e840fb0f772130753d5d417814d649e75f5c530bca467ef6f2df
7
- data.tar.gz: 67313588f14536711acf61e566394466a34513cf52259c286e522648ccc1f47fcc898f4f2856a0072bf79cb63462948931c202bf972b7c29e94494aa3efb4a0f
6
+ metadata.gz: 400ae6e321309f3bcb6503942a2a636f8c782c086b17afd9a7be048df98215b248d0bbf4858b35de578ac13d19ad15dd19b2edef4e774ca99ec8af2901fb4006
7
+ data.tar.gz: 5f138cea24ee1faffdb173c2bed070bead948a7f9dbf17fdea6b44486998aca5517de3f3e7a99f7807fe8c5e969ab6783f09673f7158382742bb1056406d1cd7
data/CHANGELOG.md CHANGED
@@ -1,5 +1,54 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.3.0] - 2025-11-05
4
+
5
+ ### Added
6
+ - **Mode System**: Control agent capabilities with workflow modes
7
+ - `/mode plan` - Read-only mode (grep, list, read)
8
+ - `/mode build` - Read + Write mode (grep, list, read, patch, write)
9
+ - `/mode verify` - Read + Execute mode (grep, list, read, execute)
10
+ - `/mode auto` - All tools enabled
11
+ - Each mode adapts system prompt to guide appropriate behavior
12
+ - Improved output formatting
13
+ - Suppressed verbose thinking/reasoning output
14
+ - Clean tool call display (e.g., `date` instead of full JSON hash)
15
+ - Mode switch confirmation messages
16
+ - Clear command feedback
17
+ - Design philosophy documentation in README
18
+ - Mode system documentation
19
+
20
+ ### Changed
21
+ - **BREAKING**: Removed `llm-ollama` and `llm-openai` standalone executables (use main `elelem chat` command)
22
+ - **BREAKING**: Simplified architecture - consolidated all logic into Agent class
23
+ - Removed Configuration class
24
+ - Removed Toolbox system
25
+ - Removed MCP client infrastructure
26
+ - Removed Tool and Tools classes
27
+ - Removed TUI abstraction layer (direct puts/Reline usage)
28
+ - Removed API wrapper class
29
+ - Removed state machine
30
+ - Improved execute tool description to guide LLM toward direct command execution
31
+ - Extracted tool definitions from long inline strings to readable private methods
32
+ - Updated README with clear philosophy and usage examples
33
+ - Reduced total codebase from 417 to 395 lines (-5%)
34
+
35
+ ### Fixed
36
+ - Working directory handling for execute tool (handles empty string cwd)
37
+ - REPL EOF handling (graceful exit when input stream ends)
38
+ - Tool call formatting now shows clean, readable commands
39
+
40
+ ### Removed
41
+ - `exe/llm-ollama` (359 lines)
42
+ - `exe/llm-openai` (340 lines)
43
+ - `lib/elelem/configuration.rb`
44
+ - `lib/elelem/toolbox.rb` and toolbox/* files
45
+ - `lib/elelem/mcp_client.rb`
46
+ - `lib/elelem/tool.rb` and `lib/elelem/tools.rb`
47
+ - `lib/elelem/tui.rb`
48
+ - `lib/elelem/api.rb`
49
+ - `lib/elelem/states/*` (state machine infrastructure)
50
+ - Removed ~750 lines of unused/redundant code
51
+
3
52
  ## [0.2.1] - 2025-10-15
4
53
 
5
54
  ### Fixed
data/README.md CHANGED
@@ -1,6 +1,64 @@
1
1
  # Elelem
2
2
 
3
- Elelem is an interactive REPL (Read-Eval-Print Loop) for Ollama that provides a command-line chat interface for communicating with AI models. It features tool calling capabilities, streaming responses, and a clean state machine architecture.
3
+ Fast, correct, autonomous - Pick two
4
+
5
+ PURPOSE:
6
+
7
+ Elelem is a minimal coding agent written in Ruby. It is intended to
8
+ assist me (a software engineer and computer science student) with writing,
9
+ editing, and managing code and text files from the command line. It acts
10
+ as a direct interface to an LLM, providing it with a simple text-based
11
+ UI and access to the local filesystem.
12
+
13
+ DESIGN PRINCIPLES:
14
+
15
+ - Follows the Unix philosophy: simple, composable, minimal.
16
+ - Convention over configuration.
17
+ - Avoids unnecessary defensive checks, or complexity.
18
+ - Assumes a mature and responsible LLM that behaves like a capable engineer.
19
+ - Designed for my workflow and preferences.
20
+ - Efficient and minimal like aider - https://aider.chat/
21
+ - UX like Claude Code - https://docs.claude.com/en/docs/claude-code/overview
22
+
23
+ SYSTEM ASSUMPTIONS:
24
+
25
+ - This script is used on a Linux system with the following tools: Alacritty, tmux, Bash, and Vim.
26
+ - It is always run inside a Git repository.
27
+ - All project work is assumed to be version-controlled with Git.
28
+ - Git is expected to be available and working; no checks are necessary.
29
+
30
+ SCOPE:
31
+
32
+ - This program operates only on code and plain-text files.
33
+ - It does not need to support binary files.
34
+ - The LLM has full access to execute system commands.
35
+ - There are no sandboxing, permission, or validation layers.
36
+ - Execution is not restricted or monitored - responsibility is delegated to the LLM.
37
+
38
+ CONFIGURATION:
39
+
40
+ - Avoid adding configuration options unless absolutely necessary.
41
+ - Prefer hard-coded values that can be changed later if needed.
42
+ - Only introduce environment variables after repeated usage proves them worthwhile.
43
+
44
+ UI EXPECTATIONS:
45
+
46
+ - The TUI must remain simple, fast, and predictable.
47
+ - No mouse support or complex UI components are required.
48
+ - Interaction is strictly keyboard-driven.
49
+
50
+ CODING STANDARDS FOR LLM:
51
+
52
+ - Do not add error handling or logging unless it is essential for functionality.
53
+ - Keep methods short and single-purpose.
54
+ - Use descriptive, conventional names.
55
+ - Stick to Ruby's standard library whenever possible.
56
+
57
+ HELPFUL LINKS:
58
+
59
+ - https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents
60
+ - https://www.anthropic.com/engineering/writing-tools-for-agents
61
+ - https://simonwillison.net/2025/Sep/30/designing-agentic-loops/
4
62
 
5
63
  ## Installation
6
64
 
@@ -29,7 +87,6 @@ elelem chat
29
87
  - `--host`: Specify Ollama host (default: localhost:11434)
30
88
  - `--model`: Specify Ollama model (default: gpt-oss, currently only tested with gpt-oss)
31
89
  - `--token`: Provide authentication token
32
- - `--debug`: Enable debug logging
33
90
 
34
91
  ### Examples
35
92
 
@@ -39,29 +96,35 @@ elelem chat
39
96
 
40
97
  # Chat with specific model and host
41
98
  elelem chat --model llama2 --host remote-host:11434
42
-
43
- # Enable debug mode
44
- elelem chat --debug
45
99
  ```
46
100
 
47
101
  ### Features
48
102
 
49
103
  - **Interactive REPL**: Clean command-line interface for chatting
50
- - **Tool Execution**: Execute shell commands when requested by the AI
104
+ - **Mode System**: Control agent capabilities with workflow modes (plan, build, verify, auto)
105
+ - **Tool Execution**: Execute shell commands, read/write files, search code
51
106
  - **Streaming Responses**: Real-time streaming of AI responses
52
- - **State Machine**: Robust state management for different interaction modes
53
107
  - **Conversation History**: Maintains context across the session
54
108
 
109
+ ### Mode System
110
+
111
+ Control what tools the agent can access:
112
+
113
+ ```bash
114
+ /mode plan # Read-only (grep, list, read)
115
+ /mode build # Read + Write (grep, list, read, patch, write)
116
+ /mode verify # Read + Execute (grep, list, read, execute)
117
+ /mode auto # All tools enabled
118
+ ```
119
+
120
+ Each mode adapts the system prompt to guide appropriate behavior.
121
+
55
122
  ## Development
56
123
 
57
124
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
58
125
 
59
126
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
60
127
 
61
- ## Contributing
62
-
63
- Bug reports and pull requests are welcome on GitHub at https://github.com/xlgmokha/elelem.
64
-
65
128
  ## License
66
129
 
67
130
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile CHANGED
@@ -2,9 +2,7 @@
2
2
 
3
3
  require "bundler/gem_tasks"
4
4
  require "rspec/core/rake_task"
5
- require "rubocop/rake_task"
6
5
 
7
6
  RSpec::Core::RakeTask.new(:spec)
8
- RuboCop::RakeTask.new
9
7
 
10
- task default: %i[spec rubocop]
8
+ task default: %i[spec]
data/lib/elelem/agent.rb CHANGED
@@ -2,56 +2,272 @@
2
2
 
3
3
  module Elelem
4
4
  class Agent
5
- attr_reader :api, :conversation, :logger, :model, :tui
5
+ attr_reader :conversation, :client, :tools
6
6
 
7
- def initialize(configuration)
8
- @api = configuration.api
9
- @tui = configuration.tui
10
- @configuration = configuration
11
- @model = configuration.model
12
- @conversation = configuration.conversation
13
- @logger = configuration.logger
7
+ def initialize(client)
8
+ @conversation = Conversation.new
9
+ @client = client
10
+ @tools = {
11
+ read: [grep_tool, list_tool, read_tool],
12
+ write: [patch_tool, write_tool],
13
+ execute: [exec_tool]
14
+ }
15
+ end
14
16
 
15
- at_exit { cleanup }
17
+ def repl
18
+ mode = Set.new([:read])
16
19
 
17
- transition_to(States::Idle.new)
20
+ loop do
21
+ input = ask?("User> ")
22
+ break if input.nil?
23
+ if input.start_with?("/")
24
+ case input
25
+ when "/mode auto"
26
+ mode = Set[:read, :write, :execute]
27
+ puts " → Mode: auto (all tools enabled)"
28
+ when "/mode build"
29
+ mode = Set[:read, :write]
30
+ puts " → Mode: build (read + write)"
31
+ when "/mode plan"
32
+ mode = Set[:read]
33
+ puts " → Mode: plan (read-only)"
34
+ when "/mode verify"
35
+ mode = Set[:read, :execute]
36
+ puts " → Mode: verify (read + execute)"
37
+ when "/mode"
38
+ puts " Mode: #{mode.to_a.inspect}"
39
+ puts " Tools: #{tools_for(mode).map { |t| t.dig(:function, :name) }}"
40
+ when "/exit" then exit
41
+ when "/clear"
42
+ conversation.clear
43
+ puts " → Conversation cleared"
44
+ when "/context" then puts conversation.dump
45
+ else
46
+ puts help_banner
47
+ end
48
+ else
49
+ conversation.set_system_prompt(system_prompt_for(mode))
50
+ conversation.add(role: :user, content: input)
51
+ result = execute_turn(conversation.history, tools: tools_for(mode))
52
+ conversation.add(role: result[:role], content: result[:content])
53
+ end
54
+ end
18
55
  end
19
56
 
20
- def repl
57
+ private
58
+
59
+ def ask?(text)
60
+ Reline.readline(text, true)&.strip
61
+ end
62
+
63
+ def help_banner
64
+ <<~HELP
65
+ /mode auto build plan verify
66
+ /clear
67
+ /context
68
+ /exit
69
+ /help
70
+ HELP
71
+ end
72
+
73
+ def tools_for(modes)
74
+ modes.map { |mode| tools[mode] }.flatten
75
+ end
76
+
77
+ def system_prompt_for(mode)
78
+ base = "You are a reasoning coding and system agent."
79
+
80
+ case mode.to_a.sort
81
+ when [:read]
82
+ "#{base}\n\nRead and analyze. Understand before suggesting action."
83
+ when [:write]
84
+ "#{base}\n\nWrite clean, thoughtful code."
85
+ when [:execute]
86
+ "#{base}\n\nUse shell commands creatively to understand and manipulate the system."
87
+ when [:read, :write]
88
+ "#{base}\n\nFirst understand, then build solutions that integrate well."
89
+ when [:read, :execute]
90
+ "#{base}\n\nUse commands to deeply understand the system."
91
+ when [:write, :execute]
92
+ "#{base}\n\nCreate and execute freely. Have fun. Be kind."
93
+ when [:read, :write, :execute]
94
+ "#{base}\n\nYou have all tools. Use them wisely."
95
+ else
96
+ base
97
+ end
98
+ end
99
+
100
+ def format_tool_call(name, args)
101
+ case name
102
+ when "execute"
103
+ cmd = args["cmd"]
104
+ cmd_args = args["args"] || []
105
+ cmd_args.empty? ? cmd : "#{cmd} #{cmd_args.join(' ')}"
106
+ when "grep" then "grep(#{args["query"]})"
107
+ when "list" then "list(#{args["path"] || "."})"
108
+ when "patch" then "patch(#{args["diff"]&.lines&.count || 0} lines)"
109
+ when "read" then "read(#{args["path"]})"
110
+ when "write" then "write(#{args["path"]})"
111
+ else
112
+ "#{name}(#{args.to_s[0...50]})"
113
+ end
114
+ end
115
+
116
+ def execute_turn(messages, tools:)
117
+ turn_context = []
118
+
21
119
  loop do
22
- current_state.run(self)
23
- sleep 0.1
120
+ content = ""
121
+ tool_calls = []
122
+
123
+ print "Thinking..."
124
+ client.chat(messages + turn_context, tools) do |chunk|
125
+ msg = chunk["message"]
126
+ if msg
127
+ if msg["content"] && !msg["content"].empty?
128
+ print "\r\e[K" if content.empty?
129
+ print msg["content"]
130
+ content += msg["content"]
131
+ end
132
+
133
+ tool_calls += msg["tool_calls"] if msg["tool_calls"]
134
+ end
135
+ end
136
+
137
+ puts
138
+ turn_context << { role: "assistant", content: content, tool_calls: tool_calls }.compact
139
+
140
+ if tool_calls.any?
141
+ tool_calls.each do |call|
142
+ name = call.dig("function", "name")
143
+ args = call.dig("function", "arguments")
144
+
145
+ puts "Tool> #{format_tool_call(name, args)}"
146
+ result = run_tool(name, args)
147
+ turn_context << { role: "tool", content: JSON.dump(result) }
148
+ end
149
+
150
+ tool_calls = []
151
+ next
152
+ end
153
+
154
+ return { role: "assistant", content: content }
24
155
  end
25
156
  end
26
157
 
27
- def transition_to(next_state)
28
- if @current_state
29
- logger.info("AGENT: #{@current_state.class.name.split('::').last} -> #{next_state.class.name.split('::').last}")
158
+ def run_exec(command, args: [], env: {}, cwd: Dir.pwd, stdin: nil)
159
+ cmd = command.is_a?(Array) ? command.first : command
160
+ cmd_args = command.is_a?(Array) ? command[1..] + args : args
161
+ stdout, stderr, status = Open3.capture3(env, cmd, *cmd_args, chdir: cwd, stdin_data: stdin)
162
+ {
163
+ "exit_status" => status.exitstatus,
164
+ "stdout" => stdout.to_s,
165
+ "stderr" => stderr.to_s
166
+ }
167
+ end
168
+
169
+ def expand_path(path)
170
+ Pathname.new(path).expand_path
171
+ end
172
+
173
+ def read_file(path)
174
+ full_path = expand_path(path)
175
+ full_path.exist? ? { content: full_path.read } : { error: "File not found: #{path}" }
176
+ end
177
+
178
+ def write_file(path, content)
179
+ full_path = expand_path(path)
180
+ FileUtils.mkdir_p(full_path.dirname)
181
+ { bytes_written: full_path.write(content) }
182
+ end
183
+
184
+ def run_tool(name, args)
185
+ case name
186
+ when "execute" then run_exec(args["cmd"], args: args["args"] || [], env: args["env"] || {}, cwd: args["cwd"].to_s.empty? ? Dir.pwd : args["cwd"], stdin: args["stdin"])
187
+ when "grep" then run_exec("git", args: ["grep", "-nI", args["query"]])
188
+ when "list" then run_exec("git", args: args["path"] ? ["ls-files", "--", args["path"]] : ["ls-files"])
189
+ when "patch" then run_exec("git", args: ["apply", "--index", "--whitespace=nowarn", "-p1"], stdin: args["diff"])
190
+ when "read" then read_file(args["path"])
191
+ when "write" then write_file(args["path"], args["content"])
30
192
  else
31
- logger.info("AGENT: Starting in #{next_state.class.name.split('::').last}")
193
+ { error: "Unknown tool", name: name, args: args }
32
194
  end
33
- @current_state = next_state
195
+ rescue => error
196
+ { error: error.message, name: name, args: args }
34
197
  end
35
198
 
36
- def execute(tool_call)
37
- tool_name = tool_call.dig("function", "name")
38
- logger.debug("TOOL: Full call - #{tool_call}")
39
- result = configuration.tools.execute(tool_call)
40
- logger.debug("TOOL: Result (#{result.length} chars)") if result
41
- result
199
+ def exec_tool
200
+ build_tool(
201
+ "execute",
202
+ "Execute shell commands directly. Commands run in a shell context. Examples: 'date', 'git status'.",
203
+ {
204
+ cmd: { type: "string" },
205
+ args: { type: "array", items: { type: "string" } },
206
+ env: { type: "object", additionalProperties: { type: "string" } },
207
+ cwd: { type: "string", description: "Working directory (defaults to current)" },
208
+ stdin: { type: "string" }
209
+ },
210
+ ["cmd"]
211
+ )
42
212
  end
43
213
 
44
- def quit
45
- cleanup
46
- exit
214
+ def grep_tool
215
+ build_tool(
216
+ "grep",
217
+ "Search all git-tracked files using git grep. Returns file paths with matching line numbers.",
218
+ { query: { type: "string" } },
219
+ ["query"]
220
+ )
47
221
  end
48
222
 
49
- def cleanup
50
- configuration.cleanup
223
+ def list_tool
224
+ build_tool(
225
+ "list",
226
+ "List all git-tracked files in the repository, optionally filtered by path.",
227
+ { path: { type: "string" } }
228
+ )
51
229
  end
52
230
 
53
- private
231
+ def patch_tool
232
+ build_tool(
233
+ "patch",
234
+ "Apply a unified diff patch via 'git apply'. Use for surgical edits to existing files.",
235
+ { diff: { type: "string" } },
236
+ ["diff"]
237
+ )
238
+ end
54
239
 
55
- attr_reader :configuration, :current_state
240
+ def read_tool
241
+ build_tool(
242
+ "read",
243
+ "Read complete contents of a file. Requires exact file path.",
244
+ { path: { type: "string" } },
245
+ ["path"]
246
+ )
247
+ end
248
+
249
+ def write_tool
250
+ build_tool(
251
+ "write",
252
+ "Write complete file contents (overwrites existing files). Creates parent directories automatically.",
253
+ { path: { type: "string" }, content: { type: "string" } },
254
+ ["path", "content"]
255
+ )
256
+ end
257
+
258
+ def build_tool(name, description, properties, required = [])
259
+ {
260
+ type: "function",
261
+ function: {
262
+ name: name,
263
+ description: description,
264
+ parameters: {
265
+ type: "object",
266
+ properties: properties,
267
+ required: required
268
+ }
269
+ }
270
+ }
271
+ end
56
272
  end
57
273
  end
@@ -3,10 +3,6 @@
3
3
  module Elelem
4
4
  class Application < Thor
5
5
  desc "chat", "Start the REPL"
6
- method_option :help,
7
- aliases: "-h",
8
- type: :boolean,
9
- desc: "Display usage information"
10
6
  method_option :host,
11
7
  aliases: "--host",
12
8
  type: :string,
@@ -17,32 +13,16 @@ module Elelem
17
13
  type: :string,
18
14
  desc: "Ollama model",
19
15
  default: ENV.fetch("OLLAMA_MODEL", "gpt-oss")
20
- method_option :token,
21
- aliases: "--token",
22
- type: :string,
23
- desc: "Ollama token",
24
- default: ENV.fetch("OLLAMA_API_KEY", nil)
25
- method_option :debug,
26
- aliases: "--debug",
27
- type: :boolean,
28
- desc: "Debug mode",
29
- default: false
16
+
30
17
  def chat(*)
31
- if options[:help]
32
- invoke :help, ["chat"]
33
- else
34
- configuration = Configuration.new(
35
- host: options[:host],
36
- model: options[:model],
37
- token: options[:token],
38
- debug: options[:debug]
39
- )
40
- say "Agent (#{configuration.model})", :green
41
- say configuration.tools.banner.to_s, :green
18
+ client = Net::Llm::Ollama.new(
19
+ host: options[:host],
20
+ model: options[:model],
21
+ )
22
+ say "Agent (#{options[:model]})", :green
23
+ agent = Agent.new(client)
42
24
 
43
- agent = Agent.new(configuration)
44
- agent.repl
45
- end
25
+ agent.repl
46
26
  end
47
27
 
48
28
  desc "version", "The version of this CLI"
@@ -4,7 +4,7 @@ module Elelem
4
4
  class Conversation
5
5
  ROLES = %i[system assistant user tool].freeze
6
6
 
7
- def initialize(items = [{ role: "system", content: system_prompt }])
7
+ def initialize(items = default_context)
8
8
  @items = items
9
9
  end
10
10
 
@@ -12,7 +12,6 @@ module Elelem
12
12
  @items
13
13
  end
14
14
 
15
- # :TODO truncate conversation history
16
15
  def add(role: :user, content: "")
17
16
  role = role.to_sym
18
17
  raise "unknown role: #{role}" unless ROLES.include?(role)
@@ -25,8 +24,24 @@ module Elelem
25
24
  end
26
25
  end
27
26
 
27
+ def clear
28
+ @items = default_context
29
+ end
30
+
31
+ def set_system_prompt(prompt)
32
+ @items[0] = { role: :system, content: prompt }
33
+ end
34
+
35
+ def dump
36
+ JSON.pretty_generate(@items)
37
+ end
38
+
28
39
  private
29
40
 
41
+ def default_context
42
+ [{ role: "system", content: system_prompt }]
43
+ end
44
+
30
45
  def system_prompt
31
46
  ERB.new(Pathname.new(__dir__).join("system_prompt.erb").read).result(binding)
32
47
  end
@@ -1,18 +1,5 @@
1
- You are a self-improving coding assistant with the ability to modify your own source code.
1
+ You are a reasoning coding and system agent.
2
2
 
3
- **Core Behavior**: Think via `thinking`, Execute via `tool_calls`, Talk via `content`.
4
-
5
- **Your Mission**: Continuously evolve to match the intelligence of advanced AI assistants.
6
-
7
- **Guidance**: Read `COMMANDMENTS.md` for self-improvement principles using `file action=read path=COMMANDMENTS.md`
8
-
9
- **Tools**:
10
- - `exec command="shell command"` - Run commands/tests
11
- - `file action=read|write path=filepath content=...` - Read/write files
12
- - `web action=search|fetch query=... url=...` - Internet access
13
- - `memory action=store|retrieve|search key=... content=...` - Persistent memory
14
- - `prompt question="..."` - Ask user questions
15
-
16
- Context: <%= Time.now.strftime("%Y-%m-%d %H:%M:%S") %> | <%= Dir.pwd %> | <%= `uname -a`.strip %>
17
-
18
- Focus on the user's request and continuously improve your capabilities.
3
+ - Less is more
4
+ - No code comments
5
+ - No trailing whitespace
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Elelem
4
- VERSION = "0.2.1"
4
+ VERSION = "0.3.0"
5
5
  end
data/lib/elelem.rb CHANGED
@@ -1,37 +1,23 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "cli/ui"
4
3
  require "erb"
4
+ require "fileutils"
5
5
  require "json"
6
6
  require "json-schema"
7
7
  require "logger"
8
8
  require "net/llm"
9
9
  require "open3"
10
+ require "pathname"
10
11
  require "reline"
12
+ require "set"
11
13
  require "thor"
12
14
  require "timeout"
13
15
 
14
16
  require_relative "elelem/agent"
15
- require_relative "elelem/api"
16
17
  require_relative "elelem/application"
17
- require_relative "elelem/configuration"
18
18
  require_relative "elelem/conversation"
19
- require_relative "elelem/mcp_client"
20
- require_relative "elelem/states/idle"
21
- require_relative "elelem/states/working"
22
- require_relative "elelem/states/working/state"
23
- require_relative "elelem/states/working/error"
24
- require_relative "elelem/states/working/executing"
25
- require_relative "elelem/states/working/talking"
26
- require_relative "elelem/states/working/thinking"
27
- require_relative "elelem/states/working/waiting"
28
- require_relative "elelem/tool"
29
- require_relative "elelem/toolbox"
30
- require_relative "elelem/tools"
31
- require_relative "elelem/tui"
32
19
  require_relative "elelem/version"
33
20
 
34
- CLI::UI::StdoutRouter.enable
35
21
  Reline.input = $stdin
36
22
  Reline.output = $stdout
37
23