zephira 0.1.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 +7 -0
- data/.rspec +3 -0
- data/CHANGELOG.md +36 -0
- data/Dockerfile +39 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +145 -0
- data/README.md +230 -0
- data/Rakefile +12 -0
- data/exe/zephira +6 -0
- data/lib/zephira/agent/status.rb +20 -0
- data/lib/zephira/agent.rb +312 -0
- data/lib/zephira/backends/open_ai_compatible.rb +74 -0
- data/lib/zephira/backends.rb +17 -0
- data/lib/zephira/cli.rb +41 -0
- data/lib/zephira/commands/about.rb +27 -0
- data/lib/zephira/commands/bye.rb +22 -0
- data/lib/zephira/commands/clear.rb +32 -0
- data/lib/zephira/commands/compact.rb +22 -0
- data/lib/zephira/commands/help.rb +22 -0
- data/lib/zephira/commands/history.rb +25 -0
- data/lib/zephira/commands/model.rb +51 -0
- data/lib/zephira/commands.rb +31 -0
- data/lib/zephira/completions/file_names.rb +22 -0
- data/lib/zephira/completions/slash_commands.rb +17 -0
- data/lib/zephira/completions.rb +22 -0
- data/lib/zephira/config.rb +17 -0
- data/lib/zephira/formatter.rb +68 -0
- data/lib/zephira/history.rb +117 -0
- data/lib/zephira/logger.rb +46 -0
- data/lib/zephira/models/base_model.rb +143 -0
- data/lib/zephira/models/chat_gpt41.rb +15 -0
- data/lib/zephira/models/chat_gpt41_mini.rb +15 -0
- data/lib/zephira/models/claude_35_sonnet.rb +15 -0
- data/lib/zephira/models/gpt_5_4.rb +15 -0
- data/lib/zephira/models/gpt_5_5.rb +15 -0
- data/lib/zephira/models/gpt_o4_mini.rb +15 -0
- data/lib/zephira/models/llama4.rb +15 -0
- data/lib/zephira/models.rb +19 -0
- data/lib/zephira/sandbox.rb +193 -0
- data/lib/zephira/tokens.rb +16 -0
- data/lib/zephira/tools/base_tool.rb +105 -0
- data/lib/zephira/tools/code_search.rb +135 -0
- data/lib/zephira/tools/delete_file.rb +47 -0
- data/lib/zephira/tools/http_request.rb +112 -0
- data/lib/zephira/tools/list_directory.rb +57 -0
- data/lib/zephira/tools/memory_delete.rb +39 -0
- data/lib/zephira/tools/memory_list.rb +37 -0
- data/lib/zephira/tools/memory_read.rb +43 -0
- data/lib/zephira/tools/memory_store.rb +51 -0
- data/lib/zephira/tools/memory_write.rb +39 -0
- data/lib/zephira/tools/read_file.rb +90 -0
- data/lib/zephira/tools/shell.rb +82 -0
- data/lib/zephira/tools/update_file.rb +46 -0
- data/lib/zephira/tools/web_search.rb +113 -0
- data/lib/zephira/tools.rb +70 -0
- data/lib/zephira/version.rb +5 -0
- data/lib/zephira.rb +24 -0
- data/license.txt +21 -0
- data/standard.yml +3 -0
- metadata +243 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 1c50d16206adc052c5236333defc539edcd65a533e975794f781427f7364fd10
|
|
4
|
+
data.tar.gz: 69fecd0054fba2316e0aaa02ef529742c5a9de2258091eedada942df3c9f8425
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 20b9495103c802b063d71f197e55f248c0eebc7f1b07d74ca0e41ebd0219a450976e7b246dec0c7d72cdcbbe659b68f8db54443c224d9291abf24df6472fbb40
|
|
7
|
+
data.tar.gz: 859aa00aa284fc405df4f7079cdf322640228986f141ab1a0142743af6c83faffd65ea68a9ba09a4fac1b64be497feaadb81cfbc79b4cb88eec5f9aa0e4841a7
|
data/.rspec
ADDED
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Zephira Changelog
|
|
2
|
+
|
|
3
|
+
## [Unreleased]
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- Concurrent execution of read-only tool calls within a single model turn (`web_search`, `read_file`, `code_search`, `list_directory`, `memory_read`, `memory_list`). Mutating tools still run sequentially in declared order.
|
|
7
|
+
- `Tools::BaseTool.read_only?` class method — tools opt in by overriding it. Default is `false`.
|
|
8
|
+
- `Zephira::Tokens` module — single token-estimator shared by `History` and `Agent`.
|
|
9
|
+
- `Zephira::Agent::Status` extracted to its own file.
|
|
10
|
+
- `Zephira::Tools::MemoryStore` shared helper backing the four memory tools.
|
|
11
|
+
- Per-model `backend` override on `BaseModel` so future provider classes can be added without forking the inference loop.
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
- Renamed `/models` slash command to `/model`.
|
|
15
|
+
- `Agent#run_loop` decomposed into focused helpers (`print_intro`, `render_status_bar`, `process_user_message`, `run_inference_with_spinner`, etc.).
|
|
16
|
+
- Cached `uname -a` and `pwd` at agent init instead of shelling out per request.
|
|
17
|
+
- Inference loop uses iteration instead of recursion for tool-call chains; max-iter guards become trivial to add.
|
|
18
|
+
- Memory tools now load YAML via `YAML.safe_load_file`.
|
|
19
|
+
- Backend `agent` is passed per call rather than held as an ivar; rescue paths nil-guard the agent.
|
|
20
|
+
- Debug toggle moved from raw `ENV["DEBUG"]` to `Config.read("ZEPHIRA_DEBUG")` for consistency.
|
|
21
|
+
- `code_search` tool uses POSIX `command -v` instead of `which`.
|
|
22
|
+
- Spinner elapsed-time updates now go through the public `TTY::Spinner#update` API instead of reaching into private `@tokens` state.
|
|
23
|
+
- `update_file` now allows empty content (declarative `allow_empty: true` is now the single source of truth).
|
|
24
|
+
|
|
25
|
+
### Fixed
|
|
26
|
+
- JSON parse failures on tool arguments now log via `agent.logger.error` with the raw payload instead of being silently swallowed.
|
|
27
|
+
|
|
28
|
+
### Tests
|
|
29
|
+
- Added thread-safe stdout/stderr silencer in `spec_helper` (`:show_output` opt-out).
|
|
30
|
+
- Added default `Config.read` stub in `spec_helper` (`:real_config` opt-out).
|
|
31
|
+
- Broadened error-path coverage for file tools and `Agent::Status`.
|
|
32
|
+
- Suite: 422 examples, 0 failures, ~96% line coverage.
|
|
33
|
+
|
|
34
|
+
## 0.1.0
|
|
35
|
+
|
|
36
|
+
In the beginning...
|
data/Dockerfile
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# syntax=docker/dockerfile:1
|
|
2
|
+
|
|
3
|
+
FROM ruby:3.4-slim AS deps
|
|
4
|
+
|
|
5
|
+
WORKDIR /build
|
|
6
|
+
|
|
7
|
+
RUN apt-get update -qq && \
|
|
8
|
+
apt-get install -y --no-install-recommends \
|
|
9
|
+
build-essential \
|
|
10
|
+
git \
|
|
11
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
12
|
+
|
|
13
|
+
COPY Gemfile Gemfile.lock zephira.gemspec ./
|
|
14
|
+
COPY lib/zephira/version.rb lib/zephira/version.rb
|
|
15
|
+
|
|
16
|
+
ENV BUNDLE_WITHOUT="development:test"
|
|
17
|
+
|
|
18
|
+
RUN bundle install --jobs 4
|
|
19
|
+
|
|
20
|
+
COPY . .
|
|
21
|
+
RUN gem build zephira.gemspec
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
FROM ruby:3.4-slim AS runtime
|
|
25
|
+
|
|
26
|
+
RUN apt-get update -qq && \
|
|
27
|
+
apt-get install -y --no-install-recommends \
|
|
28
|
+
libreadline-dev \
|
|
29
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
30
|
+
|
|
31
|
+
COPY --from=deps /usr/local/bundle /usr/local/bundle
|
|
32
|
+
COPY --from=deps /build/zephira-*.gem /tmp/
|
|
33
|
+
|
|
34
|
+
RUN gem install --local --no-document /tmp/zephira-*.gem && \
|
|
35
|
+
rm -f /tmp/zephira-*.gem
|
|
36
|
+
|
|
37
|
+
WORKDIR /workspace
|
|
38
|
+
|
|
39
|
+
CMD ["zephira"]
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
PATH
|
|
2
|
+
remote: .
|
|
3
|
+
specs:
|
|
4
|
+
zephira (0.1.0)
|
|
5
|
+
faraday (~> 2.0)
|
|
6
|
+
tty-cursor (~> 0.7)
|
|
7
|
+
tty-screen (~> 0.8)
|
|
8
|
+
tty-spinner (~> 0.9)
|
|
9
|
+
|
|
10
|
+
GEM
|
|
11
|
+
remote: https://rubygems.org/
|
|
12
|
+
specs:
|
|
13
|
+
addressable (2.9.0)
|
|
14
|
+
public_suffix (>= 2.0.2, < 8.0)
|
|
15
|
+
ast (2.4.3)
|
|
16
|
+
bigdecimal (4.1.2)
|
|
17
|
+
crack (1.0.1)
|
|
18
|
+
bigdecimal
|
|
19
|
+
rexml
|
|
20
|
+
date (3.5.1)
|
|
21
|
+
diff-lcs (1.6.2)
|
|
22
|
+
docile (1.4.1)
|
|
23
|
+
erb (6.0.3)
|
|
24
|
+
fakefs (3.2.1)
|
|
25
|
+
faraday (2.14.1)
|
|
26
|
+
faraday-net_http (>= 2.0, < 3.5)
|
|
27
|
+
json
|
|
28
|
+
logger
|
|
29
|
+
faraday-net_http (3.4.2)
|
|
30
|
+
net-http (~> 0.5)
|
|
31
|
+
hashdiff (1.2.1)
|
|
32
|
+
io-console (0.8.2)
|
|
33
|
+
irb (1.17.0)
|
|
34
|
+
pp (>= 0.6.0)
|
|
35
|
+
prism (>= 1.3.0)
|
|
36
|
+
rdoc (>= 4.0.0)
|
|
37
|
+
reline (>= 0.4.2)
|
|
38
|
+
json (2.19.3)
|
|
39
|
+
language_server-protocol (3.17.0.5)
|
|
40
|
+
lint_roller (1.1.0)
|
|
41
|
+
logger (1.7.0)
|
|
42
|
+
net-http (0.9.1)
|
|
43
|
+
uri (>= 0.11.1)
|
|
44
|
+
parallel (1.28.0)
|
|
45
|
+
parser (3.3.11.1)
|
|
46
|
+
ast (~> 2.4.1)
|
|
47
|
+
racc
|
|
48
|
+
pp (0.6.3)
|
|
49
|
+
prettyprint
|
|
50
|
+
prettyprint (0.2.0)
|
|
51
|
+
prism (1.9.0)
|
|
52
|
+
psych (5.3.1)
|
|
53
|
+
date
|
|
54
|
+
stringio
|
|
55
|
+
public_suffix (7.0.5)
|
|
56
|
+
racc (1.8.1)
|
|
57
|
+
rainbow (3.1.1)
|
|
58
|
+
rdoc (7.2.0)
|
|
59
|
+
erb
|
|
60
|
+
psych (>= 4.0.0)
|
|
61
|
+
tsort
|
|
62
|
+
regexp_parser (2.12.0)
|
|
63
|
+
reline (0.6.3)
|
|
64
|
+
io-console (~> 0.5)
|
|
65
|
+
rexml (3.4.4)
|
|
66
|
+
rspec (3.13.2)
|
|
67
|
+
rspec-core (~> 3.13.0)
|
|
68
|
+
rspec-expectations (~> 3.13.0)
|
|
69
|
+
rspec-mocks (~> 3.13.0)
|
|
70
|
+
rspec-core (3.13.6)
|
|
71
|
+
rspec-support (~> 3.13.0)
|
|
72
|
+
rspec-expectations (3.13.5)
|
|
73
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
74
|
+
rspec-support (~> 3.13.0)
|
|
75
|
+
rspec-mocks (3.13.8)
|
|
76
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
77
|
+
rspec-support (~> 3.13.0)
|
|
78
|
+
rspec-support (3.13.7)
|
|
79
|
+
rubocop (1.84.2)
|
|
80
|
+
json (~> 2.3)
|
|
81
|
+
language_server-protocol (~> 3.17.0.2)
|
|
82
|
+
lint_roller (~> 1.1.0)
|
|
83
|
+
parallel (~> 1.10)
|
|
84
|
+
parser (>= 3.3.0.2)
|
|
85
|
+
rainbow (>= 2.2.2, < 4.0)
|
|
86
|
+
regexp_parser (>= 2.9.3, < 3.0)
|
|
87
|
+
rubocop-ast (>= 1.49.0, < 2.0)
|
|
88
|
+
ruby-progressbar (~> 1.7)
|
|
89
|
+
unicode-display_width (>= 2.4.0, < 4.0)
|
|
90
|
+
rubocop-ast (1.49.1)
|
|
91
|
+
parser (>= 3.3.7.2)
|
|
92
|
+
prism (~> 1.7)
|
|
93
|
+
rubocop-performance (1.26.1)
|
|
94
|
+
lint_roller (~> 1.1)
|
|
95
|
+
rubocop (>= 1.75.0, < 2.0)
|
|
96
|
+
rubocop-ast (>= 1.47.1, < 2.0)
|
|
97
|
+
ruby-progressbar (1.13.0)
|
|
98
|
+
simplecov (0.22.0)
|
|
99
|
+
docile (~> 1.1)
|
|
100
|
+
simplecov-html (~> 0.11)
|
|
101
|
+
simplecov_json_formatter (~> 0.1)
|
|
102
|
+
simplecov-html (0.13.2)
|
|
103
|
+
simplecov_json_formatter (0.1.4)
|
|
104
|
+
standard (1.54.0)
|
|
105
|
+
language_server-protocol (~> 3.17.0.2)
|
|
106
|
+
lint_roller (~> 1.0)
|
|
107
|
+
rubocop (~> 1.84.0)
|
|
108
|
+
standard-custom (~> 1.0.0)
|
|
109
|
+
standard-performance (~> 1.8)
|
|
110
|
+
standard-custom (1.0.2)
|
|
111
|
+
lint_roller (~> 1.0)
|
|
112
|
+
rubocop (~> 1.50)
|
|
113
|
+
standard-performance (1.9.0)
|
|
114
|
+
lint_roller (~> 1.1)
|
|
115
|
+
rubocop-performance (~> 1.26.0)
|
|
116
|
+
stringio (3.2.0)
|
|
117
|
+
tsort (0.2.0)
|
|
118
|
+
tty-cursor (0.7.1)
|
|
119
|
+
tty-screen (0.8.2)
|
|
120
|
+
tty-spinner (0.9.3)
|
|
121
|
+
tty-cursor (~> 0.7)
|
|
122
|
+
unicode-display_width (3.2.0)
|
|
123
|
+
unicode-emoji (~> 4.1)
|
|
124
|
+
unicode-emoji (4.2.0)
|
|
125
|
+
uri (1.1.1)
|
|
126
|
+
webmock (3.26.2)
|
|
127
|
+
addressable (>= 2.8.0)
|
|
128
|
+
crack (>= 0.3.2)
|
|
129
|
+
hashdiff (>= 0.4.0, < 2.0.0)
|
|
130
|
+
|
|
131
|
+
PLATFORMS
|
|
132
|
+
arm64-darwin-24
|
|
133
|
+
ruby
|
|
134
|
+
|
|
135
|
+
DEPENDENCIES
|
|
136
|
+
fakefs (~> 3.2)
|
|
137
|
+
irb (~> 1.17)
|
|
138
|
+
rspec (~> 3.13.2)
|
|
139
|
+
simplecov (~> 0.22)
|
|
140
|
+
standard (~> 1.54)
|
|
141
|
+
webmock (~> 3.0)
|
|
142
|
+
zephira!
|
|
143
|
+
|
|
144
|
+
BUNDLED WITH
|
|
145
|
+
2.6.9
|
data/README.md
ADDED
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
# Zephira
|
|
2
|
+
|
|
3
|
+
Zephira is a command-line AI coding assistant written in Ruby.
|
|
4
|
+
|
|
5
|
+
It runs in your terminal, keeps per-project conversation history, calls a pluggable set of tools, and executes inside a Docker sandbox by default so the agent cannot touch the host system unless you opt out. The codebase is small, plugin-based, and intended to be read end-to-end.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- Interactive terminal chat loop with per-session token-budget tracking and automatic history compaction
|
|
10
|
+
- Built-in slash commands: `/help`, `/about`, `/model`, `/history`, `/compact`, `/clear`, `/bye`
|
|
11
|
+
- Plugin-style tool system — drop a file in `lib/zephira/tools/` and it is auto-loaded:
|
|
12
|
+
- file I/O: `read_file`, `update_file`, `delete_file`, `list_directory`
|
|
13
|
+
- search: `code_search` (ripgrep-backed), `web_search` (Brave Search API)
|
|
14
|
+
- execution: `shell`, `http_request`
|
|
15
|
+
- persistent memory: `memory_read`, `memory_write`, `memory_list`, `memory_delete`
|
|
16
|
+
- Concurrent execution of read-only tool calls in a single turn (mutating tools still run sequentially in declared order)
|
|
17
|
+
- Pluggable model + backend layer — register a new model by dropping a file in `lib/zephira/models/`; backends bind per model class
|
|
18
|
+
- OpenAI-compatible backend out of the box; structured to add provider-specific backends without forking the core loop
|
|
19
|
+
- Docker sandbox enabled by default; `--dangerously-skip-sandbox` to opt out
|
|
20
|
+
- Persistent session log + conversation history under `.zephira/` in each project
|
|
21
|
+
- ~95% line coverage on a focused RSpec suite
|
|
22
|
+
|
|
23
|
+
## Installation
|
|
24
|
+
|
|
25
|
+
Requirements:
|
|
26
|
+
|
|
27
|
+
- Ruby 3.2+
|
|
28
|
+
- Bundler
|
|
29
|
+
- Docker, if you want sandboxed execution
|
|
30
|
+
|
|
31
|
+
Install from RubyGems:
|
|
32
|
+
|
|
33
|
+
```sh
|
|
34
|
+
gem install zephira
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Or install locally for development:
|
|
38
|
+
|
|
39
|
+
```sh
|
|
40
|
+
git clone https://github.com/aarongough/zephira.git
|
|
41
|
+
cd zephira
|
|
42
|
+
bundle install
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Quick start
|
|
46
|
+
|
|
47
|
+
Start Zephira in the current project directory:
|
|
48
|
+
|
|
49
|
+
```sh
|
|
50
|
+
zephira
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Show CLI help:
|
|
54
|
+
|
|
55
|
+
```sh
|
|
56
|
+
zephira --help
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Print the installed version:
|
|
60
|
+
|
|
61
|
+
```sh
|
|
62
|
+
zephira --version
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
To run without Docker sandboxing:
|
|
66
|
+
|
|
67
|
+
```sh
|
|
68
|
+
zephira --dangerously-skip-sandbox
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Warning: skipping the sandbox gives the agent direct access to your real filesystem.
|
|
72
|
+
|
|
73
|
+
## Configuration
|
|
74
|
+
|
|
75
|
+
Zephira reads configuration from:
|
|
76
|
+
|
|
77
|
+
- environment variables
|
|
78
|
+
- `.zephira.yml` in the current project
|
|
79
|
+
- `~/.zephira.yml` in your home directory
|
|
80
|
+
|
|
81
|
+
Environment variables take precedence.
|
|
82
|
+
|
|
83
|
+
Example configuration:
|
|
84
|
+
|
|
85
|
+
```yaml
|
|
86
|
+
ZEPHIRA_API_KEY: "your_api_key_here"
|
|
87
|
+
ZEPHIRA_MODEL: "gpt-4.1-mini"
|
|
88
|
+
ZEPHIRA_BASE_URL: "https://api.openai.com/v1"
|
|
89
|
+
ZEPHIRA_BACKEND: "openai_compatible"
|
|
90
|
+
ZEPHIRA_BASE_IMAGE: "ruby:3.4-slim"
|
|
91
|
+
ZEPHIRA_BRAVE_SEARCH_API_KEY: "your_brave_api_key_here"
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Supported configuration keys
|
|
95
|
+
|
|
96
|
+
- `ZEPHIRA_API_KEY` — API key for the selected LLM backend
|
|
97
|
+
- `ZEPHIRA_MODEL` — model name to use
|
|
98
|
+
- `ZEPHIRA_BASE_URL` — base URL for OpenAI-compatible APIs
|
|
99
|
+
- `ZEPHIRA_BACKEND` — backend adapter identifier
|
|
100
|
+
- `ZEPHIRA_BASE_IMAGE` — base Docker image for sandbox execution
|
|
101
|
+
- `ZEPHIRA_BRAVE_SEARCH_API_KEY` — required for the web search tool
|
|
102
|
+
- `ZEPHIRA_SANDBOX` — internal/advanced flag to disable sandboxing
|
|
103
|
+
|
|
104
|
+
## Sandbox behavior
|
|
105
|
+
|
|
106
|
+
By default, Zephira attempts to run inside Docker for safer execution.
|
|
107
|
+
|
|
108
|
+
When sandboxing is enabled, Zephira re-executes itself inside a container and mounts your current project into `/workspace`. This gives the agent access to the project while helping isolate it from the host system.
|
|
109
|
+
|
|
110
|
+
If Docker is unavailable, Zephira exits with an error and explains how to proceed.
|
|
111
|
+
|
|
112
|
+
You can bypass sandboxing with:
|
|
113
|
+
|
|
114
|
+
```sh
|
|
115
|
+
zephira --dangerously-skip-sandbox
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Use that only if you understand the risks.
|
|
119
|
+
|
|
120
|
+
## Interactive commands
|
|
121
|
+
|
|
122
|
+
Inside Zephira, you can use slash commands:
|
|
123
|
+
|
|
124
|
+
- `/help` — show available commands
|
|
125
|
+
- `/about` — show project information
|
|
126
|
+
- `/model` — list available models
|
|
127
|
+
- `/model set MODEL_NAME` — switch models for the current session
|
|
128
|
+
- `/history` — print conversation history
|
|
129
|
+
- `/compact` — manually compact the conversation history
|
|
130
|
+
- `/clear` — clear the screen
|
|
131
|
+
- `/bye` — exit the session
|
|
132
|
+
|
|
133
|
+
## Available models
|
|
134
|
+
|
|
135
|
+
This repository currently includes model definitions for:
|
|
136
|
+
|
|
137
|
+
- `gpt-4.1`
|
|
138
|
+
- `gpt-4.1-mini`
|
|
139
|
+
- `gpt-5.4`
|
|
140
|
+
- `gpt-5.5`
|
|
141
|
+
- `gpt-o4-mini`
|
|
142
|
+
- `claude-3.5-sonnet`
|
|
143
|
+
- `llama4`
|
|
144
|
+
|
|
145
|
+
The exact names available in the running app are determined by the model classes in `lib/zephira/models`.
|
|
146
|
+
|
|
147
|
+
## Built-in tools
|
|
148
|
+
|
|
149
|
+
Zephira includes tools for:
|
|
150
|
+
|
|
151
|
+
- `read_file`
|
|
152
|
+
- `update_file`
|
|
153
|
+
- `delete_file`
|
|
154
|
+
- `list_directory`
|
|
155
|
+
- `code_search`
|
|
156
|
+
- `shell`
|
|
157
|
+
- `http_request`
|
|
158
|
+
- `web_search`
|
|
159
|
+
- `memory_write`
|
|
160
|
+
- `memory_read`
|
|
161
|
+
- `memory_list`
|
|
162
|
+
- `memory_delete`
|
|
163
|
+
|
|
164
|
+
These tools allow the agent to inspect the project, modify files, run commands, query APIs, and maintain lightweight persistent memory.
|
|
165
|
+
|
|
166
|
+
## Project structure
|
|
167
|
+
|
|
168
|
+
```text
|
|
169
|
+
exe/ Executable entrypoint
|
|
170
|
+
lib/zephira/ Core application code
|
|
171
|
+
lib/zephira/models/ Model definitions
|
|
172
|
+
lib/zephira/tools/ Tool implementations
|
|
173
|
+
lib/zephira/commands/ Slash commands
|
|
174
|
+
lib/zephira/completions/ Readline completions
|
|
175
|
+
spec/ Test suite
|
|
176
|
+
Dockerfile Sandbox/runtime image
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## Development
|
|
180
|
+
|
|
181
|
+
Install dependencies:
|
|
182
|
+
|
|
183
|
+
```sh
|
|
184
|
+
bundle install
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Run the test suite:
|
|
188
|
+
|
|
189
|
+
```sh
|
|
190
|
+
bundle exec rspec
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Run linting:
|
|
194
|
+
|
|
195
|
+
```sh
|
|
196
|
+
bundle exec standardrb --fix
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
## Design goals
|
|
200
|
+
|
|
201
|
+
Zephira favors:
|
|
202
|
+
|
|
203
|
+
- clarity over complexity
|
|
204
|
+
- small, readable components
|
|
205
|
+
- hackability and extension
|
|
206
|
+
- realistic terminal-first workflows
|
|
207
|
+
- sandboxed local agent execution
|
|
208
|
+
|
|
209
|
+
It is best thought of as a lightweight coding assistant and a learning-oriented agent framework, not a full enterprise platform.
|
|
210
|
+
|
|
211
|
+
## Logging and history
|
|
212
|
+
|
|
213
|
+
Zephira stores session information under `.zephira/` in the current project directory, including logs and conversation history. This makes sessions project-local and easy to inspect.
|
|
214
|
+
|
|
215
|
+
## License
|
|
216
|
+
|
|
217
|
+
Released under the MIT License.
|
|
218
|
+
|
|
219
|
+
See:
|
|
220
|
+
|
|
221
|
+
```text
|
|
222
|
+
license.txt
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
## Author
|
|
226
|
+
|
|
227
|
+
Aaron Gough
|
|
228
|
+
|
|
229
|
+
Project home:
|
|
230
|
+
https://github.com/aarongough/zephira
|
data/Rakefile
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "bundler/gem_tasks"
|
|
4
|
+
require "rspec/core/rake_task"
|
|
5
|
+
|
|
6
|
+
RSpec::Core::RakeTask.new(:spec)
|
|
7
|
+
|
|
8
|
+
# use Standard Ruby style guide for linting
|
|
9
|
+
require "standard/rake"
|
|
10
|
+
|
|
11
|
+
task lint: :standard
|
|
12
|
+
task default: %i[spec lint]
|
data/exe/zephira
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Zephira
|
|
4
|
+
class Agent
|
|
5
|
+
class Status
|
|
6
|
+
def initialize(agent)
|
|
7
|
+
@agent = agent
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def verbose(msg)
|
|
11
|
+
return unless @agent.verbose
|
|
12
|
+
@agent.update_status(msg)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def warn(msg)
|
|
16
|
+
@agent.update_status(Formatter.color(:dark_red, msg))
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|