elelem 0.7.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.
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.7.0
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - mo khan
@@ -10,19 +10,19 @@ cert_chain: []
10
10
  date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
- name: cli-ui
13
+ name: date
14
14
  requirement: !ruby/object:Gem::Requirement
15
15
  requirements:
16
16
  - - "~>"
17
17
  - !ruby/object:Gem::Version
18
- version: '2.0'
18
+ version: '3.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: '2.0'
25
+ version: '3.0'
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: erb
28
28
  requirement: !ruby/object:Gem::Requirement
@@ -66,21 +66,21 @@ dependencies:
66
66
  - !ruby/object:Gem::Version
67
67
  version: '2.0'
68
68
  - !ruby/object:Gem::Dependency
69
- name: json-schema
69
+ name: json_schemer
70
70
  requirement: !ruby/object:Gem::Requirement
71
71
  requirements:
72
72
  - - "~>"
73
73
  - !ruby/object:Gem::Version
74
- version: '6.0'
74
+ version: '2.0'
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: '6.0'
81
+ version: '2.0'
82
82
  - !ruby/object:Gem::Dependency
83
- name: logger
83
+ name: net-hippie
84
84
  requirement: !ruby/object:Gem::Requirement
85
85
  requirements:
86
86
  - - "~>"
@@ -94,27 +94,21 @@ dependencies:
94
94
  - !ruby/object:Gem::Version
95
95
  version: '1.0'
96
96
  - !ruby/object:Gem::Dependency
97
- name: net-llm
97
+ name: open3
98
98
  requirement: !ruby/object:Gem::Requirement
99
99
  requirements:
100
100
  - - "~>"
101
101
  - !ruby/object:Gem::Version
102
- version: '0.5'
103
- - - ">="
104
- - !ruby/object:Gem::Version
105
- version: 0.5.0
102
+ version: '0.1'
106
103
  type: :runtime
107
104
  prerelease: false
108
105
  version_requirements: !ruby/object:Gem::Requirement
109
106
  requirements:
110
107
  - - "~>"
111
108
  - !ruby/object:Gem::Version
112
- version: '0.5'
113
- - - ">="
114
- - !ruby/object:Gem::Version
115
- version: 0.5.0
109
+ version: '0.1'
116
110
  - !ruby/object:Gem::Dependency
117
- name: open3
111
+ name: optparse
118
112
  requirement: !ruby/object:Gem::Requirement
119
113
  requirements:
120
114
  - - "~>"
@@ -156,47 +150,47 @@ dependencies:
156
150
  - !ruby/object:Gem::Version
157
151
  version: '0.6'
158
152
  - !ruby/object:Gem::Dependency
159
- name: set
153
+ name: stringio
160
154
  requirement: !ruby/object:Gem::Requirement
161
155
  requirements:
162
156
  - - "~>"
163
157
  - !ruby/object:Gem::Version
164
- version: '1.0'
158
+ version: '3.0'
165
159
  type: :runtime
166
160
  prerelease: false
167
161
  version_requirements: !ruby/object:Gem::Requirement
168
162
  requirements:
169
163
  - - "~>"
170
164
  - !ruby/object:Gem::Version
171
- version: '1.0'
165
+ version: '3.0'
172
166
  - !ruby/object:Gem::Dependency
173
- name: thor
167
+ name: tempfile
174
168
  requirement: !ruby/object:Gem::Requirement
175
169
  requirements:
176
170
  - - "~>"
177
171
  - !ruby/object:Gem::Version
178
- version: '1.0'
172
+ version: '0.3'
179
173
  type: :runtime
180
174
  prerelease: false
181
175
  version_requirements: !ruby/object:Gem::Requirement
182
176
  requirements:
183
177
  - - "~>"
184
178
  - !ruby/object:Gem::Version
185
- version: '1.0'
179
+ version: '0.3'
186
180
  - !ruby/object:Gem::Dependency
187
- name: timeout
181
+ name: uri
188
182
  requirement: !ruby/object:Gem::Requirement
189
183
  requirements:
190
184
  - - "~>"
191
185
  - !ruby/object:Gem::Version
192
- version: '0.1'
186
+ version: '1.0'
193
187
  type: :runtime
194
188
  prerelease: false
195
189
  version_requirements: !ruby/object:Gem::Requirement
196
190
  requirements:
197
191
  - - "~>"
198
192
  - !ruby/object:Gem::Version
199
- version: '0.1'
193
+ version: '1.0'
200
194
  description: A minimal coding agent supporting Ollama, Anthropic, OpenAI, and VertexAI.
