botiasloop 0.0.1
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/README.md +343 -0
- data/bin/botiasloop +155 -0
- data/data/skills/skill-creator/SKILL.md +329 -0
- data/data/skills/skill-creator/assets/ruby_api_cli_template.rb +151 -0
- data/data/skills/skill-creator/references/specification.md +99 -0
- data/lib/botiasloop/agent.rb +112 -0
- data/lib/botiasloop/channels/base.rb +248 -0
- data/lib/botiasloop/channels/cli.rb +101 -0
- data/lib/botiasloop/channels/telegram.rb +348 -0
- data/lib/botiasloop/channels.rb +64 -0
- data/lib/botiasloop/channels_manager.rb +299 -0
- data/lib/botiasloop/commands/archive.rb +109 -0
- data/lib/botiasloop/commands/base.rb +54 -0
- data/lib/botiasloop/commands/compact.rb +78 -0
- data/lib/botiasloop/commands/context.rb +34 -0
- data/lib/botiasloop/commands/conversations.rb +40 -0
- data/lib/botiasloop/commands/help.rb +30 -0
- data/lib/botiasloop/commands/label.rb +64 -0
- data/lib/botiasloop/commands/new.rb +21 -0
- data/lib/botiasloop/commands/registry.rb +121 -0
- data/lib/botiasloop/commands/reset.rb +18 -0
- data/lib/botiasloop/commands/status.rb +32 -0
- data/lib/botiasloop/commands/switch.rb +76 -0
- data/lib/botiasloop/commands/system_prompt.rb +20 -0
- data/lib/botiasloop/commands.rb +22 -0
- data/lib/botiasloop/config.rb +58 -0
- data/lib/botiasloop/conversation.rb +189 -0
- data/lib/botiasloop/conversation_manager.rb +225 -0
- data/lib/botiasloop/database.rb +92 -0
- data/lib/botiasloop/loop.rb +115 -0
- data/lib/botiasloop/skills/loader.rb +58 -0
- data/lib/botiasloop/skills/registry.rb +42 -0
- data/lib/botiasloop/skills/skill.rb +75 -0
- data/lib/botiasloop/systemd_service.rb +300 -0
- data/lib/botiasloop/tool.rb +24 -0
- data/lib/botiasloop/tools/registry.rb +68 -0
- data/lib/botiasloop/tools/shell.rb +50 -0
- data/lib/botiasloop/tools/web_search.rb +64 -0
- data/lib/botiasloop/version.rb +5 -0
- data/lib/botiasloop.rb +45 -0
- metadata +250 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 6b2c58deeefe3094bad216a8dd08b0fa9df9ea5e79924a088f77723d88542a64
|
|
4
|
+
data.tar.gz: 0d7bc8c46234f75313694d9c6adc1c35642ef012bf8cce15202d63bdadf52c93
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 6f17a7416ca693846a9070b998a59355de00dd9bbf707461bf28d6ab6469dfb0e6544619f6097a809b86f11acec6e2de33371f1ec60499484ca0c7aaa09fb03c
|
|
7
|
+
data.tar.gz: ff0d76df0c00904b848581c840fa1bae29c8f707a23e38da07698894e488482194c9368760a2c78fced02d0604f750cd3b1f1cae8e29256c240d4d8fbcf4ec7d
|
data/README.md
ADDED
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
# BotiasLoop
|
|
2
|
+
|
|
3
|
+
A minimal agentic AI application built on the ReAct (Reasoning + Acting) loop pattern. BotiasLoop provides an AI agent with shell access and web search capabilities via OpenRouter, designed for dedicated infrastructure following the Rails Doctrine.
|
|
4
|
+
|
|
5
|
+
[](https://www.ruby-lang.org/)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
[](https://github.com/standardrb/standard)
|
|
8
|
+
|
|
9
|
+
## Philosophy
|
|
10
|
+
|
|
11
|
+
**Sharp Knives**: BotiasLoop intentionally provides full shell access without restrictions. This is a feature, not a bug. It's designed for dedicated infrastructure where raw power is needed, not personal devices. The agent can execute any shell command, read any file, and make system changes.
|
|
12
|
+
|
|
13
|
+
Following the Rails Doctrine:
|
|
14
|
+
- **Optimize for programmer happiness**: Beautiful, readable Ruby code
|
|
15
|
+
- **Convention over Configuration**: Sensible defaults, minimal setup required
|
|
16
|
+
- **The menu is omakase**: Curated stack (ruby_llm, StandardRB, RSpec)
|
|
17
|
+
- **No one paradigm**: Practical over pure - use what works
|
|
18
|
+
|
|
19
|
+
## Features
|
|
20
|
+
|
|
21
|
+
### Core
|
|
22
|
+
- **ReAct Loop**: AI reasons, acts using tools, observes results, and repeats
|
|
23
|
+
- **Shell Access**: Execute any shell command (full system access)
|
|
24
|
+
- **Web Search**: Search the web via SearXNG
|
|
25
|
+
- **Conversation Persistence**: SQLite-backed conversation storage with UUID tracking
|
|
26
|
+
- **Token Tracking**: Monitor input/output tokens per conversation
|
|
27
|
+
|
|
28
|
+
### Channels
|
|
29
|
+
- **CLI Mode**: Interactive REPL for local usage
|
|
30
|
+
- **Telegram Bot**: Chat with the agent via Telegram
|
|
31
|
+
- **Multi-Channel**: Run multiple channels simultaneously
|
|
32
|
+
- **Boot Auto-Start**: systemd service with automatic startup on boot
|
|
33
|
+
|
|
34
|
+
### Commands
|
|
35
|
+
Slash commands for conversation management:
|
|
36
|
+
- `/new` - Start a new conversation
|
|
37
|
+
- `/switch <label|uuid>` - Switch to a different conversation
|
|
38
|
+
- `/label <name>` - Label the current conversation
|
|
39
|
+
- `/conversations` - List all conversations
|
|
40
|
+
- `/reset` - Clear current conversation history
|
|
41
|
+
- `/compact` - Summarize and archive old messages
|
|
42
|
+
- `/status` - Show current model, token usage
|
|
43
|
+
- `/archive` - Archive old conversations
|
|
44
|
+
- `/system_prompt` - Show current system prompt
|
|
45
|
+
- `/help` - Show available commands
|
|
46
|
+
|
|
47
|
+
### Skills System
|
|
48
|
+
Skills follow the [agentskills.io](https://agentskills.io) specification:
|
|
49
|
+
- Load default skills from `data/skills/`
|
|
50
|
+
- Load custom skills from `~/skills/`
|
|
51
|
+
- Progressive disclosure: name/description in system prompt, full content on demand
|
|
52
|
+
- Includes `skill-creator` skill for creating new skills
|
|
53
|
+
|
|
54
|
+
## Installation
|
|
55
|
+
|
|
56
|
+
### Prerequisites
|
|
57
|
+
|
|
58
|
+
- Ruby 3.4 or higher
|
|
59
|
+
- OpenRouter API key
|
|
60
|
+
- (Optional) SearXNG instance for web search
|
|
61
|
+
|
|
62
|
+
### Via RubyGems
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
gem install botiasloop
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### From Source
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
git clone https://github.com/0x7466/botiasloop.git
|
|
72
|
+
cd botiasloop
|
|
73
|
+
bundle install
|
|
74
|
+
bundle exec rake install
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Using mise (Recommended)
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
# Install mise if not already installed
|
|
81
|
+
curl https://mise.run | sh
|
|
82
|
+
|
|
83
|
+
# Install Ruby and dependencies
|
|
84
|
+
mise install
|
|
85
|
+
|
|
86
|
+
# Run with mise-managed Ruby
|
|
87
|
+
mise exec ruby -- bundle install
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Configuration
|
|
91
|
+
|
|
92
|
+
Create `~/.config/botiasloop/config.yml`:
|
|
93
|
+
|
|
94
|
+
```yaml
|
|
95
|
+
# Required: OpenRouter configuration
|
|
96
|
+
providers:
|
|
97
|
+
openrouter:
|
|
98
|
+
api_key: "your-openrouter-api-key" # Or set BOTIASLOOP_API_KEY env var
|
|
99
|
+
model: "moonshotai/kimi-k2.5" # Any OpenRouter model
|
|
100
|
+
|
|
101
|
+
# Optional: Web search configuration
|
|
102
|
+
tools:
|
|
103
|
+
web_search:
|
|
104
|
+
searxng_url: "http://localhost:8080" # Your SearXNG instance
|
|
105
|
+
|
|
106
|
+
# Optional: Maximum ReAct iterations (default: 20)
|
|
107
|
+
max_iterations: 20
|
|
108
|
+
|
|
109
|
+
# Optional: Telegram channel
|
|
110
|
+
channels:
|
|
111
|
+
telegram:
|
|
112
|
+
bot_token: "your-telegram-bot-token"
|
|
113
|
+
allowed_users: [] # Empty = allow all, or list specific user IDs
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Environment Variables
|
|
117
|
+
|
|
118
|
+
- `BOTIASLOOP_API_KEY` - OpenRouter API key (overrides config file)
|
|
119
|
+
- `BOTIASLOOP_SEARXNG_URL` - SearXNG URL (overrides config file)
|
|
120
|
+
|
|
121
|
+
## Usage
|
|
122
|
+
|
|
123
|
+
### CLI Mode
|
|
124
|
+
|
|
125
|
+
Start interactive REPL:
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
botiasloop cli
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Exit with: `exit`, `quit`, `\q`, or Ctrl+C
|
|
132
|
+
|
|
133
|
+
### Gateway Mode (Telegram Bot)
|
|
134
|
+
|
|
135
|
+
Start the gateway to enable Telegram and other channels:
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
# Run in foreground
|
|
139
|
+
botiasloop gateway
|
|
140
|
+
|
|
141
|
+
# Systemd service management (boot auto-start)
|
|
142
|
+
botiasloop gateway enable # Install and enable boot auto-start
|
|
143
|
+
botiasloop gateway start # Start the service now
|
|
144
|
+
botiasloop gateway status # Check service status
|
|
145
|
+
botiasloop gateway stop # Stop the service
|
|
146
|
+
botiasloop gateway disable # Disable boot auto-start and uninstall
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### One-Shot Mode
|
|
150
|
+
|
|
151
|
+
Send a single message:
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
botiasloop "What's the weather in Tokyo?"
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Example Session
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
$ botiasloop cli
|
|
161
|
+
|
|
162
|
+
botiasloop v0.0.1 - Interactive Mode
|
|
163
|
+
Type 'exit', 'quit', or '\q' to exit
|
|
164
|
+
|
|
165
|
+
You: What files are in this directory?
|
|
166
|
+
|
|
167
|
+
Agent: I'll check what files are in the current directory for you.
|
|
168
|
+
|
|
169
|
+
[Tool] Executing shell with arguments: {"command"=>"ls -la"}
|
|
170
|
+
|
|
171
|
+
Exit: 0
|
|
172
|
+
Stdout:
|
|
173
|
+
total 128
|
|
174
|
+
drwxr-xr-x 10 user staff 320 Feb 22 14:00 .
|
|
175
|
+
drwxr-xr-x 5 user staff 160 Feb 22 13:00 ..
|
|
176
|
+
-rw-r--r-- 1 user staff 2345 Feb 22 14:00 README.md
|
|
177
|
+
...
|
|
178
|
+
|
|
179
|
+
Here are the files in your current directory...
|
|
180
|
+
|
|
181
|
+
You: /label my-project
|
|
182
|
+
|
|
183
|
+
Agent: **Conversation labeled as `my-project`**
|
|
184
|
+
|
|
185
|
+
You: exit
|
|
186
|
+
|
|
187
|
+
Goodbye!
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
## Development
|
|
191
|
+
|
|
192
|
+
### Setup
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
# Clone repository
|
|
196
|
+
git clone https://github.com/0x7466/botiasloop.git
|
|
197
|
+
cd botiasloop
|
|
198
|
+
|
|
199
|
+
# Install dependencies
|
|
200
|
+
bundle install
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### Testing
|
|
204
|
+
|
|
205
|
+
Test-first development is required:
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
# Run all tests
|
|
209
|
+
bundle exec rspec
|
|
210
|
+
|
|
211
|
+
# Run specific test file
|
|
212
|
+
bundle exec rspec spec/unit/agent_spec.rb
|
|
213
|
+
|
|
214
|
+
# Run specific test by line number
|
|
215
|
+
bundle exec rspec spec/unit/agent_spec.rb:42
|
|
216
|
+
|
|
217
|
+
# Check coverage (after running tests)
|
|
218
|
+
open coverage/index.html
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### Linting
|
|
222
|
+
|
|
223
|
+
Code must pass StandardRB with zero offenses:
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
# Check for offenses
|
|
227
|
+
bundle exec standardrb
|
|
228
|
+
|
|
229
|
+
# Auto-fix offenses
|
|
230
|
+
bundle exec standardrb --fix
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### Default Rake Task
|
|
234
|
+
|
|
235
|
+
```bash
|
|
236
|
+
# Run tests + linting
|
|
237
|
+
bundle exec rake
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
## Architecture
|
|
241
|
+
|
|
242
|
+
```
|
|
243
|
+
botiasloop/
|
|
244
|
+
├── bin/
|
|
245
|
+
│ └── botiasloop # CLI executable
|
|
246
|
+
├── lib/
|
|
247
|
+
│ ├── botiasloop.rb # Main entry point
|
|
248
|
+
│ └── botiasloop/
|
|
249
|
+
│ ├── agent.rb # Main orchestrator
|
|
250
|
+
│ ├── loop.rb # ReAct cycle implementation
|
|
251
|
+
│ ├── config.rb # Configuration management
|
|
252
|
+
│ ├── conversation.rb # Conversation persistence (SQLite)
|
|
253
|
+
│ ├── tool.rb # Base tool class
|
|
254
|
+
│ ├── tools/
|
|
255
|
+
│ │ ├── registry.rb # Tool registration
|
|
256
|
+
│ │ ├── shell.rb # Shell execution
|
|
257
|
+
│ │ └── web_search.rb # SearXNG search
|
|
258
|
+
│ ├── skills/
|
|
259
|
+
│ │ ├── skill.rb # Skill model
|
|
260
|
+
│ │ ├── loader.rb # Skill loading
|
|
261
|
+
│ │ └── registry.rb # Skill registry
|
|
262
|
+
│ ├── commands/
|
|
263
|
+
│ │ ├── registry.rb # Command registry
|
|
264
|
+
│ │ ├── context.rb # Execution context
|
|
265
|
+
│ │ └── *.rb # Individual commands
|
|
266
|
+
│ ├── channels/
|
|
267
|
+
│ │ ├── base.rb # Channel base class
|
|
268
|
+
│ │ ├── cli.rb # CLI channel
|
|
269
|
+
│ │ └── telegram.rb # Telegram bot
|
|
270
|
+
│ └── channels_manager.rb # Multi-channel orchestration
|
|
271
|
+
├── data/
|
|
272
|
+
│ └── skills/ # Default skills
|
|
273
|
+
├── spec/ # Test suite
|
|
274
|
+
└── README.md # This file
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
## Security
|
|
278
|
+
|
|
279
|
+
⚠️ **IMPORTANT**: BotiasLoop provides full shell access. The AI agent can:
|
|
280
|
+
- Execute any shell command
|
|
281
|
+
- Read, write, and delete any file
|
|
282
|
+
- Install software
|
|
283
|
+
- Modify system configuration
|
|
284
|
+
- Access network resources
|
|
285
|
+
|
|
286
|
+
**Use only on dedicated infrastructure**, never on personal devices or production systems containing sensitive data.
|
|
287
|
+
|
|
288
|
+
### Future Security Features (Roadmap)
|
|
289
|
+
- Sandboxed execution (Docker/Firejail)
|
|
290
|
+
- Command whitelist/blacklist
|
|
291
|
+
- Confirmation for destructive operations
|
|
292
|
+
- Read-only mode option
|
|
293
|
+
- Secret management integration
|
|
294
|
+
|
|
295
|
+
## Roadmap
|
|
296
|
+
|
|
297
|
+
See [ROADMAP.md](ROADMAP.md) for detailed planned features including:
|
|
298
|
+
|
|
299
|
+
- **Persistent Memory**: Vector database for semantic search
|
|
300
|
+
- **Custom Tools**: Load tools from `~/tools/`
|
|
301
|
+
- **Conversation Compaction**: Automatic summarization
|
|
302
|
+
- **Subagents**: Specialized agent instances
|
|
303
|
+
- **Streaming Responses**: Real-time token display
|
|
304
|
+
- **Multi-Modal**: Image analysis, audio transcription
|
|
305
|
+
- **Web Dashboard**: Browser-based management UI
|
|
306
|
+
- **Plugin System**: Load plugins from gems
|
|
307
|
+
|
|
308
|
+
## Contributing
|
|
309
|
+
|
|
310
|
+
1. Fork the repository
|
|
311
|
+
2. Create a feature branch
|
|
312
|
+
3. Write tests first (TDD required)
|
|
313
|
+
4. Implement the feature
|
|
314
|
+
5. Ensure all tests pass: `bundle exec rspec`
|
|
315
|
+
6. Ensure zero linting offenses: `bundle exec standardrb`
|
|
316
|
+
7. Commit with descriptive message
|
|
317
|
+
8. Push to your fork
|
|
318
|
+
9. Create a Pull Request
|
|
319
|
+
|
|
320
|
+
### Development Principles
|
|
321
|
+
|
|
322
|
+
- **Test-First**: All features built using TDD
|
|
323
|
+
- **Sharp Knives**: Keep raw power, minimal restrictions
|
|
324
|
+
- **Rails Doctrine**: Optimize for programmer happiness
|
|
325
|
+
- **Privacy First**: Local-first, user-controlled data
|
|
326
|
+
- **Unix Philosophy**: Do one thing well, compose with other tools
|
|
327
|
+
|
|
328
|
+
## License
|
|
329
|
+
|
|
330
|
+
MIT License - see [LICENSE](LICENSE) file for details.
|
|
331
|
+
|
|
332
|
+
## Credits
|
|
333
|
+
|
|
334
|
+
Built by [Tobias Feistmantl](https://github.com/0x7466) with inspiration from nanobot and the Ruby on Rails doctrine.
|
|
335
|
+
|
|
336
|
+
Powered by:
|
|
337
|
+
- [ruby_llm](https://github.com/crmne/ruby_llm) - Unified LLM API
|
|
338
|
+
- [OpenRouter](https://openrouter.ai/) - Unified LLM API gateway
|
|
339
|
+
- [SearXNG](https://docs.searxng.org/) - Privacy-respecting metasearch
|
|
340
|
+
|
|
341
|
+
---
|
|
342
|
+
|
|
343
|
+
**⚡ Built with sharp knives. Use responsibly.**
|
data/bin/botiasloop
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require_relative "../lib/botiasloop"
|
|
5
|
+
|
|
6
|
+
def print_help
|
|
7
|
+
puts "botiasloop - Minimal agentic AI with ReAct loop"
|
|
8
|
+
puts
|
|
9
|
+
puts "Usage: botiasloop [OPTIONS] [COMMAND]"
|
|
10
|
+
puts
|
|
11
|
+
puts "Options:"
|
|
12
|
+
puts " -h, --help Show this help message"
|
|
13
|
+
puts " -v, --version Show version information"
|
|
14
|
+
puts
|
|
15
|
+
puts "Commands:"
|
|
16
|
+
puts " cli Start interactive REPL mode"
|
|
17
|
+
puts " gateway Start gateway (Telegram bot and other channels)"
|
|
18
|
+
puts " help Show this help message"
|
|
19
|
+
puts
|
|
20
|
+
puts "Gateway Commands:"
|
|
21
|
+
puts " start Start the systemd service"
|
|
22
|
+
puts " stop Stop the systemd service"
|
|
23
|
+
puts " restart Restart the systemd service"
|
|
24
|
+
puts " status Show systemd service status"
|
|
25
|
+
puts " enable Install and enable systemd service (auto-start on login)"
|
|
26
|
+
puts " disable Disable and uninstall systemd service"
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def start_gateway(config)
|
|
30
|
+
# Check if any channels are configured (excluding CLI)
|
|
31
|
+
available_channels = Botiasloop::Channels.registry.channels.except(:cli)
|
|
32
|
+
|
|
33
|
+
if available_channels.empty?
|
|
34
|
+
puts "No gateway channels configured."
|
|
35
|
+
puts "Configure at least one channel (e.g., Telegram) in ~/.config/botiasloop/config.yml"
|
|
36
|
+
exit 1
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
manager = Botiasloop::ChannelsManager.new(config)
|
|
40
|
+
|
|
41
|
+
# Start all channels and wait
|
|
42
|
+
manager.start_channels.wait
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
if ARGV[0] == "-h" || ARGV[0] == "--help"
|
|
46
|
+
print_help
|
|
47
|
+
elsif ARGV[0] == "-v" || ARGV[0] == "--version"
|
|
48
|
+
puts "botiasloop #{Botiasloop::VERSION}"
|
|
49
|
+
elsif ARGV[0] == "gateway"
|
|
50
|
+
config = Botiasloop::Config.new
|
|
51
|
+
|
|
52
|
+
if ARGV[1] == "start"
|
|
53
|
+
service = Botiasloop::SystemdService.new(config)
|
|
54
|
+
if service.systemd_available?
|
|
55
|
+
begin
|
|
56
|
+
service.start
|
|
57
|
+
puts "Service started"
|
|
58
|
+
rescue Botiasloop::SystemdError => e
|
|
59
|
+
puts "Error: #{e.message}"
|
|
60
|
+
exit 1
|
|
61
|
+
end
|
|
62
|
+
else
|
|
63
|
+
puts "Error: systemd is not available on this system"
|
|
64
|
+
exit 1
|
|
65
|
+
end
|
|
66
|
+
elsif ARGV[1] == "stop"
|
|
67
|
+
service = Botiasloop::SystemdService.new(config)
|
|
68
|
+
if service.systemd_available?
|
|
69
|
+
begin
|
|
70
|
+
service.stop
|
|
71
|
+
puts "Service stopped"
|
|
72
|
+
rescue Botiasloop::SystemdError => e
|
|
73
|
+
puts "Error: #{e.message}"
|
|
74
|
+
exit 1
|
|
75
|
+
end
|
|
76
|
+
else
|
|
77
|
+
puts "Error: systemd is not available on this system"
|
|
78
|
+
exit 1
|
|
79
|
+
end
|
|
80
|
+
elsif ARGV[1] == "restart"
|
|
81
|
+
service = Botiasloop::SystemdService.new(config)
|
|
82
|
+
if service.systemd_available?
|
|
83
|
+
begin
|
|
84
|
+
service.restart
|
|
85
|
+
puts "Service restarted"
|
|
86
|
+
rescue Botiasloop::SystemdError => e
|
|
87
|
+
puts "Error: #{e.message}"
|
|
88
|
+
exit 1
|
|
89
|
+
end
|
|
90
|
+
else
|
|
91
|
+
puts "Error: systemd is not available on this system"
|
|
92
|
+
exit 1
|
|
93
|
+
end
|
|
94
|
+
elsif ARGV[1] == "status"
|
|
95
|
+
service = Botiasloop::SystemdService.new(config)
|
|
96
|
+
if service.systemd_available?
|
|
97
|
+
status = service.status
|
|
98
|
+
puts "Service status: #{status[:message]}"
|
|
99
|
+
exit(status[:active] ? 0 : 1)
|
|
100
|
+
else
|
|
101
|
+
puts "Error: systemd is not available on this system"
|
|
102
|
+
exit 1
|
|
103
|
+
end
|
|
104
|
+
elsif ARGV[1] == "enable"
|
|
105
|
+
service = Botiasloop::SystemdService.new(config)
|
|
106
|
+
if service.systemd_available?
|
|
107
|
+
begin
|
|
108
|
+
service.install unless service.installed?
|
|
109
|
+
service.enable
|
|
110
|
+
puts "Service installed and enabled. Run 'botiasloop gateway start' to start now."
|
|
111
|
+
puts "The service will start automatically on your next login."
|
|
112
|
+
rescue Botiasloop::SystemdError => e
|
|
113
|
+
puts "Error: #{e.message}"
|
|
114
|
+
exit 1
|
|
115
|
+
end
|
|
116
|
+
else
|
|
117
|
+
puts "Error: systemd is not available on this system"
|
|
118
|
+
exit 1
|
|
119
|
+
end
|
|
120
|
+
elsif ARGV[1] == "disable"
|
|
121
|
+
service = Botiasloop::SystemdService.new(config)
|
|
122
|
+
if service.systemd_available?
|
|
123
|
+
begin
|
|
124
|
+
if service.installed?
|
|
125
|
+
service.uninstall
|
|
126
|
+
puts "Service disabled and uninstalled"
|
|
127
|
+
else
|
|
128
|
+
puts "Service is not installed"
|
|
129
|
+
end
|
|
130
|
+
rescue Botiasloop::SystemdError => e
|
|
131
|
+
puts "Error: #{e.message}"
|
|
132
|
+
exit 1
|
|
133
|
+
end
|
|
134
|
+
else
|
|
135
|
+
puts "Error: systemd is not available on this system"
|
|
136
|
+
exit 1
|
|
137
|
+
end
|
|
138
|
+
else
|
|
139
|
+
start_gateway(config)
|
|
140
|
+
end
|
|
141
|
+
elsif ARGV[0] == "cli"
|
|
142
|
+
# CLI interactive mode
|
|
143
|
+
config = Botiasloop::Config.new
|
|
144
|
+
cli_channel = Botiasloop::Channels::CLI.new(config)
|
|
145
|
+
cli_channel.start
|
|
146
|
+
elsif ARGV.empty? || ARGV[0] == "help"
|
|
147
|
+
# Default to help when no args or explicit help command
|
|
148
|
+
print_help
|
|
149
|
+
else
|
|
150
|
+
# Unknown command
|
|
151
|
+
puts "Unknown command: #{ARGV[0]}"
|
|
152
|
+
puts
|
|
153
|
+
print_help
|
|
154
|
+
exit 1
|
|
155
|
+
end
|