ework-aio 0.1.3 → 0.1.5
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.
- package/README.md +82 -7
- package/bin/install.sh +255 -10
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -13,11 +13,21 @@ All-in-one installer for the **ework** self-hosted AI development stack:
|
|
|
13
13
|
## Quick start
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
|
-
|
|
16
|
+
# Recommended: user-level install (no sudo needed)
|
|
17
|
+
npm install -g ework-aio --prefix ~/.local && ework-aio install
|
|
17
18
|
```
|
|
18
19
|
|
|
19
20
|
That's the whole install. When it finishes it prints your login URL, operator login, and token.
|
|
20
21
|
|
|
22
|
+
> **PATH heads-up:** `--prefix ~/.local` puts bin shims at `~/.local/bin/`.
|
|
23
|
+
> Most distros already have `~/.local/bin` on PATH (via `systemd-user-sessions`
|
|
24
|
+
> or `~/.profile`). If `command -v ework-aio` fails after install, add this to
|
|
25
|
+
> your `~/.bashrc` / `~/.zshrc`:
|
|
26
|
+
>
|
|
27
|
+
> ```bash
|
|
28
|
+
> export PATH="$HOME/.local/bin:$PATH"
|
|
29
|
+
> ```
|
|
30
|
+
|
|
21
31
|
### Prerequisites
|
|
22
32
|
|
|
23
33
|
The install command checks for these and aborts with a hint if any are missing:
|
|
@@ -30,19 +40,28 @@ The install command checks for these and aborts with a hint if any are missing:
|
|
|
30
40
|
| `systemctl` | any | systemd-based Linux |
|
|
31
41
|
| `openssl`/`curl`/`jq`/`awk` | any | your distro package manager |
|
|
32
42
|
|
|
33
|
-
###
|
|
43
|
+
### Install variants
|
|
34
44
|
|
|
35
45
|
```bash
|
|
46
|
+
# System-level install (needs sudo; services run as root, units in /etc/systemd/system)
|
|
47
|
+
sudo npm install -g ework-aio && sudo ework-aio install --system
|
|
48
|
+
|
|
36
49
|
# Run without installing globally (downloads + runs once)
|
|
37
50
|
npx ework-aio install
|
|
38
51
|
|
|
39
|
-
#
|
|
40
|
-
HTTPS_PROXY=http://127.0.0.1:7890 npm install -g ework-aio && ework-aio install
|
|
41
|
-
|
|
42
|
-
# User-level install (no sudo) — uses ~/.local as npm prefix
|
|
43
|
-
npm install -g ework-aio --prefix ~/.local && ework-aio install
|
|
52
|
+
# Route through an HTTP proxy if npm registry is slow on your machine
|
|
53
|
+
HTTPS_PROXY=http://127.0.0.1:7890 npm install -g ework-aio --prefix ~/.local && ework-aio install
|
|
44
54
|
```
|
|
45
55
|
|
|
56
|
+
User-level (default in this README) keeps everything under your home directory:
|
|
57
|
+
|
|
58
|
+
- bins: `~/.local/bin/`
|
|
59
|
+
- npm package files: `~/.local/lib/node/`
|
|
60
|
+
- data: `~/.local/share/ework-aio/`
|
|
61
|
+
- systemd units: `~/.config/systemd/user/`
|
|
62
|
+
|
|
63
|
+
`sudo` is never required; uninstall is `rm -rf ~/.local/share/ework-aio && npm uninstall -g ework-aio --prefix ~/.local`.
|
|
64
|
+
|
|
46
65
|
### Why two steps?
|
|
47
66
|
|
|
48
67
|
`npm install -g ework-aio` **only** lays down files: the bin launcher and the bash installer. It does **not** run the installer. The second `ework-aio install` step is what actually:
|
|
@@ -84,6 +103,12 @@ ework-aio uninstall Stop services and remove units (data preserved)
|
|
|
84
103
|
ework-aio status Show service status
|
|
85
104
|
ework-aio logs [web|daemon] Tail logs
|
|
86
105
|
ework-aio env Print key paths (no secrets)
|
|
106
|
+
ework-aio config <subcommand> Read / change runtime .env keys
|
|
107
|
+
config list List settable keys + current values
|
|
108
|
+
config get <KEY> Print one key's current value
|
|
109
|
+
config set <KEY> <VALUE> Set a key, then restart affected service
|
|
110
|
+
(use --no-restart to defer)
|
|
111
|
+
config restart <web|daemon|both> Restart one or both services
|
|
87
112
|
```
|
|
88
113
|
|
|
89
114
|
### Install options
|
|
@@ -128,6 +153,56 @@ Re-running `ework-aio install` is safe:
|
|
|
128
153
|
- Systemd units are overwritten (config drift auto-corrected).
|
|
129
154
|
- Plugin merge skips if `opencode-ework` already in `plugin` array.
|
|
130
155
|
|
|
156
|
+
## Runtime configuration (`ework-aio config`)
|
|
157
|
+
|
|
158
|
+
For changing settings after install, prefer `config` over editing `.env` by hand — it writes the right file, handles cross-service dependencies, and restarts the affected service for you.
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
ework-aio config list # see all settable keys + current values
|
|
162
|
+
ework-aio config get WORK_PORT # read one
|
|
163
|
+
ework-aio config set WORK_PORT 8080 # set + auto-restart ework-web
|
|
164
|
+
ework-aio config set WORK_PORT 8080 --no-restart # stage the change, apply later
|
|
165
|
+
ework-aio config restart both # explicit restart
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Settable keys
|
|
169
|
+
|
|
170
|
+
| Key | Service | What it controls |
|
|
171
|
+
| ---------------------------- | ------- | ---------------------------------------------------------- |
|
|
172
|
+
| `WORK_PORT` | web | ework-web listen port (default 3002) |
|
|
173
|
+
| `WORK_HOST` | web | bind address (default 127.0.0.1; use 0.0.0.0 for LAN) |
|
|
174
|
+
| `WORK_OPERATOR_LOGIN` | web | login auto-promoted to admin |
|
|
175
|
+
| `WORK_OPENCODE_BIN` | web | opencode binary path used by ework-web |
|
|
176
|
+
| `WORK_TRANSLATE_URL` | web | OpenAI-compat `/v1/chat/completions` endpoint for translate |
|
|
177
|
+
| `WORK_TRANSLATE_MODEL` | web | translate model name |
|
|
178
|
+
| `WORK_TTS_SPEED` | web | TTS playback rate (default 1.0) |
|
|
179
|
+
| `WORK_FILE_ROOTS` | web | comma-separated file-viewer roots |
|
|
180
|
+
| `WORK_COMMENT_SORT` | web | `desc` or `asc` |
|
|
181
|
+
| `DAEMON_PORT` | daemon | ework-daemon listen port (default 3101) |
|
|
182
|
+
| `DAEMON_HOST` | daemon | bind address |
|
|
183
|
+
| `OPENCODE_BINARY` | daemon | opencode binary path |
|
|
184
|
+
| `OPENCODE_BASE_WORKDIR` | daemon | opencode working directory base |
|
|
185
|
+
| `COMPLETION_CHECK_API_KEY` | daemon | completion-check API key |
|
|
186
|
+
| `COMPLETION_CHECK_BASE_URL` | daemon | completion-check API base URL |
|
|
187
|
+
| `COMPLETION_CHECK_MODEL` | daemon | completion-check model name |
|
|
188
|
+
|
|
189
|
+
### Cross-service dependencies
|
|
190
|
+
|
|
191
|
+
Changing `WORK_PORT` or `DAEMON_PORT` also rewrites the URL the *other* service uses to call it (so the daemon still finds web, and web still finds the daemon), and restarts **both**:
|
|
192
|
+
|
|
193
|
+
- `config set WORK_PORT 8080` → updates `WORK_PORT` in web env + `GITEA_URL` in daemon env, restarts both
|
|
194
|
+
- `config set DAEMON_PORT 3102` → updates `DAEMON_PORT` in daemon env + `WORK_DAEMON_WEBHOOK_URL` in web env, restarts both
|
|
195
|
+
|
|
196
|
+
### Not settable here (use install)
|
|
197
|
+
|
|
198
|
+
Secrets and the web↔daemon contract aren't exposed via `config` — rerun `ework-aio install` to regenerate them (delete the relevant `.env` first if you want fresh tokens):
|
|
199
|
+
|
|
200
|
+
- Random secrets: `WORK_TOKEN`, `WORK_COOKIE_SECRET`, `WORK_DAEMON_WEBHOOK_SECRET`, `BOT_TOKEN`
|
|
201
|
+
- DB / attachment paths: `WORK_DB_PATH`, `WORK_ATTACHMENT_ROOT`, `DAEMON_DB_PATH`
|
|
202
|
+
- Web↔daemon contract: `GITEA_URL`, `GITEA_TOKEN`, `WORK_DAEMON_BOT_LOGIN`, `WORK_DAEMON_WEBHOOK_URL`, `BOT_USERNAME`
|
|
203
|
+
|
|
204
|
+
To regenerate all of them: `rm -rf ~/.local/share/ework-aio && ework-aio install`.
|
|
205
|
+
|
|
131
206
|
## Uninstall
|
|
132
207
|
|
|
133
208
|
```bash
|
package/bin/install.sh
CHANGED
|
@@ -30,12 +30,27 @@ DAEMON_PORT="3101"
|
|
|
30
30
|
BOT_NAME="ework-daemon"
|
|
31
31
|
NO_START=0
|
|
32
32
|
ASSUME_YES=0
|
|
33
|
+
NO_RESTART=0
|
|
34
|
+
CFG_ARGS=()
|
|
33
35
|
|
|
34
36
|
usage() {
|
|
35
37
|
cat <<'EOF'
|
|
36
|
-
ework-aio
|
|
37
|
-
|
|
38
|
-
|
|
38
|
+
ework-aio <command> [options]
|
|
39
|
+
|
|
40
|
+
Commands:
|
|
41
|
+
install [options] Install or upgrade the ework stack (default)
|
|
42
|
+
uninstall Stop services and remove units (data preserved)
|
|
43
|
+
status Show service status
|
|
44
|
+
logs [web|daemon] Tail logs
|
|
45
|
+
env Print key paths (no secrets)
|
|
46
|
+
config <subcommand> Read / change runtime config (.env keys)
|
|
47
|
+
config list List all settable keys + current values
|
|
48
|
+
config get <KEY> Print current value of one key
|
|
49
|
+
config set <KEY> <VALUE> Set a key, then restart affected service
|
|
50
|
+
(unless --no-restart is given)
|
|
51
|
+
config restart <web|daemon> Restart one or both services
|
|
52
|
+
|
|
53
|
+
Install options:
|
|
39
54
|
--user Use user-level systemd units (default if non-root)
|
|
40
55
|
--system Use system-level systemd units (default if root)
|
|
41
56
|
--data-dir <path> Override data directory (default: ~/.local/share/ework-aio)
|
|
@@ -44,7 +59,9 @@ Options:
|
|
|
44
59
|
--bot-name <login> Bot username (default: ework-daemon)
|
|
45
60
|
--no-start Install units but don't start services
|
|
46
61
|
--yes Skip all prompts (use generated defaults)
|
|
47
|
-
|
|
62
|
+
|
|
63
|
+
Global options:
|
|
64
|
+
--no-restart With `config set`: edit .env but skip the restart
|
|
48
65
|
-h, --help Show this help
|
|
49
66
|
EOF
|
|
50
67
|
}
|
|
@@ -52,6 +69,18 @@ EOF
|
|
|
52
69
|
while [[ $# -gt 0 ]]; do
|
|
53
70
|
case "$1" in
|
|
54
71
|
install|uninstall|status|logs|env) MODE="$1"; shift ;;
|
|
72
|
+
config)
|
|
73
|
+
MODE="config"
|
|
74
|
+
shift
|
|
75
|
+
# Consume remaining args as config subcommand + its positionals.
|
|
76
|
+
while [[ $# -gt 0 ]]; do
|
|
77
|
+
case "$1" in
|
|
78
|
+
--no-restart) NO_RESTART=1; shift ;;
|
|
79
|
+
-h|--help) CFG_ARGS=("help"); shift ;;
|
|
80
|
+
*) CFG_ARGS+=("$1"); shift ;;
|
|
81
|
+
esac
|
|
82
|
+
done
|
|
83
|
+
;;
|
|
55
84
|
--user) SCOPENAME="--user"; shift ;;
|
|
56
85
|
--system) SCOPENAME="--system"; shift ;;
|
|
57
86
|
--data-dir) DATA_DIR="$2"; shift 2 ;;
|
|
@@ -59,6 +88,7 @@ while [[ $# -gt 0 ]]; do
|
|
|
59
88
|
--daemon-port) DAEMON_PORT="$2"; shift 2 ;;
|
|
60
89
|
--bot-name) BOT_NAME="$2"; shift 2 ;;
|
|
61
90
|
--no-start) NO_START=1; shift ;;
|
|
91
|
+
--no-restart) NO_RESTART=1; shift ;;
|
|
62
92
|
--yes|-y) ASSUME_YES=1; shift ;;
|
|
63
93
|
-h|--help) usage; exit 0 ;;
|
|
64
94
|
*) die "Unknown argument: $1 (try --help)" ;;
|
|
@@ -74,15 +104,20 @@ fi
|
|
|
74
104
|
need_cmd() {
|
|
75
105
|
command -v "$1" >/dev/null 2>&1 || die "Missing required command: $1. $2"
|
|
76
106
|
}
|
|
77
|
-
|
|
78
|
-
need_cmd npm "Install Node.js or Bun (ships npm)"
|
|
79
|
-
need_cmd opencode "Install from https://opencode.ai"
|
|
107
|
+
# Commands every mode needs (status/logs/env/config/uninstall all use systemctl).
|
|
80
108
|
need_cmd systemctl "This installer requires systemd."
|
|
81
|
-
need_cmd openssl "Install the openssl package."
|
|
82
|
-
need_cmd curl "Install curl."
|
|
83
|
-
need_cmd jq "Install jq (for opencode.json merge)."
|
|
84
109
|
need_cmd awk "Should be present on any Linux."
|
|
85
110
|
|
|
111
|
+
# Install-only deps. Other modes work even if these are missing.
|
|
112
|
+
if [[ "$MODE" == "install" ]]; then
|
|
113
|
+
need_cmd bun "Install from https://bun.sh"
|
|
114
|
+
need_cmd npm "Install Node.js or Bun (ships npm)"
|
|
115
|
+
need_cmd opencode "Install from https://opencode.ai"
|
|
116
|
+
need_cmd openssl "Install the openssl package."
|
|
117
|
+
need_cmd curl "Install curl."
|
|
118
|
+
need_cmd jq "Install jq (for opencode.json merge)."
|
|
119
|
+
fi
|
|
120
|
+
|
|
86
121
|
# Verify the 3 npm packages are reachable. If not, try to install them now.
|
|
87
122
|
ensure_pkg() {
|
|
88
123
|
local pkg="$1"
|
|
@@ -227,6 +262,211 @@ EOF
|
|
|
227
262
|
|
|
228
263
|
ctl() { systemctl "$SCOPENAME" "$@"; }
|
|
229
264
|
|
|
265
|
+
# ─── Config mode: read/change runtime .env keys ─────────────────────────────
|
|
266
|
+
# Each entry: KEY|SERVICE|DESCRIPTION. Only keys in this list are settable via
|
|
267
|
+
# `config set`. Secrets (WORK_TOKEN, *_WEBHOOK_SECRET, BOT_TOKEN), DB paths,
|
|
268
|
+
# and the web<->daemon contract (GITEA_URL/TOKEN, WORK_DAEMON_WEBHOOK_*) are
|
|
269
|
+
# deliberately excluded — changing them by hand breaks the install.
|
|
270
|
+
SETTABLE_KEYS=(
|
|
271
|
+
"WORK_PORT|web|ework-web listen port (default 3002)"
|
|
272
|
+
"WORK_HOST|web|ework-web bind address (default 127.0.0.1; use 0.0.0.0 for LAN)"
|
|
273
|
+
"WORK_OPERATOR_LOGIN|web|login auto-promoted to admin"
|
|
274
|
+
"WORK_OPENCODE_BIN|web|opencode binary path used by ework-web"
|
|
275
|
+
"WORK_TRANSLATE_URL|web|OpenAI-compat /v1/chat/completions endpoint for translate"
|
|
276
|
+
"WORK_TRANSLATE_MODEL|web|translate model name"
|
|
277
|
+
"WORK_TTS_SPEED|web|TTS playback rate (default 1.0)"
|
|
278
|
+
"WORK_FILE_ROOTS|web|comma-separated file-viewer roots"
|
|
279
|
+
"WORK_COMMENT_SORT|web|comment sort order: desc|asc"
|
|
280
|
+
"DAEMON_PORT|daemon|ework-daemon listen port (default 3101)"
|
|
281
|
+
"DAEMON_HOST|daemon|ework-daemon bind address (default 127.0.0.1)"
|
|
282
|
+
"OPENCODE_BINARY|daemon|opencode binary path"
|
|
283
|
+
"OPENCODE_BASE_WORKDIR|daemon|opencode working directory base"
|
|
284
|
+
"COMPLETION_CHECK_API_KEY|daemon|completion-check API key"
|
|
285
|
+
"COMPLETION_CHECK_BASE_URL|daemon|completion-check API base URL"
|
|
286
|
+
"COMPLETION_CHECK_MODEL|daemon|completion-check model name"
|
|
287
|
+
)
|
|
288
|
+
|
|
289
|
+
key_service() {
|
|
290
|
+
local k="$1" e
|
|
291
|
+
for e in "${SETTABLE_KEYS[@]}"; do
|
|
292
|
+
[[ "$e" == "$k|"* ]] || continue
|
|
293
|
+
local rest="${e#*|}"
|
|
294
|
+
echo "${rest%%|*}"
|
|
295
|
+
return
|
|
296
|
+
done
|
|
297
|
+
}
|
|
298
|
+
key_default() {
|
|
299
|
+
local k="$1" e
|
|
300
|
+
for e in "${SETTABLE_KEYS[@]}"; do
|
|
301
|
+
[[ "$e" == "$k|"* ]] || continue
|
|
302
|
+
local rest="${e#*|}"
|
|
303
|
+
echo "${rest#*|}"
|
|
304
|
+
return
|
|
305
|
+
done
|
|
306
|
+
}
|
|
307
|
+
key_settable() { local k="$1"; local e; for e in "${SETTABLE_KEYS[@]}"; do [[ "$e" == "$k|"* ]] && return 0; done; return 1; }
|
|
308
|
+
|
|
309
|
+
env_file_for() {
|
|
310
|
+
case "$1" in
|
|
311
|
+
web) echo "$WEB_ENV" ;;
|
|
312
|
+
daemon) echo "$DAEMON_ENV" ;;
|
|
313
|
+
*) return 1 ;;
|
|
314
|
+
esac
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
env_get() {
|
|
318
|
+
local file="$1" key="$2"
|
|
319
|
+
[[ -f "$file" ]] || return 1
|
|
320
|
+
awk -F= -v k="$key" '$1==k {sub(/^[^=]*=/,""); print; found=1} END{exit !found}' "$file"
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
env_set() {
|
|
324
|
+
local file="$1" key="$2" val="$3"
|
|
325
|
+
[[ -f "$file" ]] || { mkdir -p "$(dirname "$file")"; touch "$file"; chmod 600 "$file"; }
|
|
326
|
+
if grep -q "^${key}=" "$file"; then
|
|
327
|
+
sed -i "s|^${key}=.*|${key}=${val}|" "$file"
|
|
328
|
+
else
|
|
329
|
+
printf '%s=%s\n' "$key" "$val" >> "$file"
|
|
330
|
+
fi
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
service_for_key() {
|
|
334
|
+
case "$1" in
|
|
335
|
+
WORK_PORT)
|
|
336
|
+
echo "both" ;;
|
|
337
|
+
DAEMON_PORT)
|
|
338
|
+
echo "both" ;;
|
|
339
|
+
*)
|
|
340
|
+
echo "$(key_service "$1")" ;;
|
|
341
|
+
esac
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
restart_service() {
|
|
345
|
+
local svc="$1"
|
|
346
|
+
case "$svc" in
|
|
347
|
+
web) ctl restart ework-web.service && ok "Restarted ework-web" ;;
|
|
348
|
+
daemon) ctl restart ework-daemon.service && ok "Restarted ework-daemon" ;;
|
|
349
|
+
both)
|
|
350
|
+
ctl restart ework-web.service ework-daemon.service && ok "Restarted ework-web + ework-daemon"
|
|
351
|
+
;;
|
|
352
|
+
*) return 1 ;;
|
|
353
|
+
esac
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
config_help() {
|
|
357
|
+
cat <<'EOF'
|
|
358
|
+
ework-aio config <subcommand>
|
|
359
|
+
|
|
360
|
+
Subcommands:
|
|
361
|
+
list List all settable keys + current values
|
|
362
|
+
get <KEY> Print current value of one key
|
|
363
|
+
set <KEY> <VALUE> Set a key in .env, then restart the affected
|
|
364
|
+
service (unless --no-restart is given)
|
|
365
|
+
restart <web|daemon|both> Restart one or both services
|
|
366
|
+
|
|
367
|
+
Examples:
|
|
368
|
+
ework-aio config list
|
|
369
|
+
ework-aio config get WORK_PORT
|
|
370
|
+
ework-aio config set WORK_PORT 8080
|
|
371
|
+
ework-aio config set WORK_TRANSLATE_URL http://127.0.0.1:8000/v1 --no-restart
|
|
372
|
+
ework-aio config restart both
|
|
373
|
+
|
|
374
|
+
Note: changing WORK_PORT or DAEMON_PORT also rewrites the cross-link the other
|
|
375
|
+
service uses (GITEA_URL on daemon side, WORK_DAEMON_WEBHOOK_URL on web side),
|
|
376
|
+
and restarts both. Secrets and DB paths are not settable here — rerun
|
|
377
|
+
`ework-aio install` (with `rm .env` first if you need new tokens).
|
|
378
|
+
EOF
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
config_list() {
|
|
382
|
+
hr; log "Settable config keys"; hr
|
|
383
|
+
printf ' %-28s %-8s %s\n' "KEY" "SERVICE" "VALUE"
|
|
384
|
+
local e k svc val env_file
|
|
385
|
+
for e in "${SETTABLE_KEYS[@]}"; do
|
|
386
|
+
k="${e%%|*}"
|
|
387
|
+
svc="$(key_service "$k")"
|
|
388
|
+
env_file="$(env_file_for "$svc")"
|
|
389
|
+
val="$(env_get "$env_file" "$k" 2>/dev/null || echo '')"
|
|
390
|
+
[[ -z "$val" ]] && val="(unset)"
|
|
391
|
+
printf ' %-28s %-8s %s\n' "$k" "$svc" "$val"
|
|
392
|
+
done
|
|
393
|
+
hr
|
|
394
|
+
printf 'Use %sconfig set <KEY> <VALUE>%s to change a key.\n' "$c_bold" "$c_reset"
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
config_get() {
|
|
398
|
+
local k="$1"
|
|
399
|
+
[[ -n "$k" ]] || die "Usage: ework-aio config get <KEY>"
|
|
400
|
+
key_settable "$k" || die "Key '$k' is not settable. Run 'ework-aio config list' for the allow-list."
|
|
401
|
+
local svc env_file val
|
|
402
|
+
svc="$(key_service "$k")"
|
|
403
|
+
env_file="$(env_file_for "$svc")"
|
|
404
|
+
val="$(env_get "$env_file" "$k" 2>/dev/null)" || { warn "$k is not currently set in $env_file"; exit 0; }
|
|
405
|
+
printf '%s\n' "$val"
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
config_set() {
|
|
409
|
+
local k="$1" v="$2"
|
|
410
|
+
[[ -n "$k" && -n "$v" ]] || die "Usage: ework-aio config set <KEY> <VALUE>"
|
|
411
|
+
key_settable "$k" || die "Key '$k' is not settable. Run 'ework-aio config list' for the allow-list."
|
|
412
|
+
|
|
413
|
+
local svc env_file
|
|
414
|
+
svc="$(key_service "$k")"
|
|
415
|
+
env_file="$(env_file_for "$svc")"
|
|
416
|
+
|
|
417
|
+
log "Setting $k=$v in $env_file"
|
|
418
|
+
cp "$env_file" "$env_file.bak.$(date +%s)" 2>/dev/null || true
|
|
419
|
+
env_set "$env_file" "$k" "$v"
|
|
420
|
+
ok "$k updated"
|
|
421
|
+
|
|
422
|
+
case "$k" in
|
|
423
|
+
WORK_PORT)
|
|
424
|
+
log "Propagating to daemon (GITEA_URL)"
|
|
425
|
+
cp "$DAEMON_ENV" "$DAEMON_ENV.bak.$(date +%s)" 2>/dev/null || true
|
|
426
|
+
env_set "$DAEMON_ENV" "GITEA_URL" "http://127.0.0.1:$v"
|
|
427
|
+
ok "DAEMON_ENV GITEA_URL updated"
|
|
428
|
+
;;
|
|
429
|
+
DAEMON_PORT)
|
|
430
|
+
log "Propagating to web (WORK_DAEMON_WEBHOOK_URL)"
|
|
431
|
+
cp "$WEB_ENV" "$WEB_ENV.bak.$(date +%s)" 2>/dev/null || true
|
|
432
|
+
env_set "$WEB_ENV" "WORK_DAEMON_WEBHOOK_URL" "http://127.0.0.1:$v"
|
|
433
|
+
ok "WEB_ENV WORK_DAEMON_WEBHOOK_URL updated"
|
|
434
|
+
;;
|
|
435
|
+
esac
|
|
436
|
+
|
|
437
|
+
if [[ "$NO_RESTART" == "1" ]]; then
|
|
438
|
+
local to_restart
|
|
439
|
+
to_restart="$(service_for_key "$k")"
|
|
440
|
+
warn "--no-restart: changes saved but service not reloaded. Run 'ework-aio config restart $to_restart' to apply."
|
|
441
|
+
return
|
|
442
|
+
fi
|
|
443
|
+
|
|
444
|
+
local target
|
|
445
|
+
target="$(service_for_key "$k")"
|
|
446
|
+
log "Restarting $target..."
|
|
447
|
+
restart_service "$target" || warn "restart failed — services may need manual reload"
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
config_restart() {
|
|
451
|
+
local svc="${1:-both}"
|
|
452
|
+
case "$svc" in
|
|
453
|
+
web|daemon|both) restart_service "$svc" ;;
|
|
454
|
+
*) die "Usage: ework-aio config restart <web|daemon|both>" ;;
|
|
455
|
+
esac
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
run_config() {
|
|
459
|
+
local sub="${CFG_ARGS[0]:-list}"
|
|
460
|
+
case "$sub" in
|
|
461
|
+
list) config_list ;;
|
|
462
|
+
get) config_get "${CFG_ARGS[1]:-}" ;;
|
|
463
|
+
set) config_set "${CFG_ARGS[1]:-}" "${CFG_ARGS[2]:-}" ;;
|
|
464
|
+
restart) config_restart "${CFG_ARGS[1]:-both}" ;;
|
|
465
|
+
help|-h|--help) config_help ;;
|
|
466
|
+
*) die "Unknown config subcommand: $sub (try: ework-aio config help)" ;;
|
|
467
|
+
esac
|
|
468
|
+
}
|
|
469
|
+
|
|
230
470
|
# ─── Modes ──────────────────────────────────────────────────────────────────
|
|
231
471
|
case "$MODE" in
|
|
232
472
|
env)
|
|
@@ -241,6 +481,11 @@ env)
|
|
|
241
481
|
exit 0
|
|
242
482
|
;;
|
|
243
483
|
|
|
484
|
+
config)
|
|
485
|
+
run_config
|
|
486
|
+
exit 0
|
|
487
|
+
;;
|
|
488
|
+
|
|
244
489
|
status)
|
|
245
490
|
hr; log "ework-aio status ($SCOPENAME)"; hr
|
|
246
491
|
ctl is-active ework-web.service || true
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ework-aio",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "All-in-one installer for ework (issue tracker) + ework-daemon (AI bridge) + opencode-ework (plugin). One command: npm i -g ework-aio && ework-aio install.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|