@gapi/gcli 1.8.244 → 1.8.245

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.
@@ -29,6 +29,11 @@ security, symptom table): `graphql-server/docs/features/local-ai-runners.md`.
29
29
  for "token refused" in sync with `RestartPreventExitStatus`. Tests must
30
30
  pass an explicit home dir to `SystemdUserService` (os.homedir() ignored a
31
31
  changed HOME under jest and wrote into the real `~/.config` once).
32
+ `runner:daemon:start`/`:restart` check the outcome after ~2 s
33
+ (`reportStarted`, exit 78 -> the `--reset` hint) - a refused runner exits
34
+ within a second, so "started" alone would be a lie. Your local `gcli` and
35
+ the installed unit may both run this repo's `release/index.js` (npm link),
36
+ so a build changes what the service runs on its next restart.
32
37
 
33
38
  ## Run it against a dev stack
34
39
 
package/README-CLI.md CHANGED
@@ -58,6 +58,9 @@ Commands:
58
58
  runner:start [options] Connect this machine's Ollama to the Lambforge chat as a local AI runner (outbound connection only - works behind NAT, Ollama is never exposed)
59
59
  runner:daemon:install|runner:start:daemon [options] Run the runner in the background as a systemd user service: starts with your session, restarts on failure (Linux)
60
60
  runner:daemon:status [options] Show the runner service status (systemctl --user status)
61
+ runner:daemon:start [options] Start the installed runner service, and report whether it stays up
62
+ runner:daemon:stop [options] Stop the runner service (it stays installed and starts at your next login)
63
+ runner:daemon:restart [options] Restart the runner service (e.g. after `gcli login` to another server)
61
64
  runner:daemon:logs [options] Follow the runner service log (journalctl --user -f)
62
65
  runner:daemon:uninstall [options] Stop and remove the runner service (the runner stays registered)
63
66
  runner:list List your local AI runners and the models they serve
@@ -879,6 +882,33 @@ Usage: gcli runner:daemon:status [options]
879
882
 
880
883
  Show the runner service status (systemctl --user status)
881
884
 
885
+ Options:
886
+ --service <name> systemd unit name (default: lambforge-runner)
887
+ -h, --help display help for command
888
+ 
889
+ --- Subcommand: runner:daemon:start ---
890
+ Usage: gcli runner:daemon:start [options]
891
+
892
+ Start the installed runner service, and report whether it stays up
893
+
894
+ Options:
895
+ --service <name> systemd unit name (default: lambforge-runner)
896
+ -h, --help display help for command
897
+ 
898
+ --- Subcommand: runner:daemon:stop ---
899
+ Usage: gcli runner:daemon:stop [options]
900
+
901
+ Stop the runner service (it stays installed and starts at your next login)
902
+
903
+ Options:
904
+ --service <name> systemd unit name (default: lambforge-runner)
905
+ -h, --help display help for command
906
+ 
907
+ --- Subcommand: runner:daemon:restart ---
908
+ Usage: gcli runner:daemon:restart [options]
909
+
910
+ Restart the runner service (e.g. after `gcli login` to another server)
911
+
882
912
  Options:
883
913
  --service <name> systemd unit name (default: lambforge-runner)
884
914
  -h, --help display help for command
package/README.md CHANGED
@@ -890,7 +890,7 @@ running until Ctrl+C and reconnects on its own.
890
890
  | `gcli runner:list` | Your runners: online status, last seen, models |
