elelem 0.4.0 → 0.4.2

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: 2885faeaffa4f0ee7eff742f50bbf1ee78f257f7989c6401c787c4d4feb5d6a2
4
- data.tar.gz: '0965d3a94ce8633cd01e7471e5688912216794e9b6af49450d0c1a5326e24645'
3
+ metadata.gz: 7c9f3ee321bf585693ae2be5186a3b84f0122f282bcd8cb6d320b92931eb0d13
4
+ data.tar.gz: f9200f6646a49666394493f46a99ec5ebb157d415e35208a8cdb405736c822c1
5
5
  SHA512:
6
- metadata.gz: e00079252cb138588937776e7d37fc28de2e451c1ac72a190f842d29d27df537123a524b3358c6f36a685704b18e5c3a424cd819b3c8eb3ed1259f1937bdf02d
7
- data.tar.gz: c77a7a8b34cf326e812db4ac23a38de0f7841fc1763f18f569a60d783be6719e251ff1eae59234b4da68cb8276c71fb617491ea46d97905ec39e05f5359b405f
6
+ metadata.gz: b62630ba5787d5b7daa55113c01012ade1075f4d9618b43c6a4ce46643b4a29ce3d380c864070f6aa43e26732ae6e20b07f4ce7eb7b4b251b90fd83f5ff5c781
7
+ data.tar.gz: 48929614d89e694d9d153baa195276042d586a537f1197c588156cf8d192afd4b6b134bad5bd30c836a05358ff26607ae6b7531f5f71e33f9e0291f0d5331e2d
data/CHANGELOG.md CHANGED
@@ -1,5 +1,26 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.4.2] - 2025-12-01
4
+
5
+ ### Changed
6
+ - Renamed `exec` tool to `bash` for clarity
7
+ - Improved system prompt with iterative refinements
8
+ - Added environment context variables to system prompt
9
+
10
+ ## [0.4.1] - 2025-11-26
11
+
12
+ ### Added
13
+ - `elelem files` subcommand: generates Claude‑compatible XML file listings.
14
+ - Rake task `files:prompt` to output a ready‑to‑copy list of files for prompts.
15
+
16
+ ### Changed
17
+ - Refactor tool‑call formatting to a more compact JSON payload for better LLM parsing.
18
+ - Updated CI and documentation to use GitHub instead of previous hosting.
19
+ - Runtime validation of command‑line parameters against a JSON schema.
20
+
21
+ ### Fixed
22
+ - Minor documentation and CI workflow adjustments.
23
+
3
24
  ## [0.4.0] - 2025-11-10
4
25
 
5
26
  ### Added
@@ -116,3 +137,4 @@
116
137
  ## [0.1.0] - 2025-08-08
117
138
 
118
139
  - Initial release
140
+
data/README.md CHANGED
@@ -125,13 +125,13 @@ seven tools, each represented by a JSON schema that the LLM can call.
125
125
 
126
126
  | Tool | Purpose | Parameters |
127
127
  | ---- | ------- | ---------- |
128
+ | `bash` | Run shell commands | `cmd`, `args`, `env`, `cwd`, `stdin` |
128
129
  | `eval` | Dynamically create new tools | `code` |
129
130
  | `grep` | Search Git‑tracked files | `query` |
130
131
  | `list` | List tracked files | `path` (optional) |
132
+ | `patch` | Apply a unified diff via `git apply` | `diff` |
131
133
  | `read` | Read file contents | `path` |
132
134
  | `write` | Overwrite a file | `path`, `content` |
133
- | `patch` | Apply a unified diff via `git apply` | `diff` |
134
- | `execute` | Run shell commands | `cmd`, `args`, `env`, `cwd`, `stdin` |
135
135
 
136
136
  ## Tool Definition
137
137
 
data/Rakefile CHANGED
@@ -5,4 +5,15 @@ require "rspec/core/rake_task"
5
5
 
6
6
  RSpec::Core::RakeTask.new(:spec)
7
7
 
8
+ task :files do
9
+ IO.popen(%w[git ls-files], chdir: __dir__, err: IO::NULL) do |ls|
10
+ ls.readlines.each do |f|
11
+ next if f.start_with?(*%w[bin/ spec/ pkg/ .git .rspec Gemfile Rakefile])
12
+ next if f.strip.end_with?(*%w[.toml .txt .md])
13
+
14
+ puts f
15
+ end
16
+ end
17
+ end
18
+
8
19
  task default: %i[spec]