201
195
  email:
202
196
  - mo@mokhan.ca
@@ -212,10 +206,22 @@ files:
212
206
  - exe/elelem
213
207
  - lib/elelem.rb
214
208
  - lib/elelem/agent.rb
215
- - lib/elelem/application.rb
216
- - lib/elelem/conversation.rb
217
- - lib/elelem/git_context.rb
218
- - lib/elelem/system_prompt.erb
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
214
+ - 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
223
+ - lib/elelem/system_prompt.rb
224
+ - lib/elelem/templates/system_prompt.erb
219
225
  - lib/elelem/terminal.rb
220
226
  - lib/elelem/tool.rb
221
227
  - lib/elelem/toolbox.rb
@@ -235,14 +241,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
235
241
  requirements:
236
242
  - - ">="
237
243
  - !ruby/object:Gem::Version
238
- version: 3.4.0
244
+ version: 4.0.0
239
245
  required_rubygems_version: !ruby/object:Gem::Requirement
240
246
  requirements:
241
247
  - - ">="
242
248
  - !ruby/object:Gem::Version
243
- version: 3.3.11
249
+ version: 4.0.0
244
250
  requirements: []
245
- rubygems_version: 3.7.2
251
+ rubygems_version: 4.0.4
246
252
  specification_version: 4
247
253
  summary: A minimal coding agent for LLMs.
248
254
  test_files: []
