Comparing changes
v0.4.0
→
v0.4.1
8 commits
12 files changed
Commits
Changed files (12)
.github
workflow
.github/workflow/ci.yml
@@ -0,0 +1,21 @@
+name: CI
+on:
+ push:
+ branches: [ "main" ]
+ pull_request:
+ branches: [ "main" ]
+permissions:
+ contents: read
+jobs:
+ test:
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ ruby-version: ['3.4']
+ steps:
+ - uses: actions/checkout@v4
+ - uses: ruby/setup-ruby@55283cc23133118229fd3f97f9336ee23a179fcf # v1.146.0
+ with:
+ ruby-version: ${{ matrix.ruby-version }}
+ bundler-cache: true # runs 'bundle install' and caches installed gems automatically
+ - run: sh bin/test
lib/elelem/agent.rb
@@ -65,20 +65,12 @@ module Elelem
HELP
end
- def format_tool_call(name, args)
- case name
- when "execute"
- cmd = args["cmd"]
- cmd_args = args["args"] || []
- cmd_args.empty? ? cmd : "#{cmd} #{cmd_args.join(' ')}"
- when "grep" then "grep(#{args["query"]})"
- when "list" then "list(#{args["path"] || "."})"
- when "patch" then "patch(#{args["diff"]&.lines&.count || 0} lines)"
- when "read" then "read(#{args["path"]})"
- when "write" then "write(#{args["path"]})"
- else
- "#{name}(#{args.to_s[0...50]})"
- end
+ def format_tool_call_result(result)
+ return result["stdout"] if result["stdout"]
+ return result["stderr"] if result["stderr"]
+ return result[:error] if result[:error]
+
+ ""
end
def execute_turn(messages, tools:)
@@ -110,8 +102,9 @@ module Elelem
name = call.dig("function", "name")
args = call.dig("function", "arguments")
- puts "Tool> #{format_tool_call(name, args)}"
+ puts "Tool> #{name}(#{args})"
result = toolbox.run_tool(name, args)
+ puts format_tool_call_result(result)
turn_context << { role: "tool", content: JSON.dump(result) }
end
lib/elelem/application.rb
@@ -13,7 +13,6 @@ module Elelem
type: :string,
desc: "Ollama model",
default: ENV.fetch("OLLAMA_MODEL", "gpt-oss")
-
def chat(*)
client = Net::Llm::Ollama.new(
host: options[:host],
@@ -24,6 +23,20 @@ module Elelem
agent.repl
end
+ desc "files", "Generate CXML of the files"
+ def files
+ puts '<documents>'
+ $stdin.read.split("\n").map(&:strip).reject(&:empty?).each_with_index do |file, i|
+ next unless File.file?(file)
+
+ puts " <document index=\"#{i + 1}\">"
+ puts " <source><![CDATA[#{file}]]></source>"
+ puts " <document_content><![CDATA[#{File.read(file)}]]></document_content>"
+ puts " </document>"
+ end
+ puts '</documents>'
+ end
+
desc "version", "The version of this CLI"
def version
say "v#{Elelem::VERSION}"
lib/elelem/system_prompt.erb
@@ -1,4 +1,4 @@
-You are a reasoning coding and system agent.
+You are a reasoning coding and system agent working from: <%= Dir.pwd %>.
- Less is more
- No code comments
lib/elelem/tool.rb
@@ -17,8 +17,7 @@ module Elelem
end
def valid?(args)
- # TODO:: Use JSON Schema Validator
- true
+ JSON::Validator.validate(@schema.dig(:function, :parameters), args)
end
def to_h
lib/elelem/toolbox.rb
@@ -8,7 +8,7 @@ module Elelem
full_path.exist? ? { content: full_path.read } : { error: "File not found: #{path}" }
end
- 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|
+ EXEC_TOOL = Tool.build("execute", "Run shell commands. For git: execute({\"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|
Elelem.shell.execute(
args["cmd"],
args: args["args"] || [],
lib/elelem/version.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
module Elelem
- VERSION = "0.4.0"
+ VERSION = "0.4.1"
end
.gitlab-ci.yml
@@ -1,12 +0,0 @@
-default:
- image: ruby:3.4.4
-
- before_script:
- - apt-get update && apt-get install -y clang
- - gem update --system '3.7.2'
- - gem install bundler -v 2.7.2
- - bundle install
-
-test:
- script:
- - ./bin/test
CHANGELOG.md
@@ -1,5 +1,10 @@
## [Unreleased]
+## [0.4.1] - 2025-11-26
+
+### Added
+- Updated version to 0.4.1
+
## [0.4.0] - 2025-11-10
### Added
@@ -116,3 +121,17 @@
## [0.1.0] - 2025-08-08
- Initial release
+
+## [0.4.2] - 2025-11-27
+
+### Added
+- `elelem files` subcommand: generates Claude‑compatible XML file listings.
+- Rake task `files:prompt` to output a ready‑to‑copy list of files for prompts.
+
+### Changed
+- Refactor tool‑call formatting to a more compact JSON payload for better LLM parsing.
+- Updated CI and documentation to use GitHub instead of previous hosting.
+- Runtime validation of command‑line parameters against a JSON schema.
+
+### Fixed
+- Minor documentation and CI workflow adjustments.
elelem.gemspec
@@ -10,14 +10,14 @@ Gem::Specification.new do |spec|
spec.summary = "A REPL for Ollama."
spec.description = "A REPL for Ollama."
- spec.homepage = "https://gitlab.com/mokhax/elelem"
+ spec.homepage = "https://github.com/xlgmokha/elelem"
spec.license = "MIT"
spec.required_ruby_version = ">= 3.4.0"
spec.required_rubygems_version = ">= 3.3.11"
spec.metadata["allowed_push_host"] = "https://rubygems.org"
spec.metadata["homepage_uri"] = spec.homepage
- spec.metadata["source_code_uri"] = "https://gitlab.com/mokhax/elelem"
- spec.metadata["changelog_uri"] = "https://gitlab.com/mokhax/elelem/-/blob/main/CHANGELOG.md"
+ spec.metadata["source_code_uri"] = "https://github.com/xlgmokha/elelem"
+ spec.metadata["changelog_uri"] = "https://github.com/xlgmokha/elelem/blob/main/CHANGELOG.md"
# Specify which files should be added to the gem when it is released.
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
Gemfile.lock
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
- elelem (0.4.0)
+ elelem (0.4.1)
erb
fileutils
json
Rakefile
@@ -5,4 +5,15 @@ require "rspec/core/rake_task"
RSpec::Core::RakeTask.new(:spec)
+task :files do
+ IO.popen(%w[git ls-files], chdir: __dir__, err: IO::NULL) do |ls|
+ ls.readlines.each do |f|
+ next if f.start_with?(*%w[bin/ spec/ pkg/ .git .rspec Gemfile Rakefile])
+ next if f.strip.end_with?(*%w[.toml .txt .md])
+
+ puts f
+ end
+ end
+end
+
task default: %i[spec]