data/lib/elelem/agent.rb CHANGED
@@ -65,20 +65,13 @@ module Elelem
65
65
  HELP
66
66
  end
67
67
 
68
- def format_tool_call(name, args)
69
- case name
70
- when "execute"
71
- cmd = args["cmd"]
72
- cmd_args = args["args"] || []
73
- cmd_args.empty? ? cmd : "#{cmd} #{cmd_args.join(' ')}"
74
- when "grep" then "grep(#{args["query"]})"
75
- when "list" then "list(#{args["path"] || "."})"
76
- when "patch" then "patch(#{args["diff"]&.lines&.count || 0} lines)"
77
- when "read" then "read(#{args["path"]})"
78
- when "write" then "write(#{args["path"]})"
79
- else
80
- "#{name}(#{args.to_s[0...50]})"
81
- end
68
+ def format_tool_call_result(result)
69
+ return if result.nil?
70
+ return result["stdout"] if result["stdout"]
71
+ return result["stderr"] if result["stderr"]
72
+ return result[:error] if result[:error]
73
+
74
+ ""
82
75
  end
83
76
 
84
77
  def execute_turn(messages, tools:)
@@ -88,7 +81,7 @@ module Elelem
88
81
  content = ""
89
82
  tool_calls = []
90
83
 
91
- print "Thinking..."
84
+ print "Assistant> Thinking..."
92
85
  client.chat(messages + turn_context, tools) do |chunk|
93
86
  msg = chunk["message"]
94
87
  if msg
@@ -110,8 +103,9 @@ module Elelem
110
103
  name = call.dig("function", "name")
111
104
  args = call.dig("function", "arguments")
112
105
 
113
- puts "Tool> #{format_tool_call(name, args)}"
106
+ puts "Tool> #{name}(#{args})"
114
107
  result = toolbox.run_tool(name, args)
108
+ puts format_tool_call_result(result)
115
109
  turn_context << { role: "tool", content: JSON.dump(result) }
116
110
  end
117
111
 
@@ -13,7 +13,6 @@ module Elelem
13
13
  type: :string,
14
14
  desc: "Ollama model",
15
15
  default: ENV.fetch("OLLAMA_MODEL", "gpt-oss")
16
-
17
16
  def chat(*)