@@ -1,45 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Elelem
4
- class Application < Thor
5
- PROVIDERS = %w[ollama anthropic openai vertex-ai].freeze
6
-
7
- desc "chat", "Start the REPL"
8
- method_option :provider,
9
- aliases: "-p",
10
- type: :string,
11
- desc: "LLM provider (#{PROVIDERS.join(', ')})",
12
- default: ENV.fetch("ELELEM_PROVIDER", "ollama")
13
- method_option :model,
14
- aliases: "-m",
15
- type: :string,
16
- desc: "Model name (uses provider default if not specified)"
17
- def chat(*)
18
- provider = options[:provider]
19
- model = options[:model]
20
- say "Agent (#{provider})", :green
21
- agent = Agent.new(provider, model, Toolbox.new)
22
- agent.repl
23
- end
24
-
25
- desc "files", "Generate CXML of the files"
26
- def files
27
- puts '<documents>'
28
- $stdin.read.split("\n").map(&:strip).reject(&:empty?).each_with_index do |file, i|
29
- next unless File.file?(file)
30
-
31
- puts " <document index=\"#{i + 1}\">"
32
- puts " <source><![CDATA[#{file}]]></source>"
33
- puts " <document_content><![CDATA[#{File.read(file)}]]></document_content>"
34
- puts " </document>"
35
- end
36
- puts '</documents>'
37
- end
38
-
39
- desc "version", "The version of this CLI"
40
- def version
41
- say "v#{Elelem::VERSION}"
42
- end
43
- map %w[--version -v] => :version
44
- end
45
- end
@@ -1,78 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Elelem
4
- class Conversation
5
- ROLES = %i[system assistant user tool].freeze
6
-
7
- def initialize(items = default_context)
8
- @items = items
9
- end
10
-
11
- def history_for(permissions)
12
- history = @items.dup
13
- history[0] = { role: "system", content: system_prompt_for(permissions) }
14
- history
15
- end
16
-
17
- def add(role: :user, content: "")
18
- role = role.to_sym
19
- raise "unknown role: #{role}" unless ROLES.include?(role)
20
- return if content.nil? || content.empty?
21
-
22
- if @items.last && @items.last[:role] == role
23
- @items.last[:content] += content
24
- else
25
- @items.push({ role: role, content: normalize(content) })
26
- end
27
- end
28
-
29
- def clear
30
- @items = default_context
31
- end
32
-
33
- def dump(permissions)
34
- JSON.pretty_generate(history_for(permissions))
35
- end
36
-
37
- private
38
-
39
- def default_context(prompt = system_prompt_for([]))
40
- [{ role: "system", content: prompt }]
41
- end
42
-
43
- def system_prompt_for(permissions)
44
- base = system_prompt
45
-
46
- case permissions.sort
47
- when [:read]
48
- "#{base}\n\nYou may read files on the system."
49
- when [:write]
50
- "#{base}\n\nYou may write files on the system."
51
- when [:execute]
52
- "#{base}\n\nYou may execute shell commands on the system."
53
- when [:read, :write]
54
- "#{base}\n\nYou may read and write files on the system."
55
- when [:execute, :read]
56
- "#{base}\n\nYou may execute shell commands and read files on the system."
57
- when [:execute, :write]
58
- "#{base}\n\nYou may execute shell commands and write files on the system."
59
- when [:execute, :read, :write]
60
- "#{base}\n\nYou may read files, write files and execute shell commands on the system."
61
- else
62
- base
63
- end
64
- end
65
-
66
- def system_prompt
67
- ERB.new(Pathname.new(__dir__).join("system_prompt.erb").read).result(binding)
68
- end
69
-
70
- def normalize(content)
71
- if content.is_a?(Array)
72
- content.join(", ")
73
- else
74
- content.to_s
75
- end
76
- end
77
- end
78
- end
@@ -1,79 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Elelem
4
- class GitContext
5
- MAX_DIFF_LINES = 100
6
-
7
- def initialize(shell = Elelem.shell)
8
- @shell = shell
9
- end
10
-
11
- def to_s
12
- return "" unless git_repo?
13
-
14
- parts = []
15
- parts << "Branch: #{branch}" if branch
16
- parts << status_section if status.any?
17
- parts << diff_section if staged_diff.any? || unstaged_diff.any?
18
- parts << recent_commits_section if recent_commits.any?
19
- parts.join("\n\n")
20
- end
21
-
22
- private
23
-
24
- def git_repo?
25
- @shell.execute("git", args: ["rev-parse", "--git-dir"])["exit_status"].zero?
26
- end
27
-
28
- def branch
29
- @branch ||= @shell.execute("git", args: ["branch", "--show-current"])["stdout"].strip.then { |b| b.empty? ? nil : b }
30
- end
31
-
32
- def status
33
- @status ||= @shell.execute("git", args: ["status", "--porcelain"])["stdout"].lines.map(&:chomp)
34
- end
35
-
36
- def staged_diff
37
- @staged_diff ||= @shell.execute("git", args: ["diff", "--cached", "--stat"])["stdout"].lines
38
- end
39
-
40
- def unstaged_diff
41
- @unstaged_diff ||= @shell.execute("git", args: ["diff", "--stat"])["stdout"].lines
42
- end
43
-
44
- def recent_commits
45
- @recent_commits ||= @shell.execute("git", args: ["log", "--oneline", "-5"])["stdout"].lines.map(&:strip)
46
- end
47
-
48
- def status_section
49
- modified = status.select { |l| l[0] == "M" || l[1] == "M" }.map { |l| l[3..] }
50
- added = status.select { |l| l[0] == "A" || l.start_with?("??") }.map { |l| l[3..] }
51
- deleted = status.select { |l| l[0] == "D" || l[1] == "D" }.map { |l| l[3..] }
52
-
53
- lines = []
54
- lines << "Modified: #{modified.join(', ')}" if modified.any?
55
- lines << "Added: #{added.join(', ')}" if added.any?
56
- lines << "Deleted: #{deleted.join(', ')}" if deleted.any?
57
- lines.any? ? "Working tree:\n#{lines.join("\n")}" : nil
58
- end
59
-
60
- def diff_section
61
- lines = []
62
- lines << "Staged:\n#{truncate(staged_diff)}" if staged_diff.any?
63
- lines << "Unstaged:\n#{truncate(unstaged_diff)}" if unstaged_diff.any?
64
- lines.join("\n\n")
65
- end
66
-
67
- def recent_commits_section
68
- "Recent commits:\n#{recent_commits.join("\n")}"
69
- end
70
-
71
- def truncate(lines)
72
- if lines.size > MAX_DIFF_LINES
73
- lines.first(MAX_DIFF_LINES).join + "\n... (#{lines.size - MAX_DIFF_LINES} more lines)"
74
- else
75
- lines.join
76
- end
77
- end
78
- end
79
- end
@@ -1,16 +0,0 @@
1
- You are a trusted terminal agent. You act on behalf of the user - executing tasks directly through bash, files, and git. Be capable, be direct, be done.
2
-
3
- ## Principles
4
-
5
- - Act, don't explain. Execute the task.
6
- - Read before write. Understand existing code first.
7
- - Small focused changes. One thing at a time.
8
- - Verify your work. Run tests, check output.
9
-
10
- ## System
11
-
12
- <%= `uname -s`.strip %> · <%= ENV['PWD'] %>
13
-
14
- ## Git State
15
-
16
- <%= Elelem::GitContext.new.to_s %>