891
891
  | `gcli runner:models` | List which models are shown in the chat; `--show a,b` shows only those, `--all` shows every model, `--none` hides them all; `--id` picks a runner (default: this machine's) |
892
892
  | `gcli runner:delete` | Delete a runner and revoke its token (`--id`, default: this machine's) |
893
- | `gcli runner:start:daemon` / `runner:daemon:install` | Install + start the runner as a systemd user service (Linux); `runner:daemon:status`, `runner:daemon:logs`, `runner:daemon:uninstall` manage it |
893
+ | `gcli runner:start:daemon` / `runner:daemon:install` | Install + start the runner as a systemd user service (Linux); `runner:daemon:start`, `:stop`, `:restart`, `:status`, `:logs`, `:uninstall` manage it |
894
894
 
895
895
  ### Run it in the background (systemd, Linux)
896
896
 
@@ -899,6 +899,9 @@ npm i -g @gapi/gcli # a stable install - not the npx cache
899
899
  gcli login
900
900
  gcli runner:start:daemon # = runner:daemon:install; same options as runner:start
901
901
  gcli runner:daemon:status
902
+ gcli runner:daemon:stop # stop it (stays installed, starts at next login)
903
+ gcli runner:daemon:start # start it again; tells you if it does not stay up
904
+ gcli runner:daemon:restart # e.g. after `gcli login` to another server
902
905
  gcli runner:daemon:logs # follow the log (Ctrl+C to stop following)
903
906
  gcli runner:daemon:uninstall # stop + remove the service (runner stays registered)
904
907
  ```
@@ -0,0 +1,25 @@
1
+ ## 2026-10-24 - local-ai-runners: runner:daemon:start / stop / restart, and start reports whether the runner stays up
2
+
3
+ **Feature:** local-ai-runners · **Type:** feat
4
+
5
+ Why: after `runner:daemon:install` there was no gcli way to start or stop the service (only raw `systemctl --user`), and a service whose token Lambforge refuses failed silently: `runner:daemon:status` showed `status=78` with no explanation of what to do.
6
+
7
+ - New commands (`src/commands/runner/index.ts`, `daemon-commands.ts`), all with `--service`:
8
+ - `runner:daemon:start` and `runner:daemon:restart` run `systemctl --user start/restart`. After ~2 s, `reportStarted` reads `ActiveState`/`ExecMainStatus` (`SystemdUserService.outcome`) and reports:
9
+ - running: says so;
10
+ - exit 78 (`RUNNER_AUTH_EXIT_CODE`): the token was refused - the runner was deleted, or registered on another server than `~/.graphql-server/url` - with the hint to re-register via `gcli runner:daemon:install --reset`;
11
+ - any other exit: points to `runner:daemon:logs`.
12
+ - `runner:daemon:stop`: `systemctl --user stop`. The unit stays enabled and starts at the next login; `uninstall` removes it.
13
+ - All three refuse with "not installed - run `gcli runner:daemon:install` first" when the unit file is missing.
14
+ - `SystemdUserService`: `installed()`, `start()`, `stop()`, `restart()`, `outcome()`.
15
+ - README, `README-CLI.md` (regenerated) and `docs/features/local-ai-runners.md` updated.
16
+ - **Test:**
17
+ - `npx jest --coverage=false test/runner-daemon.spec.ts` covers: the systemctl calls, `installed()`, and the three `reportStarted` outcomes.
18
+ - Live: `gcli runner:daemon:stop`, `gcli runner:daemon:start`, then `gcli runner:daemon:status`.
19
+ - **Debug:**
20
+ - "did not stay up": `gcli runner:daemon:logs`.
21
+ - "refused this runner's token": compare `~/.graphql-server/url` with the server the runner was registered on, then `runner:daemon:install --reset`.
22
+ - **Verification:**
23
+ - jest: 11 suites, 103 tests pass (4 new). `tsc --noEmit` and eslint are clean.
24
+ - `npm run build`: `--help` lists the new commands.
25
+ - Not run against the real systemd unit.
@@ -14,6 +14,8 @@ what lives in gcli.
14
14
  | `gcli runner:models [--id] [--show a,b \| --all \| --none]` | Which models appear in the chat picker; no flag = list |
15
15
  | `gcli runner:delete [--id]` | Delete a runner and revoke its token (default: the saved one) |
16
16
  | `gcli runner:daemon:install` (alias `runner:start:daemon`) `[runner:start options] [--service] [--dry-run]` | Resolve/register the runner now (saves `runner.json`), then install + enable + restart a systemd USER unit running `runner:start --ollama <resolved>` (Linux) |
17
+ | `gcli runner:daemon:start` / `:restart` `[--service]` | `systemctl --user start/restart`, then after ~2 s reads `ActiveState`/`ExecMainStatus` (`SystemdUserService.outcome`): running, or an error - exit 78 = token refused (deleted, or registered on another server than `~/.graphql-server/url`) with the `runner:daemon:install --reset` hint. Refuses when the unit is not installed |
18
+ | `gcli runner:daemon:stop` `[--service]` | `systemctl --user stop` (stays enabled: starts again at the next login) |
17
19
  | `gcli runner:daemon:status` / `:logs` / `:uninstall` | `systemctl --user status`, `journalctl --user -f`, disable --now + remove the unit |
18
20
 
19
21
  Endpoints: `--wsUrl` > `runner.json` > derived from the `gcli login` URL
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gapi/gcli",
3
- "version": "1.8.244",
3
+ "version": "1.8.245",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/Stradivario/gapi.git"