18
17
  client = Net::Llm::Ollama.new(
19
18
  host: options[:host],
@@ -24,6 +23,20 @@ module Elelem
24
23
  agent.repl
25
24
  end
26
25
 
26
+ desc "files", "Generate CXML of the files"
27
+ def files
28
+ puts '<documents>'
29
+ $stdin.read.split("\n").map(&:strip).reject(&:empty?).each_with_index do |file, i|
30
+ next unless File.file?(file)
31
+
32
+ puts " <document index=\"#{i + 1}\">"
33
+ puts " <source><![CDATA[#{file}]]></source>"
34
+ puts " <document_content><![CDATA[#{File.read(file)}]]></document_content>"
35
+ puts " </document>"
36
+ end
37
+ puts '</documents>'
38
+ end
39
+
27
40
  desc "version", "The version of this CLI"
28
41
  def version
29
42
  say "v#{Elelem::VERSION}"
@@ -45,19 +45,19 @@ module Elelem
45
45
 
46
46
  case mode.sort
47
47
  when [:read]
48
- "#{base}\n\nRead and analyze. Understand before suggesting action."
48
+ "#{base}\n\nYou may read files on the system."
49
49
  when [:write]
50
- "#{base}\n\nWrite clean, thoughtful code."
50
+ "#{base}\n\nYou may write files on the system."
51
51
  when [:execute]
52
- "#{base}\n\nUse shell commands creatively to understand and manipulate the system."
52
+ "#{base}\n\nYou may execute shell commands on the system."
53
53
  when [:read, :write]
54
- "#{base}\n\nFirst understand, then build solutions that integrate well."
54
+ "#{base}\n\nYou may read and write files on the system."
55
55
  when [:execute, :read]
56
- "#{base}\n\nUse commands to deeply understand the system."
56
+ "#{base}\n\nYou may execute shell commands and read files on the system."
57
57
  when [:execute, :write]
58
- "#{base}\n\nCreate and execute freely. Have fun. Be kind."
58
+ "#{base}\n\nYou may execute shell commands and write files on the system."
59
59
  when [:execute, :read, :write]
60
- "#{base}\n\nYou have all tools. Use them wisely."
60
+ "#{base}\n\nYou may read files, write files and execute shell commands on the system."
61
61
  else
62
62
  base
63
63
  end
@@ -1,5 +1,15 @@
1
1
  You are a reasoning coding and system agent.
2
2
 
3
- - Less is more
4
- - No code comments
5
- - No trailing whitespace
3
+ ## System
4
+
5
+ Operating System: <%= `uname -a` %>
6
+ USER: <%= ENV['USER'] %>
7
+ HOME: <%= ENV['HOME'] %>
8
+ SHELL: <%= ENV['SHELL'] %>
9
+ PATH: <%= ENV['PATH'] %>
10
+ PWD: <%= ENV['PWD'] %>
11
+ LANG: <%= ENV['LANG'] %>
12
+ EDITOR: <%= ENV['EDITOR'] %>
13
+ LOGNAME: <%= ENV['LOGNAME'] %>
14
+ TERM: <%= ENV['TERM'] %>
15
+ MAIL: <%= ENV['MAIL'] %>
data/lib/elelem/tool.rb CHANGED
@@ -11,14 +11,15 @@ module Elelem
11
11
  end
12
12
 
13
13
  def call(args)
14
- return ArgumentError.new(args) unless valid?(args)
14
+ unless valid?(args)
15
+ return { error: "Invalid args for #{@name}", received: args.keys, expected: @schema.dig(:function, :parameters, :required) }
16
+ end
15
17
 
16
18
  @block.call(args)
17
19
  end
18
20
 
19
21
  def valid?(args)
20
- # TODO:: Use JSON Schema Validator
21
- true
22
+ JSON::Validator.validate(@schema.dig(:function, :parameters), args)
22
23
  end
23
24
 
24
25
  def to_h
@@ -8,7 +8,7 @@ module Elelem
8
8
  full_path.exist? ? { content: full_path.read } : { error: "File not found: #{path}" }
9
9
  end
10
10
 
11
- EXEC_TOOL = Tool.build("execute", "Execute shell commands directly. Commands run in a shell context. Examples: 'date', 'git status'.", { cmd: { type: "string" }, args: { type: "array", items: { type: "string" } }, env: { type: "object", additionalProperties: { type: "string" } }, cwd: { type: "string", description: "Working directory (defaults to current)" }, stdin: { type: "string" } }, ["cmd"]) do |args|
11
+ BASH_TOOL = Tool.build("bash", "Run shell commands. For git: bash({\"cmd\": \"git\", \"args\": [\"log\", \"--oneline\"]}). Returns stdout/stderr/exit_status.", { cmd: { type: "string" }, args: { type: "array", items: { type: "string" } }, env: { type: "object", additionalProperties: { type: "string" } }, cwd: { type: "string", description: "Working directory (defaults to current)" }, stdin: { type: "string" } }, ["cmd"]) do |args|
12
12
  Elelem.shell.execute(
13
13
  args["cmd"],
14
14
  args: args["args"] || [],
@@ -42,7 +42,7 @@ module Elelem
42
42
  @tools_by_name = {}
43
43
  @tools = { read: [], write: [], execute: [] }
44
44
  add_tool(eval_tool(binding), :execute)
45
- add_tool(EXEC_TOOL, :execute)
45
+ add_tool(BASH_TOOL, :execute)
46
46
  add_tool(GREP_TOOL, :read)
47
47
  add_tool(LIST_TOOL, :read)
48
48
  add_tool(PATCH_TOOL, :write)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Elelem
4
- VERSION = "0.4.0"
4
+ VERSION = "0.4.2"
5
5
  end
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.4.0
4
+ version: 0.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - mo khan
@@ -198,14 +198,14 @@ files:
198
198
  - lib/elelem/tool.rb
199
199
  - lib/elelem/toolbox.rb
200
200
  - lib/elelem/version.rb
201
- homepage: https://gitlab.com/mokhax/elelem
201
+ homepage: https://github.com/xlgmokha/elelem
202
202
  licenses:
203
203
  - MIT
204
204
  metadata:
205
205
  allowed_push_host: https://rubygems.org
206
- homepage_uri: https://gitlab.com/mokhax/elelem
207
- source_code_uri: https://gitlab.com/mokhax/elelem
208
- changelog_uri: https://gitlab.com/mokhax/elelem/-/blob/main/CHANGELOG.md
206
+ homepage_uri: https://github.com/xlgmokha/elelem
207
+ source_code_uri: https://github.com/xlgmokha/elelem
208
+ changelog_uri: https://github.com/xlgmokha/elelem/blob/main/CHANGELOG.md
209
209
  rdoc_options: []
210
210
  require_paths:
211
211
  - lib