SHA256
90 lines
3.7 KiB
Markdown
90 lines
3.7 KiB
Markdown
# sjcode
|
|
|
|
ein terminal coding agent, der die ollama API nutzt
|
|
|
|
## Setup
|
|
|
|
```bash
|
|
cp config.toml.example config.toml # then edit port / model / limits
|
|
python3 server/server.py # starts the daemon + admin CLI
|
|
```
|
|
|
|
`config.toml` is machine-local and git-ignored; `config.toml.example` is the
|
|
template. On first start the daemon creates the SQLite database (`sjcode.db`).
|
|
|
|
## Daemon (server.py)
|
|
|
|
On startup it prints its settings and drops into a minimal admin CLI
|
|
(accounts are stored in SQLite):
|
|
|
|
| command | effect |
|
|
|--------------------------|-------------------------------------------------|
|
|
| `create <name> [role]` | create account (asks for password, default role `user`) |
|
|
| `list` | show all accounts |
|
|
| `delete <name>` | remove account |
|
|
| `role <name> <role>` | change role |
|
|
| `passwd <name>` | set a new password |
|
|
| `usage [name]` | used minutes today vs. limit |
|
|
| `reset [name]` | reset the daily usage counter |
|
|
| `status` | show daemon settings |
|
|
| `quit` | stop the daemon |
|
|
|
|
While the CLI runs, an HTTP API is served in the background:
|
|
|
|
- `POST /login` — `{"username", "password"}` → `{"token", ...}`
|
|
- `POST /chat` — `{"token", "message", "model"?}` → `{"response", ...}`
|
|
- `GET /models?token=...` — list ollama models
|
|
|
|
Every user row stores: `username`, `password_hash`, `last_logged_in`,
|
|
`role`, `used_today` (minutes of AI usage; resets on a new day).
|
|
|
|
## Roles and limits
|
|
|
|
In `config.toml` each role gets a daily limit in minutes:
|
|
|
|
```toml
|
|
[limits]
|
|
user = 120 # default role for new accounts
|
|
admin = -1 # negative = unlimited
|
|
```
|
|
|
|
Login and every chat request are blocked once `used_today` reaches the limit.
|
|
|
|
## Client (client.py)
|
|
|
|
```bash
|
|
./coder # or: python3 client.py
|
|
python3 client.py 10.0.0.5:8420 # explicit daemon address
|
|
python3 client.py --model qwen3-coder # skip the model picker
|
|
python3 client.py --no-probe # skip the reachability check (use behind
|
|
# HTTP proxies that answer on every port)
|
|
```
|
|
|
|
On start the client asks which server to connect to: pick one of the saved
|
|
ones, or add a new one (`n`). Every server you use is saved in
|
|
`~/.config/sjcode/client.json` together with the username and the last
|
|
model, so the next start is just Enter-Enter. Addresses without a port use
|
|
8420; `host:port`, `http(s)://...` URLs and IPv6 literals are accepted.
|
|
|
|
After login and model choice you get the agent banner and a chat REPL.
|
|
Commands:
|
|
|
|
| command | effect |
|
|
|---------------|-----------------------------------------|
|
|
| `/help` | list commands |
|
|
| `/server` | show the connected server |
|
|
| `/models` | list models on the server |
|
|
| `/model <n>` | switch model (saved for this server) |
|
|
| `/limit` | remaining minutes today (last known) |
|
|
| `/clear` | forget the conversation history |
|
|
| `/quit` | exit |
|
|
|
|
Anything else is sent to the model. The client keeps the last few turns as
|
|
context (the daemon API itself is stateless) and renders the reply in the
|
|
agent style (`✓` lines for actions the model reports).
|
|
|
|
## Requirements
|
|
|
|
- Python 3.11+ (stdlib only; `tomllib` is included)
|
|
- ollama listening on the address from `config.toml`
|